Usage reconciliation ledger
CJ Ackley | SWE | Project brief

STATUS
Ledger design brief; event policy to define. Implementation and tests are planned.

THE PROBLEM
A service receives usage events late, twice, or after a correction. Adding the latest records into a total makes disputes hard to investigate. This ledger preserves the original events and produces reproducible period totals with a trace back to each input.

DESIGN QUESTION
Can an operator rebuild a total and explain every adjustment without rewriting history?

SCOPE
- Store events in PostgreSQL with a unique source and event ID; use exact quantities and declared units.
- Record corrections as linked adjustments; close periods explicitly and version calculation rules.
- Provide a reconciliation view and export; keep prices, tax, and payment processing out of scope.

CONSTRAINTS
Identity: Duplicate IDs must carry identical payloads or be rejected
Periods: Event time, arrival time, and late-event policy are separate
Quantities: Integer or fixed-decimal arithmetic; no binary-float totals
Access: Account-scoped queries and audited adjustment permissions

ENGINEERING DECISIONS (PROPOSED)
Period cutoffs and linked adjustments
Serialize ingestion and closing for each account-period. Assign accepted events a durable ingestion sequence and close at a recorded cutoff. Freeze that close version. Late events and corrections remain linked adjustments for a later reconciliation rather than changing the closed export.

ALTERNATIVE
Recomputing a mutable total from event timestamps is simple, but the same closed period can change whenever a delayed event arrives.

TRADEOFF
The ledger keeps event time, arrival sequence, close versions, and adjustment links. More storage and a clearer operator workflow are needed to make those differences inspectable.

PROPOSED TOOLS AND METHODS
PostgreSQL, Exact-decimal arithmetic, Ingestion API

VERIFICATION SCENARIO (NOT YET RUN)
An event arrives while its period is closing
Synchronize an ingest transaction with a period close. Then replay the input in different orders, including duplicate IDs, a conflicting duplicate payload, and a reversal.

PASS CONDITION
Each accepted event belongs to the recorded close cutoff or to a visible later adjustment. Identical retries add nothing, conflicting IDs are rejected, and rebuilding the same close version reproduces its exact totals.

EVIDENCE TO RETAIN
A deterministic race test, an independent aggregation query, property tests over reordered fixtures, and a trace from each export row back to its inputs.

MEASUREMENT AND LIMITS
Compare incremental totals with a full rebuild over the same accepted event set. State the time zone, units, decimal precision, and rule version in each export. This service measures usage; it does not calculate prices or collect payments.

COMPLETION CRITERIA (PLANNED)
- Ingestion, adjustment review, close, and export work against the seeded accounts.
- Replay, close-race, unit-validation, and cross-account access tests pass.
- A reviewer can rebuild one closed export without trusting a cached total.

VERIFICATION PLAN
Duplicate events
Replay a batch in different orders; the total remains unchanged.

Corrections
Trace a reversal and replacement to the original event.

Closed period
A late event creates a visible pending adjustment, not a silent rewrite.

PLANNED DELIVERABLES
- Ingestion API, reconciliation UI, and immutable event model
- Replay, period-boundary, and account-isolation tests
- Sample event generator, exports, and an operator runbook

SCOPE NOTE
The service exports usage quantities. Pricing, taxes, invoices, and payment collection belong to downstream systems.

NEXT STEP
Define the usage units, period boundary, and late-event adjustment policy.
