conformance-results §4.1: a relying party that admits an implementation on a
conform-result/1 record requires the record accepted, its run passed (not_conformant), its
suite one whose corpus the party holds (suite_unknown), and its corpus digest that corpus's
(corpus_mismatch). wai verify --conformant [--root <wai-dir>] applies the rules against a
checkout; without it a record of a run that did not pass verifies as before. A sink kind:
wai conform sink --suite native-sink gives a sink each session of
live-conformance/native-sink/ with its answers withheld, and each configuration the corpus
states a session refuses; wai_native_sink_vectors answers [--c-abi] is the reference sink,
through its module or through the C interface the platform integrations link.
wai-breaking.yml's runner job runs the native sink both ways and the score decoder, each
record admitted against the checkout's corpus, and a planted sink that presents an object
whose digest does not match: its run must exit 1 with tampered-fragment failed, and
admission must refuse its record at rule 2. tests/cli_conform_sinks.rs holds the same, and
corpus_mismatch and suite_unknown; it has its [[test]] entry with its required features,
so check-tests-in-ci.py passes. The binaries are built with the test step's features, so
cargo reuses what that step built. The browser sink has no sink suite, and §7 says that
§4.1 has only this reference implementation, with no admission vectors.
The catalogue's receipt.verify (the new options, and the envelopes the pin-by-default commit
added) and conformance.run (the sink kind, the {case} placeholder) are exported again, and
Studio's actions regenerated from the export: actions.mjs --check had failed since that
commit. c_abi::take reads and frees no null buffer.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
64 lines
4.6 KiB
Markdown
64 lines
4.6 KiB
Markdown
# live-conformance/native-sink — the native sink
|
|
|
|
The corpus of [`extensions/native-sink.md`](../../extensions/native-sink.md) §10: scripts of the
|
|
calls a native host makes to its sink over one session, each with the answer the call gets, and the
|
|
outcome the owner's collector reaches for the session's bundle (stream-audit §10).
|
|
|
|
**Sink equivalence.** For each case, a conforming sink opened with the case's `config`, the session
|
|
key whose seed is `seed` and the start `start_us`, and given each call's `do` in order, gives each
|
|
call the `answer` it states: a playlist's verdict (§4.2), an object's verdict (§4.3), an
|
|
observation's `{"end"}` (§6.1), `{"ok": true}` for an event, a parent receipt, an energy entry or an
|
|
attachment, a CMCD batch, or the `bundle` (stream-audit §9) as the JSON text the sink writes; and a
|
|
refused call `{"error": <reason>}`. The bundle, verified for `owner` serving `channels`, reaches the
|
|
case's `outcome`. Each configuration under `configs` is refused with the reason it states. A sink
|
|
that gives another answer, byte or reason does not conform.
|
|
|
|
**Provenance.** Generated here: `wai_native_sink_vectors gen` writes `vectors.json` from fixed seeds.
|
|
Each key is SHA-256 of the corpus's label (`wai:native-sink/corpus/key`, a zero byte) and an index
|
|
byte (0 the owner, 1 the publisher that seals the playlists, 2 a stranger); each session's seed is
|
|
SHA-256 of `wai:native-sink/corpus/session`, a zero byte and an index byte; every time is a constant
|
|
after 2026-10-25T00:00:00Z; and Ed25519 signing is deterministic (RFC 8032), so the file is the same
|
|
bytes on every machine. The media are the reference package
|
|
[`pack-conformance/packs/video-base-01`](../../pack-conformance/packs/video-base-01/)'s floor: its
|
|
CMAF initialization section and five fragments, each named by its SHA-256 (packaging §7), copied
|
|
byte for byte; a tampered fragment differs from its original in one bit of its last byte. The WAI
|
|
objects are opaque test bytes (`WAI1` and a SHA-256 of a label), named by their content hashes, which
|
|
nothing decodes. The playlists are written here: the floor's, in the form http-delivery Appendix G
|
|
renders, sealed by playlist receipts under the publisher's key; a WAI playlist of the objects; live
|
|
revisions chained by their receipts; and a stream of another service, with a key, program times and
|
|
an ad marked by `EXT-X-DATERANGE`. The observation cadences, stalls and energy figures are synthetic
|
|
constants chosen to exercise the rules and were measured by nothing. The origins are `.example`
|
|
names (RFC 2606). The generator asserts that each case gets the answers it was written to have
|
|
before it writes it.
|
|
|
|
## Layout
|
|
|
|
One file, `vectors.json`:
|
|
|
|
- `owner`, `channels`: the collector's key and the channels it serves;
|
|
- `objects`: every body a call names, hexadecimal, by name;
|
|
- `configs`: configurations a session refuses;
|
|
- `cases`: each with its `name`, a `note`, its `config`, `seed`, `start_us`, `calls` (each a `do`
|
|
and its `answer`) and the bundle's `outcome`:
|
|
- `signed-vod`, `tampered-fragment`, `unsigned-refused`, `receipt-refusals`, `live-chain`,
|
|
`wai-objects`, `live-rebound`, `third-party-ad`, `content-addressed`, `names-are-names`,
|
|
`hidden`, `idle`, `energy`, `log-order`, `page-parity` and `refused-calls`.
|
|
|
|
`page-parity` is also replayed by the page's integration of stream-audit,
|
|
[`wai-audit/web/native-sink.test.mjs`](../../wai-audit/web/native-sink.test.mjs), which signs the
|
|
same bundle byte for byte.
|
|
|
|
Rebuilding: `cd wai/wai-rs && cargo run --no-default-features --features native_sink --bin
|
|
wai_native_sink_vectors gen ../live-conformance/native-sink`; `… verify ../live-conformance/native-sink`
|
|
checks it; `python3 -I ../live-conformance/native_sink_verify.py ../live-conformance/native-sink` is
|
|
the second implementation.
|
|
|
|
**Running a sink against it.** `wai conform sink --suite native-sink --impl "<command> {case}"` gives a
|
|
sink each case with its answers withheld: the bodies its calls name (`objects`, hexadecimal), its
|
|
`config`, `seed` and `start_us`, and each call's `do`; and each configuration under `configs` as a case
|
|
of no call, under a seed of zeros. The sink writes its answer to each call in order, or, refusing the
|
|
configuration, that refusal alone, one JSON text a line in RFC 8785 form. A case passes when what it
|
|
writes has the SHA-256 of the answers this file states, written the same way, and the run's outcome is
|
|
a signed `conform-result/1` record ([conformance-results](../../extensions/conformance-results.md)).
|
|
`wai_native_sink_vectors answers {case}` is the reference sink, and `… answers --c-abi {case}` the same
|
|
sink through its C interface.
|