wai: key release — the proxy form of wai.video.keys and a signing proxy in front of any licence server #471

Closed
dcharlot wants to merge 0 commits from wai/key-release into main
Owner

What this is

Key release: the proxy form of wai.video.keys, and a signing proxy that sits in front of any licence server.

  • The extension, wai/extensions/key-release.md, adds form 2 of the wai.video.keys receipt. A proxy signs one receipt for every licence request it answers, a release or a refusal. Form 2 signs under its own domain. Form 1 keeps its bytes and its identity, and the two share the key commitment and the identity domain.

    • Schemes (§3.1): ISO/IEC 23001-7 cenc, cbc1, cens, cbcs; the HLS methods AES-128, SAMPLE-AES, AES-256-GCM (draft-pantos-hls-rfc8216bis-22 §4.4.4.4).
    • Key deliveries (§3.2): an HLS key file (identity KEYFORMAT); W3C Clear Key (EME WD 2026-10-13 §9.1); a content protection system named by its DASH-IF system ID. §3.3 says which delivery carries which scheme.
    • CPIX: each receipt carries the SHA-256 of the CPIX document (DASH-IF CPIX 2.3, ETSI TS 103 799) the keys came in.
  • Records:

    • WKL1 commitment list (§4). The key holder derives it from the CPIX key material (§4.4: KID, scheme, key period, commitment). The proxy copies every key_commit from this list, so the proxy holds no key.
    • WKE1 entitlement (§5). The operator's entitlement authority signs it, and it is bound to a key the viewer's device holds. The device signs every request over SHA-256 with Ed25519 (§6.1), which the Web Cryptography API can do.
    • WKT1 release ticket (§9.3). A key delivered in the clear is answered with a 307 and a ticket, and the key holder's key server redeems the ticket once. The proxy never relays a key. A content protection system's licence carries the key encrypted for the client's decryption module, and the proxy forwards it unchanged.
  • The decision (§7.2) is a pure function of signed inputs, the proxy's clock and its earlier receipts. The checks run in this order:

    1. the entitlement holds and its authority is trusted;
    2. the request is fresh (300 s);
    3. the request is not a replay;
    4. the key is known;
    5. the class matches;
    6. the entitlement has started (not before);
    7. the entitlement has not ended (not after);
    8. the key's period meets the entitlement (key rotation);
    9. the entitlement allows offline licences;
    10. a renewal names a released licence;
    11. the renewal count is not exceeded;
    12. the renewal comes before the licence lapses.

    An offline licence never outlives its entitlement (§7.3). §8.4 rule 8 means a refused request is never forwarded, and a key is released only by the licence server's 2xx answer or by a ticket. A verifier recomputes every decision over the proxy's whole log (§10).

  • Reference: the key_release module of wai-rs (feature key_release, no new dependency). It includes its own CPIX reader, which refuses a document type declaration and reads no encrypted key. The module is behind /// cbindgen:ignore, so include/wai.h is unchanged.

  • Corpus: wai/live-conformance/keys/, with 8 accepted logs and 26 negative controls.

    • The accepted logs cover releases over each delivery, every decision of §7.2, an expired entitlement, rotation over three periods, offline licences with their renewals, lapse and clamp, and a licence server that refused or gave no answer.
    • The controls give every reason of §11.
    • The corpus is generated from fixed seeds by wai_key_release_vectors gen and checked byte for byte by tests/key_release.rs.
  • Second implementation: wai/live-conformance/key_release_verify.py. It is written from the text, standard library only, and run as python3 -I. It reads the extension's tables, derives each list from its CPIX document with xml.etree, recomputes every decision, and requires each of 17 mutated copies of the corpus to fail. Rust and Python agree on every vector.

  • Service: wai/wai-key-proxy/, its own crate and lock.

    • The proxy appends each receipt to a durable, single-writer log (File::try_lock, sync_data) before it answers. It reads the log back on restart and cuts a torn last line.
    • A replay that arrives while the first request is still at the licence server waits, and is refused after it, so the log stays in decision order.
    • The key server redeems each ticket once and keeps the redemptions durably.
    • CLI: serve, keyserver, keygen, pubkey, list (CPIX → WKL1), entitle, sign-request, verify.
    • tests/end_to_end.rs runs the proxy, the key server and a fixture licence server on loopback. smoke.sh runs the release binary the way an operator would.
  • Registry: WKL1, WKE1, WKT1, and the WAI-Key-* header fields (proposed). The export is regenerated.

  • Text: the SPEC §5 wai.video.keys row and a §5 paragraph; a CHANGELOG entry; the live-conformance/README.md index.

  • CI:

    • a "key release" step in wai-conformance.yml's independent-verifiers job, with the extension added to its paths;
    • a new wai-key-proxy.yml workflow: tests, clippy -D warnings, the release binary end to end.

