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.