From 0c17e8c846ca32d1ea9c23400b7097ee4091191c Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Mon, 7 Sep 2026 04:19:49 -0400 Subject: [PATCH] moq-streaming-format: declare WAI as a MoQ streaming format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WAI already references MoQ for confidentiality (MLS + SFrame), and that binding treats MoQ as a pipe. MoQ is not a pipe — it is a two-layer design, and the upper layer has an open slot exactly where a container of capability-dispatched objects belongs. MOQT moves objects in groups on tracks and does not know what an object means. MSF (draft-ietf-moq-msf) says what objects mean: it fragments a stream into objects, declares what a publisher emits in a catalog, and sets prioritisation. The alignment with WAI is structural rather than aspirational — MSF's unit is an object in a group, WAI envelopes are already objects, and jwp-receipts already commits per object and signs per group. Neither layer has to change to agree. THE SLOT IS OPEN, AND CHEAPLY. MSF's `packaging` field has a fixed value set and no central registry, which reads closed. draft-ietf-moq-cmsf shows it is not: a sibling I-D that declares packaging value `cmaf`, says it extends the allowed values defined in MSF, inherits MSF wholesale, adds two track-level catalog fields, and registers nothing — "this document has no IANA actions". LOCMAF is a second instance. A sibling draft, no registry action, no permission sought. What CMSF did NOT take is the per-object slot. MSF §12 defines properties at Track AND Object scope with an IANA type registry holding essentially one entry (MSF_COMPRESSION); CMSF defines no per-object property. §5 takes that slot with WAI_RECEIPT — content hash, joules, acquisition class, group-receipt hash — which is the shape jwp-receipts already has. `acquisition` MUST accompany `joules_micro`, because a joule figure without its acquisition class is what energy-measurement §2 forbids, and putting it on a wire does not make it acceptable. The load-bearing rule is §3: the object boundary MUST be the envelope boundary. That is what makes MOQT's object identity and the receipt's per-object commitment the same unit. If they diverge, every guarantee that composes them is void. §4 makes the catalog do work rather than decorate: `wai_capabilities` MUST be exhaustive, a sink MUST NOT subscribe assuming an undeclared capability will not appear, and `wai_determinism` is the WEAKEST tier on the track — declaring the strongest would let a track advertise a guarantee most of its objects do not meet. §6 states what this does not do, so it is not re-argued: no MOQT wire encoding, no replacement for CMSF or LOC, no making MoQ WAI's transport, and no pinning of a draft revision. MOQT is pre-Last-Call; where it and this text disagree, MOQT wins and this text is what changes. Ingest queue item 13b from the landscape survey (#80 §4.4). Sourced from direct reads of draft-ietf-moq-msf and draft-ietf-moq-cmsf-00. Co-Authored-By: Claude Opus 5 --- wai/extensions/moq-streaming-format.md | 139 +++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 wai/extensions/moq-streaming-format.md diff --git a/wai/extensions/moq-streaming-format.md b/wai/extensions/moq-streaming-format.md new file mode 100644 index 000000000..c55042f7b --- /dev/null +++ b/wai/extensions/moq-streaming-format.md @@ -0,0 +1,139 @@ +# WAI Extension: MoQ Streaming Format + +> Status: Draft, and deliberately tracking rather than pinning — MOQT is +> pre-Working-Group-Last-Call and its text still moves. Declares WAI as a +> **streaming format** over Media over QUIC Transport, so a WAI envelope is a +> first-class MOQT object rather than an opaque payload inside someone else's +> container. No new transport: WAI defines none by charter, and this extension +> does not change that. Field semantics and rules over them only — never MOQT's +> byte encoding. +> Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119/8174. + +## 1. Why a streaming format + +MoQ separates two things that other stacks fuse: + +- **MOQT** (`draft-ietf-moq-transport`) moves objects, in groups, on tracks. It + does not know what an object means. +- **MSF** (`draft-ietf-moq-msf`) says what objects mean: it fragments a stream + into objects, declares what a publisher emits in a **catalog**, and sets + prioritisation. + +WAI already references MoQ for confidentiality (MLS + SFrame; see +[confidentiality](confidentiality.md)). That binding treats MoQ as a pipe. This +one treats it as what it is — a two-layer design with an open slot at the upper +layer, which is precisely where a container that carries capability-dispatched +objects belongs. + +The alignment is structural, not aspirational. MSF fragments a stream into +objects in groups; WAI envelopes are already objects, and +[jwp-receipts](jwp-receipts.md) already commits per object and signs per group. +The two layers agree on the unit without either being changed. + +## 2. Precedent: the slot is open, and cheaply + +MSF's catalog names a format in its `packaging` field, over a value set MSF's own +text fixes (`loc`, `mediatimeline`, `eventtimeline`, `moqlog`, `moqmetrics`, +`catalog`). There is no central streaming-format registry. Read alone, that is +closed. + +`draft-ietf-moq-cmsf` shows it is not. CMSF is a sibling Internet-Draft that +declares `packaging` value `cmaf`, stating that it *extends the allowed packaging +values defined in MSF*; inherits MSF wholesale — *all of the specifications, +requirements and terminology defined in MSF apply to implementations of this +extension*; adds two track-level catalog fields; and registers nothing: **this +document has no IANA actions**. LOCMAF is a second instance of the same move. + +So the path is a sibling draft with no registry action and no permission sought. +This extension is the WAI-side statement of what such a draft would say. + +## 3. The packaging value + +A track carrying WAI envelopes **MUST** declare `packaging` value `"wai"`. + +- Every object on such a track **MUST** be exactly one WAI envelope (`WAI1` + magic + manifest + payload), whole. An object carrying a fragment of an + envelope, or more than one, is not this packaging. +- The object boundary **MUST** be the envelope boundary. This is what makes the + receipt's per-object commitment (`jwp-receipts` §2.1) and MOQT's object + identity the same unit; if they diverge, every guarantee that composes them is + void. +- A sink that does not recognise `"wai"` **MUST NOT** attempt to interpret the + objects. MSF's tolerant-parser rule covers unknown *fields*; it does not + license guessing at unknown *packaging*. + +## 4. Catalog declaration + +A WAI track's catalog entry **MUST** declare, in addition to MSF's required +fields, the capabilities a sink needs to dispatch what the track carries: + +| field | type | meaning | +|---|---|---| +| `wai_capabilities` | array of string | Capability strings (WAI SPEC.md §4) that objects on this track may dispatch to. | +| `wai_determinism` | string | The weakest tier any object on the track claims — see [determinism-tiers](determinism-tiers.md). Absent means no tier is claimed. | +| `wai_receipts` | boolean | Whether objects carry receipts per §5. | + +- `wai_capabilities` **MUST** be exhaustive for the track. A publisher that + dispatches to a capability it did not declare has broken the catalog's + purpose, which is letting a sink decide **before** subscribing whether it can + play what it is about to receive. +- A sink **MUST NOT** subscribe on the assumption that an undeclared capability + will not appear, and **MUST** treat an undeclared capability at dispatch as a + protocol error rather than falling back silently. +- `wai_determinism` is the **weakest** tier on the track, not the strongest. + Declaring the strongest would let a track advertise a guarantee most of its + objects do not meet. + +These are custom catalog fields under MSF's extension rule; they are namespaced +by their `wai_` prefix and MUST NOT collide with MSF-defined names. + +## 5. The per-object property + +MSF §12 defines **MSF Properties** at **Track** and **Object** scope, with an +IANA registry of property types that today holds essentially one entry +(`MSF_COMPRESSION`). CMSF adds track-level catalog fields and defines **no +per-object property**. The object-scope slot is empty. + +A WAI receipt is already per-object. This extension therefore defines one +object-scope property, `WAI_RECEIPT`, whose value is the object's receipt +commitment: + +| field | type | meaning | +|---|---|---| +| `content_hash` | 32 B | `jwp-receipts` §2.1 BLAKE3 over the envelope bytes. | +| `joules_micro` | u64 | Microjoules producing this object. | +| `acquisition` | string | Acquisition class per [energy-measurement](energy-measurement.md) §2. | +| `group_receipt` | 32 B | BLAKE3 of the group receipt covering this object. | + +- `acquisition` **MUST** accompany `joules_micro`. A joule figure without its + acquisition class is exactly what `energy-measurement.md` §2 forbids, and + putting it on the wire does not make it acceptable. +- A relay **MUST** preserve this property unchanged, per `jwp-receipts` §4.1. + A relay that recomputes it is asserting something it did not measure. +- Absence of the property is not evidence of absence of a receipt; receipts MAY + ride elsewhere (§1 of `jwp-receipts` lists sidecar and trailer carriage). A + sink **MUST NOT** infer that an object without the property is unattested. + +## 6. What this extension does not do + +Stated so it is not re-argued: + +- It does **not** define, profile, or restate MOQT's wire encoding — not the + object header, not the extension-header byte layout, not the control messages. + Those are MOQT's, and the property that makes this binding cheap is that WAI + rides a transport instead of defining one. +- It does **not** replace CMSF or LOC. A publisher with CMAF-packaged media + should use CMSF; this packaging is for tracks whose objects are WAI envelopes. +- It does **not** make MoQ WAI's transport. WAI remains carrier-agnostic; this + is one binding among the several `jwp-receipts` §1 anticipates. +- It does **not** pin a MOQT draft revision. MOQT is pre-Last-Call; an extension + that pinned a moving target would be wrong within a meeting cycle. Where MOQT + and this text disagree, MOQT wins and this text is the thing that must change. + +## 7. Framing + +The delivery industry is converging on MoQ, and the layer above it is where +formats declare themselves. A container that carries instructions, dispatches by +capability, and commits per object has a natural home there — not because it +competes with the transport, but because the transport deliberately left the +question of meaning to someone else. -- 2.54.0 (Apple Git-157)