open-standards/wai/decisions.md
Transaction Science e313fa32cb
Some checks failed
wai-audit collector and player integration / does this change touch it (push) Successful in 18s
joule-moq-web browser client / joule-moq-web · does this change touch it (push) Successful in 23s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Waiting to run
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Waiting to run
joule-moq-remote host agent / joule-moq-remote · does this change touch it (push) Successful in 29s
wai-key-proxy / does this change touch it (push) Successful in 17s
joule-moq-remote host agent / joule-moq-remote, every target (macos) (push) Waiting to run
wai-sink-swift native sink package / does this change touch it (push) Successful in 20s
wai-sink-android native sink library / does this change touch it (push) Successful in 25s
WAI Studio / does this change touch it (push) Successful in 15s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Waiting to run
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Waiting to run
WAI Studio / Studio in Chromium and Firefox · macos (push) Waiting to run
wai-app and Create / wai-app · does this change touch it (push) Successful in 55s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Waiting to run
joule-moq-room room service / joule-moq-room · does this change touch it (push) Successful in 1m7s
WAI operation catalogue / does this change touch it (push) Successful in 1m19s
wai-quantum studio and desktop / does this change touch it (push) Successful in 1m11s
wai-ledger service / does this change touch it (push) Successful in 1m12s
joule-moq-http live HTTP egress / joule-moq-http · does this change touch it (push) Successful in 1m31s
wai-quantum studio and desktop / desktop app · macos (push) Waiting to run
wai-ledger service / service · macos (push) Waiting to run
wai-quantum for JavaScript / does this change touch it (push) Successful in 1m13s
wai-fleet service / does this change touch it (push) Successful in 1m20s
wai-fleet service / service · macos (push) Waiting to run
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 26s
wai-quantum energy-landscape jobs / does this change touch it (push) Successful in 13s
wai-quantum energy-landscape jobs / the same bits · macos (push) Waiting to run
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Successful in 1m1s
wai-key-proxy / proxy · linux (push) Successful in 1m35s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Successful in 1m36s
wai-audit collector and player integration / collector · linux (push) Successful in 2m22s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (push) Successful in 3m40s
joule-moq-http live HTTP egress / joule-moq-http, every target (push) Successful in 2m8s
wai-fleet service / service · linux (push) Successful in 2m16s
wai-ledger service / service · linux (push) Successful in 3m27s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Successful in 5m42s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Successful in 7m4s
wai-quantum for JavaScript / javascript · linux (push) Successful in 5m1s
joule-moq-room room service / joule-moq-room, every target (push) Failing after 6m38s
wai-quantum studio and desktop / studio · browser (push) Successful in 6m36s
WAI operation catalogue / the catalogue and every door · linux (push) Successful in 9m27s
wai-quantum studio and desktop / desktop app · linux (push) Successful in 12m50s
WAI Studio / Studio in WebKit · linux (push) Successful in 24m36s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Successful in 1m25s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Successful in 5m58s
wai-quantum energy-landscape jobs / native against WebAssembly, over many seeds (push) Successful in 4m46s
wai-quantum energy-landscape jobs / the same bits · linux-arm64 (push) Successful in 13m27s
wai-quantum studio and desktop / desktop app · windows (push) Successful in 10m48s
wai-quantum energy-landscape jobs / the module under wasm32-wasip2 (wasmtime) (push) Successful in 13m1s
wai-quantum energy-landscape jobs / reader, kernels, answers and the stated result · linux, release (push) Successful in 14m51s
Cache metadata: http-delivery's cache rules as a CDNI configuration for another party's edge cache
WAI extensions/cache-metadata.md (delivery profile, no capability, no record): the cache rules
of http-delivery §9 written as a CDNI metadata configuration (RFC 8006) for ten classes of
path, in a form of RFC 8006's objects with one object of WAI's own (WAI.ByteStore, mandatory to
enforce) and in a form that adds the cache-control and compression objects of the open-caching
configuration interface, and the capability advertisement (RFC 8008, RFC 9388 footprints) of a
cache that takes one. A reader refuses a configuration that states anything but the rules, each
refusal with its own reason; an advertisement is checked for a region. A cache stays untrusted
for content and what it served stays on settlement's signed records: no record is added.

wai-rs: http_binding::cdni and its corpus (cache-conformance/cdni, 119 cases), with a second
implementation in Python written from the text. Decision D12.

Co-Authored-By: Claude <[email protected]>
2026-11-10 23:59:52 -05:00

