open-standards/wai/live-conformance/audit/README.md
Transaction Science 519c968e84 wai: stream audit, wai.delivery.audit (spec, reference, corpus)
A content owner's evidence from the players of a stream another service
delivers over HTTP. settlement §14 acknowledges such objects by plain
SHA-256 from an upstream named by its origin. stream-audit defines the
session key and channel, the acknowledgement windows and chains, the
WAS1 session record (spans presented, start time and stalls recomputed
from the delivery-telemetry log, energy per role with its class, how the
session ended), WPC1 claims for marked ads under the channel, the bundle
a collector verifies, and the channel report it signs and any holder of
the bundles recomputes. No price, tariff or amount.

wai-rs module stream_audit (feature stream_audit), the generator
wai_stream_audit_vectors, tests/stream_audit.rs, and the corpus
live-conformance/audit/.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 21:26:40 -04:00

73 lines
5.1 KiB
Markdown

# live-conformance/audit — stream audit
The corpus of [`extensions/stream-audit.md`](../../extensions/stream-audit.md) §15: an owner's key,
the channels it serves, the objects its players fetched, and two kinds of vector: sessions, each a
bundle (§9) with the outcome a collector's verification gives it (§10), and channel reports (§11),
each with the outcome its recomputation gives it.
It sits beside [`settlement/`](../settlement/) and [`presentation/`](../presentation/) because a
session's acknowledgements are settlement's `WDA1` under settlement §14 and its claims are
ad-presentation's `WPC1`, read by those corpora's second implementations, `settlement_verify.py`
and `ad_presentation_verify.py`; its log is read by `live_metering_verify.py`.
**Audit equivalence.** For each session, a conforming verifier given the bundle's bytes (`bundle`
serialized as JSON, or `bundle_text` exactly), the `owner` key and the `channels` it serves reaches
the outcome the vector states:
- `refuse`: the `reason` and where, `at`: `["bundle"]`, `["session"]`, `["ack", i]` or `["ack", i,
"entry", j]` for the record's `i`-th acknowledgement, `["log"]`, `["notes"]`, `["attachment",
i]`, or `["claim", i]`;
- `accept`: the record's `digest`, its `channel`, `presentation`, `start`, `end` and `ended`; the
time `presented_ms`, `viewable_ms`, `audible_ms` and `ad_ms`; the acknowledged `delivery` by
origin and class and the `repeats`; `startup_ms`, `stalls` and `stall_ms`; each `energy` entry
with its role, class label and figure; each claim's verdict, and for a presented claim its
`quartile`, `run_ms`, `viewable_ms` and whether it is `viewable`; the `notes` count; and the
`attachments` count.
For each report, a conforming verifier given the bundles of the sessions the vector names, the
channel's name, the owner key and the served report (`served`: the report and its signature)
reaches the outcome it states: `accept` with the digest of the report's bytes (§11.3), or `refuse`
with its `reason` and place. A verifier that reaches another outcome, reason, place or figure does
not conform.
**Provenance.** Generated here: `wai_stream_audit_vectors gen` writes `vectors.json` from figures
written in code, from fixed seeds: each key is SHA-256 of the corpus's fixed label
(`wai:stream-audit/corpus/key`, then a zero byte) and an index byte (0 the owner, 1 a stranger, 10
to 13 the four sessions' players, 100 to 151 those of channel `fifty`); each object's bytes are a
SHA-256 stream of a second label (`wai:stream-audit/corpus/object`, a zero byte, the object's name
and a little-endian u32 counter), truncated to its length; and every time is a constant after
2026-10-25T00:00:00Z. Ed25519 signing is deterministic (RFC 8032), so the file is the same bytes on
every machine. The objects are opaque test bytes standing for playlists and segments, which
nothing parses or decodes. The durations, stalls and joule figures are synthetic constants chosen
to exercise the rules, and were measured by nothing: the corpus states what the rules compute and
claims nothing about any stream or device. The origins are `.example` names (RFC 2606). The
generator asserts that each vector reaches the outcome it was written to have before it writes it.
## Layout
One file, `vectors.json`:
- `owner`: the collector's key; `channels`: the channel names it serves (`other-channel`, which a
control names, is not among them).
- `objects`: each object's bytes, hexadecimal, by name (for the reference producer's tests; a
verifier never reads them).
- `sessions`: each with its `name`, its `bundle` (or `bundle_text`), and its `outcome`; accepted
sessions also carry `cmcd`, the Event-mode CMCD batch (live-metering §6.3) of their log, and
`live_two_origins` carries `script`, the inputs its player had (its key's index, its window,
each object received with its time and origin, and its log's control events), from which the
reference producer's tests rebuild every record of its bundle.
- **Accepted**: `live_two_origins` (two origins, two marked ads, one in view and one half out of
it, a repeat, CMSD notes, a stall, an `Estimator` figure beside an unmetered display);
`on_demand_hidden` (ended `hidden`, an `OnChipCounter` figure, an attachment);
`nothing_presented` (ended `error`); `claim_verdicts` (one claim of each verdict);
`nothing_presented_again` (the same session as `nothing_presented`, a record of its own); and
`fifty_00` to `fifty_51`, the sessions of channel `fifty`.
- **Refused**: one control per defect, named for it.
- `reports`: each with its `name`, its `channel`, the `sessions` whose bundles it is given, the
`served` report, and its `outcome`: `news_east` (its rebuffering suppressed, fewer than 50
sessions), `film_library`, `fifty` (its rebuffering stated), and the refused controls.
Rebuilding: `cd wai/wai-rs && cargo run --no-default-features --features stream_audit --bin
wai_stream_audit_vectors gen ../live-conformance/audit`; `… verify ../live-conformance/audit`
checks it; `python3 -I ../live-conformance/stream_audit_verify.py ../live-conformance/audit` is the
second implementation.