106 lines
6.8 KiB
Markdown
106 lines
6.8 KiB
Markdown
# live-conformance/ads — live ads
|
|
|
|
The corpus of [`extensions/live-ads.md`](../../extensions/live-ads.md) §11: rooms whose `cue`
|
|
events open ad breaks, each a room (its `WRD1` descriptor, `WRG1` grants, key-log head or none,
|
|
and each principal's `WEV1` chain, the break annotations `WAB1` among them), its `WAP1` ad
|
|
policy, the presentation time of `t0` on the DASH Period (`pt0_ms`), and the break-form
|
|
`wai.video.ssai` receipts of its viewers, each with the pod its decision ran over; what a
|
|
verifier states of them; and each accepted room's HLS tags, byte for byte.
|
|
|
|
**Ads equivalence.** For each vector, a conforming ads verifier given its `descriptor`,
|
|
`grants`, `key_log`, `chains`, `policy`, `pt0_ms`, `receipts` and `pods` (§9.1) reaches the
|
|
outcome the vector states (§9.4):
|
|
|
|
- `refuse`: the `reason` and where, `at`: `["room", …]` with the room verifier's own place
|
|
(live-rooms §9.1), `["policy"]`, `["record", c, i]` for record `i` of chain `c`, or
|
|
`["receipt", k]`;
|
|
- `gap`: the room's `gaps`, each `principal`, `first` and `last`;
|
|
- `accept`: the `room` id; the `breaks` (§4.3), each its `digest`, `id` and `event_id` (§4.4),
|
|
`author`, `cue_id`, `t`, `type` (`out` or `break`), `placement` (`mid` or `post`),
|
|
`planned_ms`, `avail_ms`, `duration_ms`, `closed_by` and `end` (`null` while it is open),
|
|
and its `hls_list_uri` and `dash_list_uri` (§7.2, §7.3); the `chapters`, each `digest`, `t`
|
|
and `duration_ms`; `hls`, the file holding the room's HLS tags; `dash`, the Period's event
|
|
streams (§6.3); `dash_open`, each out's event as written before its in, by the out's index
|
|
among the `breaks`; `receipt_facts`, each receipt's `identity` (§8.4), the `asset_list` it
|
|
binds as the verifier writes it, and its `spend_micros`; and `spend_micros`, the spend of
|
|
every receipt together.
|
|
|
|
Each tag file, `NAME.m3u8`, is the HLS tags of vector `NAME` (§5.1 to §5.3), one tag a line in
|
|
the order §5.4 gives, each line ended by a line feed. It is the date ranges of the room's Media
|
|
Playlists, not a whole playlist: the segments are the room's tracks.
|
|
|
|
A verifier that reaches another outcome, reason, place, break, tag byte, event byte, asset-list
|
|
byte, identity or spend does not conform.
|
|
|
|
**Provenance.** Generated here: `wai_live_ads_vectors gen` writes every file from rooms
|
|
authored in code, from fixed seeds. Each principal's key is SHA-256 of a fixed label and the
|
|
principal's index; each creative's hash and each session id likewise; every time is a
|
|
constant (the rooms' `t0` is 2026-10-16T00:00:00Z); every origin and base URI is an
|
|
`.example` name (RFC 2606); and Ed25519 signing is deterministic (RFC 8032), so every file is
|
|
the same bytes on every machine. The generator asserts that each vector reaches the outcome it
|
|
was written to have, and that the corpus gives every reason of §10, before it writes. No
|
|
recorded data.
|
|
|
|
## Layout
|
|
|
|
- `vectors.json`: `principals` (the keys, by name, informative) and `vectors`.
|
|
- `NAME.m3u8`: the HLS tags of each accepted room.
|
|
|
|
Every room has a producer, whose grant permits `cue`, `meta` and `chat`; a viewer, whose grant
|
|
permits `chat`; and the decider, whose grant permits no event and carries the room's ad budget,
|
|
2 minor units of EUR (2 000 000 millionths), and which never joins. The clock admits the
|
|
producer and the viewer at the room's start.
|
|
|
|
The rooms:
|
|
|
|
- `live_break`: an out at 60 s with no planned duration and its in at 90 s, under a policy
|
|
whose open avail is 30 s and whose preload is 4 s. One viewer, present at the break's start,
|
|
is filled with two 15 s ads from an HLS asset list (its decision energy model-based); a
|
|
second joins 12 s into the break and is filled with what remains, one ad, from a DASH list
|
|
MPD (its decision energy an on-chip counter's reading). No pre-roll.
|
|
- `mid_roll`: a 30 s break, annotated mid-roll, under a policy that restricts skipping and
|
|
jumping, snaps both ways and offers a skip control after 5 s, with `pt0_ms` 5000. One
|
|
viewer's pod has two ads at one price, ordered by `ad_id`, and three fill the avail; another
|
|
viewer's only ad costs more than its funds, so its fill is empty and its DASH list MPD is no
|
|
bytes.
|
|
- `post_roll`: two chapters, a 15 s mid-roll at 30 s, and a 20 s break annotated post-roll at
|
|
120 s; one viewer filled in both breaks, another in the post-roll only.
|
|
- `chapters`: a chapter of a stated length and one of none, then an out with a planned
|
|
duration of 15 s and its in, which states no duration.
|
|
- `gap`: `live_break`'s room as a subscriber holds it when the out was not delivered.
|
|
- refused, one defect each: `cue_kind_not_permitted` (refused by the room,
|
|
`kind_not_permitted`), `policy_slots_zero`, `policy_wrong_room`, `policy_bad_signature`,
|
|
`decider_grant_unknown`, `decider_grant_revoked` (a room whose key log revokes the decider
|
|
grant, `grant_revoked`), `annotation_placement`, `annotation_on_out`, `cue_after_post_roll`,
|
|
`overlapping_breaks`, `open_break_no_avail`, `break_of_no_duration`, `in_without_out`,
|
|
`in_duration_mismatch`, `receipt_extra_member`, `receipt_wrong_room`,
|
|
`receipt_bad_signature`, `receipt_quartile_six` and, for the other rules of §8.5 each
|
|
broken alone, `receipt_format_three`, `receipt_work_below_fill`,
|
|
`receipt_figure_without_class`, `receipt_below_resolution` and `receipt_over_its_ceiling`
|
|
(all `receipt_invalid`), `receipt_not_decider`,
|
|
`receipt_grant_mismatch`, `receipt_names_the_in`, `decider_grant_expired`
|
|
(`outside_grant_window`), `pod_mismatch`, `decision_mismatch`, `asset_list_mismatch`,
|
|
`receipt_duplicate` and `funds_exceeded` (a budget of 1 minor unit, and two viewers each
|
|
billed 600 000 millionths).
|
|
|
|
## Running
|
|
|
|
```
|
|
cd ../../wai-rs
|
|
cargo run --no-default-features --features live_ads --bin wai_live_ads_vectors -- verify ../live-conformance/ads
|
|
cargo run --no-default-features --features live_ads --bin wai_live_ads_vectors -- gen ../live-conformance/ads # regenerate
|
|
cargo test --no-default-features --features live_ads --test live_ads
|
|
cd ../live-conformance
|
|
python3 -I live_ads_verify.py ads
|
|
```
|
|
|
|
`wai_live_ads_vectors verify` and `tests/live_ads.rs` require every file to regenerate byte for
|
|
byte, no other file but this one to be there, and `wai-rs` to give every case its outcome; the
|
|
test also requires §10 to list exactly the reasons the reference reports, and the generator
|
|
that the corpus gives each of them. `live_ads_verify.py` is the second implementation, written
|
|
from the extension's text and sharing no code with `wai-rs`: it verifies each room with
|
|
`live_rooms_verify.py`, writes every tag, event and asset list itself, verifies every receipt's
|
|
signature with WAI's strict Ed25519 rule and computes its BLAKE3 hashes from the specification,
|
|
reads §10 from the extension, gives every case the same outcome, requires every reason of §10
|
|
to appear, and then mutates copies of the corpus, one defect each, each of which must fail.
|
|
Pass = an exit status of 0 from each.
|