Epic-2469 Phase 3. The Story exempts a user-facing walkthrough (backend cutover);
this document exists for the pr-closes-check gate and records the two
halves of the change and the proof artifacts.
Every customer-facing brain emits one model.usage receipt per provider
generation (Story-2542), including a flush before run.failed. The broker
(src/clerk_worker/runner.py) now appends ONE
billing.vendor_cost_event row per consumed receipt, at the moment the
event is consumed — not on terminal success — so failed/aborted runs' provider
spend still reaches unit economics.
openrouter:<generation_id>
(fallback openrouter:<run_id>:seq:N when the provider
reported no generation id).cost_source=provider_actual → event_kind='actual',
integer micro-USD end-to-end (sub-cent survives; no float money math).cost_source=unreported → event_kind='estimate' priced
by the conservative-high static table (token_cost_usd), zero-cost
when even tokens are unknown, with served-model metadata for later re-pricing.Proof: tests/integration/test_inference_receipt_reconciliation.py
— consumed receipts == persisted events (count + sum micros), failed-run receipt
included, duplicate generations dedupe; plus
tests/unit/clerk_worker/test_runner_usage_receipts.py.
| Kind | Deleted |
|---|---|
| Routes | POST /app/firm/credits/topup · POST /app/firm/credits/razorpay/order · PATCH /app/firm/seats-and-billing/extra-usage · POST /webhooks/stripe · POST /webhooks/razorpay · POST /admin/firms/{firm_id}/billing/credits/adjustment |
| 410 stubs (final removal with Story-2548) | GET /app/firm/credits · GET /app/firm/credits/chat/{chat_session_id} |
| Tables | billing.credit_ledger · billing.firm_credit_balance (migration 0180, working downgrade) |
| Modules | src/shared/billing/credits.py · src/shared/billing/credit_ledger_writes.py · src/shared/webhooks/stripe.py · src/shared/webhooks/razorpay.py · src/app_api/seats_and_billing/credits.py · src/domains/credit_ledger/ · src/domains/firm_credit_balance/ |
| Broker logic | credit gate (D-13) · per-firm overage cap gate (S4) · per-run credit debit (D-14) · CREDIT_METERING_ENABLED / CREDIT_GATE_ENFORCED env flags |
| Other | starter-credit seeding at firm creation · Stripe/Razorpay settings keys + the admin-api deploy workflow's Razorpay secret step · credit-cap metrics |
src/shared/billing/platform_wallet.py,
ops.platform_wallet, pricing_config.wallet_floor_usd).COST_CAP_USD / MIRA_COMMAND_COST_CAP_USD).perimeter.record_spend) — abuse guard.