Integer paise, all the way down.
Most personal finance software answers where the money went, which is the least interesting question a household has. The interesting ones are forward-looking and involve other people — and answering them needs a model of the household, not just the account.
A ledger is one module inside it.
- My role
- Executed — concept, architecture, implementation
- Dates, from version control
- 22 – 31 August 2026
- Built with
- Flutter · SQLite, running on desktop, mobile and in a browser
- Network calls
- None, unless the user turns on an optional language model
- State
- Pre-release v0.1.0. Not released
Three layers and one absolute rule.
Layering is usually a diagram nobody enforces. Here it is the reason the interview, the leak finder, the affordability planner and the tax calculators can all be proven correct without rendering a single widget.
User interface
Flutter widgets
Consumes engines. Never touches a repository, never contains a calculation.
Engines
All business logic
Every decision, verdict, projection and rupee figure. No SQL, no widgets — which is exactly why they are testable in isolation.
Repositories
All SQL
Reads and writes. No business logic and no decisions of any kind.
Storage
SQLite, platform-split
The same engine code runs on desktop, mobile and in a browser. Composed once in a single composition root, the only thing the interface depends on.
Four decisions, each with a cost attached.
- Money is integer paise everywhere — no float in any monetary path
- The ledger is the single source of truth
- Deletes are soft only
- Every mutation writes to an immutable audit log
- Byte-identical results on every platform; a total can never drift from its parts
- Balances are a cache, recomputable at any time — and there is a button that does it
- Financial history is never destroyed; a deleted transaction is listed and restorable
- Nine additive migrations, none destructive
Shipping untestable crypto is worse than shipping none.
- Before
- The standard answer for an encrypted local database was the plan: an encrypted SQLite build.
- What forced it
- It has no browser build, reaching it meant breaking a version pin that exists to keep the browser build working, and it could not be tested on the development machine at all.
- The decision
- Encrypt the contents rather than the pages. Locked, there is one AES-256-GCM blob on disk and nothing else; unlocked, an in-memory database rebuilt from it; on change, the blob is rewritten. Enabling is ordered so it cannot lose data — write the vault, read it back, decrypt it, and only then delete the plaintext.
- What it changed
- The passphrase is never stored and there is no recovery, and both the lock screen and the settings card say so in those words rather than offering a reset that cannot exist. Untestable cryptography converts an understood exposure into an assumed protection; that was the thing being refused.
This project cannot tell me how many tests it has.
It carries two self-descriptions — a status sheet dated 21 August 2026 and a README written later — and they disagree on every count it publishes. So neither figure is cited, here or in the artifact.
| What is being counted | Status sheet | README | Cited |
|---|---|---|---|
| Automated tests | 72 | 380 | Neither |
| Engines | 15 | 24 | Neither |
| Screens | 14 | 19 | Neither |
| Glossary entries | 27 | 29 | Neither |
| Schema migrations | v1 → v6 | nine, additive | Neither |
The likely explanation is that the status sheet stopped being updated. That is a reasonable guess and it is still a guess, so it does not license picking the larger number. One conflict does resolve, because version control outranks prose: the sheet records the project as not yet committed to git, and the repository shows it committed the day after that sheet was written.
Proven logically. Unproven in almost every other way.
- A redaction guard that throws rather than logs before anything can leave the device — it has already caught member names inside insurance gap titles
- Every rupee figure computed locally and identically whether or not a language model is configured
- A cross-engine audit that found a laptop priced at ₹800 crore, a headline overstated by more than half, and savings reported as leaks
- Honest empty states: with three months of data the app says so and declines to find patterns
- Nothing has been verified to look right — no screenshot was taken during development
- Its own design tokens comment one step as “readable on white” when it measures 1.91:1, and the secondary text colour is 3.14:1 on the canvas
- PDF import, the file picker and on-device message reading all have real code and no test against the real thing
- Nobody has yet seen this application get an answer from a real language model; every test uses a mock
- The security design has had no external cryptographic review