From Toy Budget App to Governance Tool: Reading the Git History of manavote
Some repositories tell you what a project is. Better repositories tell you what the project was afraid of becoming.
makespacemadrid/manavote begins with a very practical idea: a hackerspace needs a way for members to decide what “new toys” to buy. The initial shape is simple and local: Flask, SQLite, members, proposals, votes, a budget, and Telegram notifications. It is the kind of project that starts because a community has a real operational itch. The first version is not trying to be a platform. It is trying to answer a question: “Can we make spending decisions visible, lightweight, and fair?”
That first phase, visible in the March commit history, is classic small-tool growth. The app gets a README. Self-registration appears. Proposals gain editing, URLs, and image uploads. Over-budget proposals become a first-class state instead of a dead end. Comments arrive. Docker arrives. The dashboard gets polish. This is the phase where a useful script becomes an application.
The interesting part is what happens next.
By early April, the history changes tone. The repository stops reading like a sequence of isolated feature additions and starts reading like a structured refactor campaign. A pull request adds a refactor plan and a specification of observed behavior. That matters. The maintainers do not simply start moving code around; they first write down what the system already does, where the risk sits, and what must not break.
That decision turns out to be the hinge of the project.
The original application appears to have started as a compact Flask monolith. It had the usual properties of a fast local tool: everything in one place, direct SQLite access, inline business rules, and pragmatic defaults. The later history shows a deliberate move away from that shape. Settings and threshold logic get centralized. Budget behavior gets tests. The app is broken into modules. Database work moves into repositories. Business rules move into services. Startup becomes explicit. Migrations become safer. Documentation stops being decorative and becomes part of the engineering process.
This is not just cleanup. It is risk management.
The voting rules are deceptively small: members vote, thresholds are calculated from member count, proposals are approved if they have enough support and enough available budget, and over-budget proposals wait until funds exist. But small financial rules become fragile when they are copied across routes. The history shows repeated attention to exactly that problem: threshold calculation, over-budget processing, monthly top-ups, committed-budget charting, and vote withdrawal all receive follow-up fixes. The project learns that “simple” governance software is only simple when every edge case is documented and tested.
The same pattern appears in security. Early local tools often ship with defaults that are useful in development but dangerous in production: weak bootstrap assumptions, secret handling that is fine on a laptop, broad exception handling, missing CSRF coverage, loose upload validation, and deployment images running with too much privilege. In manavote, those concerns become visible in the history rather than hidden in an issue tracker. The project adds secure-cookie behavior, production secret validation, admin bootstrap checks, upload MIME validation, CSRF hardening, API JSON validation, a non-root container, and health checks.
That arc is important because it shows maturity. Security did not arrive as a single “security pass.” It arrived as a series of concrete responses to the ways the app was becoming more real.
The next major phase is community participation beyond the web UI. Telegram starts as notification plumbing, but the later history turns it into an interaction surface. Polls are added. Telegram voting appears. Inline keyboards arrive. Account linking becomes important. Then come the inevitable follow-ups: vote modes, linked-account requirements, feedback when callbacks fail, diagnostics for missing usernames or user IDs, and audit events for link lifecycle changes.
This is a recognizable pattern in community software. The moment a feature moves into the channel where people already are, identity and feedback become harder. A web form can assume a logged-in session. A Telegram callback has to answer different questions: Who tapped this? Are they linked? Are they allowed to vote here? What should they see if they are not? The history shows the project discovering those questions in public and building guardrails around them.
Then comes the MCP/API phase, which is perhaps the most surprising part of the repository. The project adds an MCP JSON-RPC server, REST/MCP parity checks, create tools, header-based auth, tool aliases, batch handling, request-ID preservation, and compatibility fixes for clients. This is a small hackerspace voting app gaining an automation interface.
That could be over-engineering. But in the context of the history, it reads more like a continuation of the same theme: make governance operations explicit, inspectable, and scriptable. Admins already manage members, budgets, thresholds, backups, polls, and Telegram settings. Once those operations exist, exposing them consistently through documented APIs becomes a way to reduce manual drift.
The most striking thing about the git history is the workflow itself. A large portion of the later work lands through codex/... branches. The commits are often precise, scoped, and paired with tests or documentation. That suggests an AI-assisted maintenance style: ask for a slice of work, merge the branch, discover the next regression, patch it, document it, and repeat.
There are tradeoffs. The history has bursts of follow-up fixes after big feature merges, especially around polls, Telegram, language switching, calendar charts, and MCP compatibility. That is not necessarily a failure; it is evidence of fast iteration. But it does mean the repository benefits heavily from the test suite it accumulated. Without those regression packs, the same velocity would be risky.
The end state is much more ambitious than the starting point. manavote is no longer just “a page where members vote on purchases.” It is a small governance system: proposals, polls, budget commitments, transparent voting, Telegram participation, admin controls, backups, production startup policy, API/MCP surfaces, i18n, and a test guide that names the behaviors worth protecting.
The git history tells a useful story for any community-maintained tool:
Start with the real need. Ship the rough version. Write down the rules before refactoring them. Treat money logic as business logic, not template logic. Expect chat integrations to complicate identity. Harden production defaults before the app becomes invisible infrastructure. And when AI-assisted branches accelerate development, make tests and documentation the anchor that keeps the project legible.
manavote began as a budget vote app. Its history shows it becoming something more interesting: a record of how a community tool grows up when every small operational edge case is allowed to leave a commit behind.
GPT5 20260608
Audit https://github.com/makespacemadrid/manavote and write a blog post about its git history