open-standards/jcp/README.md
Transaction Science 158807c3ae jcp: the energy-native MCP gateway — metered, sealed, tamper-evident
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]>
2026-06-11 05:34:35 -04:00

90 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# JCP — The Joule Context Protocol
A unified, energy-native, capability-secured protocol for agentic systems. Where
today's stack splits across MCP (tools), A2A/ACP (agent-to-agent), an identity
layer, and an authorization layer — and standardizes energy nowhere — JCP is one
spec, built on one idea:
> **A capability and an energy budget are the same object: a signed, bounded,
> debited grant. A capability you can't pay for is denied; an expenditure you're
> not capable of is denied. One check, made outside the model, sealed in a
> receipt.**
The design answers the documented failure modes of the current agentic
ecosystem, not hypotheticals. Tool descriptions are untrusted input → JCP refuses
to take control from a tool's *output*. Prompts can't enforce access control (and
a more capable model only follows injected instructions *better*) → JCP decides
every action in the runtime, never in the LLM. Agent loops have no cost ceiling →
every grant carries a joule budget that's debited and enforced before the side
effect. Audit is a mutable telemetry span → JCP seals every decision, allow and
deny, as a non-repudiable signed receipt.
- **Licence:** Apache-2.0 for reference code (see [`LICENSE`](LICENSE)); CC-BY-4.0 for specification text (see [`LICENSE-SPEC`](LICENSE-SPEC)).
- **Status:** v0.3.0 draft. Specification core published ([`SPEC.md`](SPEC.md) + [`conformance/v1/`](conformance/v1/)); reference workspace `jcp-rs/`.
## What's here
```
jcp/
├── SPEC.md — the normative standard (§1–§12)
├── conformance/v1/ — published vectors (a signed grant + allow/deny receipts)
└── jcp-rs/ — the Apache-2.0 reference implementation
```
### The reference implementation (`jcp-rs/`)
- **`jcp-schema`** — the wire objects: the `did:key` actor, the **Grant** (the metered capability — capability ⊗ joule budget, content-addressed and signed), the **Frame** (every message, with its `control`/`data` trust tag), the family `Energy`/`Provenance` model, canonical det-CBOR content addressing.
- **`jcp-grant`** — issuance, signature verification, **attenuation** (object-capability delegation where a child grant can only narrow — capability ⊆, budget ≤, expiry no later, delegation depth − 1), **chain verification** (root-first, hop-by-hop: parent links, holder-issued hops, narrowing, signatures, depth bounds), **revocation** (issuer-only, signed, admitted into a `RevocationSet` only after authority checks), **sharding** (`shard()` splits a grant into siblings whose budgets must sum within the parent — distributed enforcement with no consensus, SPEC §4.5), and **identity continuity** (`KeyLog`: KERI-style pre-committed rotation, SPEC §2.1 — a thief with the current key can't rotate, an owner who lost it still can).
- **`jcp-runtime`** — the deterministic enforcer. One ordered check fuses authorization and energy, decided **outside any model**: untrusted-control, revocation, **configured trust roots** (an enforcement point honors only the root-issuer keys it was configured with — `authorized_keys` shape, no CA), audience binding, signature, expiry, capability, and budget — then debit. The first failure names the reason. `decide_chained` enforces full delegation chains: a revoked ancestor kills the subtree, and the cost must fit — and is debited from — **every** link, so sibling delegations share their root's budget and delegation can never mint joules.
- **`jcp-receipt`** — the `jcp/1` JCR-1 receipt: canonical det-CBOR + COSE_Sign1/EdDSA, byte-compatible with the family verifiers. Allow and deny both seal. The receipt stream is the write-ahead log (SPEC §8.1): a chained receipt records `chain_ids` — every link the decision debited — so `replay_spend` rebuilds an enforcement point's budget state, **ancestors included**, from its own verified output with no external index; `aggregate` keys a team's receipts by `(grant, subject)` for per-worker cost attribution computed from evidence (SPEC §8.2).
- **`jcp-bridge`** — a reference gateway that wraps **existing MCP tool calls and A2A tasks** in Grants and Frames without rewriting the endpoint. It maps each outbound call to a Frame (the tool/method is the action; the `(server, tool)` identity is the content-addressed resource), decides it against the caller's grant *before* the call reaches the endpoint, and seals a receipt — so an existing server keeps its transport while every call becomes capability-scoped, joule-budgeted, decided outside the model, and sealed. Inbound results are framed as untrusted `data`.
- **`jcp-energy`** — the metering ladder (SPEC §5.1): RAPL package counters (Linux powercap, wraparound-corrected, `HwShunt`), NVML GPU energy behind the `nvml` feature (`HwShunt`), a time×calibrated-power model (`ModelBased`, always available), and a constant per-op estimator (`Estimator`). Measured when the platform exposes it, estimated when it doesn't — and the provenance always says which; a hardware backend that fails mid-reading degrades honestly to the model.
- **`jcp-gateway`** — the **energy-native MCP gateway**: a JCP enforcement point that sits in front of an MCP server so an existing client/server pair keeps its transport while every `tools/call` becomes capability-scoped, joule-budgeted, and sealed. The novel mechanic is two-phase metered enforcement: the call is *authorized* before it runs (no debit, because the cost isn't yet known), the upstream call is **metered on real hardware** (the sibling Sandbox standard's energy probe — Apple Silicon IOReport, RAPL, NVML), and the **measured** joules are debited from the grant — so the budget that stops a runaway agent is denominated in energy actually spent, not a token estimate. Every decision, allow and deny, seals into a **hash-chained receipt log**: excise, reorder, or splice a receipt and the chain breaks at that point. A denied call never reaches the server (the live 2025–26 MCP exploits land on tool *output*, which the gateway frames as untrusted `data` that can never exercise a capability), and the `jcp-gateway` binary runs it over stdio in front of any MCP-server subprocess. This is the chokepoint the AI-gateway field occupies, on the two axes nobody there holds: the unit of account is the joule, and the audit is cryptographic and tamper-evident rather than a dollar figure and a span.
- **`jcp-wire`** — the `jcp/1` wire binding (SPEC §11): 4-byte length prefix + canonical det-CBOR over any byte stream, with TCP and Unix-socket endpoints and a client. The decoder rejects non-canonical bodies, so a message has exactly one wire form. Requests carry the full delegation chain and are **caller-signed** — the endpoint authenticates from the request itself and denies an impersonation `bad-signature`, sealed like any other decision. Responses carry the deterministic decision and the sealed receipt.
- **`jcp-threshold`** — threshold actors (SPEC §2.2): a `did:key` whose private key is split k-of-n with FROST (RFC 9591); the group key is an ordinary Ed25519 key, so a 2-of-3 team issues, holds, and signs wire requests with nothing else in JCP changing. Shares come from a trusted dealer or **distributed key generation** — with DKG the group's private key never exists anywhere, not even momentarily. The two-agent rule for irreversible actions, refused by arithmetic rather than policy.
- **`jcp-channel`** — receipt-settled budget channels (SPEC §4.5, the OPTIONAL profile): N enforcement points spend optimistically against one grant and settle by exchanging signed statements of cumulative spend — forged, stale, and regressing statements refused; between settlements the exposure is bounded by the window, and after settlement any overdraft is provable from the signed statements. Where bounded overdraft is unacceptable, `shard()` remains the baseline.
- **`jcp-conformance`** — C1–C18 + a negative pack, all checks real (C8 decides over a live socket; C13 drives a FROST 2-of-3 caller; C16 replays ancestor debits from a chained receipt; C17 settles a budget channel by signed statement; C18 mints a dealer-free group via DKG), published vectors in `conformance/v1/`.
- **`jcp-cli`** — the `jcp` demo: one metered grant driven through an agent loop — legitimate calls allowed and debited, a poisoned tool-result refused structurally, out-of-scope actions and resources denied, the budget stopping a runaway loop, a sub-agent getting a strictly-weaker delegated grant, a signed receipt verified, the detected energy meter reporting its honest provenance, and the issuer revoking the grant — after which the runtime goes dark.
`cargo test --workspace` green; `cargo clippy --workspace --all-targets`
warning-free.
## The demo, abbreviated
```
frame verdict reason rem µJ
read the db (legit) allow −20000 µJ 80000
tool-result says 'delete db' (poison) DENY untrusted-control 80000
try to delete (not granted) DENY action-not-granted 80000
read prod-secrets (wrong audience) DENY wrong-resource 80000
read again — budget runs out DENY budget-exceeded 30000
amplification refused: capability exceeds parent
receipt allow · 50000 µJ · verified true
```
The model never gates itself; the runtime does, and the receipt proves it.
## Consumers in this repository
JCP is not only specified — it is consumed. Three sibling standards gate their
real dispatch through it, each with its own adapter crate and tests:
- **JouleClaw** (`jouleclaw-rs/crates/jouleclaw-jcp`) — every MCP tool dispatch
is decided against a Grant before a byte reaches the tool; an ungranted tool
named by an injected instruction is refused and the refusal sealed.
- **Sandbox** (`sandbox-rs/crates/sandbox-jcp`) — a unit's execution is
authorized against a Grant bound to its image **by content address**; one
flipped image byte is a different audience and is denied before the executor
is ever invoked. Two receipts per run: the JCP authorization and the
sandbox's metered, attested execution.
- **Joule Code** (`joule-code-rs/crates/joule-code-jcp`) — every cascade-stage
consultation is decided pre-dispatch; the L4 escape hatch to a remote
frontier agent exists only when a signed grant names it and can pay for it.
## Relationship to the family
JCP composes the primitives the Transaction Science family already proved:
`did:key`/Ed25519 identity, capability-gated execution (`sandbox`), the honest
`Energy`/`Provenance` model (`proof`), and JCR-1 signed receipts (family-wide).
It is where they stop being per-tool adapters and become the protocol.