open-standards/wai/live-conformance/events
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Transaction Science ab23c8ab6b live rooms: AI participants are marked in their grant, and chat and reactions state their origin
live-events §4.4 and §4.5: a chat and a reaction may state an origin after their last
field (1 human, 2 machine, 3 machine-reviewed, with the model's digest for 2 and 3), as a
caption does. live-rooms §4.4: the grant attribute `ai` names the model that acts for an AI
participant; §9.2 step 6 refuses its chat, reaction or caption that does not state origin 2
or 3 with that model (`ai_unmarked`), and a relay does not forward one. Both corpora gain
vectors (additions only); both second implementations read the new fields.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 05:17:43 -04:00
..
README.md wai: register wai.live.events (SPEC §5, registry rows and wire identifiers), CHANGELOG, corpus README, CI step and path gate 2026-10-16 04:57:16 -04:00
vectors.json live rooms: AI participants are marked in their grant, and chat and reactions state their origin 2026-10-21 05:17:43 -04:00

live-conformance/events — live events

The corpus of extensions/live-events.md §10: WEV1 event records in stream order, the policies their principals are held to, and the outcome a verifier gives them; WEP1 policy records; and the records' bindings onto MoQ, LL-HLS and CMAF/DASH.

Live-event equivalence. For each vector, a conforming verifier of the vector's room, holding each principal to the policy the vector names for it (policies, else default_policy) and offered events one at a time in the order given, reaches the outcome the vector states (§6.4):

  • refuse: the reason and the index of the first record refused (§6.1–§6.3, or §7's tally_mismatch at the index of the poll_close whose stated counts the replay does not reach);
  • gap: no record refused, and the gaps (principal, first and last seq not held) in the order found, under the code delivery_gap (§6.2);
  • accept: no record refused, no gap, and every stated tally equal to the replay.

A vector that does not refuse also states each record's SHA-256 digest (§3.2). An accepted vector states the tally (§7): each poll's state and counts, and the BLAKE3 state hash of the wai.feed.state records they replay to; and each record's MSF event timeline record, EXT-X-DATERANGE tag and version 1 emsg box (§8), which a verifier must render byte for byte and read back to the record. A verifier that reaches another outcome, reason, index, gap, digest, tally or rendering does not conform.

Provenance. Generated here: wai_live_events_vectors gen writes every record from events authored in code, from fixed seeds. Each principal's key is SHA-256 of a fixed label and the principal's index, each room id likewise, every time is a constant, and Ed25519 signing is deterministic (RFC 8032), so the file is the same bytes on every machine. The generator asserts that each vector reaches the outcome it was written to have before it writes it. The SCTE 35-1 sections are built to that standard's syntax, with their CRC; the SCTE 35-2 message is a stand-in byte string, which the extension carries opaque. No recorded data.

Layout

One file, vectors.json:

  • t0_unix_us, pt0_ms: the room's t0 as microseconds since 1970 (for the MSF t index and START-DATE), and the presentation time of t0 in milliseconds (for emsg).
  • principals, rooms: the keys and room ids, by name (informative).
  • policies: the policy records the vectors name, in hexadecimal: default (§5's defaults), authority (the defaults with the lifecycle kinds), chat_only (chat, reaction and vote) and slow (the defaults with max_events 3).
  • vectors: each with name, about, room, default_policy, policies (principal key → policy name), events (records in hexadecimal, in stream order), outcome, and as above reason, index, gaps, digests, tally and bindings (per record: msf, daterange, and emsg in hexadecimal).
  • policy_cases: policy records (§5), each read (accept) or refused with its reason.
  • binding_cases: an input for one binding (daterange, emsg in hexadecimal, or msf), read back to its record or refused with its reason (§8).

Vectors:

  • one accepted vector per kind of §4 (kind_*): metadata that is empty, anchored, and at the default bound; cues of every type, with and without an SCTE-35 message of each form; chat across scripts and at the text bound; standalone reactions exactly one window apart and targeted ones; a poll with a changed vote, a vote after the close and a vote for no poll, closed with its tally, and a poll left open; markers with and without an attachment; every control command; captions of each origin; moderation decisions; take commitments; and the lifecycle kinds under the authority's policy;
  • room_interleaved: several principals' chains interleaved in delivery order across three one-minute groups, with anchored events and a poll;
  • join_set_repeats and joiner_mid_stream: one host's track as a continuous subscriber receives it, with each group's first object repeating its join set (§8.2), and as a subscriber that joins at group 1 receives it, which reports what it does not hold as gaps;
  • chain_gap: a chain with a seq not delivered;
  • one negative control per refusal, each a single defect refused with its reason: a flipped signature bit; three forgeries a lenient Ed25519 verifier accepts (an identity key, its non-canonical spelling, an R of small order); a broken chain and a broken genesis; a reorder; a replayed seq; t going back; an oversize payload; a kind not permitted, and a lifecycle kind from a participant; the event rate and the reaction rate exceeded; an overlong and a surrogate UTF-8 encoding; text over the bound; two truncations; an unknown version; a bad magic, trailing bytes and a bad anchor flag; an unknown kind and a reserved lifecycle kind; the wrong room; a malformed cue, language tag and poll; and a stated tally the replay does not reach.

Running

cd ../../wai-rs
cargo run --no-default-features --features live_events --bin wai_live_events_vectors -- verify ../live-conformance/events
cargo run --no-default-features --features live_events --bin wai_live_events_vectors -- gen    ../live-conformance/events   # regenerate
cargo test --no-default-features --features live_events --test live_events
cd ../live-conformance
python3 live_events_verify.py events

wai_live_events_vectors verify and tests/live_events.rs require the file to regenerate byte for byte and wai-rs to give every case its outcome; the test also requires the corpus to cover every kind and every reason, and the extension's §9 to list exactly the reasons the reference reports. live_events_verify.py is the second implementation, written from the extension's text and sharing no code with wai-rs: it gives every case the same outcome, renders every binding itself, and requires the same coverage. Pass = an exit status of 0 from each.