253 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# WAI decisions
Each choice here is decided, and its reason is written beside it: what was read, and why the
choice follows. A choice that is the owner's (money, contracts, licences, going live) is not
made here.
- **D1. The video floor is AV1's Main profile, at the Main tier, at level 4.1 and below.**
Decided 2026-11-10. SPEC §5, *Video floor*; packaging §7.1; `floor-conformance/`.
- **What was read.** The AV1 Bitstream & Decoding Process Specification, version 1.0.0
with Errata 1, Annex A. A.2: a Main-profile decoder decodes `seq_profile` 0, 4:2:0 or
monochrome at 8 or 10 bits; High adds 4:4:4, and Professional adds 12 bits and 4:2:2.
A.3: each operating point carries a `seq_level_idx`; level 4.0 is 2 359 296 samples a
picture, at most 6144 wide and 3456 high, and 70 778 880 samples a second (its example
1920 × 1080 at 30 frames); level 4.1 is the same picture at 141 557 760 samples a second
(1920 × 1080 at 60), with a Main-tier rate of 20 Mbit/s (High tier, 50); level 5.0
raises the picture to 8 912 896 samples (3840 × 2160); `seq_level_idx` 31 is *maximum
parameters*, which carries no limits. A.4: a level X.Y decoder decodes every stream
that conforms to that level. And a major mobile platform's compatibility definition
(read 2026-11-10): every handheld decodes AV1 and offers it to applications; an AV1
decoder decodes the Main profile at 8 and 10 bits; a hardware AV1 decoder decodes
1920 × 1080 at 30 frames and 16 Mbit/s where the display is that tall; its media
performance class requires a hardware AV1 decoder of Main 10 at level 4.1, and requires
AV1 only to 1080p where it asks other codecs for 2160p.
- **What the packager's floor renditions need.** The floor rendition is the one rendition
of a packaged video that every sink that presents video plays (packaging §7). It is the
HD rendition of content made at 24 to 60 frames a second. Level 4.1 holds 1920 × 1080 at
60 (124 416 000 samples a second) and 2048 × 1152 at 60 exactly; level 4.0 holds
1080-line pictures at 30 only, so content at 50 or 60 frames would have to fall to a
720-line floor. A level of 5.0 or above would hold 2160-line pictures, which a floor
rendition does not need, and would raise the picture every video sink must decode nearly
fourfold.
- **What platform decoders broadly hold.** The platform requirements read ask AV1 at
1080p, Main profile, 8 and 10 bits, and name level 4.1 where they name a level; a
1080p30 decode at 16 Mbit/s is past level 4.0's Main-tier 12 Mbit/s and within level
4.1's 20. None asks AV1 above 1080p. So level 4.1 is the highest level those
requirements reach and the lowest that holds the floor's renditions.
- **The tier.** Main. The High tier raises the bit rate a decoder of the level must
take (to 50 Mbit/s at 4.1), which no requirement read asks of a floor.
- **What stays outside the floor.** The High and Professional profiles, the High tier and
the levels above 4.1 stay in the recommended set: a sink SHOULD decode them (SPEC §5).
- **What follows.** A sink that presents video MUST decode a `wai.video.av1` payload in
the video-floor profile: every sequence header at `seq_profile` 0, every operating point
at `seq_tier` 0 and `seq_level_idx` ≤ 9, and the framing's largest frame and frame rate
within level 4.1's limits. A packager's first floor rung of a video component is the
floor rendition and is refused outside it (`floor-av1-profile`, `floor-av1-level`). The
decoder suite's video-floor case signals level 4.1, the top of the bound, and the suite
holds a High-profile stream and a level-5.0 stream that are refused as a floor.
- **D2. A core candidate is re-pinned, not given a new version.** Decided 2026-11-10.
CORE.md, *The freeze rule*; `scripts/check-wai-core-freeze.py`.
- The freeze rule let a change of meaning pass only with the core version raised. The
core is a 1.0 candidate that its maintainers have not declared; raising its version for
the edits that must precede 1.0 would make it a 1.1 candidate, and 1.0 could never be
declared. A release candidate is numbered within its version.
- So, while the lock's status is `candidate`, a change of meaning raises the lock's
`candidate` by exactly one, rewrites the digests, and adds a dated note naming each
item whose pin changed and why. A changed pin without both fails; so do a note that
leaves out a changed item or names an unchanged one, a candidate raised with no changed
pin, and a re-pin of a core that is not a candidate. A declared core changes by a
version bump alone; an erratum stays the way to change wording without meaning.
- Candidate 2 is one re-pin for the whole of its change: the six splits CORE.md listed and
the video floor's bound (D1).
- **D3. `claim-conformance/` and `signer-conformance/` stay unpinned.** Decided 2026-11-10.
CORE.md, *What is not pinned*.
- Every vector of both carries profile content: a claim's class, a key log's authorities
(which name classes), an authority case's item. Both are written byte for byte by
generators that build even their envelope, signature and chain cases from profile
classes, so pinning them would freeze those classes, and a class is a profile's to
change under its version. The rules every class keeps are pinned as text instead
(`receipts.2.4.4`, `receipts.3.1`, `receipts.7.5`, `receipts.7.9` and the rest of
jwp-receipts §7).
- **D4. OER/2's exception to the signature rule stays in the core's text.** Decided
2026-11-10. SPEC §7, *Signatures*; CORE.md, *What is held although it names a profile*.
- The rule fixes which signatures every conforming verifier accepts, so an exception to it
is part of the rule. Stated over a profile's list, it would let a profile change what a
core verifier accepts. It stays held, naming the one record family whose chain signature
was settled before the rule.
- **D5. An invalid-traffic rule is one that signed records decide; the rest stays out of
scope.** Decided 2026-11-10. ad-presentation §14.1; stitched-presentation §12.
- Read: *Invalid Traffic Detection and Filtration Standards Addendum*, June 2020 update
(final), §1 to §2.4.1 and §4.2 to §4.2.2. Its general invalid traffic is found by "lists
or with other standardized parameter checks", its sophisticated invalid traffic by
analysis. A WAI verifier's verdict must be the same in every implementation, so a rule
here is a comparison of signed bytes or integers and never a score, a rate or a model.
- So six rules are in: two claims of one impression, a span past the creative or a media
time in two claims, an absent attestation where the terms require one, sessions past a
signed cap under one device key, a signed address in a list pinned by digest, and a
signed user agent holding a token of a list pinned by digest. Traffic judged by browser
type, speed, interval, repetition or outliers, and all sophisticated invalid traffic, are
not approximated; the texts name them as the measurer's.
- A list rule decides membership in the pinned bytes. Whether a range's traffic is invalid
is the list's publisher's judgment and the pinning authority's: the addendum requires
data-center traffic to be "known to be invalid in order to be filtered", and a verifier
cannot know that.
- An impression a turned-on rule has no record for is undecided and its spend withheld,
apart from both the valid and the excluded, as the addendum keeps impressions "without
sufficient information to make an IVT decision" out of the invalid counts. An excluded
impression is counted as excluded, never dropped.
- The texts set no rule for how an operator identifies a person: a device key is a key the
device holds, and an address is what a named edge signed that it saw.
- **D6. An identity assertion's holder signs the core deterministic encoding of the signer
payload, and WAI keeps those bytes where a C2PA SDK's validator verifies others.** Decided
2026-11-10. c2pa-binding §4.10, §4.11 and §9.3.
- Read: *Identity Assertion*, version 1.3 (DIF Ratified Specification, 17 August 2026), §5.2
and §8.2.1 to §8.2.2. §8.2.1: the `signer_payload` "MUST be serialized as described in
Section 4.2.1, 'Core Deterministic Encoding,' of RFC 8949", and "the resulting byte string
is presented to the credential holder for signature". RFC 8949 §4.2.1 sorts a map's keys
bytewise by their encodings, so the members are signed as `role`, `sig_type`,
`referenced_assertions`. The text names one serialization and admits no other.
- The SDK `c2pa_emit` signs through (the `c2pa` crate, 0.91.7) verifies an identity
assertion's signature over the members in the schema's order (`referenced_assertions`,
`sig_type`, `role`), and so reports `cawg.x509.signature.mismatch` of every assertion
signed as §8.2.1 says, and none of one signed over that order.
- So WAI writes and verifies §8.2.1's bytes, on its own stores and through the SDK alike,
and does not read the other order: an assertion signed over it is refused
(`identity_signature_mismatch`). Accepting both would have a verifier accept a signature
over bytes the specification does not name. The difference is stated in c2pa-binding §9.3
and pinned by a test that fails when the SDK's validator changes which bytes it verifies.
- **D7. Over HTTP a room's part is served when its group's receipts are held, and low
latency is a measurement.** Decided 2026-11-10. live-http-egress §3.2, §6.2, §9.
- Read: `draft-pantos-hls-rfc8216bis-22` §4.4.3.7 to §4.4.5.3 and §6.2.2 to §6.2.6;
`draft-ietf-moq-cmsf-01`, whole; the DASH Industry Forum's change request *Low-latency
Modes for DASH* of 27 March 2020, clauses 9.X.4 and 9.X.5. ISO/IEC 23009-1 and ISO/IEC
23000-19 were not read.
- A group's receipts are signed over all its objects (jwp-receipts §2.2), and an egress
serves no byte it has not verified. So a part is served as it arrives only where the
publisher published the group's receipts before the group; a publisher that signs at a
group's end has the group's parts served then. No receipt over part of a group is
defined: it would be a second signature format, and is left until a publisher needs it.
- A latency figure states its host, its path, what was timed and the parameters. The
HLS part hold-back and the DASH `ServiceDescription` target are what an egress asks of a
player, and are never written as what a viewer gets.
- The MPD addresses segments by number at one duration, as the change request's
`SegmentTemplate@duration` with `$Number$` does, so it is served only for tracks whose
groups are on a grid; tracks off a grid are served over HLS alone. A `SegmentTimeline`
would lift that at the cost of an MPD that changes with every segment.
- A room's CMAF track carries receipts as any media track of the room does, and its
catalog entry names its receipts track. The packaging draft's text
(`ietf/`, §5.3.3) states that link for `wai` and `wai-link` tracks and has not yet been
revised to name `cmaf`; `ietf/catalog_check.py` holds a `cmaf` track's link to the same
rules meanwhile.
- **D8. A MoQ extension draft is implemented with what the transport draft spoken has; its
unmerged or unassigned parts are not sent.** Decided 2026-11-10.
moq-streaming-format §4.6; co-watch §15.
- Track switching is stated as a SUBSCRIBE and a REQUEST_UPDATE of
`draft-ietf-moq-transport-23`. `SWITCH_FROM` (two pull requests against MOQT, unmerged)
and `draft-gurel-moq-track-switching-01`'s `altTrackGroup` and Switch Track Alias are in
no MOQT revision, so no implementation would read them, and they are not sent.
- Where a draft's code points are unassigned (`draft-nandakumar-moq-tempo-00`'s TBD1, TBD2,
TBD3 and TBD6), the reference uses placeholders in the range MOQT leaves to an
application, held in one module and stated as placeholders wherever they appear. A
message parameter among them is sent only on a session whose peer declared a Setup
Option for it: an unknown message parameter cannot be skipped (-23 §9.19), and an unknown
Setup Option is ignored (§9.1).
- A relay's measurement is a record of one host on one day, signed, and compared only with
that host's own earlier record. No public text states a figure of one as a property of
the relay, and none compares it with another implementation's.
- **D9. Coding for machines is registered as two candidates with no probe, and its split of
work is receipted by two claims, never one figure.** Decided 2026-11-10. SPEC §5,
*Candidate capabilities*; format-probes §19; task-fidelity §5; machine-descriptors.
- **What was read.** The committee's public project pages for MPEG-AI Part 2 (video coding
for machines, ISO/IEC 23888-2) and Part 4 (feature coding for machines, ISO/IEC 23888-4),
as served on 2026-11-10. Each states its objectives, gives its first edition a publication
year of 0 and the status `ongoing`, and lists as documents only the common test conditions
of each meeting (for Part 4, the common test and training conditions).
- **What was not readable.** The text of either part, at any stage: neither project page links a
draft, and the ISO catalogue's search page answered the fetch with 403, so its entries for
the standard were not read. No
stage (committee draft, draft international standard) is stated on the pages read, so the
specification states none.
- **What follows for the registry.** Both are candidates: a registered string with no pinned
payload format, never emitted and never dispatched. Neither has a probe. A probe is written
from a text that says how a payload begins and where its parameters lie, and none read says
either; a probe from a draft's software would pin a bitstream the next meeting may change.
Their licence class is `patent-pool`, provisional, as for every candidate whose royalty
terms no text states, and that is a registry class, not a reading of any patent.
- **What follows for claims.** A candidate is registered for what its bitstream and records
are. No benchmark was run and no task accuracy is claimed for either format: a claim about
a task's result is a task-fidelity claim, with its model, test, tolerance and observation,
made by whoever ran the test.
- **The split of work.** Feature coding puts part of a network on each side of the wire, so
one figure for "producing the object" would name a producer that does not exist. Each side
signs its own half, with its own meter's class or none. A verifier adds two figures only
when they are of one acquisition class, gives no total across classes, and lists an
unmetered side as unmetered. The halves are shown to belong together by a digest over the
cut and both parameter sets that each half must restate, not by either party's word about
the other.
- **Descriptors.** A machine's labels, regions and embeddings are a signed statement by the
machine that a named model gave them for a named object. They are carried on the existing
`meta` event rather than a new kind, so no event reader, relay or policy record changes; an
embedding is named by digest and its vector is not carried in the event.
- **D10. SCTE 224 is imported from its schema and a public practice; what its clauses alone
define is refused, never guessed.** Decided 2026-11-10. audience-decision §10.
- Read: the XML schema `scte_224_20211011.xsd` of ANSI/SCTE 224 2021, as the schema
documentation of the EPG Linear Schedule Data specification reproduces it, and *Blackouts and
Airing Substitution, Encoding Best Practice* (BP-EPG-BLK v1.0 draft, 1 October 2026), CC BY
4.0. The standard's own text was requested from its publisher's site on 10 November 2026 and
refused to an unattended client, so its clauses were not read.
- So the import binds what those two fix: the elements and their order, `match`'s three
values, time-matched media points, `Apply`'s duration, `Remove` by reference, the audience
and action namespaces, `audience:Zip`, and the blackout value of `action:Content`. Anything
else a document uses (`MatchSignal`, the eligibility window, `priority`, `matchOffset`,
`order`, `reusable`, `source`, an audience of `ALL` over several members, re-application) is
refused `scte224_not_carried`, with no meaning given to it.
- No audience property the public texts fix maps exactly onto a region code: a postal code is
not one and lies in none. A blackout's regions are therefore carried in a property of WAI's
own namespace, in the place the schema gives to properties of another namespace, and
`audience:Zip` and an excluded audience (`NONE`) are refused `scte224_audience_unmappable`.
A postal code is never mapped to the region that holds it.
- Open: whether the standard's clauses define a country or subdivision property. If they do,
it is imported once the text is read, beside WAI's own.
- **D11. An ad creative record is checked against a receipt, never in its place; a stitched
track is recomputed.** Decided 2026-11-10. live-ads §13, §14.
- Read: `draft-riedl-moq-ad-creative-signaling-01` and
`draft-englishm-moq-content-stitching-00`, whole, with the first's schema and vectors.
SVTA 2053-1 was not read; the payload is read only as far as the draft states it.
- A record's signer must be the decider and its pod the fill a receipt signs. A record that
names tracking or verification resources is read, and a WAI sink requests none of them:
presentation is stated by a signed claim.
- The content stitching draft defines no format. The composed track is fixed here as a
function of the programme's listing, the schedule and the receipts, changing ingredient
at Group boundaries alone, so that a verifier recomputes it. Nothing is asked of a relay.
- **D12. An edge cache's rules are written as CDNI metadata with one object of WAI's own, and
the open-caching objects follow the IETF drafts.** Decided 2026-11-10. cache-metadata §4,
§6.
- Read: RFC 8006 §3.3, §4.1, §4.2.1, §4.2.2.2, §4.2.6, §4.3.1 to §4.3.3, §4.3.8, §6.5 to §6.7
and §7.3; RFC 8008 §5.1 to §5.4, §5.7 and Appendix B; RFC 9388 §1 and §2;
`draft-ietf-cdni-cache-control-metadata-06` §3; `draft-ietf-cdni-edge-control-metadata-13`
§4. The Streaming Video Technology Alliance lists its open-caching configuration interface
as a set of documents on its site; their text could not be retrieved without an account
and was not read. `draft-ietf-cdni-processing-stages-metadata-02` was fetched and is not
relied on.
- RFC 8006 has no metadata for range handling, transformation, request-header variation or a
lifetime, and the cache-control draft covers the lifetime only. So those rules travel in
one GenericMetadata type of WAI's own, `WAI.ByteStore`, marked mandatory to enforce: RFC
8006 §6.6 then has a cache that does not know it serve nothing, which is the safe failure.
The name identifies whose it is, as RFC 8006 §6.5 recommends for a type outside the
registry. It is not registered; registering it is left until a cache implements it.
- The open-caching form writes the drafts' `MI.CachePolicy`, `MI.StaleContentCachePolicy`
and `MI.AllowCompress`, and restates nothing else. If the published interface differs from
the drafts in a member's name or default, the form is revised against the published text
once it has been read; the `cdni` form does not depend on it.
- A reader refuses a configuration that departs from the rules rather than taking the nearest
reading, access-control metadata included, which this revision's form does not carry. A
configuration is an instruction: no sink relies on one, and no record is added for it.