docs(adr): ADR-0009 amendment — shared spend accounting (review M5)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012QndwfhjyTiZcUYp87dwW8
Signed-off-by: Aaron D. Lee <himself@adlee.work>
This commit is contained in:
2026-07-04 20:53:30 -04:00
parent 418f29e3c7
commit df1ec3360d
3 changed files with 33 additions and 2 deletions

View File

@@ -53,6 +53,10 @@ Recommending "Redis" undercuts the data-ownership pillar ([ADR-0002](0002-north-
persistence (RDB/AOF) is async-ish — fine for transport / replay / fleeting retention, **wrong**
for "the CDR that proves what we billed." CDR and recordings emit **durably to object storage**
in their own services; the bus only *flows* events into that pipeline and lets services *react*.
3. **Constraint 2 governs the durable CDR, not enforcement counters.** The spend gate's
live accounting state (spend/pacing/rate counters) is ephemeral control state and DOES
belong in Valkey KV at N>1 — see the
[ADR-0009 amendment 2026-07-04](0009-spend-gate-honest-rescope.md#amendment-2026-07-04--enforcement-locality--accounting-locality).
## Consequences

View File

@@ -82,6 +82,32 @@ security-constitutive), but its guarantees are restated precisely:
[market feature scan F5](../reviews/2026-07-03-market-feature-scan.md), since integrator unit
economics run on cost-per-contained-call).
## Amendment 2026-07-04 — enforcement locality ≠ accounting locality
- **Status:** Proposed (pending maintainer ratification)
- **Origin:** [2026-07-04 scalability & infra-fit review](../reviews/2026-07-04-scalability-infra-review.md),
finding M5.
Guarantee 2 above prescribes where the **check** sits — in-process with the tap and the
provider call-control client. It is silent on where the **accounting state** lives, and at
N>1 core instances that silence becomes a correctness trap: per-instance counters make
every spend/pacing cap silently N× the fleet intent, and toll-fraud thresholds never trip
because attempts spread across instances.
Clarification, binding on the step-6 implementation:
1. **Enforcement is in-process** (unchanged — constitutive; guarantee 2 stands).
2. **Accounting is shared.** The gate is built against a ledger trait with atomic
check-and-reserve semantics from day one: an in-memory implementation for single-node,
a Valkey-backed one ([ADR-0005](0005-event-bus.md)) for fleets. The check path never
assumes counter locality.
3. **ADR-0005 constraint 2 is not a counter-argument.** "The bus is not the source of
truth for billing- or call-loss-critical state" governs the *durable CDR*. Live
enforcement counters (spend/pacing/rate state) are ephemeral control state — exactly
what Valkey KV is for. Losing them on a Valkey restart degrades fail-safe (re-count
from zero, provider-side caps as the backstop per this ADR's deployment guidance) —
not to billing corruption.
## References
- [ADR-0002](0002-north-star-and-fused-core.md) — the pillar this amends