open-standards/wai/ietf/draft-charlot-moq-wai-packaging-00.xml
Transaction Science 0e56b96963
Some checks failed
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 3m1s
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Successful in 4s
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 6s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 5s
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Successful in 1m27s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 6s
joule-code conformance gate / joule-moq-relay, every target (pull_request) Successful in 2m15s
wai cross-architecture byte-equality / does this change touch it (pull_request) Successful in 5s
WAI conformance / does this change touch it (pull_request) Successful in 5s
WAI energy receipts / does this change touch it (pull_request) Successful in 4s
WAI HTTP delivery / WAI HTTP · does this change touch it (pull_request) Successful in 4s
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Has been skipped
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Has been skipped
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Has been skipped
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Has been skipped
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Has been skipped
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Has been skipped
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 5s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 4s
wai-web wasm32 / does this change touch it (pull_request) Successful in 5s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 54s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m51s
wai cross-architecture byte-equality / linux-x86_64 (pull_request) Successful in 31s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m29s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m28s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 32s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 10m0s
wai-pack / wai-pack · linux (pull_request) Successful in 1m31s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 2m36s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 19m4s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 4m3s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 1m58s
wai cross-architecture byte-equality / linux-aarch64 (pull_request) Successful in 40s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 9m28s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 51s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Failing after 4m46s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 23s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 50s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m22s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 8m59s
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Successful in 25s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 9m22s
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Successful in 8s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 19m25s
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Successful in 3m48s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 2m22s
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Successful in 3m9s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 36s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m13s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 16m51s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 4m45s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 1m9s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 27m13s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 50s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 4m43s
wai-pack / wai-pack · macos (pull_request) Successful in 1m7s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 2m4s
wai/ietf: draft-charlot-moq-wai-packaging-00 and a comment on NMSF
The Internet-Draft (xml2rfc v3 source and its text rendering) for WAI as
an MSF packaging: the "wai" and "wai-receipts" packaging values; the
envelope, dispatch with fallback, the parameter-set pin by SHA-256 and the
determinism tiers; catalog fields wai_capabilities, wai_determinism,
wai_priors, the receipts fields and wai_staged; the receipts track (WJR1),
its verification and the WAI_RECEIPT object property; the codecs
parameter; security and IANA considerations (WAI_RECEIPT requested from
the Specification Required range, 0x3A41 meanwhile; no action for the
packaging values; application/wai registered). 36 pages; idnits 3.3.0
reports only the three normative references to Internet-Drafts.

Not submitted, and the NMSF comment is not sent: both are the owner's
decision. Author email is a placeholder until the owner confirms it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 05:19:38 -04:00

