- txns_db.py: SQLite store with the same list-of-dicts shape, ACID writes
(no corruption / no lost-update race), indexes, and a fast unreviewed COUNT.
- app.py: get_transactions/save_transactions delegate to txns_db; one-time
idempotent migration from transactions.json on startup (JSON kept as backup);
nav badge uses count_unreviewed() instead of parsing the whole store (#33).
- Verified against the live 265-row dataset: counts, fields, splits, mutation.
- Other small JSON files intentionally stay JSON.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>