d582f15681
- Implemented tests for import polling functionality, ensuring correct behavior for active and terminal import statuses. - Created tests for the login page, validating user interactions and error handling. - Added unit tests for money utility functions, covering parsing, formatting, and summation of monetary values. - Developed tests for query keys, ensuring proper scoping and invalidation roots. chore: setup testing environment and configuration - Added setup file for testing with Vitest and Testing Library. - Configured TypeScript and Vite for the frontend project. - Created Docker and Nginx configurations for local development and production environments. - Established a PostgreSQL initialization script for setting up application roles. docs: add README and environment configuration for infra - Included README for the infra directory, detailing local development setup and service descriptions. - Created an example environment configuration file for local development with placeholders for sensitive information.
2.3 KiB
2.3 KiB
ADR 0002: Journal of operations/postings and budget reserves
- Status: Accepted
- Date: 2026-09-11
- Scope: ledger model, balance derivation, budget plan/funding separation
Context
The product needs trustworthy account balances including credit-card debt, zero-based monthly budgeting where the plan is separate from actual funded money, carry-over savings envelopes, and permanent per-card credit reserves. History must remain auditable and deterministic: closed budget facts must never silently change.
Decision
- The ledger is a journal of
operations(expense | income | transfer | refund;confirmed | voided) andpostings(one posting for external income/expense/refund; two equal and opposite postings for an internal transfer). Amounts are integer kopecks; no floats. - Balances are derived, never mutated directly: opening position plus confirmed, non-voided postings. Credit debt follows one documented sign convention.
- This is not event sourcing and not full double-entry against the external world: the journal is just enough structure to make balances reconstructable and voiding explicit.
- Budgeting splits plan from funding:
plan_assignmentsexpress intent,funding_movementsmove actually received money from the general pool. Monthly categories fold their remainder into the pool at close; savings envelopes carry balances forward; each credit card has a permanent reserve. - Period closure writes an immutable snapshot. Changing or voiding an operation in a closed month requires an explicit cascade reopen of all subsequent periods; late refunds after closure credit the current pool and never rewrite the closed fact.
Consequences
- All balance-affecting mutations must go through journal/budget services; direct updates are excluded by convention and tests.
- Analytics for closed periods read from closure snapshots, not live aggregates.
- Plan/funding separation and closure snapshots shape the write model permanently (hard to reverse once history exists).
Alternatives rejected
- Event sourcing — complexity without a matching need at MVP scale.
- Mutable stored balances without a journal — loses auditability and voiding semantics.
- Folding envelopes/reserves into the pool — destroys carried-forward user intent.