This slice needs none of the open PRs (#457, #460, #461, #463, #465), and none of them touches wai_video_keys.rs. They do share the usual append points (registry.rs, lib.rs, Cargo.toml, SPEC, CHANGELOG, wai-conformance.yml), so whichever lands second has a mechanical merge.

Design decisions

  • The entitlement is a signed record bound to a device key, not a field the proxy fills in. Form 1 recomputes its decision from fields its own signer chose, including the expiry. In form 2, every input to the decision except the proxy's clock is signed by someone else: the authority signs the entitlement, the key holder signs the list, the device signs the request. A proxy therefore cannot choose a window or a class.
  • Clear keys go by ticket. For an HLS key file or a Clear Key licence, the response is the key itself. Relaying it would put the key in the proxy, so the proxy signs a release ticket instead and the key holder's key server redeems it. A drm route forwards to any licence server unchanged. A clear route that names an upstream is a configuration error.
  • The log is the decision's input. Replay (check 3) and renewals (checks 10 to 12) are decided against the proxy's own earlier receipts. Verification is therefore over a whole log, not over a lone receipt. A lone receipt still has its own rules (§8.4), which a licensor checks alone.
  • One request names a set of keys and is refused whole. A licence challenge can ask for several keys. The receipt names each requested key, and one failing check refuses all of them.
  • No TLS in the proxy. The upstream is http:// through a local forwarder that originates TLS, and the reverse proxy in front terminates the client's TLS. This keeps the dependency set to the axum/hyper stack the quantum service's lock already pins.
  • Energy: the proxy signs the unmetered marker (0, no class). The corpus carries one receipt with an OnChipCounter figure, to exercise the class encoding and the resolution floor.

Checks (all cargo on the build host via rb)

check command result
module unit tests cargo test --locked --no-default-features --features key_release --lib key_release:: 13 passed
form 1 unit tests (legacy pin unchanged) … --lib wai_video_keys:: 7 passed
corpus test … --test key_release 4 passed (regenerates byte for byte, every outcome, §11 reasons, §3.1/§3.2/§7.2 tables)
other wai.video.* modules cargo test --locked --no-default-features --features video_workflow --lib wai_video 50 passed
registry cargo test --locked --no-default-features --lib codecs::registry; wai registry export --check 14 passed; up to date
default-feature lib build cargo build --locked --lib clean
clippy, wai-rs cargo clippy --locked --no-default-features --features key_release --all-targets zero notes in the touched files
proxy tests cd wai/wai-key-proxy && cargo test --locked 1 + 2 end-to-end passed; end-to-end looped 10× green
proxy clippy cargo clippy --locked --all-targets -- -D warnings clean
proxy release binary bash smoke.sh 8/8 PASS
independent verifier python3 -I wai/live-conformance/key_release_verify.py wai/live-conformance/keys 34 logs PASS, 17 mutated copies fail, exit 0
every other live-conformance verifier each python3 -I <x>_verify.py <dir> all exit 0
lockfiles scripts/check-lockfiles.sh wai/wai-rs wai/wai-key-proxy; cargo metadata --locked --offline current; ok
advisories python3 -I scripts/check-advisories.py 0 gated
repo checks check-tests-in-ci.py, check-workflow-concurrency.sh, check-spec-refs.py, check-wai-section-refs.py, check-no-vanity-metrics.sh, test-public-text-checks.sh, check-comparative-prose.sh, check-orphan-sources.py all exit 0
workflows ruby -ryaml over .github/workflows/*.yml; wfsteps.py HEAD origin/main HEAD parse; 0 problem(s)
public names scripts/check-public-names.sh over every changed file; commit messages and this body against the same patterns clean

Falsifications

All of these were run after a commit, on a snapshot on the build host. Each breaks one rule, and every run exited non-zero:

  • Rust:
    • replay check off
    • period check off
    • licence not clamped to the entitlement
    • §8.4 rule 8 first clause off
    • rule 4 (scheme/delivery) off
    • CPIX commitments not compared
    • the list's copy not checked
    • ticket KIDs not compared
    • freshness bound off by one (caught by the unit test)
    • the CPIX reader accepting a DOCTYPE (caught by the unit test)
    • a scheme code changed in the extension's §3.1 (caught by the table test)
  • Python:
    • replay check off
    • rule 4 off
    • CPIX keys not compared
    • renewal count off
    • rule 8 first clause off
    • Ed25519's small-order checks skipped
    • one byte of a committed receipt
  • Service:
    • no wait for an in-flight replay
    • the log not locked
    • a refusal forwarded
    • a ticket redeemable twice
    • a torn last line not cut

One falsification first came back missed: removing rule 8's first clause alone. The rule's other clauses caught every existing control, but a granted drm receipt with no upstream answer would have passed. I added the control n_granted_not_forwarded, and that falsification is now caught in both implementations.

Not done

  • Encrypted CPIX keys (CPIX §8.1: AES-256-CBC under a document key, RSA-OAEP-wrapped) are refused as cpix_unsupported. Reading them needs AES and RSA in the key holder's tool. Per-key @contentId, key hierarchies (@dependsOnKey) and VOD offset periods are refused the same way.
  • Licence contents are not checked (§13). The receipt binds the SHA-256 of the licence and forwards WAI-Key-Ids and WAI-Key-Licence-Expiry. A licence server that ignores them could put in more keys, or a longer duration, than the receipt states.
  • No player integration. No EME or HLS request hook signs the six fields in a browser yet. sign-request is the reference client.
  • The log grows without bound and is read whole at start, roughly 2 KB per request. Compaction would need a signed checkpoint of the replay window and of open offline chains, and it is not built.
  • No device limit (that is a separate rule), and no rate limiting.
  • The key server's redemptions are an unsigned list. A signed redemption record is not defined.
  • Not deployed. The run and deploy instructions (ports 9710 to 9713, launchd and systemd units, Caddy routes with CORS preflight, health checks) are in the slice's deploy note.

🤖 Generated with Claude Code


Closed: Landed on main through merge train E (#499, merge bf39ec9a); verified by content: this PR's head is in main

## What this is Key release: the proxy form of `wai.video.keys`, and a signing proxy that sits in front of any licence server. - **The extension**, [`wai/extensions/key-release.md`](wai/extensions/key-release.md), adds **form 2** of the `wai.video.keys` receipt. A proxy signs one receipt for every licence request it answers, a release or a refusal. Form 2 signs under its own domain. Form 1 keeps its bytes and its identity, and the two share the key commitment and the identity domain. - **Schemes (§3.1):** ISO/IEC 23001-7 `cenc`, `cbc1`, `cens`, `cbcs`; the HLS methods `AES-128`, `SAMPLE-AES`, `AES-256-GCM` (`draft-pantos-hls-rfc8216bis-22` §4.4.4.4). - **Key deliveries (§3.2):** an HLS key file (identity `KEYFORMAT`); W3C Clear Key (EME WD 2026-10-13 §9.1); a content protection system named by its DASH-IF system ID. §3.3 says which delivery carries which scheme. - **CPIX:** each receipt carries the SHA-256 of the CPIX document (DASH-IF CPIX 2.3, ETSI TS 103 799) the keys came in. - **Records:** - `WKL1` commitment list (§4). The key holder derives it from the CPIX key material (§4.4: KID, scheme, key period, commitment). The proxy copies every `key_commit` from this list, so **the proxy holds no key**. - `WKE1` entitlement (§5). The operator's entitlement authority signs it, and it is bound to a key the viewer's device holds. The device signs every request over SHA-256 with Ed25519 (§6.1), which the Web Cryptography API can do. - `WKT1` release ticket (§9.3). A key delivered in the clear is answered with a 307 and a ticket, and the key holder's key server redeems the ticket once. **The proxy never relays a key.** A content protection system's licence carries the key encrypted for the client's decryption module, and the proxy forwards it unchanged. - **The decision (§7.2)** is a pure function of signed inputs, the proxy's clock and its earlier receipts. The checks run in this order: 1. the entitlement holds and its authority is trusted; 2. the request is fresh (300 s); 3. the request is not a replay; 4. the key is known; 5. the class matches; 6. the entitlement has started (not before); 7. the entitlement has not ended (not after); 8. the key's period meets the entitlement (key rotation); 9. the entitlement allows offline licences; 10. a renewal names a released licence; 11. the renewal count is not exceeded; 12. the renewal comes before the licence lapses. An offline licence never outlives its entitlement (§7.3). §8.4 rule 8 means a refused request is never forwarded, and a key is released only by the licence server's 2xx answer or by a ticket. A verifier recomputes every decision over the proxy's whole log (§10). - **Reference:** the `key_release` module of `wai-rs` (feature `key_release`, no new dependency). It includes its own CPIX reader, which refuses a document type declaration and reads no encrypted key. The module is behind `/// cbindgen:ignore`, so `include/wai.h` is unchanged. - **Corpus:** [`wai/live-conformance/keys/`](wai/live-conformance/keys/), with 8 accepted logs and 26 negative controls. - The accepted logs cover releases over each delivery, every decision of §7.2, an expired entitlement, rotation over three periods, offline licences with their renewals, lapse and clamp, and a licence server that refused or gave no answer. - The controls give every reason of §11. - The corpus is generated from fixed seeds by `wai_key_release_vectors gen` and checked byte for byte by `tests/key_release.rs`. - **Second implementation:** [`wai/live-conformance/key_release_verify.py`](wai/live-conformance/key_release_verify.py). It is written from the text, standard library only, and run as `python3 -I`. It reads the extension's tables, derives each list from its CPIX document with `xml.etree`, recomputes every decision, and requires each of 17 mutated copies of the corpus to fail. Rust and Python agree on every vector. - **Service:** [`wai/wai-key-proxy/`](wai/wai-key-proxy/), its own crate and lock. - The proxy appends each receipt to a durable, single-writer log (`File::try_lock`, `sync_data`) before it answers. It reads the log back on restart and cuts a torn last line. - A replay that arrives while the first request is still at the licence server waits, and is refused after it, so the log stays in decision order. - The key server redeems each ticket once and keeps the redemptions durably. - CLI: `serve`, `keyserver`, `keygen`, `pubkey`, `list` (CPIX → `WKL1`), `entitle`, `sign-request`, `verify`. - `tests/end_to_end.rs` runs the proxy, the key server and a fixture licence server on loopback. `smoke.sh` runs the release binary the way an operator would. - **Registry:** `WKL1`, `WKE1`, `WKT1`, and the `WAI-Key-*` header fields (proposed). The export is regenerated. - **Text:** the SPEC §5 `wai.video.keys` row and a §5 paragraph; a CHANGELOG entry; the `live-conformance/README.md` index. - **CI:** - a "key release" step in `wai-conformance.yml`'s independent-verifiers job, with the extension added to its paths; - a new `wai-key-proxy.yml` workflow: tests, clippy `-D warnings`, the release binary end to end. This slice needs none of the open PRs (#457, #460, #461, #463, #465), and none of them touches `wai_video_keys.rs`. They do share the usual append points (`registry.rs`, `lib.rs`, `Cargo.toml`, SPEC, CHANGELOG, `wai-conformance.yml`), so whichever lands second has a mechanical merge. ## Design decisions - **The entitlement is a signed record bound to a device key, not a field the proxy fills in.** Form 1 recomputes its decision from fields its own signer chose, including the expiry. In form 2, every input to the decision except the proxy's clock is signed by someone else: the authority signs the entitlement, the key holder signs the list, the device signs the request. A proxy therefore cannot choose a window or a class. - **Clear keys go by ticket.** For an HLS key file or a Clear Key licence, the response is the key itself. Relaying it would put the key in the proxy, so the proxy signs a release ticket instead and the key holder's key server redeems it. A `drm` route forwards to any licence server unchanged. A clear route that names an upstream is a configuration error. - **The log is the decision's input.** Replay (check 3) and renewals (checks 10 to 12) are decided against the proxy's own earlier receipts. Verification is therefore over a whole log, not over a lone receipt. A lone receipt still has its own rules (§8.4), which a licensor checks alone. - **One request names a set of keys and is refused whole.** A licence challenge can ask for several keys. The receipt names each requested key, and one failing check refuses all of them. - **No TLS in the proxy.** The upstream is `http://` through a local forwarder that originates TLS, and the reverse proxy in front terminates the client's TLS. This keeps the dependency set to the axum/hyper stack the quantum service's lock already pins. - **Energy:** the proxy signs the unmetered marker (0, no class). The corpus carries one receipt with an `OnChipCounter` figure, to exercise the class encoding and the resolution floor. ## Checks (all cargo on the build host via `rb`) | check | command | result | |---|---|---| | module unit tests | `cargo test --locked --no-default-features --features key_release --lib key_release::` | 13 passed | | form 1 unit tests (legacy pin unchanged) | `… --lib wai_video_keys::` | 7 passed | | corpus test | `… --test key_release` | 4 passed (regenerates byte for byte, every outcome, §11 reasons, §3.1/§3.2/§7.2 tables) | | other `wai.video.*` modules | `cargo test --locked --no-default-features --features video_workflow --lib wai_video` | 50 passed | | registry | `cargo test --locked --no-default-features --lib codecs::registry`; `wai registry export --check` | 14 passed; up to date | | default-feature lib build | `cargo build --locked --lib` | clean | | clippy, wai-rs | `cargo clippy --locked --no-default-features --features key_release --all-targets` | zero notes in the touched files | | proxy tests | `cd wai/wai-key-proxy && cargo test --locked` | 1 + 2 end-to-end passed; end-to-end looped 10× green | | proxy clippy | `cargo clippy --locked --all-targets -- -D warnings` | clean | | proxy release binary | `bash smoke.sh` | 8/8 PASS | | independent verifier | `python3 -I wai/live-conformance/key_release_verify.py wai/live-conformance/keys` | 34 logs PASS, 17 mutated copies fail, exit 0 | | every other live-conformance verifier | each `python3 -I <x>_verify.py <dir>` | all exit 0 | | lockfiles | `scripts/check-lockfiles.sh wai/wai-rs wai/wai-key-proxy`; `cargo metadata --locked --offline` | current; ok | | advisories | `python3 -I scripts/check-advisories.py` | 0 gated | | repo checks | `check-tests-in-ci.py`, `check-workflow-concurrency.sh`, `check-spec-refs.py`, `check-wai-section-refs.py`, `check-no-vanity-metrics.sh`, `test-public-text-checks.sh`, `check-comparative-prose.sh`, `check-orphan-sources.py` | all exit 0 | | workflows | `ruby -ryaml` over `.github/workflows/*.yml`; `wfsteps.py HEAD origin/main HEAD` | parse; 0 problem(s) | | public names | `scripts/check-public-names.sh` over every changed file; commit messages and this body against the same patterns | clean | ## Falsifications All of these were run after a commit, on a snapshot on the build host. Each breaks one rule, and every run exited non-zero: - **Rust:** - replay check off - period check off - licence not clamped to the entitlement - §8.4 rule 8 first clause off - rule 4 (scheme/delivery) off - CPIX commitments not compared - the list's copy not checked - ticket KIDs not compared - freshness bound off by one (caught by the unit test) - the CPIX reader accepting a DOCTYPE (caught by the unit test) - a scheme code changed in the extension's §3.1 (caught by the table test) - **Python:** - replay check off - rule 4 off - CPIX keys not compared - renewal count off - rule 8 first clause off - Ed25519's small-order checks skipped - one byte of a committed receipt - **Service:** - no wait for an in-flight replay - the log not locked - a refusal forwarded - a ticket redeemable twice - a torn last line not cut One falsification first came back **missed**: removing rule 8's first clause alone. The rule's other clauses caught every existing control, but a granted `drm` receipt with no upstream answer would have passed. I added the control `n_granted_not_forwarded`, and that falsification is now caught in both implementations. ## Not done - **Encrypted CPIX keys** (CPIX §8.1: AES-256-CBC under a document key, RSA-OAEP-wrapped) are refused as `cpix_unsupported`. Reading them needs AES and RSA in the key holder's tool. Per-key `@contentId`, key hierarchies (`@dependsOnKey`) and VOD offset periods are refused the same way. - **Licence contents are not checked** (§13). The receipt binds the SHA-256 of the licence and forwards `WAI-Key-Ids` and `WAI-Key-Licence-Expiry`. A licence server that ignores them could put in more keys, or a longer duration, than the receipt states. - **No player integration.** No EME or HLS request hook signs the six fields in a browser yet. `sign-request` is the reference client. - **The log grows without bound** and is read whole at start, roughly 2 KB per request. Compaction would need a signed checkpoint of the replay window and of open offline chains, and it is not built. - **No device limit** (that is a separate rule), and no rate limiting. - **The key server's redemptions are an unsigned list.** A signed redemption record is not defined. - **Not deployed.** The run and deploy instructions (ports 9710 to 9713, launchd and systemd units, Caddy routes with CORS preflight, health checks) are in the slice's deploy note. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- **Closed:** Landed on main through merge train E (#499, merge bf39ec9a); verified by content: this PR's head is in main
The scheme (cenc, cbc1, cens, cbcs; the HLS methods AES-128, SAMPLE-AES,
AES-256-GCM) and the key delivery (HLS key URI, Clear Key, a content protection
system by its system ID) of each released key; the commitment list WKL1 derived
from a CPIX document, so the proxy copies each key_commit and holds no key; the
entitlement WKE1 bound to a device key and the device's proof over each request;
the release decision as a pure function of signed inputs (freshness, replay, key
periods, offline licences and renewals); the release ticket WKT1 for a clear
delivery, so the proxy never relays a key; verification of a proxy's log.

The key_release module of wai-rs (feature key_release), its unit tests, and the
corpus live-conformance/keys/, generated from fixed seeds by
wai_key_release_vectors and checked by tests/key_release.rs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Written from extensions/key-release.md, sharing no code with wai-rs: it reads the
scheme, delivery, decision and reason tables from the extension, derives each list
from its CPIX document with the standard library's XML parser, recomputes every
decision of every log, and requires every mutated copy of the corpus to fail.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A proxy in front of any licence server: it decides each licence request from signed
inputs, appends its signed receipt to a durable single-writer log before it
answers, refuses without forwarding, forwards a granted content protection
system's request and returns the licence unchanged, and answers a clear key with a
307 and a release ticket instead of relaying it. A replay sent while the first
request is still being forwarded waits and is refused after it, so the log stays in
decision order. The key server, run by the key holder, redeems each ticket once.

CLI: serve, keyserver, keygen, pubkey, list (a commitment list from a CPIX
document), entitle, sign-request, verify. tests/end_to_end.rs runs everything on
loopback against a fixture licence server; smoke.sh runs the release binary.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The wire identifiers of extensions/key-release.md (WKL1, WKE1, WKT1 and the WAI-Key-*
header fields) in the registry table, and the export regenerated; the wai.video.keys
row of SPEC §5 names its proxy form, and a §5 paragraph describes it; §6.2 states
how a request missing a field is read. CI: the key-release step in the independent
verifiers job (the module's tests, form 1's, tests/key_release.rs and
key_release_verify.py), the extension under the workflow's paths, and the
wai-key-proxy workflow (tests, clippy, the release binary end to end).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai: key release corpus, a grant of a licence never forwarded
Some checks failed
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / does this change touch it (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Has been cancelled
WAI energy receipts / does this change touch it (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (pull_request) Has been cancelled
e60c7dbee5
A negative control for §8.4 rule 8's first clause on its own: a granted request of a
content protection system whose receipt records no answer from the licence server.
Falsifying that clause alone had let the corpus pass, the other clauses of the rule
catching each earlier control.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
dcharlot closed this pull request 2026-10-26 20:58:36 -04:00
Some checks failed
wai-key-proxy / does this change touch it (pull_request) Has been cancelled
wai-key-proxy / proxy · linux (pull_request) Has been cancelled
wai-web wasm32 / does this change touch it (pull_request) Has been cancelled
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Has been cancelled
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Has been cancelled
wai-quantum studio and desktop / does this change touch it (pull_request) Has been cancelled
wai-quantum studio and desktop / studio · browser (pull_request) Has been cancelled
wai-quantum studio and desktop / desktop app · macos (pull_request) Has been cancelled
wai-pack / wai-pack · does this change touch it (pull_request) Has been cancelled
wai-pack / wai-pack · linux (pull_request) Has been cancelled
wai-pack / wai-pack · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · macos (pull_request) Has been cancelled
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / does this change touch it (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Has been cancelled
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Has been cancelled
WAI energy receipts / does this change touch it (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (pull_request) Has been cancelled

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!471
No description provided.