# JouleClaw Receipt Specification (JCR-1) — Draft **Status:** Draft · **Version:** 1 (`jc_receipt: "1"`) · **License:** CC-BY-4.0 (text), Apache-2.0 (vectors) An open, implementation-independent format for a **signed, per-resolution thermodynamic receipt**: proof that a given output cost a given number of joules, on hardware of a stated measurement honesty, verifiable by a third party who never ran the cascade. This document formalizes the `jouleclaw-prov` receipt shape and **closes the gap the reference crate leaves open**: it defines (a) a canonical serialization, (b) a dependency-free signed envelope, and (c) a verification flow — so conformance does not depend on any JouleClaw code. Key words MUST / SHOULD / MAY per RFC 2119. --- ## 1. Design invariants 1. **Honesty over precision.** A receipt MUST NOT claim accuracy finer than the worst energy counter in its span can deliver. 2. **Determinism.** The signed bytes MUST be reproducible bit-for-bit from the receipt fields. No field that cannot be canonically encoded may enter the signed core. 3. **Producer/verifier separation.** A producer mints and signs; a verifier needs only this spec, the public key, and (for joule re-validation) the conformance vectors. Verification MUST NOT require re-running proprietary code. 4. **Additive evolution.** Unknown fields MUST be ignored, never rejected. v1 only adds optional fields. --- ## 2. The Receipt object Units are fixed: **energy is microjoules as an unsigned 64-bit integer (`joules_uj`)**; floating point is forbidden in the signed core. Timestamps are RFC 3339 UTC. Hashes are lowercase hex BLAKE3-256. Tier tags are `L0`–`L4`. ### 2.1 Top-level fields | Field | Type | Req | Meaning | |---|---|---|---| | `jc_receipt` | string | MUST | Schema version. `"1"` for this spec. | | `id` | string | MUST | Stable receipt id, monotonic per steward. | | `closed_at` | string (RFC3339) | MUST | When the cascade walk closed. | | `input_hash` | string (blake3-hex) | MUST | BLAKE3 of the normalized input that started the walk. | | `tier` | enum `L0..L4` | MUST | Tier that **closed** the query. | | `joules_uj` | u64 | MUST | Total microjoules across all tiers walked. | | `energy_provenance` | enum | MUST | Honesty tier of the **worst** counter in the span (§2.3). | | `steward` | string | MUST¹ | Signing identity (KERI AID or `did:key`). Binds receipt to issuer. | | `tools_touched` | array⟨ToolTouch⟩ | MAY | Per-tool energy, in call order. | | `claims` | array⟨ClaimProvenance⟩ | MAY | Sources that grounded the resolution. Empty for L0/L1. | | `tool_receipts` | array⟨ToolReceipt⟩ | MAY | Gateway-HMAC'd attestations (§2.6). | | `eoc_stage` | string | MAY | EOC cascade stage label, if driven by one. | | `citations` | array⟨Citation⟩ | MAY | Span→source grounding (advisory). | | `token_attributions` | array⟨TokenAttribution⟩ | MAY | Per-token saliency (advisory, **not in signed core** — §3.3). | ¹ `steward` is added by this spec; the reference crate carried the issuer in the outer Smart Byte envelope. Carrying it inline makes the receipt self-describing. ### 2.2 CascadeTier `L0` Cache (picojoules) · `L1` Lawful/deterministic (nanojoules) · `L2` Embed (sub-mJ) · `L3` Model (joules) · `L4` Wire/remote frontier (tens of J+). Wire tags `L0`–`L4` are stable across versions. ### 2.3 Provenance (the honesty tag) — normative Every energy reading carries one of: - `HwShunt` — hardware reading: a shunt (Jetson INA3221), or a vendor energy counter (x86 RAPL MSR, NVIDIA cumulative-energy counter, Apple IOReport) while it is live for the domain it claims (below). Honest to the counter's resolution. - `ModelBased` — vendor model estimate from freq/voltage/utilization (NVML `power.draw`, ROCm SMI). Millijoule-quantized at best. - `Estimator` — JouleClaw static cost model. Wide tolerance by construction. A vendor energy counter's reading is a real reading; the trust gap is provenance (which counter, which domain, whether it was live), not accuracy. Hence a live vendor counter is `HwShunt`, under this condition: **Liveness (MUST):** A reading from a vendor energy counter (RAPL, NVML, Apple IOReport, …) MAY be graded as a hardware reading only while the counter is demonstrably live for the domain the figure claims: the implementation MUST have observed the counter covering that domain advance under load (for Apple IOReport: the CPU energy rail itself advancing in at least 5 sample intervals, in at least 4 of every 5, over at least 300 ms while the probing thread burns CPU; an interval runs from when one sample is in hand to when the next is, and only one no longer than three of the probe's ticks, 75 ms at its 25 ms tick, counts: a longer one counts as nothing, neither among the intervals, nor as an advance, nor towards the 300 ms, which is the summed length of the intervals that count). A counter that is present but not live — frozen, or republished in lumps — MUST NOT produce a hardware-graded figure; the implementation falls back to its estimator or reports the work unmetered, and SHOULD record why. A figure MUST NOT claim coverage of a domain its counter does not read; where the format has a coverage field, such a figure is Partial. (JCR-1 v1 has no coverage field: a figure for a domain its counter does not read is not a `HwShunt` figure for that work at all.) Apple IOReport's GPU rail is machine-wide (display compositing moves it with nothing of the metered work running), so it is not a partial reading of CPU work: where only the GPU rail is live, the reference implementation declines the counter and the CPU work is graded `Estimator`. **Worst-counter rule (MUST):** `Receipt.energy_provenance` = the least-honest provenance among all readings contributing to `joules_uj`, ordered `HwShunt > ModelBased > Estimator`. A receipt whose span mixed a HwShunt GPU read and an Estimator NPU read MUST report `Estimator`. **Resolution floor (MUST):** `joules_uj` MUST NOT be reported at finer resolution than the worst counter's `resolution_uj`. For `ModelBased`/`Estimator` the realistic floor is ~1000 µJ (1 mJ); values SHOULD be rounded to that quantum and the receipt MUST NOT imply sub-mJ precision it cannot support. ### 2.4 ClaimProvenance `source` (string: URL/DOI/did) · `content_hash` (blake3-hex of claim bytes at fetch) · `fetched_at` (RFC3339) · `trust_tier` (u8, higher = more trusted). PROV-O mapping: each claim is a `prov:Entity`; `source` is the IRI, `content_hash` the `wasGeneratedBy` fingerprint. ### 2.5 ToolTouch `tool_id` (string, e.g. `mcp:filesystem/read`, `iac:fs.read`, `model:gemma4-9b-q5_k_m`) · `joules_uj` (u64) · `energy_provenance` (enum). ### 2.6 ToolReceipt (gateway-attested) Proves a tool was invoked **through the gateway**, not asserted by the model. `tool_id` · `joules_uj` · `energy_provenance` · `minted_at` (RFC3339) · `gateway_id` (string) · `hmac_sha256_hex` (64 hex chars). The HMAC (§5) is keyed by a gateway secret the model never holds. ### 2.7 Citation / TokenAttribution `Citation`: `text_span {start:u32, end:u32}` (half-open byte range over the output the consumer holds) · `source_chunk_id` · `exact_quote` (verbatim, findable in the chunk). `TokenAttribution`: `token_idx:u32` · `chunk_scores: map` (provider-defined, **ordinal not absolute**) · optional `method`. Advisory only. --- ## 3. Canonicalization (the signed core) ### 3.1 Signed core vs advisory The **signed core** is every MUST/MAY field in §2.1 **except** `token_attributions` (provider-defined floats, ordinal, not reproducible across methods). `citations` are in the core (strings/ints, deterministic, and grounding-relevant). `token_attributions` are carried alongside, outside the signature. ### 3.2 Canonical encoding The signed core MUST be encoded as **deterministic CBOR** per RFC 8949 §4.2: - Map keys are the field names as text strings, sorted by byte-wise lexicographic order of the UTF-8 key. - Integers use the shortest form; `joules_uj`, `start`, `end`, `token_idx`, `trust_tier` are unsigned. - Absent optional fields are **omitted**, not encoded as null. - Arrays preserve producer order (`tools_touched`, `claims`, `tool_receipts`, `citations` are order-significant). - No floats appear in the signed core (see §3.1). A JSON projection (RFC 8785 JCS) MAY accompany the CBOR for debugging, but the signature is ALWAYS over the deterministic CBOR bytes. ### 3.3 The bytes to sign `CORE = det_cbor(signed_core_fields)`. The envelope signature (§4) is computed over `CORE`. Recomputing `CORE` from the parsed fields MUST yield identical bytes; a verifier that cannot reproduce `CORE` MUST treat the receipt as invalid. --- ## 4. The signed envelope Receipts are sealed in a **COSE_Sign1** structure (RFC 9052) so they interoperate with the RATS/CoRIM attestation tooling JouleClaw already uses. ``` COSE_Sign1 = [ protected: bstr .cbor { 1: alg, 4: kid }, ; alg = -8 (EdDSA) or -7 (ES256) unprotected: { }, payload: bstr, ; = CORE (det-CBOR signed core) signature: bstr ; over Sig_structure per RFC 9052 ] ``` - **alg (MUST):** EdDSA/Ed25519 (`-8`) is the default; ES256 (`-7`) permitted. - **kid (MUST):** the `steward` identity — a KERI AID (recommended; supports key rotation/witnessing) or a `did:key`. The verifier resolves `kid` → public key out of band. - **payload:** the deterministic-CBOR signed core (§3.3). Key management is explicitly out of scope. KERI AID rotation is the RECOMMENDED substrate; any resolvable `kid → public key` mapping conforms. --- ## 5. Tool-receipt HMAC (sub-signatures) Each `ToolReceipt.hmac_sha256_hex` is `HMAC-SHA-256(gateway_key, payload)`, lowercase hex, where `payload` is the NUL-delimited canonical byte string: ``` tool_id ‖ 0x00 ‖ ascii(joules_uj) ‖ 0x00 ‖ prov_tag ‖ 0x00 ‖ minted_at ‖ 0x00 ‖ gateway_id ``` `prov_tag` ∈ {`HwShunt`,`ModelBased`,`Estimator`}; `joules_uj` as decimal ASCII. Verifiers look up the gateway key by `gateway_id` and recompute. Comparison MUST be constant-time. This sub-signature is independent of the envelope: it survives replay into a different context, attesting the gateway — not the model — observed the cost. --- ## 6. Verification flow A verifier processes a received envelope in this order; failure at any step makes the receipt **invalid** (steps 1–4) or **unverified-but-structurally-valid** (step 5, when vectors are unavailable): 1. **Structural.** Parse COSE_Sign1; parse payload as det-CBOR; reject unknown `jc_receipt` major versions; ignore unknown fields. 2. **Canonical re-encode.** Recompute `CORE` from parsed fields; it MUST equal the payload bytes byte-for-byte. 3. **Envelope signature.** Resolve `kid → public key`; verify the COSE_Sign1 signature over `CORE`. 4. **Tool receipts.** For each `tool_receipts[i]`, look up `gateway_id`'s key and verify the HMAC (§5). A receipt asserting gateway-metered tools whose HMAC fails is invalid. 5. **Honesty consistency.** Check `energy_provenance` equals the worst provenance across `tools_touched[*].energy_provenance` and `tool_receipts[*]`; check `joules_uj ≥ Σ tools_touched.joules_uj`; check the resolution floor (§2.3). 6. **(Optional) joule re-validation.** If the verifier holds the conformance vector for this `input_hash` class, re-execute the cascade and confirm `joules_uj` falls within the **drift band** for the receipt's provenance tier (§7). Absent vectors, the receipt is signature-valid but joule-unverified. --- ## 7. Conformance ### 7.1 Drift bands (joule re-validation tolerance) Re-execution will not reproduce joules exactly; the permitted band scales with honesty: | Provenance | Drift band on `joules_uj` | |---|---| | `HwShunt` | ±10% | | `ModelBased` | ±35% | | `Estimator` | ±100% (order-of-magnitude only) | (Bands are the v1 defaults and are themselves part of the conformance vector; publish measured bands as data accrues rather than asserting these forever.) ### 7.2 Conformance levels - **Producer-conformant:** emits receipts whose signed core re-encodes identically (§3) and whose `energy_provenance`/resolution obey §2.3. - **Verifier-conformant:** implements steps 1–5 and reproduces published vectors. - **Vector-conformant standard:** an *independent* implementation round-trips all 10 published conformance vectors (verify + re-encode), proving the spec — not the reference code — is the source of truth. ### 7.3 Vector slots (to populate + sign) 1 L0 cache hit · 2 L1 deterministic (no model) · 3 L1 IaC/tool-only · 4 L2 retrieval-grounded · 5 L3 local model · 6 L3 with citations · 7 L4 wire with claims · 8 mixed-span worst-counter (HwShunt+Estimator → Estimator) · 9 gateway tool-receipt HMAC · 10 promoted-skill (L3-derived → L1 cost). *(Reference repo currently ships 3 of 10 — the gating work for "standard" status.)* --- ## 8. Versioning & extensibility `jc_receipt` is the schema major. Within `"1"`, only optional fields are added, guarded so older verifiers ignore them. A breaking change increments to `"2"`; verifiers reject unknown majors at step 1. The `L0`–`L4` tags and field semantics in §2 are frozen for v1. ## 9. Security & honesty considerations - A receipt proves **cost + provenance**, not output correctness. Pair with the calibrated escalation gate so the *answer* is trustworthy, not just the bill. - The signed core deliberately excludes advisory floats; do not infer that `token_attributions` are attested. - The worst-counter rule is the spec's spine: a system that quietly upgrades an `Estimator` span to `HwShunt` to look precise is non-conformant and defeats the entire purpose. Honest meters are the whole product. - HMAC keys are per-gateway secrets; envelope keys are per-steward. Compromise of one does not forge the other. --- ## 10. Worked example (JSON projection; signature over det-CBOR of the core) ```json { "jc_receipt": "1", "id": "rcpt-000128", "closed_at": "2026-05-31T18:04:22Z", "input_hash": "b3:9f2c...e1", "tier": "L1", "joules_uj": 4200, "energy_provenance": "HwShunt", "steward": "did:keri:EJ9...", "tools_touched": [ { "tool_id": "iac:aws.ec2.describe", "joules_uj": 4200, "energy_provenance": "HwShunt" } ], "claims": [], "tool_receipts": [ { "tool_id": "iac:aws.ec2.describe", "joules_uj": 4200, "energy_provenance": "HwShunt", "minted_at": "2026-05-31T18:04:22Z", "gateway_id": "gw-edge-7", "hmac_sha256_hex": "3f1a...c0" } ] } ``` A deterministic motif (an IaC describe call) closed the query at L1 for **4.2 mJ**, HwShunt-honest, with a gateway HMAC proving the gateway — not a model — ran it. No tokens burned; the receipt proves it. ``` ```