Systems designer · 2026 · personal project

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.

Local-firstNo telemetryExplainable by constructionPre-release
Overview02

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
Architecture03

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.

The four rules04

Four decisions, each with a cost attached.

The rule
  • 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
What it buys
  • 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
Encryption at rest05

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.
Documenting honestly06

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 countedStatus sheetREADMECited
Automated tests72380Neither
Engines1524Neither
Screens1419Neither
Glossary entries2729Neither
Schema migrationsv1 → v6nine, additiveNeither

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.

What holds, and what is unproven07

Proven logically. Unproven in almost every other way.

Where it stands
  • 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
Still open
  • 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

Eleven panels, read end to end.

B-SIDEOff the record