Status: Accepted
Date: 2026-08-22
Version: 4.6.0
Custody, pricing, reservations, and budgets existed, but callers still assembled their state machines from shallow helpers. HTTP and Gateway code knew topic/TTL details, Gateway estimated pricing through a pass-through module, Budget cache/rate-limit identities omitted tenant, and Gateway created a hold before separately registering its Reservation. That last ordering left an orphan-hold crash window.
The metering runtime has four explicit deep modules:
TokenEventCustodyowns identity, envelope, Kafka delivery, quarantine, backpressure, and reconciliation behindaccept/accept_many.PricingCatalogowns catalog validation, normalization, exact quotes, tier traversal, and advisory completion estimates.Reservationowns every hold transition. Gatewayopenreserves and registers atomically in one Redis Lua operation; settlement and expiry are idempotent.Budgetowns configuration, top-up, snapshots, authorization, cache fallback, rate limiting, hierarchy caps, and API-key caps. Cache and RPM identity are tenant-scoped.
HTTP routes and Gateway orchestration are adapters. Fakeredis and fake Kafka producers exercise the same interfaces used by production callers. The removed budget_gate, budget_ops, and Gateway pricing-estimate modules must not be recreated as compatibility layers.
- State-machine changes have one locality and one interface-level test surface.
- Same customer/span/session IDs cannot share Budget cache, RPM, or new scope keys across tenants.
- A process crash cannot occur between Gateway hold creation and Reservation registration.
- Pricing validation and runtime quotes cannot drift within the Python runtime.
- Redis Lua remains a single-node implementation constraint; a future distributed adapter must preserve these interfaces and atomic transitions.