1601 lines
85 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!--
Source of draft-charlot-moq-wai-packaging-00, in xml2rfc v3.
Render: xml2rfc &#45;-text &#45;-html draft-charlot-moq-wai-packaging-00.xml
Status: NOT submitted. Submission is the owner's decision.
Author contact: the email address is a placeholder until the owner confirms it at
submission.
-->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
version="3"
category="info"
docName="draft-charlot-moq-wai-packaging-00"
ipr="trust200902"
submissionType="IETF"
tocInclude="true"
tocDepth="3"
sortRefs="true"
symRefs="true">
<front>
<title abbrev="WAI Packaging for MSF">WAI Packaging for the MOQT Streaming Format</title>
<seriesInfo name="Internet-Draft" value="draft-charlot-moq-wai-packaging-00"/>
<author fullname="David Charlot" initials="D." surname="Charlot">
<organization>Transaction Science</organization>
<address>
<email>TBD (owner confirms at submission)</email>
</address>
</author>
<date year="2026" month="October" day="21"/>
<area>Web and Internet Transport</area>
<workgroup>Media Over QUIC</workgroup>
<keyword>MoQ</keyword>
<keyword>MSF</keyword>
<keyword>packaging</keyword>
<keyword>receipts</keyword>
<keyword>learned codecs</keyword>
<abstract>
<t>This document specifies how WAI envelopes are carried as a packaging of
the MOQT Streaming Format (MSF) over Media over QUIC Transport (MOQT). A WAI
envelope names the decoding capability its payload needs and a fallback, and
can name, by SHA-256 digest, the parameter set a learned decoder must hold
to decode it. This document defines the MSF packaging value "wai", in which
every MOQT object is exactly one WAI envelope. It defines track-level catalog
fields that declare a track's capabilities, the parameter sets its objects
pin, by digest, and the reproducibility tier of each. It defines a staged
form in which a base and its refinement layers travel on separate tracks. It
defines a receipts track that carries an Ed25519-signed Merkle commitment to
each MOQT group's objects, and an object property that carries an object's
receipt commitment. It also registers the media type application/wai.</t>
</abstract>
<note removeInRFC="true">
<name>About This Document</name>
<t>The source of this document is kept with the WAI specification it
draws on, in the directory wai/ietf of
<eref target="https://git.transaction.science/Transaction-Science/open-standards"/>.
The WAI extension texts it restates are cited as informative references
in <xref target="correspondence"/>.</t>
</note>
</front>
<middle>
<section anchor="intro">
<name>Introduction</name>
<t>MOQT <xref target="MOQT"/> moves objects, in groups, on tracks, and
orders them by priority; it does not say what an object means. MSF
<xref target="MSF"/> says what objects mean: its catalog names, for each
track, a "packaging" that fixes how the track's objects are encapsulated,
and a sibling document can add a packaging value together with the
catalog fields it needs <xref target="CMSF"/>.</t>
<t>WAI <xref target="WAI"/> is a container and capability-dispatch format.
A WAI envelope carries a manifest and a payload. The manifest names the
capability a receiver needs to decode the payload, a fallback capability
for a receiver that lacks it, and, for a capability that decodes against a
parameter set (for example the weights of a learned decoder), a pin: the
SHA-256 digest of that set. A receiver that cannot verify the pin does not
decode the payload against another set. WAI defines no transport.</t>
<t>This document defines how WAI envelopes are carried as MSF objects. Its
aims are:</t>
<ul>
<li>A receiver can decide before it subscribes whether it can decode a
track: which capabilities the track's objects use, which parameter sets
they pin, by digest, and which reproducibility tier each is offered at
(<xref target="catalog"/>).</li>
<li>A receiver can establish that each object it received is the one the
publisher's key committed to, at that MOQT group and object, and can
account for an object it did not receive (<xref target="receipts"/>).</li>
<li>A relay needs no knowledge of WAI. Every rule here uses MOQT's own
objects, groups, priorities, properties and delivery timeouts, and a
relay treats every payload as opaque, as <xref target="MOQT" section="7.8"/>
requires.</li>
</ul>
<t>This document changes nothing in MOQT or MSF. It defines no transport
and no codec.</t>
</section>
<section anchor="conventions">
<name>Conventions and Definitions</name>
<t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>",
"<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>",
"<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are
to be interpreted as described in BCP 14 <xref target="RFC2119"/>
<xref target="RFC8174"/> when, and only when, they appear in all capitals,
as shown here.</t>
<t>Section numbers of <xref target="MOQT"/> and <xref target="MSF"/> are
those of the revisions referenced. Where a later revision of either moves
or changes what is cited, that revision governs and the citation is what
changes.</t>
<dl newline="false" spacing="normal">
<dt>Envelope:</dt>
<dd>A WAI container in the form of <xref target="layout"/>, beginning
with the four bytes "WAI1".</dd>
<dt>Capability:</dt>
<dd>A string naming how a payload is decoded, such as
"wai.image.png" or "wai.neural.int_hyper". Capabilities are registered
by <xref target="WAI"/>, Section 5.</dd>
<dt>Parameter set:</dt>
<dd>Every byte, other than the payload, that a capability's decode reads
and that its output depends on: networks, entropy tables, normative
constants. A receiver holds it; an envelope never carries it.</dd>
<dt>Pin:</dt>
<dd>A manifest member that names a parameter set by the SHA-256 digest
of its bytes (<xref target="pins"/>).</dd>
<dt>Tier:</dt>
<dd>A reproducibility guarantee of a decode
(<xref target="tiers"/>).</dd>
<dt>Publisher, receiver, relay:</dt>
<dd>The MOQT original publisher of a track; an endpoint that subscribes
to a track and decodes its objects; and an MOQT relay.</dd>
<dt>Stage set:</dt>
<dd>A base and the refinement layers that improve it, delivered as
staged delivery (<xref target="staged"/>).</dd>
<dt>Link hash:</dt>
<dd>The identity of a group receipt (<xref target="link"/>).</dd>
</dl>
<t>In byte layouts, "||" is concatenation; u8, u32_be and u64_be are
unsigned integers of 1, 4 and 8 bytes in network byte order; u32_le is a
4-byte unsigned integer in little-endian order; a string is u32_be(length)
|| its UTF-8 bytes; and a quoted domain string such as
"moq-jwp:object\x01" is its ASCII bytes followed by the single byte that
\x01 denotes. BLAKE3 is the 32-byte output of the BLAKE3 hash
<xref target="BLAKE3"/>, and SHA-256 is that of <xref target="SHS"/>.
Digests written in JSON are 64 lowercase hexadecimal digits.</t>
</section>
<section anchor="msf-extension">
<name>MSF Extension</name>
<t>All of the specifications, requirements and terminology defined in
<xref target="MSF"/> apply to implementations of this extension unless
explicitly noted otherwise in this document. Tracks of the packaging
defined here can share a catalog, and a render group, with tracks of
any other packaging.</t>
</section>
<section anchor="envelope">
<name>The WAI Envelope</name>
<section anchor="layout">
<name>Layout</name>
<artwork><![CDATA[
+--------+---------+---------------+-------------+---------+
| "WAI1" | man_len | manifest | payload_len | payload |
| 4 B | u32_le | man_len bytes | u32_le | |
+--------+---------+---------------+-------------+---------+
]]></artwork>
<ul>
<li>A reader <bcp14>MUST</bcp14> refuse bytes whose first four are
not "WAI1" (0x57 0x41 0x49 0x31).</li>
<li>The manifest is a JSON object <xref target="RFC8259"/> in UTF-8,
serialized with no insignificant whitespace. No member name occurs
twice in one object, at any depth. A member that must be an integer is
written as one: digits, with a minus sign only before a non-zero value,
and no fraction or exponent.</li>
<li>The payload's interpretation is fixed by the capability that
decodes it (<xref target="dispatch"/>) and, for a capability that
decodes against a parameter set, by that set.</li>
<li>A reader <bcp14>MUST NOT</bcp14> refuse a manifest for its size
while it is at most 2^27 bytes long, nests arrays and objects at most
127 deep (the manifest object counting as one), and holds at most 2^22
JSON values. It <bcp14>MAY</bcp14> refuse a larger one, from man_len
alone for its length, before it reads it.</li>
</ul>
<t><xref target="WAI"/> Section 7.1 also defines a multi-rendition
container, "WAI2". This document carries "WAI1" envelopes only.</t>
</section>
<section anchor="manifest">
<name>Manifest</name>
<t>The members this document reads are:</t>
<dl newline="true" spacing="normal">
<dt>wai:</dt>
<dd>The version, "1.0". A reader refuses an unknown major version and
accepts an unknown minor one. A reader ignores a member it does not
understand.</dd>
<dt>model_requirement.capability:</dt>
<dd>The capability that decodes the payload.</dd>
<dt>model_requirement.fallback:</dt>
<dd>A capability a receiver <bcp14>MAY</bcp14> decode the payload with
if it lacks the first, or if the pin does not resolve for the first;
or null, in which case the envelope is inert without the first.</dd>
<dt>conditioning.prior:</dt>
<dd><bcp14>OPTIONAL</bcp14>. The pin (<xref target="pins"/>) of the parameter set the
payload was coded against. It applies to whichever of the capability
and the fallback decodes the payload.</dd>
<dt>intent:</dt>
<dd>"replicate" states that every conforming receiver reconstructs the
source as the capability's tier promises (<xref target="tiers"/>).</dd>
<dt>refines:</dt>
<dd>Present exactly when the capability is refinement-only: what the
payload refines (<xref target="staged"/>).</dd>
<dt>security:</dt>
<dd><bcp14>OPTIONAL</bcp14>. Whether the payload is encrypted, as
<xref target="WAI"/> Section 6 defines. The capability and the pin
always describe the plaintext.</dd>
</dl>
</section>
<section anchor="dispatch">
<name>Capability Dispatch</name>
<t>A receiver dispatches an envelope as follows:</t>
<ol>
<li>If the major version in "wai" is unknown, refuse the envelope.</li>
<li>Let cap be the capability. If the receiver can decode cap, cap is
dispatchable, and either no pin applies to cap or the pin resolves for
cap (<xref target="pins"/>), decode the payload with cap, against the
verified parameter set, and stop. A pin that does not resolve makes
cap unsupported for this envelope; keep its reason.</li>
<li>Otherwise, if the fallback is not null and step 2's conditions hold
for it, decode with the fallback and stop; keep a pin's reason if it
does not resolve.</li>
<li>Otherwise the envelope is inert at this receiver. Report the reason
kept at step 2, else the one kept at step 3, else
"missing_capability".</li>
</ol>
<t>A capability is dispatchable unless <xref target="WAI"/> Section 4
registers it as something a receiver does not decode on its own: a
candidate, a companion-only, a refinement-only, a record or a derivation
string. A string <xref target="WAI"/> does not register is dispatchable
by a receiver that has a decoder for it. A pin that does not resolve is
never a reason to decode against another parameter set: a learned
decode against the wrong parameters yields plausible output, not an
error.</t>
</section>
<section anchor="pins">
<name>Parameter-Set Pins</name>
<t>A pin is a JSON object:</t>
<table>
<name>Pin Members</name>
<thead>
<tr><th>Member</th><th>Presence</th><th>Meaning</th></tr>
</thead>
<tbody>
<tr><td>id</td><td><bcp14>REQUIRED</bcp14>, string</td><td>A name for people. A
receiver <bcp14>MUST NOT</bcp14> select or accept a parameter set by
it.</td></tr>
<tr><td>sha256</td><td><bcp14>REQUIRED</bcp14>, string</td><td>The SHA-256 of the
parameter set in its form, as 64 lowercase hexadecimal
digits.</td></tr>
<tr><td>determinism</td><td><bcp14>REQUIRED</bcp14>, string</td><td>How the decode is
made reproducible, in words.</td></tr>
<tr><td>form</td><td><bcp14>OPTIONAL</bcp14>, string</td><td>The form the digest is
computed over (below).</td></tr>
<tr><td>tier</td><td><bcp14>OPTIONAL</bcp14>, string</td><td>The tier the sender
claims: "decode-equivalence", "entropy-consistency" or
"none".</td></tr>
</tbody>
</table>
<t>A member of a pin with another JSON type makes the manifest
malformed. A null optional member is an absent one.</t>
<t>With form absent, sha256 is the SHA-256 of the one file that holds
the set; that is admissible only for a capability <xref target="WAI"/>
registers with a one-file set. With form "wai.prior.set", sha256 is the
SHA-256 of the set's listing. The listing has one line per file: the
file's SHA-256 as 64 lowercase hexadecimal digits, two spaces, the
file's path below the set's root, and a line feed. A path is one or more
segments joined by "/"; a segment begins with one of A-Z, a-z, 0-9, "_"
and "-", continues with those and ".", and does not end with ".". Lines
are in strictly ascending order of their paths as byte strings; no two
paths are equal once A-Z are mapped to a-z, and no path followed by "/"
begins another. The listing has at least one line and nothing else.
<xref target="WAI-PRIOR"/> registers further forms.</t>
<t>A receiver that is to decode through a capability to which a pin
applies <bcp14>MUST</bcp14> verify the pin first. The pin resolves when
the receiver holds a parameter set whose digest, in the pin's form,
equals sha256: for "wai.prior.set", a listing with that digest together
with every file it names, each with the digest its line gives. Nothing
else satisfies a pin: not a matching id, and not a set in another form
whose unpacked parameters compare equal. A pin that does not resolve is
refused with the first of these reasons that applies:</t>
<ol>
<li>"pin_malformed": sha256 is not 64 lowercase hexadecimal
digits.</li>
<li>"form_not_registered": form names no registered form.</li>
<li>"form_unreadable": the receiver has no reader for the form.</li>
<li>"form_required": form is absent and the capability is not
registered with a one-file set.</li>
<li>"prior_revoked" or "prior_not_authorised": the receiver holds a key
log and refuses the set under it, as <xref target="WAI"/> Section 3.1
specifies. A receiver that holds no key log skips this check.</li>
<li>"prior_not_held": the receiver holds no set with that digest
("digest_superseded" where it holds the set that the pin's optional
supersedes member names).</li>
<li>"set_malformed": the listing breaks a rule above.</li>
<li>"part_mismatch": a file the listing names is missing, unreadable,
or has another digest.</li>
</ol>
<t>A pinned decode <bcp14>MUST</bcp14> read its parameters only from the
set it verified; a decode that needs a file the set lacks is refused
("set_incomplete") and is treated as a pin that did not resolve. A
refused pin makes its capability unsupported for that envelope; it is
not a reason to decode anyway.</t>
</section>
<section anchor="tiers">
<name>Determinism Tiers</name>
<t>A learned decode evaluated in floating point does not in general
reproduce its output across devices. WAI names two reproducibility
guarantees <xref target="WAI-TIERS"/>:</t>
<dl newline="true" spacing="normal">
<dt>entropy-consistency:</dt>
<dd>The entropy decode reproduces byte for byte on every conforming
receiver: the decoded symbols have a portable hash. The reconstruction
to the final medium can differ between conforming receivers.</dd>
<dt>decode-equivalence:</dt>
<dd>The whole decode, to the final medium, reproduces byte for byte on
every conforming receiver: the reconstructed samples have a portable
hash. The capability's registration specifies the decode in integer or
fixed-point arithmetic, entropy stage and synthesis alike.</dd>
</dl>
<t>"none" claims neither. The tiers are ordered none &lt;
entropy-consistency &lt; decode-equivalence. A tier is a property of a
capability as registered: <xref target="WAI"/> gives each capability a
registry class, and the class gives the tier. A pin's tier above its
capability's does not conform ("tier_exceeds_class"), and a receiver
<bcp14>MUST NOT</bcp14> rely on it. A receiver reads a tier token it
does not recognize as "none".</t>
<t>An envelope with intent "replicate" over a learned capability
<bcp14>MUST</bcp14> be over a capability registered at
decode-equivalence, with a pin that declares decode-equivalence;
entropy-consistency <bcp14>MUST NOT</bcp14> back "replicate". A tier
covers the medium a receiver emits: a receiver that alters the decoded
medium (for example with a post-decode filter) <bcp14>MUST NOT</bcp14>
claim the tier for the result.</t>
<t>At the time of writing, <xref target="WAI"/> registers
"wai.neural.int_synth", "wai.neural.int_hyper", "wai.video.int_hyper",
"wai.audio.int_codec", "wai.splat.int_codec" and "wai.neural.int_mlicpp"
at decode-equivalence, and "wai.image.jpegai" at entropy-consistency.
This list is informative; the registry governs.</t>
</section>
</section>
<section anchor="catalog">
<name>Catalog</name>
<section anchor="packaging">
<name>Packaging Values</name>
<t>This specification extends the allowed packaging values defined in
<xref target="MSF" section="5.2.4"/> with two entries:</t>
<table>
<name>Packaging Values</name>
<thead>
<tr><th>Name</th><th>Value</th><th>Reference</th></tr>
</thead>
<tbody>
<tr><td>WAI</td><td>wai</td><td>This document</td></tr>
<tr><td>WAI receipts</td><td>wai-receipts</td><td><xref target="receipts-track"/></td></tr>
</tbody>
</table>
<t>Every track whose objects are WAI envelopes <bcp14>MUST</bcp14>
declare packaging "wai". On such a track:</t>
<ul>
<li>every object <bcp14>MUST</bcp14> be exactly one whole envelope. An
object that holds part of an envelope, or more than one, is not this
packaging;</li>
<li>the object boundary <bcp14>MUST</bcp14> be the envelope boundary, so
that the receipt's commitment to an object (<xref target="receipts"/>)
and MOQT's object identity are the same unit;</li>
<li>a receiver that does not recognize the packaging value "wai"
<bcp14>MUST NOT</bcp14> attempt to interpret the objects. MSF's rule
that a parser ignores fields it does not understand covers unknown
fields, not unknown packaging values.</li>
</ul>
</section>
<section anchor="fields">
<name>Track Fields</name>
<t>This specification adds the following track-level catalog fields for
tracks with packaging "wai". They are custom fields under
<xref target="MSF" section="5"/>; their "wai_" prefix keeps them from
colliding with fields MSF defines.</t>
<table>
<name>Track Fields</name>
<thead>
<tr><th>Field</th><th>Name</th><th>Required</th><th>JSON Type</th><th>Definition</th></tr>
</thead>
<tbody>
<tr><td>Capabilities</td><td>wai_capabilities</td><td>Yes</td><td>Array of String</td><td><xref target="f-caps"/></td></tr>
<tr><td>Determinism</td><td>wai_determinism</td><td>No</td><td>String</td><td><xref target="f-det"/></td></tr>
<tr><td>Pinned parameter sets</td><td>wai_priors</td><td>No</td><td>Array of Object</td><td><xref target="priors"/></td></tr>
<tr><td>Receipts</td><td>wai_receipts</td><td>Yes</td><td>Boolean</td><td><xref target="f-receipts"/></td></tr>
<tr><td>Receipt alias</td><td>wai_receipt_alias</td><td>Cond.</td><td>Number</td><td><xref target="f-receipts"/></td></tr>
<tr><td>Receipts track</td><td>wai_receipts_track</td><td>Cond.</td><td>String</td><td><xref target="f-receipts"/></td></tr>
<tr><td>Stage</td><td>wai_staged</td><td>Cond.</td><td>Object</td><td><xref target="staged"/></td></tr>
</tbody>
</table>
<section anchor="f-caps">
<name>Capabilities</name>
<t>wai_capabilities lists every capability that an object on the track
names as its capability or as its fallback. The list
<bcp14>MUST</bcp14> be exhaustive for the track: its purpose is to let a
receiver decide before subscribing whether it can decode what it is
about to receive. A receiver <bcp14>MUST NOT</bcp14> subscribe on the
assumption that an undeclared capability will not appear. A receiver
<bcp14>MUST</bcp14> treat an object whose envelope names, as the
capability it is about to dispatch to, a capability the list does not
hold as a protocol error, and <bcp14>MUST NOT</bcp14> fall back
silently.</t>
</section>
<section anchor="f-det">
<name>Determinism</name>
<t>wai_determinism is the weakest tier (<xref target="tiers"/>) that any
object on the track claims, not the strongest. Absent means no tier is
claimed. A receiver reads a value it does not recognize as "none". The
field helps a receiver choose a track; the tier a receiver claims for
an object is the one its own decode earns.</t>
</section>
<section anchor="f-receipts">
<name>Receipts Fields</name>
<dl newline="true" spacing="normal">
<dt>wai_receipts:</dt>
<dd>Whether the track's objects are covered by receipts
(<xref target="receipts"/>). A receiver reads an absent value as
false.</dd>
<dt>wai_receipt_alias:</dt>
<dd>An integer from 0 to 2^53-1, written as an integer: the
track_alias that the track's receipts sign
(<xref target="signature"/>). MOQT's own Track Alias is chosen per
session, by each hop (<xref target="MOQT" section="3.1.3"/>), so past
the first hop it is not the number the receipts sign. Two tracks of a
catalog <bcp14>MUST NOT</bcp14> carry the same value.</dd>
<dt>wai_receipts_track:</dt>
<dd>The name, in this track's namespace, of the track of packaging
"wai-receipts" that carries this track's receipts
(<xref target="receipts-track"/>). Two tracks of a catalog
<bcp14>MUST NOT</bcp14> name the same receipts track.</dd>
</dl>
<t>A track of a stage set that declares wai_receipts true
<bcp14>MUST</bcp14> carry wai_receipt_alias and wai_receipts_track
(<xref target="staged"/>). On another track both are
<bcp14>OPTIONAL</bcp14>; a receiver finds a track's receipts chain
and receipts track by them. A clone
(<xref target="MSF" section="5.1.6"/>) inherits every field of its
parent but its name, so a clone of a track that declares receipts
<bcp14>MUST</bcp14> override both.</t>
</section>
</section>
<section anchor="priors">
<name>Pinned Parameter Sets</name>
<t>A track <bcp14>MAY</bcp14> state, in wai_priors, the pins its objects
carry. A receiver can then tell before it subscribes whether it holds
the parameter sets the track needs, and at which tier each is
offered.</t>
<sourcecode type="json"><![CDATA[
"wai_priors": [
{ "capability": "wai.neural.int_hyper",
"sha256": "<64 lowercase hexadecimal digits>",
"form": "wai.prior.set",
"tier": "decode-equivalence" }
]
]]></sourcecode>
<table>
<name>Members of a wai_priors Entry</name>
<thead>
<tr><th>Member</th><th>Presence</th><th>Meaning</th></tr>
</thead>
<tbody>
<tr><td>capability</td><td><bcp14>REQUIRED</bcp14>, string</td><td>A capability the
track's wai_capabilities lists.</td></tr>
<tr><td>sha256</td><td><bcp14>REQUIRED</bcp14>, string</td><td>A pin's sha256: 64
lowercase hexadecimal digits.</td></tr>
<tr><td>form</td><td><bcp14>OPTIONAL</bcp14>, string</td><td>The pin's form. Absent,
or null, where the pin declares none.</td></tr>
<tr><td>tier</td><td><bcp14>OPTIONAL</bcp14>, string</td><td>The tier the publisher
offers the set at. Advisory.</td></tr>
</tbody>
</table>
<t>An entry lists a pin for a capability when its capability is that
capability, its sha256 is the pin's, and its form is the pin's (both
absent, or the same string). A member of an entry that this document does
not define is ignored.</t>
<dl newline="true" spacing="normal">
<dt>Reading.</dt>
<dd>wai_priors, where present and not null, is an array of objects,
each with the members above of their types, each capability one that
the track's wai_capabilities lists, and no two with the same
capability, sha256 and form. A receiver that reads anything else
refuses the track ("catalog_priors_malformed") and does not subscribe
to it. A tier this document does not define is read as "none".</dd>
<dt>Exhaustive.</dt>
<dd>
<t>Where a track carries wai_priors, the publisher
<bcp14>MUST</bcp14> list in it every pin that its objects carry. An
object breaks the catalog when:</t>
<ol>
<li>it carries a pin that no entry lists for its capability or for
its fallback; or</li>
<li>an entry names its capability, or its fallback (when not null),
and the object carries no pin, or carries a pin that no entry lists
for that capability.</li>
</ol>
<t>A publisher whose objects' pin can decode through the fallback
<bcp14>SHOULD</bcp14> list the set for the fallback as well.</t>
</dd>
<dt>Mismatch.</dt>
<dd>A receiver checks each object of such a track against the track's
wai_priors before it dispatches the object. An object that breaks the
catalog is refused ("catalog_prior_mismatch"), and the track is refused
with it: the receiver dispatches no further object of the track, and
<bcp14>MAY</bcp14> unsubscribe from it. The catalog never stands in for
the envelope. A receiver verifies an object's pin
(<xref target="pins"/>) whether or not the catalog lists it; an entry
never satisfies a pin, never supplies a pin the envelope lacks, and
never changes which set a decode reads.</dd>
<dt>Tier.</dt>
<dd>A listed tier is advisory. A publisher <bcp14>MUST NOT</bcp14> list
a tier above the one the capability's registry class gives. A receiver
<bcp14>MUST NOT</bcp14> claim a tier on the strength of a listed tier:
the tier it claims for an object is the one its own decode earns
(<xref target="tiers"/>). A listed tier that differs from the tier an
object's pin states is not a mismatch.</dd>
</dl>
</section>
<section anchor="staged">
<name>Staged Tracks</name>
<t>WAI's staged delivery <xref target="WAI-STAGED"/> sends a base first
and refinement layers after it; a receiver presents the base, and
applies each layer that arrives in time. Each layer is a WAI envelope
whose capability is refinement-only and whose manifest names, in
refines, what it refines. A stage set is carried as one track per
layer: a base track, which carries the set's bases, and a layer track
for each layer index k, which carries the layers of index k. A receiver
chooses its stage by the tracks it subscribes to; a relay forwards
tracks and never reads an envelope.</t>
<t>Each track of a set <bcp14>MUST</bcp14> carry, in its catalog entry, a
wai_staged object:</t>
<sourcecode type="json"><![CDATA[
"wai_staged": { "set": "cam1", "layer": 1, "lead_ms": 40 }
]]></sourcecode>
<dl newline="true" spacing="normal">
<dt>set:</dt>
<dd>A non-empty string, the same on every track of the set.</dd>
<dt>layer:</dt>
<dd>An integer from 0 to 255: 0 on a base track, k on a track that
carries layer k.</dd>
<dt>lead_ms:</dt>
<dd>On a layer track of a live set, an integer from 0 to 2^53-1: the
time before a unit's presentation by which the layer must arrive to be
applied to it. null on a base track. A receiver ignores it when isLive
is false.</dd>
</dl>
<t>A set's extent is the tracks present: layers 0 to the highest layer a
track of the set states. More than one track <bcp14>MAY</bcp14> carry one
layer, as renditions of it, each with a receipts chain of its own. A
publisher puts on a track of layer k only envelopes whose refines.layer
is k, and on a base track only envelopes with no refines; a receiver
applies a layer by its own refines, whichever track it came on. A layer
track's wai_capabilities lists refinement capabilities, so a receiver
that does not implement staged delivery finds them unsupported and has
no reason to subscribe.</t>
<t>The tracks of a set <bcp14>MUST</bcp14> share one namespace, one
isLive (<xref target="MSF" section="5.2.7"/>) and one renderGroup
(<xref target="MSF" section="5.2.11"/>), present on each and written as
an integer. Every entry of a track's depends
(<xref target="MSF" section="5.2.14"/>) <bcp14>MUST</bcp14> name a track
of the catalog in the track's namespace; the depends of a track of layer
k <bcp14>MUST</bcp14> name at least one track of the set at each layer
below k and none at k or above, and a base track's <bcp14>MUST
NOT</bcp14> name a track of the set. A layer track <bcp14>MUST
NOT</bcp14> carry altGroup, temporalId or spatialId
(<xref target="MSF" section="5.2.12"/>, <xref target="MSF" section="5.2.16"/>,
<xref target="MSF" section="5.2.17"/>); an altGroup <bcp14>MAY</bcp14>
group the base tracks of alternative sets. Every track of a set that
declares wai_receipts true carries its own wai_receipt_alias and
receipts track (<xref target="f-receipts"/>).</t>
<t>A receiver checks each set's entries in this order, stops at the
first check that fails, and treats the layer tracks of a set that fails
as absent (its base tracks remain tracks of packaging "wai"):</t>
<ol>
<li>wai_staged has its three members, of their types and ranges;
packaging is "wai"; isLive is a boolean; the track's name is a string
and its namespace absent or a string, and no other track has that
namespace and name; renderGroup, if present, is an integer below 2^64;
depends, if present, is an array of strings
("staged-malformed").</li>
<li>The set has a track at each layer from 0 to its highest
("staged-set-incomplete").</li>
<li>The depends rules above hold ("staged-depends").</li>
<li>The tracks share one namespace, one isLive and one renderGroup,
present on each, and no layer track carries altGroup, temporalId or
spatialId ("staged-grouping").</li>
<li>On a live set, lead_ms is an integer on every layer track and null
on every base track ("staged-lead").</li>
<li>Every wai_receipt_alias of the catalog is an integer from 0 to
2^53-1; each track of the set that declares receipts carries an alias
and names a receipts track of packaging "wai-receipts" in its
namespace; and no other track carries that alias or names that
receipts track ("staged-receipts").</li>
</ol>
<t>A track that declares no namespace inherits the catalog track's
(<xref target="MSF" section="5.2.2"/>). A checker that does not know the
catalog track's namespace refuses a set that mixes declared and
inherited namespaces ("staged-malformed").</t>
<t>Groups and objects. On a live track each group <bcp14>MUST</bcp14>
carry exactly one object, which travels in a subgroup of its own
(<xref target="MOQT" section="2.2"/>). A group of one object is complete
when its object is, so its group receipt is signed before the object is
sent. Group and object identifiers of different tracks need not align:
refines names what a layer refines.</t>
<t>Priority. The base track's publisher priority
(<xref target="MOQT" section="5.1"/>) <bcp14>MUST</bcp14> be strictly
below every layer track's, and the priority of a track of layer k
<bcp14>MUST</bcp14> be no greater than that of any track of a layer above
k. This holds for each track's DEFAULT_PUBLISHER_PRIORITY
(<xref target="MOQT" section="10.4"/>) and for every subgroup that sets
its own. A receipts track's priority is its media track's. A subscriber
that wants the publisher's order <bcp14>SHOULD</bcp14> give its requests
for a set's tracks one subscriber priority.</t>
<t>Delivery timeouts. A publisher <bcp14>SHOULD</bcp14> set a live layer
object's OBJECT_DELIVERY_TIMEOUT (<xref target="MOQT" section="5.2"/>) to
no more than its slack: the time from publication to the presentation of
the last unit the object covers, less the layer's lead_ms, less the
publisher's estimate of the path. An object whose slack is zero or less
cannot arrive in time, and the publisher <bcp14>MAY</bcp14> withhold it.
A publisher <bcp14>MUST NOT</bcp14> set on a base track a delivery
timeout of either kind shorter than the time from a base's publication
to the presentation of its last unit. A delivery timeout releases
bandwidth hop by hop; it is not an end-to-end deadline, and whether a
layer is late is decided by the receiver, as
<xref target="WAI-STAGED"/> specifies.</t>
<t>Capping. A receiver caps its stage by subscribing to the base tracks,
to the tracks of layers 1 to n, and to their receipts tracks, and to no
others. A relay <bcp14>MUST NOT</bcp14> read an envelope to cap
layers.</t>
</section>
</section>
<section anchor="receipts">
<name>Receipts</name>
<section anchor="receipts-overview">
<name>Overview</name>
<t>A publisher that declares wai_receipts true commits to every object of
a track, group by group. For each MOQT group it computes each object's
content hash, builds a Merkle tree over them, and signs the root and the
group's metadata with its Ed25519 key <xref target="RFC8032"/>: the
group receipt. Each object has an object receipt that carries its
Merkle inclusion proof. Group receipts form a chain for each publisher
key and receipt alias: each names the link hash of the one before. The
receipts of group g travel as one object in group g of the track's
receipts track (<xref target="receipts-track"/>), so that a receiver can
verify the tracks it subscribes to without the receipts of others, and
can account for an object it did not receive.</t>
<t>The rules here are those of <xref target="WAI-JWP"/> for the binary
form that this carriage uses. That document also defines a JSON form,
signed claims and key discovery, which this document does not
need.</t>
</section>
<section anchor="content-hash">
<name>Content Hash</name>
<artwork><![CDATA[
content_hash = BLAKE3("moq-jwp:object\x01" || envelope)
]]></artwork>
<t>envelope is the object's payload: the whole envelope, from "WAI1" to
the last payload byte, with nothing inserted or reframed.</t>
</section>
<section anchor="merkle">
<name>Merkle Tree</name>
<t>A group's objects are its leaves, in MOQT Object ID order, starting
at 0. An object's leaf takes the first form below when its receipt
carries no energy label, and the second when it does
(<xref target="energy-class"/>):</t>
<artwork><![CDATA[
leaf_v1 = BLAKE3("moq-jwp:merkle-leaf\x01" || content_hash)
leaf_v2 = BLAKE3("moq-jwp:merkle-leaf\x02" || content_hash
|| u64_be(joules_micro) || class
|| u32_be(len(origin)) || origin)
node = BLAKE3("moq-jwp:merkle-node\x01" || left || right)
]]></artwork>
<t>When a level has an odd number of nodes, its last node is duplicated
to make a pair. The root is the single node at the top; the root of an
empty group is 32 zero bytes. Since an object receipt's object_id is
both its MOQT Object ID (<xref target="receipts-track"/>) and its leaf
index (<xref target="verification"/>), a publisher that declares
receipts numbers each group's objects from 0, without gaps. joules_micro is the energy, in
microjoules, that producing the object took, and 0 is the unmetered
marker, never a figure of zero joules. origin is a UTF-8 label of where
the object was produced.</t>
</section>
<section anchor="energy-class">
<name>Energy Class Encoding</name>
<t>An energy figure's acquisition class says how the figure was
obtained <xref target="WAI-ENERGY"/>. Where a receipt signs it, the class
is one tag byte followed by its evidence:</t>
<table>
<name>Acquisition Classes</name>
<thead>
<tr><th>Tag</th><th>Class</th><th>Followed by</th></tr>
</thead>
<tbody>
<tr><td>0</td><td>unmetered</td><td>nothing</td></tr>
<tr><td>1</td><td>HwShunt (legacy)</td><td>nothing</td></tr>
<tr><td>2</td><td>ModelBased</td><td>nothing</td></tr>
<tr><td>3</td><td>Estimator</td><td>nothing</td></tr>
<tr><td>4</td><td>OnChipCounter</td><td>u32_be(relative_ppm) || u64_be(window_us) || u8(filtering: 0 unknown, 1 off, 2 on)</td></tr>
<tr><td>5</td><td>CalibratedInstrument</td><td>u32_be(relative_ppm) || u64_be(window_us) || u32_be(len) || calibration reference, UTF-8</td></tr>
</tbody>
</table>
<t>relative_ppm is the standard relative uncertainty of the figure in
parts per million, and window_us the integration window in
microseconds. A class in a receipt is valid only when: tag 0 stands
beside a zero figure and every other tag beside a non-zero one; tag 1
does not appear (it is accepted only in receipts that predate the
labels); and for tags 4 and 5, relative_ppm and window_us are both
non-zero and figure x relative_ppm is at least 288676, the least
uncertainty a whole number of microjoules can carry. The classes are
ordered, strongest first: CalibratedInstrument, OnChipCounter, HwShunt,
ModelBased, Estimator.</t>
</section>
<section anchor="signature">
<name>Group Signature</name>
<t>The publisher signs, with pure Ed25519 <xref target="RFC8032"/>, one
of two signing payloads:</t>
<artwork><![CDATA[
legacy = "moq-jwp:group-sign\x01"
|| u64_be(track_alias) ; the track's wai_receipt_alias
|| u64_be(group_id) ; the MOQT Group ID
|| merkle_root ; 32 bytes
|| u64_be(leaf_count) ; objects in the group
|| u64_be(total_joules_micro) ; sum over the group's objects
|| string(group_start) ; RFC 3339, first object
|| string(group_end) ; RFC 3339, last object
|| publisher_key ; 32 bytes, Ed25519 public key
|| string(signer_id) ; identity label
labelled = "moq-jwp:group-sign\x02"
|| (the fields of legacy after its domain, in order)
|| class ; the total's class
|| u8(coverage) ; 0 Whole, 1 Partial
|| u8(has_parent) || parent ; 1 and the parent's link hash,
; or 0 and 32 zero bytes
]]></artwork>
<t>group_start and group_end are timestamps of the form of
<xref target="RFC3339"/>. signer_id names the signer; a receiver reads
nothing from it unless it can confirm it by a means outside this
document.</t>
<t>The labelled payload signs the link to the parent group; the legacy
payload does not. A labelled group's class is the one its objects
compose to:</t>
<ul>
<li>if an object with a non-zero figure carries no label, the group
<bcp14>MUST</bcp14> be signed in the legacy form;</li>
<li>if no object has a non-zero figure, the class is tag 0 and the
coverage 0;</li>
<li>otherwise the class is the weakest of the objects' classes among
those with a non-zero figure, and the coverage is 1 exactly when some
object's figure is zero. For a hardware class (tag 4 or 5),
relative_ppm is at least the ceiling of (sum of figure_i x
relative_ppm_i) / (sum of figure_i), and window_us is the longest of
the objects'. A tag-4 total's filtering state is the objects' common
one, or 0. A tag-5 total needs one calibration reference shared by
every object, or the group is signed in the legacy form.</li>
</ul>
<section anchor="link">
<name>Link Hash</name>
<artwork><![CDATA[
canonical_bytes = signing_payload || signature ; 64-byte signature
link_hash = BLAKE3("moq-jwp:receipt-link\x01" || canonical_bytes)
]]></artwork>
<t>signing_payload is the payload of the form the group was signed in.
A group's parent is the link hash of the previous group of its chain,
or none for the first. A legacy group's link hash does not cover its
parent link, which the legacy payload does not sign.</t>
</section>
</section>
<section anchor="binary">
<name>Binary Forms</name>
<artwork><![CDATA[
group_bin = canonical_bytes ; labelled form
| canonical_bytes ; legacy form
|| u8(has_parent) || parent ; parent: 32 bytes
object_body = u64_be(object_id)
|| content_hash ; 32 bytes
|| u64_be(joules_micro)
|| string(origin)
|| u8(n) || sibling x n ; 32 bytes each, leaf up
|| u64_be(direction_bits)
|| u64_be(leaf_index)
|| u8(leaf_version) ; 1 leaf_v1, 2 leaf_v2
|| class ; leaf_version 2 only
receipts_bin = "WJR1"
|| group_bin
|| u32_be(count)
|| object_body x count
]]></artwork>
<t>The first 19 bytes of group_bin, the signing domain, give its form.
Every field's length is known when the bytes are read in order. Bit i
of direction_bits is 1 when the node at level i is the right child. An
object receipt inside receipts_bin takes the group's track_alias and
group_id.</t>
<t>A reader reads exactly the bytes it is given and refuses them as
"malformed" at the first of these that holds: the magic is not "WJR1";
the signing domain is neither of <xref target="signature"/>; the bytes
end before a field, or bytes follow the last object; a string is not
UTF-8; a class tag is not one of <xref target="energy-class"/> or its
evidence does not read; a coverage byte, parent flag or filtering byte
is out of range; a parent flag of 0 is followed by bytes that are not
zero; or leaf_version is neither 1 nor 2. The form is canonical: a
receipt has one binary form, and a writer reproduces the bytes it
read.</t>
</section>
<section anchor="receipts-track">
<name>The Receipts Track</name>
<t>A receipts track has packaging "wai-receipts" and is named by its
media track's wai_receipts_track. Each media track has a receipts track
of its own.</t>
<ul>
<li>Group g of a receipts track carries one object, the receipts_bin of
group g of its media track: its group receipt and object receipts. The
publisher publishes it no later than that group's first object.</li>
<li>A receipt is about one MOQT object. The group receipt in group g of
a receipts track has group_id g; each object receipt in it has that
group_id and, as object_id, the MOQT Object ID of its object; its
publisher_key is the publisher's key and its track_alias the media
track's wai_receipt_alias. A receiver refuses a receipt that breaks this
("moqt_mismatch") before it verifies its signature, and holds nothing
of it.</li>
<li>A receipts track has no delivery timeout of either kind: the
publisher sets none, and a subscriber sets none on its subscription
(<xref target="MOQT" section="9.20.3"/>,
<xref target="MOQT" section="9.20.4"/>). Its publisher priority is its
media track's.</li>
<li>Its objects are receipts, not envelopes; <xref target="packaging"/>'s
object rules do not apply to them.</li>
</ul>
<t>A receiver learns the publisher's key by a means outside this
document: configuration, the session in which it subscribed, or key
discovery as <xref target="WAI-JWP"/> Section 7 specifies.</t>
</section>
<section anchor="verification">
<name>Verification</name>
<t>A receiver verifies each group receipt and each object receipt it
uses in these steps, in order:</t>
<ol>
<li>Read. The receipts_bin reads (<xref target="binary"/>); otherwise
"malformed". A labelled group's class reads and is valid with the
group alone: tag 1 does not appear, tag 0 stands exactly beside a zero
total with coverage 0, and a hardware class meets the floor of
<xref target="energy-class"/>; otherwise "group_label_invalid".</li>
<li>Signature. The publisher key and the signature pass, in order:
the key is the one encoding of its point that
<xref target="RFC8032" section="5.1.3"/> allows; the key's point is not
of small order; S is less than L; R is not of small order; and the
cofactorless equation holds: the point S*B - k*A, with
k = SHA-512(R || A || M) mod L over the bytes of R and A as the
signature and key give them, encodes to R byte for byte. A key that fails one of the first two checks is
"bad_signer_key"; a signature that fails a later one is
"signature_verify_failed". These checks fix what
<xref target="RFC8032"/> leaves to the verifier, so that every
conforming receiver accepts the same signatures. The receiver then
holds a verified root.</li>
<li>Chain. Chains are kept per (publisher key, track_alias). With no
group of the chain held, a group with no parent starts it. A group
whose parent is the head's link hash extends it. A group already
admitted, offered again with the same bytes, passes and changes
nothing. A second group with no parent, or one whose parent is the
link hash of a group of the chain other than its head, is
"chain_break". A group whose parent the receiver does not hold is
"parent_not_held": the receiver <bcp14>MAY</bcp14> hold it while it
recovers the parent, by a FETCH (<xref target="MOQT" section="3.2"/>)
of the receipts track, and <bcp14>MUST NOT</bcp14> accept it until
then. A legacy group whose group_id does not exceed its chain head's
is "group_id_not_increasing".</li>
<li>Content hash. For an object the receiver received, the content
hash of its bytes (<xref target="content-hash"/>) equals the object
receipt's; otherwise "content_hash_mismatch".</li>
<li>Inclusion. A labelled object receipt's class is valid
(<xref target="energy-class"/>); otherwise "object_label_invalid".
leaf_index is below leaf_count, the proof holds exactly
ceil(log2(leaf_count)) siblings (none for one leaf), direction_bits
equals leaf_index, and object_id equals leaf_index; otherwise
"proof_position_mismatch". The object's leaf, in the form its
leaf_version gives, walked up the proof, reaches the verified root;
otherwise "inclusion_proof_failed".</li>
<li>Accept. The object's bytes are bound to the publisher key at
(track_alias, group_id, object_id). Where its leaf is labelled, its
figure, class and origin are bound with them; otherwise they are the
publisher's unsigned statements.</li>
</ol>
<t>A rejection at steps 1 to 5 is a hard failure for the object. A
receiver <bcp14>MUST NOT</bcp14> accept a partial verification, such as
a valid proof against an unverified root.</t>
<t>An object receipt checked by steps 1, 2, 3 and 5 for an object the
receiver did not receive is "inclusion-verified": the publisher signed an
object with that content hash at that position. A receiver
<bcp14>MUST</bcp14> report it as such, and <bcp14>MUST NOT</bcp14>
report it, or anything read from it, as delivered, or dispatch on
it.</t>
<t>A receiver that holds an accepted object receipt for every leaf of a
group <bcp14>MUST</bcp14> check that their figures sum to the group's
total ("group_total_mismatch"), and, for a labelled group, that the
group's class, coverage and uncertainty are those its objects compose to
(<xref target="signature"/>).</t>
<t>Holding and joining. A receiver that holds groups for missing parents
<bcp14>MUST</bcp14> state a finite bound on what it holds: per chain,
and across all its chains, since any key makes a chain. Past the bound
it refuses what it holds ("parent_not_recovered") and re-anchors the
chain at the next validly signed group whose group_id exceeds the
head's. A receiver that subscribes to a live track after its first group
(<xref target="MOQT" section="3.5"/>) anchors each chain at the first
validly signed group it receives. An anchor establishes only that the
key signed that group; a receiver <bcp14>MUST</bcp14> report a chain it
anchored as anchored, with the anchor's group_id, and <bcp14>MUST
NOT</bcp14> report the groups the anchor skipped as verified.
<xref target="WAI-JWP"/> Section 3 specifies how the groups of such a
gap, fetched later, are admitted as history.</t>
</section>
<section anchor="property">
<name>The WAI_RECEIPT Object Property</name>
<t>An object on a track of packaging "wai" <bcp14>MAY</bcp14> carry its
receipt commitment as an MOQT Object Property
(<xref target="MOQT" section="8.4"/>), WAI_RECEIPT. Its value is:</t>
<artwork><![CDATA[
value = content_hash ; 32 bytes
|| vi64(joules_micro)
|| vi64(len) || acquisition ; UTF-8 class name, or empty
|| vi64(len) || acquisition_evidence
|| group_receipt ; 32 bytes
]]></artwork>
<t>vi64 is the variable-length integer of
<xref target="MOQT" section="8.1"/>. acquisition is the class name of
<xref target="energy-class"/> ("ModelBased", "Estimator",
"OnChipCounter", "CalibratedInstrument", or "HwShunt"), or empty;
acquisition_evidence is, for tags 4 and 5, the evidence that follows
the tag byte, and empty otherwise; group_receipt is the link hash of the
group receipt covering the object. The publisher
<bcp14>MUST</bcp14> place the property inside Immutable Properties
(<xref target="MOQT" section="10.7"/>), which no relay may change or
remove.</t>
<ul>
<li>A receiver refuses a value that ends early, has bytes after
group_receipt, or whose acquisition is not UTF-8
("property_invalid").</li>
<li>A non-zero joules_micro <bcp14>MUST</bcp14> be accompanied by
acquisition. A zero joules_micro is the unmetered marker:
acquisition and acquisition_evidence <bcp14>MUST</bcp14> be empty, and
a receiver <bcp14>MUST NOT</bcp14> present it as zero joules.
acquisition_evidence <bcp14>MUST</bcp14> be non-empty for
OnChipCounter and CalibratedInstrument and empty for every other
class. A receiver <bcp14>MUST</bcp14> discard a property that breaks
this item ("property_invalid").</li>
<li>No signature covers the property. A receiver <bcp14>MUST
NOT</bcp14> report its class as signed unless the class, evidence and
figure equal those in the object's labelled leaf, once the object
receipt is accepted against the group receipt group_receipt names;
where they differ, the receiver <bcp14>MUST</bcp14> discard the
property ("property_disagrees").</li>
<li>A relay <bcp14>MUST</bcp14> forward the property unchanged.</li>
<li>The property rides on its object and is lost with it; the
receipts track carries the receipts of an object that is not
delivered. Absence of the property is not evidence that an object
has no receipt.</li>
</ul>
<t>Until a type is assigned (<xref target="iana-property"/>), a track of
packaging "wai" carries the property as type 0x3A41, from the range
<xref target="MOQT" section="8.4"/> sets aside for an application's own
use. Another application can give that type another meaning, so a
receiver reads it only on a track of packaging "wai".</t>
</section>
<section anchor="relays">
<name>Relays</name>
<t>An MOQT relay forwards tracks of packaging "wai" and "wai-receipts"
as it forwards any track, their payloads opaque
(<xref target="MOQT" section="7.8"/>). It needs no knowledge of this
document and verifies no receipt: the receiver verifies every receipt
itself. A relay that does not forward an object, because a delivery
timeout passed or at its discretion, still forwards the receipts track's
objects, which are separate MOQT objects. A relay that verifies receipts
before forwarding them is permitted, and <xref target="WAI-JWP"/>
Section 4 states what it must preserve.</t>
</section>
</section>
<section anchor="codecs">
<name>The codecs Parameter</name>
<t>The optional codecs parameter of application/wai
(<xref target="iana-media-type"/>) lists the capabilities a sequence of
objects uses, in the form of <xref target="RFC6381"/>. Its WAI elements
follow this grammar <xref target="RFC5234"/>:</t>
<sourcecode type="abnf"><![CDATA[
wai-element = wai-prefix "." alt *( "|" alt )
wai-prefix = "wai1" / "wai2"
alt = cap *( "+" cap )
cap = 1*lcalnum 1*( "." 1*( lcalnum / "_" ) )
lcalnum = %x61-7A / %x30-39
]]></sourcecode>
<t>A cap is a capability string without its leading "wai.". In an alt,
the first cap is a capability a receiver can select, and each "+cap" is
one whose payload is applied with it. The element lists every
capability that any object it describes may dispatch to or apply. An
element that begins with "wai", in any case, <bcp14>MUST</bcp14> match
the grammar. <xref target="WAI-HTTP"/> Section 4 gives the remaining
rules.</t>
</section>
<section anchor="implementation-status">
<name>Implementation Status</name>
<t>(Note to the RFC Editor: please remove this section before
publication, as <xref target="RFC7942"/> describes.)</t>
<t>One open-source implementation family exists, in the repository named
in the note at the start of this document, under the Apache License
2.0:</t>
<ul>
<li>"wai-rs", the WAI reference library: the envelope, dispatch and
pin verification (<xref target="envelope"/>), the tier rules, the
catalog check of staged tracks and the reading and check of wai_priors
(<xref target="catalog"/>), and a receipts verifier
(<xref target="receipts"/>).</li>
<li>"joule-moq", an MOQT implementation of
<xref target="MOQT"/>: the receipts track in its binary form, receipt
chains per key and alias, the WAI_RECEIPT property at type 0x3A41 inside
Immutable Properties, and a test relay that drops late objects and still
forwards their receipts. A browser receiver built on it refuses an
object whose capability its track does not declare.</li>
<li>Conformance corpora for the catalog checks, wai_priors, the
receipts and the property. Each is checked by the library and by an
independent verifier, written in Python from the specification text,
that shares no code with the library.</li>
</ul>
<t>Not implemented at the time of writing: no publisher in the
implementation writes wai_priors, and the browser receiver does not read
it (it dispatches no capability that decodes against a parameter set);
no receiver reads wai_determinism; and no type is assigned for
WAI_RECEIPT.</t>
</section>
<section anchor="security">
<name>Security Considerations</name>
<t>This document relies on MOQT <xref target="MOQT"/> for transport
security: QUIC protects each hop. The receipts of
<xref target="receipts"/> add integrity from the publisher to the
receiver across relays; they add no confidentiality.</t>
<section anchor="sec-keys">
<name>Receipt Keys</name>
<t>Each group receipt has one signer, the publisher key in it. Forging
one requires the private key or a break of Ed25519. A valid signature
shows that a key signed; it does not show whose key it is. A receiver
<bcp14>MUST NOT</bcp14> present a receipt as the publisher's unless it
holds the key as the publisher's by a means it trusts (configuration,
the session, or key discovery as <xref target="WAI-JWP"/> Section 7
specifies). Publishers <bcp14>MUST</bcp14> generate keys with a
cryptographically secure random number generator and <bcp14>MUST
NOT</bcp14> use one key for distinct publisher identities. The strict
verification of <xref target="verification"/> step 2 refuses keys of
small order, under which a signature can verify without any private
key, and makes every conforming receiver accept the same signatures. A
compromised key can sign any group; rotation and revocation are outside
this document.</t>
</section>
<section anchor="sec-replay">
<name>Replay</name>
<t>A group receipt binds the publisher key, track_alias and group_id
under its signature, and an object receipt is bound to its leaf
position, so neither can be moved to another track, group or position
without detection. The receipts-track rule of
<xref target="receipts-track"/> binds each receipt to the MOQT group and
object it is carried for.</t>
<t>Chains are kept per key and track. The labelled payload signs the
link to the parent group; the legacy payload does not, so in a legacy
chain anyone on the path can rewrite the link, and the rule that a
legacy group's group_id exceeds its head's is the only order that chain
signs. A relay can drop a legacy group and rewrite the next one's link
to hide the gap; only the labelled payload rules that out.</t>
<t>An anchor (<xref target="verification"/>) proves nothing about the
groups before it: a relay can withhold groups, or offer a joining
receiver an old group that is validly signed. A receiver reports
anchors and gaps, and <bcp14>MAY</bcp14> refuse a live group whose
group_end is older than a freshness window it states; it applies such
a window only to the live edge, never to history it fetches.</t>
</section>
<section anchor="sec-relays">
<name>Relay Transparency</name>
<t>A relay forwards payloads without reading them. It cannot alter an
envelope without changing its content hash, nor alter a receipt without
breaking its signature. It can drop, delay or withhold objects, whole
groups of a receipts track, or whole tracks; the receipts of
<xref target="receipts"/> make an undelivered object accountable, as
inclusion-verified, but they do not make delivery happen.</t>
<t>The WAI_RECEIPT property is not signed. Immutable Properties forbid a
relay to change it, but a receiver cannot detect a relay that breaks
that rule from the property alone, which is why
<xref target="property"/> lets a receiver report its class only when it
matches a signed leaf.</t>
<t>A relay sees what MOQT exposes: track names, catalogs (unless they
are encrypted), object sizes, timing and properties, including
WAI_RECEIPT.</t>
</section>
<section anchor="sec-catalog">
<name>Catalog Integrity</name>
<t>Receipts do not cover the catalog. Where the catalog is not protected
end to end, an on-path party able to rewrite it can misdeclare a track's
capabilities, tiers or pinned parameter sets. The envelope remains the
authority: a receiver verifies every pin before it decodes
(<xref target="pins"/>), and an object that breaks wai_priors refuses
its track (<xref target="priors"/>), so a misdeclared catalog leads to
refusal, not to a decode against the wrong parameters. A listed tier is
advisory and confers nothing.</t>
</section>
<section anchor="sec-params">
<name>Parameter Sets</name>
<t>A learned decoder run against parameters other than the ones a
payload was coded against produces plausible but wrong output, with no
error. The pin makes the parameter set part of what the receiver
checks, by digest. A receiver that decodes from bytes other than the
ones it verified (for example by reading a file again after checking
it) loses that protection; a receiver <bcp14>SHOULD</bcp14> decode from
the very bytes it verified.</t>
</section>
<section anchor="sec-resources">
<name>Resource Consumption</name>
<t>A receiver bounds what it parses and holds: the manifest limits of
<xref target="layout"/>; a bound on the receipts it holds for missing
parents (<xref target="verification"/>); and the bounds of
<xref target="WAI"/> Section 2 on decoded payloads. A receiver
<bcp14>SHOULD</bcp14> check a receipts_bin's object count, and a Merkle
proof's sibling count, against the bytes that remain before it
allocates anything for them.</t>
</section>
<section anchor="sec-privacy">
<name>Privacy</name>
<t>Receipts carry the publisher key, a signer label, origin labels,
timestamps and energy figures in cleartext, and a receipts track is
visible to every relay that forwards it. They reveal when and where
objects were produced, and what producing them cost. A publisher can
send the unmetered marker in place of a figure and an empty origin. A
deployment that needs these hidden from relays encrypts the receipts
track's objects end to end, for example with
<xref target="SECURE-OBJECTS"/>; the receipts then commit to the bytes
carried.</t>
</section>
</section>
<section anchor="iana">
<name>IANA Considerations</name>
<section anchor="iana-packaging">
<name>MSF Packaging Values</name>
<t>This document requests no IANA action for the packaging values "wai"
and "wai-receipts". <xref target="MSF"/> lists its allowed packaging
values in its own text (<xref target="MSF" section="5.2.4"/>) and
creates no registry for them, and this document extends that list
(<xref target="packaging"/>), as other MSF packaging documents do.</t>
</section>
<section anchor="iana-property">
<name>MOQ Properties</name>
<t>This document requests that IANA register the following entry in the
"MOQ Properties" registry established by
<xref target="MOQT" section="16.8"/>, with a type from the range
0x80 to 0x37FF, whose registration policy is Specification Required:</t>
<table>
<name>WAI_RECEIPT Property</name>
<thead>
<tr><th>Type</th><th>Name</th><th>Scope</th><th>Specification</th></tr>
</thead>
<tbody>
<tr><td>TBD (odd)</td><td>WAI_RECEIPT</td><td>Object</td><td><xref target="property"/> of this document</td></tr>
</tbody>
</table>
<t>The type is odd, since the value is a byte sequence
(<xref target="MOQT" section="8.3"/>). Until a type is assigned,
implementations use 0x3A41, from the range 0x3800 to 0x3FFF that
<xref target="MOQT" section="8.4"/> reserves for application-specific
use; no registration is possible in that range, and none is
requested for it.</t>
</section>
<section anchor="iana-media-type">
<name>Media Type application/wai</name>
<t>This document requests that IANA register the media type
application/wai in the "Media Types" registry, in the standards tree,
as <xref target="RFC6838"/> provides for a registration made by an IETF
document.</t>
<dl newline="false" spacing="normal">
<dt>Type name:</dt><dd>application</dd>
<dt>Subtype name:</dt><dd>wai</dd>
<dt>Required parameters:</dt><dd>N/A</dd>
<dt>Optional parameters:</dt><dd>codecs, as <xref target="codecs"/>
of this document defines.</dd>
<dt>Encoding considerations:</dt><dd>binary</dd>
<dt>Security considerations:</dt><dd>See
<xref target="security"/> of this document. A WAI object names the
decoder its payload needs and does not carry executable code.</dd>
<dt>Interoperability considerations:</dt><dd>An object is a "WAI1"
envelope (<xref target="layout"/>) or a "WAI2" envelope
(<xref target="WAI"/> Section 7.1). A reader refuses an unknown major
version.</dd>
<dt>Published specification:</dt><dd>This document, and
<xref target="WAI"/>.</dd>
<dt>Applications that use this media type:</dt><dd>Media publishers,
relays, caches and players that carry WAI envelopes over MOQT or
HTTP.</dd>
<dt>Fragment identifier considerations:</dt><dd>None defined by this
document.</dd>
<dt>Additional information:</dt>
<dd>
<t>Deprecated alias names for this type: N/A</t>
<t>Magic number(s): 57 41 49 31 ("WAI1") or 57 41 49 32 ("WAI2")
at offset 0</t>
<t>File extension(s): .wai</t>
<t>Macintosh file type code(s): N/A</t>
</dd>
<dt>Person and email address to contact for further
information:</dt><dd>The author of this document.</dd>
<dt>Intended usage:</dt><dd>COMMON</dd>
<dt>Restrictions on usage:</dt><dd>N/A</dd>
<dt>Author:</dt><dd>See the Author's Address section of this
document.</dd>
<dt>Change controller:</dt><dd>IETF</dd>
</dl>
</section>
<section anchor="iana-none">
<name>Capability Strings</name>
<t>This document creates no registry for capability strings or tier
names. <xref target="WAI"/> registers them under its own registry
policy.</t>
</section>
</section>
</middle>
<back>
<references>
<name>References</name>
<references>
<name>Normative References</name>
<reference anchor="MOQT" target="https://datatracker.ietf.org/doc/html/draft-ietf-moq-transport-22">
<front>
<title>Media over QUIC Transport</title>
<author/>
<date year="2026" month="October" day="1"/>
</front>
<seriesInfo name="Internet-Draft" value="draft-ietf-moq-transport-22"/>
</reference>
<reference anchor="MSF" target="https://datatracker.ietf.org/doc/html/draft-ietf-moq-msf-01">
<front>
<title>MOQT Streaming Format</title>
<author/>
<date year="2026" month="June" day="2"/>
</front>
<seriesInfo name="Internet-Draft" value="draft-ietf-moq-msf-01"/>
</reference>
<reference anchor="WAI" target="https://git.transaction.science/Transaction-Science/open-standards/src/branch/main/wai/SPEC.md">
<front>
<title>WAI v1.0: Web AI Media Transport and Execution</title>
<author/>
<date year="2026" month="October"/>
</front>
<refcontent>Draft Standard, open-standards repository, wai/SPEC.md</refcontent>
</reference>
<reference anchor="BLAKE3" target="https://datatracker.ietf.org/doc/html/draft-aumasson-blake3-00">
<front>
<title>The BLAKE3 Hashing Framework</title>
<author/>
<date year="2024" month="July"/>
</front>
<seriesInfo name="Internet-Draft" value="draft-aumasson-blake3-00"/>
</reference>
<reference anchor="SHS" target="https://doi.org/10.6028/NIST.FIPS.180-4">
<front>
<title>Secure Hash Standard (SHS)</title>
<author><organization>National Institute of Standards and Technology</organization></author>
<date year="2015" month="August"/>
</front>
<seriesInfo name="FIPS PUB" value="180-4"/>
<seriesInfo name="DOI" value="10.6028/NIST.FIPS.180-4"/>
</reference>
<reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119">
<front>
<title>Key words for use in RFCs to Indicate Requirement Levels</title>
<author/>
<date year="1997" month="March"/>
</front>
<seriesInfo name="BCP" value="14"/>
<seriesInfo name="RFC" value="2119"/>
<seriesInfo name="DOI" value="10.17487/RFC2119"/>
</reference>
<reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174">
<front>
<title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
<author/>
<date year="2017" month="May"/>
</front>
<seriesInfo name="BCP" value="14"/>
<seriesInfo name="RFC" value="8174"/>
<seriesInfo name="DOI" value="10.17487/RFC8174"/>
</reference>
<reference anchor="RFC8032" target="https://www.rfc-editor.org/info/rfc8032">
<front>
<title>Edwards-Curve Digital Signature Algorithm (EdDSA)</title>
<author/>
<date year="2017" month="January"/>
</front>
<seriesInfo name="RFC" value="8032"/>
<seriesInfo name="DOI" value="10.17487/RFC8032"/>
</reference>
<reference anchor="RFC8259" target="https://www.rfc-editor.org/info/rfc8259">
<front>
<title>The JavaScript Object Notation (JSON) Data Interchange Format</title>
<author/>
<date year="2017" month="December"/>
</front>
<seriesInfo name="STD" value="90"/>
<seriesInfo name="RFC" value="8259"/>
<seriesInfo name="DOI" value="10.17487/RFC8259"/>
</reference>
<reference anchor="RFC3339" target="https://www.rfc-editor.org/info/rfc3339">
<front>
<title>Date and Time on the Internet: Timestamps</title>
<author/>
<date year="2002" month="July"/>
</front>
<seriesInfo name="RFC" value="3339"/>
<seriesInfo name="DOI" value="10.17487/RFC3339"/>
</reference>
<reference anchor="RFC5234" target="https://www.rfc-editor.org/info/rfc5234">
<front>
<title>Augmented BNF for Syntax Specifications: ABNF</title>
<author/>
<date year="2008" month="January"/>
</front>
<seriesInfo name="STD" value="68"/>
<seriesInfo name="RFC" value="5234"/>
<seriesInfo name="DOI" value="10.17487/RFC5234"/>
</reference>
<reference anchor="RFC6381" target="https://www.rfc-editor.org/info/rfc6381">
<front>
<title>The 'Codecs' and 'Profiles' Parameters for "Bucket" Media Types</title>
<author/>
<date year="2011" month="August"/>
</front>
<seriesInfo name="RFC" value="6381"/>
<seriesInfo name="DOI" value="10.17487/RFC6381"/>
</reference>
<reference anchor="RFC6838" target="https://www.rfc-editor.org/info/rfc6838">
<front>
<title>Media Type Specifications and Registration Procedures</title>
<author/>
<date year="2013" month="January"/>
</front>
<seriesInfo name="BCP" value="13"/>
<seriesInfo name="RFC" value="6838"/>
<seriesInfo name="DOI" value="10.17487/RFC6838"/>
</reference>
</references>
<references>
<name>Informative References</name>
<reference anchor="CMSF" target="https://datatracker.ietf.org/doc/html/draft-ietf-moq-cmsf-01">
<front>
<title>CMSF- a CMAF compliant implementation of MOQT Streaming Format</title>
<author/>
<date year="2026" month="June" day="3"/>
</front>
<seriesInfo name="Internet-Draft" value="draft-ietf-moq-cmsf-01"/>
</reference>
<reference anchor="SECURE-OBJECTS" target="https://datatracker.ietf.org/doc/html/draft-ietf-moq-secure-objects-01">
<front>
<title>End-to-End Secure Objects for Media over QUIC Transport</title>
<author/>
<date year="2026"/>
</front>
<seriesInfo name="Internet-Draft" value="draft-ietf-moq-secure-objects-01"/>
</reference>
<reference anchor="RFC7942" target="https://www.rfc-editor.org/info/rfc7942">
<front>
<title>Improving Awareness of Running Code: The Implementation Status Section</title>
<author/>
<date year="2016" month="July"/>
</front>
<seriesInfo name="BCP" value="205"/>
<seriesInfo name="RFC" value="7942"/>
<seriesInfo name="DOI" value="10.17487/RFC7942"/>
</reference>
<reference anchor="WAI-MOQ" target="https://git.transaction.science/Transaction-Science/open-standards/src/branch/main/wai/extensions/moq-streaming-format.md">
<front>
<title>WAI Extension: MoQ Streaming Format</title>
<author/>
<date year="2026" month="October"/>
</front>
<refcontent>open-standards repository, wai/extensions/moq-streaming-format.md</refcontent>
</reference>
<reference anchor="WAI-JWP" target="https://git.transaction.science/Transaction-Science/open-standards/src/branch/main/wai/extensions/jwp-receipts.md">
<front>
<title>WAI Extension: JWP Receipt Chain</title>
<author/>
<date year="2026" month="October"/>
</front>
<refcontent>open-standards repository, wai/extensions/jwp-receipts.md</refcontent>
</reference>
<reference anchor="WAI-TIERS" target="https://git.transaction.science/Transaction-Science/open-standards/src/branch/main/wai/extensions/determinism-tiers.md">
<front>
<title>WAI Extension: Determinism Tiers for Neural Decode</title>
<author/>
<date year="2026" month="October"/>
</front>
<refcontent>open-standards repository, wai/extensions/determinism-tiers.md</refcontent>
</reference>
<reference anchor="WAI-PRIOR" target="https://git.transaction.science/Transaction-Science/open-standards/src/branch/main/wai/extensions/prior-carriage.md">
<front>
<title>WAI Extension: Prior Carriage</title>
<author/>
<date year="2026" month="October"/>
</front>
<refcontent>open-standards repository, wai/extensions/prior-carriage.md</refcontent>
</reference>
<reference anchor="WAI-STAGED" target="https://git.transaction.science/Transaction-Science/open-standards/src/branch/main/wai/extensions/staged-delivery.md">
<front>
<title>WAI Extension: Staged Delivery</title>
<author/>
<date year="2026" month="October"/>
</front>
<refcontent>open-standards repository, wai/extensions/staged-delivery.md</refcontent>
</reference>
<reference anchor="WAI-ENERGY" target="https://git.transaction.science/Transaction-Science/open-standards/src/branch/main/wai/extensions/energy-measurement.md">
<front>
<title>WAI Extension: Energy Measurement</title>
<author/>
<date year="2026" month="October"/>
</front>
<refcontent>open-standards repository, wai/extensions/energy-measurement.md</refcontent>
</reference>
<reference anchor="WAI-HTTP" target="https://git.transaction.science/Transaction-Science/open-standards/src/branch/main/wai/extensions/http-delivery.md">
<front>
<title>WAI Extension: HTTP Delivery</title>
<author/>
<date year="2026" month="October"/>
</front>
<refcontent>open-standards repository, wai/extensions/http-delivery.md</refcontent>
</reference>
</references>
</references>
<section anchor="example">
<name>Catalog Example</name>
<t>A live catalog with a stage set (a base track and one layer track,
each with its receipts track) and an on-demand track of a learned
image capability that states its pinned parameter set. The digest is a
placeholder.</t>
<sourcecode type="json"><![CDATA[
{ "version": 1,
"tracks": [
{ "namespace": "example/cam1", "name": "cam1/base",
"packaging": "wai", "isLive": true, "targetLatency": 300,
"role": "video", "renderGroup": 1,
"wai_capabilities": ["wai.video.int_motion"],
"wai_determinism": "decode-equivalence",
"wai_receipts": true, "wai_receipt_alias": 7,
"wai_receipts_track": "cam1/base/receipts",
"wai_staged": { "set": "cam1", "layer": 0,
"lead_ms": null } },
{ "namespace": "example/cam1", "name": "cam1/L1",
"packaging": "wai", "isLive": true, "targetLatency": 300,
"role": "video", "renderGroup": 1, "depends": ["cam1/base"],
"wai_capabilities": ["wai.video.int_refine"],
"wai_determinism": "decode-equivalence",
"wai_receipts": true, "wai_receipt_alias": 8,
"wai_receipts_track": "cam1/L1/receipts",
"wai_staged": { "set": "cam1", "layer": 1, "lead_ms": 20 } },
{ "namespace": "example/cam1", "name": "cam1/base/receipts",
"packaging": "wai-receipts", "isLive": true },
{ "namespace": "example/cam1", "name": "cam1/L1/receipts",
"packaging": "wai-receipts", "isLive": true },
{ "namespace": "example/net", "name": "pictures",
"packaging": "wai", "isLive": false, "role": "video",
"wai_capabilities": ["wai.neural.int_hyper",
"wai.image.png"],
"wai_determinism": "decode-equivalence",
"wai_priors": [
{ "capability": "wai.neural.int_hyper",
"sha256":
"a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1",
"form": "wai.prior.set", "tier": "decode-equivalence" } ],
"wai_receipts": true, "wai_receipt_alias": 9,
"wai_receipts_track": "pictures/receipts" },
{ "namespace": "example/net", "name": "pictures/receipts",
"packaging": "wai-receipts", "isLive": false } ] }
]]></sourcecode>
<t>An object on "pictures" is a WAI envelope whose capability is
"wai.neural.int_hyper", whose fallback is "wai.image.png", and whose pin
names the listed set. A receiver that holds that set decodes the learned
payload; one that does not falls back to PNG. An object whose pin named
another set would refuse the track.</t>
</section>
<section anchor="reasons">
<name>Refusal Reasons</name>
<table>
<name>Refusal Reasons</name>
<thead>
<tr><th>Reason</th><th>Raised by</th></tr>
</thead>
<tbody>
<tr><td>missing_capability</td><td><xref target="dispatch"/></td></tr>
<tr><td>pin_malformed, form_not_registered, form_unreadable, form_required, prior_revoked, prior_not_authorised, prior_not_held, digest_superseded, set_malformed, part_mismatch, set_incomplete</td><td><xref target="pins"/></td></tr>
<tr><td>tier_exceeds_class</td><td><xref target="tiers"/></td></tr>
<tr><td>catalog_priors_malformed, catalog_prior_mismatch</td><td><xref target="priors"/></td></tr>
<tr><td>staged-malformed, staged-set-incomplete, staged-depends, staged-grouping, staged-lead, staged-receipts</td><td><xref target="staged"/></td></tr>
<tr><td>moqt_mismatch</td><td><xref target="receipts-track"/></td></tr>
<tr><td>malformed, group_label_invalid, bad_signer_key, signature_verify_failed, chain_break, parent_not_held, parent_not_recovered, group_id_not_increasing, content_hash_mismatch, object_label_invalid, proof_position_mismatch, inclusion_proof_failed, group_total_mismatch</td><td><xref target="verification"/></td></tr>
<tr><td>property_invalid, property_disagrees</td><td><xref target="property"/></td></tr>
</tbody>
</table>
</section>
<section anchor="correspondence">
<name>Correspondence with the WAI Texts</name>
<t>This document restates, for carriage over MOQT, parts of the WAI
specification and its extensions. Where this document and the cited text
differ, the difference is a defect in one of them.</t>
<table>
<name>Correspondence</name>
<thead>
<tr><th>This document</th><th>WAI text</th></tr>
</thead>
<tbody>
<tr><td><xref target="layout"/>, <xref target="manifest"/></td><td><xref target="WAI"/> Sections 2 and 3</td></tr>
<tr><td><xref target="dispatch"/></td><td><xref target="WAI"/> Section 4</td></tr>
<tr><td><xref target="pins"/></td><td><xref target="WAI"/> Section 3.1; <xref target="WAI-PRIOR"/></td></tr>
<tr><td><xref target="tiers"/></td><td><xref target="WAI-TIERS"/> Sections 2 and 3</td></tr>
<tr><td><xref target="packaging"/>, <xref target="fields"/></td><td><xref target="WAI-MOQ"/> Sections 3 and 4</td></tr>
<tr><td><xref target="priors"/></td><td><xref target="WAI-MOQ"/> Section 4.2</td></tr>
<tr><td><xref target="staged"/></td><td><xref target="WAI-MOQ"/> Section 4.1</td></tr>
<tr><td><xref target="content-hash"/> to <xref target="verification"/></td><td><xref target="WAI-JWP"/> Sections 2, 2.7 and 3; <xref target="WAI-ENERGY"/> Sections 2.3 and 2.7</td></tr>
<tr><td><xref target="property"/></td><td><xref target="WAI-MOQ"/> Section 5</td></tr>
<tr><td><xref target="codecs"/>, <xref target="iana-media-type"/></td><td><xref target="WAI-HTTP"/> Sections 3 and 4</td></tr>
</tbody>
</table>
</section>
</back>
</rfc>