open-standards/wai/live-conformance/watermark/README.md
Transaction Science aafbf8e1d6 wai.live.watermark: the corpus, its second implementation, the CI step and the changelog
live-conformance/watermark/vectors.json from wai_live_watermark_vectors, and
live_watermark_verify.py, written from the extension's text, which agrees on every
vector, fails every mutated copy and catches a verifier that leaves out any one of
its checks.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 08:40:15 -04:00

55 lines
3.8 KiB
Markdown

# live-conformance/watermark — forensic watermark sessions
The corpus of [`extensions/forensic-watermark.md`](../../extensions/forensic-watermark.md) §12,
in one file, `vectors.json`: three rooms, ETSI TS 104 002 watermark tokens, lists of `WWS1`
session records with or without their tokens, `WWQ1` recovered sequences matched against
records, and `WWD1` disclosures, each with the outcome the extension gives it.
- **`rooms`**: each room's `WRD1` descriptor, its `WRG1` grants, its key-log head (or `null`)
and its `WRE1` confidentiality record (or `null`), as hexadecimal; `broadcast` (an origin
whose key log lists two edges with `live/watermark`, a relay with `live/relay` alone and a
revoked edge; region pin `DE`, `FR`; retention 30 days), `keyless` (no origin; its clock is
its edge) and `e2ee` (end-to-end encrypted). A vector names its room and may carry a
`room_override`, whose members replace the room's.
- **`tokens`**: each token's bytes, read by §4.2: `read` with what it gives (§4.3: `cwt_tag`,
`alg`, `vendor`, `patlen`, `source`, the clear `pattern` or `null`, `iat`, `exp`, `nbf`), or
`refuse` with `token_malformed` or `token_unsupported`.
- **`sessions`**: a list of records, each `record` with its `token` or `null`, verified by
§9.1: `accept` with each record's facts (its `digest`, `edge`, `owner`, `media`, `kids`,
span, `vendor`, `source`, `patlen`, the number of positions `served`, `segments`,
`unmarked`, `region`, `expires`, and its `token`'s facts or `null`), or `refuse` with the
`reason` and the place `at`: `descriptor`, `key_log`, `grant` and its `index`,
`confidentiality`, or `session` and its `index`.
- **`matches`**: the records and a `sequence`, by §9.2: `matched` or `unmatched` (with
`no_match` or `ambiguous_match`), and the `match`: the sequence's digest, the positions it
`stated`, each `candidate` (its `index`, `digest`, whether it `agrees`, and its `first`
disagreement, a `position` and `unserved` or `differs`), and the matched `session` or
`null`; or `refuse` at `sequence` (or at a record).
- **`disclosures`**: one `record` with its `token`, a `sequence` and a `disclosure`, by §9.3:
`accept` with its `facts` (its `digest`, the `session`'s, the `sequence`'s, the `grant`, the
`principal`, the positions `stated`, and `token_given`), or `refuse` with the `reason` and
`at`.
A verifier that reaches another outcome, reason, place or fact does not conform.
**Provenance.** Generated here: `wai_live_watermark_vectors gen` writes `vectors.json` from
records authored in code, from fixed seeds. Every key is SHA-256 of a fixed label and an
index (`principals` lists them); every pattern, salt, KID and copy digest is SHA-256 of a label
and an index; every time is a constant (the rooms' `t0` is 2026-10-18T00:00:00Z); every origin
is an `.example` name (RFC 2606); and Ed25519 signing is deterministic (RFC 8032), so the file
is the same bytes on every machine. The tokens are COSE_Mac0 under HMAC 256/256 keyed by
`wmt_key`, which no verifier checks (§4.4); an encrypted pattern is a COSE_Encrypt0 or
COSE_Encrypt of the right shape whose bytes no verifier opens. Nothing here was recorded from
a deployment.
**Checks.** `wai_live_watermark_vectors verify` and `tests/live_watermark.rs` (wai-rs, feature
`live_watermark`) regenerate the file byte for byte and give every vector its outcome; the
generator asserts that every reason of §11 appears. `../live_watermark_verify.py` is the
second implementation, written from the extension's text: it shares no code with wai-rs, reads
rooms with `../live_rooms_verify.py`, reads tokens with a CBOR reader of its own, mutates
copies of the corpus and requires each to fail, and drops each of its own checks in turn and
requires the corpus to catch the weakened verifier.
```
python3 -I live_watermark_verify.py watermark
```