jwp-receipts: typed claims, key discovery, and a second binding class #84
Merged
dcharlot
merged 1 commit from 2026-09-10 12:21:02 -04:00
wai/receipt-classes-and-key-discovery into main 2026-09-10
jwp-receipts: typed claims, key discovery, and a second binding class
Some checks failed
standards workspaces build + test / aac-rs (pull_request) Successful in 32s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 36s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 2m13s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 35s
standards workspaces build + test / map-rs (pull_request) Successful in 30s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m47s
standards workspaces build + test / mesh-rs (pull_request) Successful in 26s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m13s
standards workspaces build + test / openpay (pull_request) Successful in 1m16s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 37s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 16s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m15s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m0s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m32s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 31s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 14s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 41s
standards workspaces build + test / arl-rs (pull_request) Successful in 9m6s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 9m56s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 10m28s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 9m47s
standards workspaces build + test / sense-rs (pull_request) Successful in 10m9s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 2m56s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 34s
WAI conformance / cargo-class corpora · windows (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · windows (pull_request) Has been cancelled
Three holes, all in the receipt layer, all found by the landscape survey and verified against this file. 1. THE RECEIPT ANSWERS ONE QUESTION (§2.4.3). `group` and `object` say what was delivered, by whom, at what energy cost. Three other bodies now issue per-object signed artifacts answering different questions over the same objects: a lawful-basis declaration bound to a media service (ABNT NBR 25608 §8.8), a transparency-log inclusion proof (RFC 9942 COSE Receipts), and a recovered-binding assertion (C2PA soft binding). Rather than grow a field set per question, `kind: "claim"` carries a class discriminator and a class-scoped body on the same chain. The rules are about refusal, not carriage: a verifier MUST reject a class it does not know rather than ignore it; the class MUST NOT be inferred from the body's shape; where a claim and a delivery receipt disagree the verifier MUST reject rather than choose; and a claim carries the authority of its signer and no more — `class` says what is asserted, never that it is true. 2. EVERY SIGNATURE PRESUMED THE VERIFIER ALREADY HELD THE KEY (§7). `signer_pubkey` rides in the receipt, which makes the signature checkable but not trustworthy — a forger supplies a key as easily as a signature. For a party who was never on the delivery path that presumption fails, and every guarantee in §6 fails with it. Adds a REQUIRED `signer_locator` (cert-uri / trust-record / did), borrowing the design H.274's `dsci` SEI already uses rather than inventing a third shape. A verifier that cannot resolve it MUST report "signature-valid, identity-unconfirmed" — a materially weaker statement that MUST NOT be reported as verification. The locator MUST be inside the signed payload: one a relay can rewrite is one an attacker can rewrite. 3. A RECEIPT DID NOT SURVIVE NORMAL DISTRIBUTION (§8). The hard binding is BLAKE3 over envelope bytes, destroyed by any transcode, remux or platform re-encode. Those are not attacks; they are what distribution does. With one binding class a re-encode left no recovery path: receipt intact, object no longer matching, nothing connecting them. Adds an explicitly weaker second class — a soft binding computed from the samples plus a resolution endpoint — with the ancestor rule as its centre: a recovered receipt attests THE ANCESTOR the object was derived from, not the object in hand, and an implementation that cannot express that distinction MUST NOT implement soft binding at all. A recovery presented as a hard binding is worse than no recovery, because it launders a transformation nobody attested. No new cryptography and no new transport. §1 already anticipated a MoQT object header as a carrier, which is the slot #80 §4.4 identifies. Co-Authored-By: Claude Opus 5 <[email protected]>