open-standards/joule-code/spec/receipt.md
David Charlot 8f5e6f80e6 joule-code: v0.2 — receipts seal as JCR-1 (family wire format)
Reconciles the Joule Code receipt with JCR-1, the signed-receipt format shared
across the Transaction Science family, so a Joule Code receipt verifies under the
family's existing JCR-1 tooling (and its cross-language Python/Go verifiers)
instead of a bespoke preimage. v0.1 -> v0.2 wire change.

- SPEC 6.1: the receipt's signed form is now a JCR-1 envelope — canonical
  det-CBOR (RFC 8949 4.2.1, length-first key order) of the "joule-code/1"
  profile, inside a COSE_Sign1 envelope (RFC 9052, EdDSA alg -8); steward in kid.
- joule-code-receipt: new jcr1 module (canonical CBOR + COSE_Sign1, vendored
  from the JCR-1 reference algorithm — no JouleClaw dependency, keeping the lean
  lib self-contained) + Receipt::to_jcr1_wire / seal / verify_envelope. Removed
  the bespoke sign/verify. A test pins the canonical encoder byte-for-byte
  against a published JCR-1 conformance vector.
- Conformance C3 vectors regenerated as JCR-1 COSE_Sign1 envelopes; the harness
  verifies the envelope and that its payload is the receipt's canonical core.
- spec/receipt.md, CHANGELOG (0.2.0), READMEs, workspace version -> 0.2.0.

Verified: the conformance harness passes the whole pack with no skips;
cargo test --workspace green; vanity scanner clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-03 05:53:24 -04:00

69 lines
4.1 KiB
Markdown

# Joule Code — The Receipt
Normative sub-specification of [`../SPEC.md`](../SPEC.md) §6. CC-BY-4.0.
Every coding operation carries a **receipt**: a signed, two-part energy record carried in a Joule Wire Protocol (JWP) frame. The receipt is the falsifiable cost basis of the operation — not its market price, but its honest energy cost.
## 1. Structure
```
Receipt {
op_id: ContentId,
tier: Tier,
energy: Energy,
sequence: u64,
nonce: [u8; 8],
sig: [u8; 64], // Ed25519 over the energy preimage (§3)
}
Energy {
measured_uj: Option<u64>, // present ONLY when from a hardware interface
estimated_uj: u64, // always present
provenance: Provenance,
}
Provenance = HwShunt | ModelBased | Estimator
```
## 2. The provenance contract (REQUIRED)
The `Provenance` tag states how honest the figure is, and the spec never claims more than the platform delivers:
- `HwShunt` — read from a hardware energy interface (RAPL, Apple SMC/IOReport, an external shunt). A reading tagged `HwShunt` **MUST** have `measured_uj = Some`.
- `ModelBased` — computed from a calibrated per-operation energy model. `measured_uj` **MAY** be absent.
- `Estimator` — a coarse constant estimator (e.g. per-token coefficients applied to L4 token counts). `measured_uj` **MUST** be absent.
A runtime **MUST NOT** populate `measured_uj` from anything but a hardware interface, and **MUST NOT** tag a reading `HwShunt` without a present `measured_uj`. Absence is the honest answer when the platform cannot measure.
## 3. Signed form — JCR-1 (v0.2)
As of v0.2 the receipt's signed form is a **JCR-1 envelope** (SPEC §6.1), the signed-receipt format shared across the Transaction Science family — not a bespoke preimage. A Joule Code receipt therefore verifies under the family's existing JCR-1 tooling and its cross-language (Python/Go) reference verifiers.
```
core = canonical-det-CBOR( # RFC 8949 §4.2.1, length-first keys
{ jc_receipt: "joule-code/1", op_id, tier, estimated_uj,
measured_uj?, energy_provenance, sequence, nonce, steward } )
envelope = COSE_Sign1( # RFC 9052, EdDSA -8
protected = { 1: -8, 4: bstr(steward) },
payload = core,
signature = Ed25519_sign(endpoint_secret, Sig_structure) )
```
`Sig_structure` is `["Signature1", protected, external_aad(empty), core]` (RFC 9052 §4.4). Verification parses the tagged COSE_Sign1 (CBOR tag 18), rejects any `alg` but `-8`, rejects a `kid` other than the expected steward, checks the Ed25519 signature, and confirms the payload equals the receipt's canonical core. Sealing the receipt this way makes the cost basis non-repudiable by the endpoint that produced it and interoperable with every other family pillar.
> v0.1 used a bespoke `estimated_uj ‖ sequence ‖ nonce [‖ measured_uj]` preimage; v0.2 replaces it with JCR-1. This is the v0.1→v0.2 wire change.
## 4. The estimator of last resort (non-normative coefficients)
When only token counts are available — the common L4 case, where a remote ACP agent reports `input_tokens` / `output_tokens` but no energy — the estimator computes:
```
estimated_uj = input_tokens * J_IN_uj
+ output_tokens * J_OUT_uj
```
and tags the reading `Estimator`. The coefficients are **non-normative** and tunable; the reference consumer ships datacenter-scale defaults where output dominates prefill. Reference values (illustrative, not part of conformance): `J_IN_uj = 200_000`, `J_OUT_uj = 2_000_000` (i.e. 0.2 J / 2.0 J per token). The point of the standard is not the constant — it is that the figure is reported, signed, and honestly tagged as an estimate.
## 5. From estimated to measured
Promoting a tier's receipts from `Estimator` to `HwShunt`/`ModelBased` is the work item that turns the meter "real" (ROADMAP v0.2). The receipt schema does not change; only the `provenance` tag and the presence of `measured_uj` improve as the platform gains a hardware interface. A consumer's UI **SHOULD** surface the provenance so a reader can tell a measured joule from an estimated one.