The chokepoint position the AI-gateway field occupies (LiteLLM, Bifrost,
Portkey), rebuilt on the two axes nobody there holds: the unit of
account is the joule, and the audit is a hash-chained cryptographic
receipt log rather than a dollar figure and an OpenTelemetry span.
jcp-runtime gains two-phase metered enforcement. A metered gateway
cannot know a call's cost until it runs, so `decide` (check + debit a
known cost) splits: `authorize` runs every validity check and gates on
"any budget remains" without debiting; `charge` debits the MEASURED
cost afterward, saturating at the ceiling so the final call's overrun
is recorded (budget_remaining 0, cost > debited) rather than hidden.
jcp-receipt gains ReceiptLog: an append-only, hash-chained log where
each entry's signed core commits to the prior entry's envelope content
id (genesis links to an all-zero sentinel). verify_log walks the chain
end to end; excising, reordering, or splicing a receipt breaks it at
that index — the integrity layer OTel lacks and the property the EU AI
Act logging obligations and the notarized-agents research both reach
for. Allows and denies are both chained.
jcp-gateway: the gateway crate + stdio binary. relay() classifies each
client message, passes through non-tools/call traffic, and turns every
tools/call into an enforcement point: authorize → meter the upstream
call on real hardware (sandbox-meter: IOReport/RAPL/NVML) → debit
measured joules → seal into the chain. A denied call never reaches the
server. The Upstream trait keeps policy testable without a subprocess.
Live, in front of a subprocess MCP server: read_file calls allowed and
debited (827,000 and 834,825 µJ measured on Apple Silicon), a
shell/`rm -rf /` call DENIED before reaching the server, three sealed
receipts (allow/deny/allow) in a chain that verifies.
69 jcp tests (gateway: allow/deny/budget-exhaustion+chain-verify;
receipt: tamper-evidence via excise+reorder), clippy zero.
Co-Authored-By: Claude Fable 5 <[email protected]>