You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Phase D operability: explain_total + verify_period HTTP endpoints
Two new operator-facing endpoints answer the questions billing
operators actually need:
GET /v1/accounts/{account_id}/explain?from&to
Returns the breakdown that contributed to an account's total over a
period, plus segment provenance and the corrections that affected
the total. Specifically:
- `lines` — breakdown by (product, meter, model, source, unit)
via the rollup-with-raw-tail path; same SUM/COUNT the regular
/usage endpoint returns but grouped by every billing dimension
- `rollup_segments` / `raw_segments` — segment IDs that overlap
the range for this account's bucket (so an operator can drill
into them later via inspect-segment)
- `corrections` — raw Correction/Retraction events in the range,
returned individually rather than netted
- `watermark_ms` — current rollup watermark so the caller knows
which part of the range is sealed
GET /v1/accounts/{account_id}/verify?from&to
Computes SUM(quantity) two ways (raw scan and rollup) and reports
both totals plus drift = raw - rollup. Drift of zero on a sealed
period (`to <= watermark_ms`, indicated by `period_sealed: true` in
the response) is the invariant. Non-zero drift indicates a rollup
bug, a late event that landed below the watermark, or a missing
rollup segment that operator-driven rebuild_rollups should fix.
These are the building blocks for the spec §10/§19 "explainable
totals" + "reconcilable raw vs rollup" guarantees the external
review called out as essential for a billing-grade store.
Refactored start_server to expose `build_router(state) -> Router` so
the HTTP layer can be tested via `tower::oneshot` (used by the new
tests) without binding a port.
Tests (tests/explain_verify.rs, 6 tests):
- explain_breaks_down_by_billing_dimensions
- explain_surfaces_corrections_separately (Correction event listed
individually + net total = 100 - 40 = 60)
- explain_rejects_invalid_dates
- verify_reports_zero_drift_when_rollup_matches_raw
- verify_detects_drift_when_rollup_misses_late_event (late event
after watermark advance ⇒ drift = 50)
- verify_reports_period_sealed_status
Adds http-body-util as a dev-dependency for axum response body
parsing in tests.
Total tests: 88 (was 82; +6). Clean under RUSTFLAGS=-D warnings.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments