A jcp/1 receipt proved that a decision happened over a grant for an action at a
cost — but NOT what it was over. Two decisions differing only in payload sealed
to identical bytes, so a tool-call receipt did not commit its arguments and a
payload substitution was undetectable in the audit. This adds `payload_hash` to
the signed core and bumps the profile to `jcp/2`.
The bump is honest rather than silent. Until now the `jcp_receipt` tag was
WRITTEN BUT NEVER READ — decorative. It is now load-bearing: `verify` and
`verify_chained` read the profile out of the signed core and recompute the
preimage under THAT profile, so receipts sealed as `jcp/1` keep verifying, and an
unrecognised tag is refused rather than assumed. `jcp/1` is no longer minted.
Scope, verified rather than assumed. JCR-1 is a FAMILY OF SIBLING PROFILES that
share the envelope (canonical det-CBOR + COSE_Sign1/EdDSA) and vocabulary, each
signing its own core. jouleclaw-jcr1 is an independent implementation but signs
its own receipt kinds (coding/stream windows, ui output) — zero grant_id/verdict
— and sense/map/sandbox vectors carry their own cores (map tags its own "map/1").
So this changes ONE profile among siblings and does not touch theirs. SPEC §8 now
says exactly that, instead of implying a single family-wide core.
- to_jcr1_wire gains `payload_hash`; `_chained` and `_logged` inherit it (both
already funnel through it — one insertion point, not three).
- to_jcr1_wire_v1 retains the byte-exact legacy projection, for verification only.
- ReceiptCore exposes `payload_hash: Option<String>` — Some on jcp/2, None on a
legacy receipt, so callers can tell a payload-bound receipt from one that isn't.
- New ReceiptError::UnknownProfile.
Migration proven with REAL bytes, not a reconstruction: the allow receipt
published in conformance/v1/vectors.json before this change is embedded in a test
and MUST still verify. The v1 receipts are also preserved as
conformance/v1/legacy_jcp1.json so cross-language verifiers can prove they honour
the dispatch. Vectors regenerated to jcp/2 (both duplicate paths kept in sync).
SPEC §8 rewritten (field list, the REQUIRED version-dispatch rule, the
sibling-profile clarification) + conformance class C23, executable in the harness:
payload committed, payload-swap forgery caught, jcp/1 still verifies.
40 workspace suites green, clippy clean, all conformance checks pass.
Co-Authored-By: Claude Opus 4.8 <[email protected]>