Zaccount turns a validated local CSV ledger into a disposable interactive report. The owner edits the working data file directly, runs one fast command, and opens a new snapshot without starting or maintaining an application service.
The report must let its owner:
- understand income, expense, net change, account balances, monthly expense, category distribution, and tag distribution;
- combine date, account, type, category-path, tag, and description filters;
- trace every result back to the matching ledger entries;
- regenerate the complete result from
transaction.csvin one command; - keep all source data and generated artifacts local.
There is no entry form, write interface, HTTP server, cloud sync, authentication, telemetry, multi-user model, or database.
- Generation is the refresh action. A report is a snapshot, not a long-running application that synchronizes itself.
- Local is a data guarantee. The report contains no remote assets or network requests.
- Analysis leads back to evidence. Every filter updates summaries, charts, and the visible entry list together.
- One calculation model. Initial rendering and browser interaction follow the same type signs and category-prefix rules.
- The working source is never modified. Before analysis, report generation preserves the first observed ledger state of the day as a dated sibling CSV.
- Generated output is private. The report embeds the fields required for interactive analysis and must be protected like the source CSV.
The canonical language is recorded in CONTEXT.md.
- Amounts are positive decimal text.
- Initial balance, income, and transfer-in add funds.
- Expense and transfer-out subtract funds.
- Initial balance has no category and is not counted as income.
- Dates use
YYYY-MM-DDand remain in ascending order. - A category path is a valid prefix of the fixed tree for its type.
- Selecting a category in the report matches that path and every descendant.
- Selecting multiple tags requires a ledger entry to contain every selected tag.
- Internal transfer-in and transfer-out totals must balance.
- The durable header is
date,account,type,amount,categories,tags,desc.
transaction.csv + category tree
│
▼
Report generation module
├── read and validate ledger
├── calculate canonical totals
├── create versioned report data
└── atomically write both artifacts
│
├── report.json
└── report.html
└── local browser filtering and rendering
The Report generation module is the principal deep module. Its interface accepts the ledger path, category tree, and output directory. Callers do not manage CSV rows, validation order, serialization, template escaping, fingerprints, or atomic output replacement.
The Ledger module is the adapter for the durable CSV seam. Before reading, it
creates transaction_YYYY-MM-DD.csv beside the working file when that day's
snapshot does not already exist. It never changes the working file or overwrites a
daily snapshot. The Analysis module is pure in-process calculation. The HTML
renderer is an offline adapter over the versioned report data; it does not become
a second source of durable truth.
report.json has a top-level schemaVersion. Money is serialized as decimal
strings. It contains:
- generation time;
- source file name, date range, entry count, and SHA-256 fingerprint;
- the category tree;
- canonical full-ledger analysis;
- normalized entries required for arbitrary local filtering.
The absolute source path is deliberately excluded. The HTML embeds the exact same JSON after escaping characters that could terminate its data script.
Filters apply immediately with no submit action:
- start and end dates, plus year shortcuts;
- one account and one type;
- one category path at any depth;
- any number of tags, with all-selected semantics;
- description text.
Changing a filter updates the funds scale, summary totals, account movements, monthly expense, category drill-down, tag distribution, and evidence table. When a start date is selected, account results are labelled as interval movement instead of current balance.
The report resembles a precise personal ledger rather than an administration dashboard. It uses local system typefaces and these tokens:
- paper:
#F2F5F9 - surface:
#FFFFFF - ink:
#17233B - ledger blue:
#3157D5 - expense coral:
#D9584D - income teal:
#1D806E - rule:
#D9E0EB
Its signature is the funds scale: expense extends left from zero and income extends right, making the current filtered relationship visible before reading individual values. Motion is limited to value and bar transitions and respects reduced-motion preferences.
- Domain and ledger tests cover decimal signs, initial balances, fields, ordering, category paths, and transfer balance.
- Analysis tests cover shared filters and category prefix semantics.
- Reporting tests cover schema version, decimal serialization, source privacy, template escaping, CLI output, and standalone artifacts.
- Browser verification covers combined date, tag, and category interaction at desktop and mobile widths using synthetic data.