Household financial ledger
Personal finance
Keeledger
A server-rendered household ledger in Go where thirteen financial invariants are enforced by the database itself, and AI extraction proposes entries a person commits.
- Status
- In use
- Invariants
- 13, enforced by database triggers
- History
- Append-only, corrections by supersession
- AI guardrails
- Breaker, budget, privacy deny-list
- Stack
- Go 1.26, PostgreSQL (Supabase, RLS), sqlc, html/template, Tailwind v4, Anthropic Go SDK
The problem
Households hold money across banks, brokerages, retirement accounts, property and loans. Consumer finance apps sync balances and quietly rewrite history, so the number you see today may not be the number you saw last quarter. A ledger should be append-only and correct by construction.
What we built
- A server-rendered Go application: standard library HTTP, HTML templates, generated SQL, and Supabase Postgres with row-level security scoped to the household.
- Double-entry financial events with legs, corrections by supersession rather than deletion, and net asset value at any date as the headline feature.
- Thirteen financial invariants enforced in the database: legs balance per currency, no overdraft on cash-like holdings, a single currency per event, append-only events, no cycles in corrections, money stored as integer minor units, idempotent ingestion, and more. Each has a dedicated test that drives the database directly.
- A screenshot-to-ledger pipeline: upload a statement image, review extracted candidates, and commit a batch in one transaction.
Where AI fits
- A vision model reads a statement screenshot into structured candidates, with a stub extractor for environments without an API key.
- An occasions planner holds a short conversation to gather what it needs, decides each turn whether to ask or synthesize, and gives up on a question after two attempts so it converges instead of looping.
Engineering discipline
- Invariants in the database, not the application, so a raw SQL client or a future service cannot violate them either.
- Race tests for concurrent writers: two transfers that overdraft exactly once, two corrections that resolve to exactly one winner.
- A standard audit target that runs vet, static analysis and vulnerability checks; HTML-first pages that work without JavaScript.
What it is worth
- Balances you can trust because every one is a replay of events that were never edited.
- AI removes the typing, not the judgment.
The two lanes
Kept deterministic
- Double-entry balance
- Household isolation
- Supersession chain
- Batch commit
Where intelligence helps
- Statement extraction
- Occasion planning conversation