Two additions to the WAI standard, rebased clean onto current main: - SPEC.md gains section 6 Confidentiality (OPTIONAL): a security.encryption manifest field, keys as a requirement-of-existence (never transported), relay-sees-only-ciphertext transparency, and a decrypt-then-dispatch refinement of the capability-dispatch algorithm. Conformance/Versioning renumbered to 7/8; the neural intent bullet's replicate-soundness ref follows to 7. No cross-references broken. - New extensions/confidentiality.md sub-spec: byte-level SFrame (RFC 9605 suite 0x0006) framing + HKDF-SHA-512 schedule + nonce, the MLS (RFC 9420) exporter binding with single- vs multi-sender keying, and how it composes with the JWP receipt chain over ciphertext. - extensions/jwp-receipts.md: cross-links payload- vs receipt-confidentiality, and documents the optional wall-clock freshness bound on the live edge (companion to the monotonic group_id guard already in 6.1). Grounded byte-for-byte in the moq-sframe / joule-comm-mls reference impl; the private-channel path is live at wai.transaction.science/private-channel. Co-authored-by: Transaction Science <[email protected]> Co-authored-by: Claude Opus 4.8 <[email protected]>
616 lines
34 KiB
Markdown
616 lines
34 KiB
Markdown
# WAI v1.0 — Web AI Media Transport & Execution
|
||
|
||
Status: **Draft Standard**. Reference implementation: `wai-rs/` (Rust
|
||
lib + cdylib + staticlib, C FFI). Two paths open every conforming
|
||
file:
|
||
|
||
- the **neural condition** — the sink regenerates the media from a
|
||
compact conditioning payload against a *shared ambient prior* (a
|
||
model). The model is a **requirement of existence**, never
|
||
transported and never hash-pinned, exactly as `.mp3` does not ship
|
||
its decoder.
|
||
- the **zeroth condition** — a *menu of registered SOTA standard
|
||
codecs*. Always satisfiable on any device that ships ffmpeg or
|
||
equivalent. WAI does **not** define new codecs; it dispatches to the
|
||
field's best-in-class lossy+lossless libraries (AVIF, JPEG-XL, PNG,
|
||
Opus, FLAC, AV1, zstd, XZ).
|
||
|
||
The capability a file requires is *named*, not supplied. Sinks that
|
||
have the named capability use it; sinks that don't fall back to a
|
||
declared `fallback` capability.
|
||
|
||
Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119.
|
||
|
||
---
|
||
|
||
## 1. Scope and model
|
||
|
||
WAI is a **container + capability dispatch standard**. It is media-
|
||
general (image, audio, video, text), royalty-free, and built around the
|
||
principle that the standard's value is the envelope and the dispatch
|
||
rules — not in re-implementing existing SOTA codecs.
|
||
|
||
A WAI file declares (in its manifest):
|
||
- what media it carries,
|
||
- what *capability* a sink must have to decode it,
|
||
- a fallback capability the sink can use if it lacks the primary,
|
||
- and the conditioning bytes for that capability.
|
||
|
||
Conforming sinks MUST implement the container envelope (§2), the
|
||
manifest schema (§3), the capability-dispatch algorithm (§4), and at
|
||
least the **mandatory floor** capabilities (§5). Other capabilities
|
||
(neural and additional zeroth) are OPTIONAL but RECOMMENDED.
|
||
|
||
---
|
||
|
||
## 2. Container
|
||
|
||
```
|
||
+--------+----------------+-------------------+----------------+-----------+
|
||
| "WAI1" | u32 man_len | manifest (JSON) | u32 payload_len| payload |
|
||
| 4 B | little-endian | man_len bytes | little-endian | bytes |
|
||
+--------+----------------+-------------------+----------------+-----------+
|
||
```
|
||
|
||
- Bytes 0..4 MUST be ASCII `WAI1`. A reader MUST reject any file whose
|
||
first 4 bytes differ.
|
||
- `man_len` and `payload_len` are unsigned 32-bit little-endian.
|
||
- The manifest is UTF-8 JSON, serialized with no insignificant
|
||
whitespace, preserving key insertion order. Readers MUST NOT depend
|
||
on key order for *semantics*; encoders SHOULD preserve order so files
|
||
round-trip byte-identically.
|
||
- The payload is opaque codec bytes whose interpretation is fully
|
||
determined by the manifest's `model_requirement.capability`.
|
||
|
||
All WAI multi-byte integers are little-endian unless stated otherwise.
|
||
|
||
---
|
||
|
||
## 3. Manifest schema
|
||
|
||
```json
|
||
{
|
||
"wai": "1.0",
|
||
"media": "image" | "audio" | "video" | "text",
|
||
"intent": "replicate" | "create" | "improve" | "...",
|
||
"model_requirement": { "capability": "<capability-string>",
|
||
"fallback": "<capability-string>" | null },
|
||
"conditioning": { "kind": "<codec-id>" },
|
||
"security": { "encryption": "<scheme>" | "none", "kid": <u64> },
|
||
"target": { ... }
|
||
}
|
||
```
|
||
|
||
- `wai` — spec version. This document defines `"1.0"`. Unknown major →
|
||
reject. Unknown minor → accept by ignoring unknown fields.
|
||
- `media` — media class; informational. The capability is authoritative.
|
||
- `intent` — generative intent. `replicate` (reconstruct the source) is
|
||
the only intent with normative reconstruction semantics in v1.0. For a
|
||
**neural** capability, `replicate` is sound only under the integer-entropy
|
||
contract (§7, *Replicate-soundness*) — a float neural decode MUST NOT claim it.
|
||
- `model_requirement.capability` — the capability string a sink MUST
|
||
resolve. See §5 for the registered set.
|
||
- `model_requirement.fallback` — a second capability the sink MAY use
|
||
if it lacks the primary. `null` means the file is inert without the
|
||
primary.
|
||
- `conditioning.kind` — short codec id matching the capability. Helps
|
||
multiplexers route bytes without parsing the full capability string.
|
||
- `security` — OPTIONAL. Absent, `null`, or `encryption: "none"` ⇒ the
|
||
payload is plaintext (the default). Otherwise the payload is encrypted
|
||
and MUST be recovered before dispatch; see §6. The capability, media,
|
||
and conditioning fields always describe the **plaintext** codec.
|
||
- `target` — codec-specific reconstruction parameters (dimensions,
|
||
sample rate, duration, frame count). Informational; the payload is
|
||
self-describing per the codec's own format.
|
||
|
||
---
|
||
|
||
## 4. Capability dispatch
|
||
|
||
A conforming sink MUST implement this algorithm:
|
||
|
||
1. Read the manifest. If `wai` major version is unknown → reject.
|
||
2. Let `cap = model_requirement.capability`.
|
||
3. If the sink advertises `cap`, decode `payload` via the codec
|
||
registered for `cap` (§5) and return.
|
||
4. Else, let `fb = model_requirement.fallback`.
|
||
5. If `fb != null` and the sink advertises `fb`, decode via `fb`'s
|
||
codec and return.
|
||
6. Else the file is **inert at this sink** — return a clear "missing
|
||
capability" error to the calling application.
|
||
|
||
A WAI **payload always corresponds to exactly one capability**. v1.0
|
||
does not support multi-codec multiplexed payloads.
|
||
|
||
If the manifest declares `security.encryption` other than `"none"`
|
||
(§6), the sink MUST recover the plaintext payload before step 3 and run
|
||
this algorithm on the plaintext; see §6.4.
|
||
|
||
---
|
||
|
||
## 5. Registered capabilities (the zeroth menu)
|
||
|
||
WAI v1.0 registers the following capabilities. Each names a SOTA
|
||
royalty-free standard codec. The "payload format" column is the
|
||
on-the-wire payload bytes; in every case it is the canonical bytes
|
||
that codec normally emits (a JXL file, an Opus stream, etc.) — WAI
|
||
does not wrap or re-frame them.
|
||
|
||
### Mandatory floor
|
||
|
||
Every conforming sink MUST implement:
|
||
|
||
| capability | payload | role |
|
||
|---|---|---|
|
||
| `wai.image.png` | PNG (RFC 2083) | universal lossless image |
|
||
| `wai.audio.flac` | FLAC (xiph.org/flac) | universal lossless audio |
|
||
| `wai.text.zstd` | zstd (RFC 8478) | universal compressed bytes |
|
||
|
||
These three guarantee that any sink with the standard system codec
|
||
libraries can open *some* file in every WAI-supported media class.
|
||
|
||
### Recommended modern set
|
||
|
||
Every conforming sink SHOULD implement:
|
||
|
||
| capability | payload | role |
|
||
|---|---|---|
|
||
| `wai.image.jxl` | JPEG-XL (ISO/IEC 18181) | lossless + lossy, modern SOTA |
|
||
| `wai.image.avif` | AVIF (ISO/IEC 23000-22) | lossy SOTA (AV1-based) |
|
||
| `wai.image.jpeg` | JPEG (ITU-T T.81) | legacy compatibility |
|
||
| `wai.audio.opus` | Opus (RFC 6716) | lossy SOTA |
|
||
| `wai.video.av1` | AV1 (AOMedia) | lossy SOTA |
|
||
| `wai.video.av1.lossless` | AV1 (AOMedia), `quantizer=0` | mathematically lossless YUV (lossy in RGB due to color conversion) |
|
||
| `wai.text.xz` | XZ/LZMA2 | maximum classical text ratio |
|
||
|
||
### Neural capabilities (OPTIONAL, sink advertises if its ML runtime supports them)
|
||
|
||
Each names a model the sink MAY have installed. Payload is a compact
|
||
conditioning representation specific to the capability (latent tokens,
|
||
prompt embeddings, etc.). The standard does NOT specify the byte
|
||
layout of these payloads — the capability owner does.
|
||
|
||
Neural capabilities are picked on the **best-quality-per-bit at each
|
||
bitrate band** principle — not on whatever model is famous or small.
|
||
2026 SOTA per medium, with the wire-byte win each one delivers. The
|
||
decode route for each is implemented in the reference sink (see the
|
||
`source` column / `neural/*.rs`); the model weights are sink-supplied.
|
||
|
||
*Audio:*
|
||
|
||
| capability | model | win vs zeroth | source |
|
||
|---|---|---|---|
|
||
| `wai.neural.encodec32` | Meta EnCodec at 32 kHz, 4 codebooks | ~3 kbps acceptable music | `facebook/encodec_32khz` |
|
||
| `wai.neural.dac` | Descript Audio Codec at 44.1 kHz | 6 kbps near-transparent music | `descript/dac_44khz` |
|
||
| `wai.neural.mimi` | Kyutai Mimi, 12.5 Hz frame rate | ~1.1 kbps real-time speech | `kyutai/mimi` |
|
||
| `wai.neural.wavtokenizer` | WavTokenizer single-codebook VQ | 0.9 kbps beats DAC @ 9 kbps on UTMOS | `novateur/WavTokenizer-large-*` |
|
||
| `wai.neural.snac` | SNAC multi-resolution RVQ (hierarchical code levels, own sample rate) | low-bitrate TTS standard | `neural/snac.rs` |
|
||
|
||
*Image:*
|
||
|
||
| capability | model | win vs zeroth | source |
|
||
|---|---|---|---|
|
||
| `wai.neural.bmshj2018` | bmshj2018-factorized + rANS (byte-exact CompressAI port) | ~80× vs raw RGB at q=3 (~0.26 bpp, 29 dB PSNR) | CompressAI |
|
||
| `wai.neural.mbt2018_mean` | mean-scale hyperprior (Gaussian-conditional entropy) | conditional-entropy family, stronger than factorized | `neural/hyperprior.rs` |
|
||
| `wai.neural.int_synth` | integer fixed-point synthesis (all-i64 transposed-conv, no float/ONNX) | bit-identical on every machine — soundly backs `intent = replicate` | `neural/int_synth.rs` (QAT weights sink-supplied) |
|
||
| `wai.neural.int_hyper` | integer fixed-point **conditional** codec — whole bitstream→image path integer (integer hyper-decoder σ → integer-σ entropy → integer synthesis) | the integer-entropy contract fully assembled; SOTA quality (PTQ of mbt2018_mean) bit-identical on every machine | `int_hyper_synth.rs` (tables sink-supplied) |
|
||
| `wai.generate.spectral` | deterministic integer GENERATIVE synthesis (`intent=create`) — prompt+seed → integer-LUT spectral composition, no float/ONNX | byte-identical on every machine, pinned to (model, prompt, seed, steps); the create-side of "conformance is a hash" (generation-equivalence) | `generate.rs` (small pinned model bundle) |
|
||
| `wai.neural.elic` | checkerboard context model (hyperprior + 2-pass spatial context) | the JPEG-AI / MLIC++ entropy class | `neural/context.rs` |
|
||
| `wai.neural.mlicpp` | MLIC++ multi-reference entropy (channel-AR slices + checkerboard + global attention) | −13.39% BD-rate vs VVC/VTM-17 | research code, `neural/mlicpp.rs` |
|
||
| `wai.neural.mlicv2` | MLICv2 / MLICv2+ (2025), MetaFormer transform | −20.46% BD-rate vs VTM-17 — current SOTA learned image; shares the mlicpp route | research code, `neural/mlicpp.rs` |
|
||
| `wai.neural.cmic` | Content-Adaptive Mamba (ICLR 2026), SSM transform + SCCTX entropy | learned-image frontier; shares the mlicpp route | arXiv 2508.02192, `neural/mlicpp.rs` |
|
||
| `wai.neural.glc` | Generative Latent Coding — categorical / VQ entropy | <0.05 bpp where JPEG-XL collapses | research code, `neural/glc.rs` |
|
||
|
||
*Video:*
|
||
|
||
| capability | model | win vs zeroth | source |
|
||
|---|---|---|---|
|
||
| `wai.neural.video_bmshj2018` | per-frame bmshj2018 | 1000×+ vs raw RGB, browser-decodable on WebGPU | CompressAI |
|
||
| `wai.neural.dcvc_rt` | DCVC-RT (2025), inter-frame with reference-feature propagation | −21% vs VTM; real-time at 1080p/4K | research code, `neural/video_dcvc.rs` |
|
||
| `wai.neural.dcvc_fm` | DCVC-FM (feature modulation), wide single-model quality range (RGB + YUV) | SOTA-RD neural video; shares the inter-frame route | research code, `neural/video_dcvc.rs` |
|
||
| `wai.video.int_motion` | DETERMINISTIC INTEGER inter-frame — I-frame + integer block motion-compensated P-frames + integer-quantized residual over rANS, no float/ONNX; motion is whole-pel or **half-pel** (`mv_precision`), the latter predicting at the half-grid by integer bilinear interpolation (`(a+b+1)>>1`, `(a+b+c+d+2)>>2`) so real footage — which pans a non-integer number of pixels per frame — costs fewer residual bits while staying byte-exact | byte-identical frame-by-frame on every machine (*frame-state-equivalence*, a per-frame portable hash); the temporal extension of the integer contract, vs the float DCVC family that desyncs down the GOP | `int_video.rs` (whole-pel `tools/wai_int_video_encode.py`; half-pel from real footage `tools/wai_int_video_real_encode.py`) |
|
||
| `wai.video.int_hyper` | NEURAL-KEYFRAME inter-frame — the I-frame is the LEARNED integer codec `int_hyper` decoded byte-exact, the P-frames are integer block-MC residuals on top | a learned keyframe you can put in a receipt + integer inter-frames; whole decode integer, byte-identical everywhere | `int_video::decode_pframes` ∘ `int_hyper_synth::decode_conditional` |
|
||
|
||
**Sink-architecture note:** the inter-frame neural video codecs (DCVC-RT,
|
||
DCVC-FM) decode through `ort` and are **CPU-capable** for native sinks —
|
||
their real-time figures come from GPU execution, but the decode is not
|
||
CUDA-only. They are heavier than per-frame image codecs (a temporal net
|
||
plus reference-feature state), so a browser sink that cannot host the
|
||
temporal net should declare only `wai.neural.video_bmshj2018` (or another
|
||
browser-decodable neural video codec) for the `video` media class. The
|
||
choice is the deployer's, advertised per sink — the envelope is identical.
|
||
|
||
**TAESD is intentionally absent.** TAESD is a distilled SD VAE decoder
|
||
— it inverts a generative pipeline's encoder, not a general image
|
||
codec. Outside the SD pipeline it underperforms JPEG-XL at most
|
||
bitrates while costing ~5 MB of weights and ONNX compute. Don't ship
|
||
codecs for the brand; ship them for the bit budget.
|
||
|
||
**Image/video scope is honest:** zeroth codecs (JPEG-XL, AV1) are
|
||
already SOTA-adjacent in the bitrate bands where most media lives.
|
||
Neural image/video capabilities are registered for the bands where
|
||
zeroth codecs collapse (ultra-low bpp images, bandwidth-constrained
|
||
streaming) — not as defaults.
|
||
|
||
Each capability owns its payload format. Decoder implementations
|
||
(Python source-side, ONNX-export, browser onnxruntime-web) live in
|
||
`tools/wai_<capability>_*.py` and `wai-web/demo/`. New neural
|
||
capabilities are added by registration; the WAI envelope is unchanged.
|
||
|
||
See [`extensions/jwp-receipts.md`](extensions/jwp-receipts.md) for the
|
||
receipt-chain sub-spec covering per-object content hashes, per-group
|
||
Merkle roots, Ed25519 group signatures, and cross-hop preservation.
|
||
See [`extensions/confidentiality.md`](extensions/confidentiality.md) for the
|
||
private-channel sub-spec: MLS (RFC 9420) group keys + SFrame (RFC 9605)
|
||
object encryption, the byte-level framing behind §6.
|
||
|
||
### Interactive & temporal content (extensions)
|
||
|
||
Media that consumes input or moves over time. Each registers its own
|
||
payload format and a deterministic `*-equivalence` conformance criterion
|
||
over the `wai.det.fixed64` fixed-point floor — the reconstruct half of
|
||
the standard. See the linked extension for each.
|
||
|
||
| capability | payload | conformance · extension |
|
||
|---|---|---|
|
||
| `wai.world.scene` / `.replay` / `.live` | WWLD container (op log) | replay-equivalence · [interactive-worlds](extensions/interactive-worlds.md) |
|
||
| `wai.world.model` | generative-world transport: a signed **action trace** (the world CausalOp log) + a declared `model_id` (`world_model.rs`) | the wire carries the *action trace*, not the pixels — it replays under canonical total order to one **session hash** on every machine (replay-equivalence), the generated frames vouched for by a signed, joules-accounted provenance receipt. The neural sibling of `.replay`; with an `int_*` renderer the frames hash-converge too (a generative interactive world you can put in a receipt) |
|
||
| `wai.mesh.glb` | glTF 2.0 Binary (Khronos) | asset, content-addressed (decoder sink-supplied) |
|
||
| `wai.splat.spz` | SPZ (Niantic) | asset, content-addressed; presentation only |
|
||
| `wai.audio.scene` | WSCN scene (objects + trajectories) | mixdown-equivalence · [spatial-audio](extensions/spatial-audio.md) |
|
||
| `wai.audio.score` | WSCR container (note events) | music as instructions; sink synthesizes, mixdown-equivalence · [score](extensions/score.md) |
|
||
| `wai.audio.int_codec` | LEARNED 1-D transform codec — integer transposed-conv synthesis + integer IGDN over a factorized-rANS latent (model + bitstream from `tools/wai_int_audio_export.py`) | **sample-equivalence**: int16 PCM byte-identical on every machine (a portable PCM hash); the audio analog of `wai.neural.int_hyper`, vs the float SoundStream/EnCodec family (`wai.neural.{encodec32,dac,mimi,…}`) that desyncs on ~1e-5 round-off. Pure i64, no float/ONNX (`int_audio.rs`) |
|
||
| `wai.haptic.signal` | WHAP envelope (intensity/sharpness keyframes) | sample-equivalence · [haptics](extensions/haptics.md) |
|
||
| `wai.feed.state` | WWLD, sim `wai.world.sim.feed0` | replay-equivalence · [state-feeds](extensions/state-feeds.md) |
|
||
| `wai.avatar.pose` | WWLD, sim `wai.world.sim.skeletal0` | pose-equivalence · [avatars](extensions/avatars.md) |
|
||
| `wai.splat.4d` | W4DS container (per-Gaussian keyframed tracks) | frame-state-equivalence · [volumetric](extensions/volumetric.md) |
|
||
| `wai.splat.int_codec` | LEARNED Gaussian-splat ATTRIBUTE codec — a learned transform over the `[14,S,S]` attribute image (pos/scale/rot/color/opacity), integer synthesis (int_hyper machinery, 14 channels) over a factorized-rANS latent (`int_splat.rs`; model + bitstream from `tools/wai_int_splat_export.py`) | **splat-equivalence**: the decoded attribute tensor is byte-identical on every machine (a portable cloud hash) — the int_hyper of 3D, vs the float SOG / self-organizing-Gaussian codecs whose decode desyncs. The float rasterizer stays sink-supplied presentation; the *attributes* are the contract. Pure i64, no float/ONNX |
|
||
| `wai.film.linear` | WFLM container (sealed world + camera track + frame schedule) | film-equivalence · [linear-film](extensions/linear-film.md) |
|
||
| `wai.film.reel` | WREL container (sealed world + a sequence of shots = camera track + schedule each) | reel-equivalence (film-equivalence with cuts) · [linear-film](extensions/linear-film.md) |
|
||
|
||
And the verify half — a signed, energy-accounted lineage for opaque
|
||
captured content WAI does **not** reconstruct (content-addressing +
|
||
receipts + measured joules): [`extensions/provenance.md`](extensions/provenance.md)
|
||
(`wai.asset.provenance`).
|
||
|
||
### Immersive audio, cinema, volumetric, haptics, HDR (registered, sink-supplied)
|
||
|
||
The same "name the capability, the sink supplies the decoder" pattern extends
|
||
to the standard carriers of the immersive / theatrical / volumetric media a
|
||
full distributor needs. Each names an open reference where one exists; the
|
||
proprietary and SEP-pool entries are flagged, never defaults. Payload is the
|
||
named standard's canonical bytes.
|
||
|
||
| class | capabilities |
|
||
|---|---|
|
||
| immersive audio | `wai.audio.iamf` (IAMF/Eclipsa, royalty-free) · `wai.audio.ac4` (Dolby AC-4, proprietary) · `wai.audio.ivas` (3GPP IVAS, SEP-pool) |
|
||
| cinema mastering | `wai.image.jp2` · `wai.video.j2k` (JPEG 2000 / DCP, OpenJPEG) |
|
||
| volumetric / 3D | `wai.mesh.draco` (royalty-free) · `wai.pc.gpcc` · `wai.pc.vpcc` (MPEG point clouds) · `wai.splat.sog` (Gaussian-splat compression, candidate) |
|
||
| haptics | `wai.haptic.mihs` (MPEG-I Haptics, ISO/IEC 23090-31; its 23090-33 ships bit-exact conformance vectors) |
|
||
| HDR dynamic metadata | `wai.meta.hdr10plus` (royalty-free) · `wai.meta.dovi` (Dolby Vision, proprietary) — **companion descriptors** to a video payload, not standalone media |
|
||
|
||
Every registered capability also carries an IP class —
|
||
`codecs::capability_license(cap)` ∈ {royalty-free, patent-pool, proprietary,
|
||
non-commercial}, with `is_royalty_free(cap)` as the predicate. It is a registry
|
||
property (not a per-file manifest claim — a codec's licence can't be honestly
|
||
asserted in an envelope's header), so a deployer can audit a title or a whole
|
||
catalogue in code: encode only to royalty-free capabilities, or flag every
|
||
pool/proprietary one. The per-title choice of which toll road to pay is a
|
||
property of the format, enforceable, not a policy on a slide.
|
||
|
||
See [`research/media-codec-registry.md`](research/media-codec-registry.md) for
|
||
the per-capability standard / spec number / verified royalty status / reference
|
||
library and the remaining spec follow-up (companion-component binding for the
|
||
HDR / audio metadata descriptors).
|
||
|
||
---
|
||
|
||
## 6. Confidentiality (OPTIONAL — encrypted payloads / private channels)
|
||
|
||
By default a WAI payload is **plaintext**: any sink that advertises the
|
||
named capability (§4–§5) can decode it. This is correct for public
|
||
media — a shared world, a broadcast film. Some channels are instead
|
||
**private**: only an intended group may recover the content, and any
|
||
relay or multiplexer that carries it MUST be able to route, meter, and
|
||
attest the bytes **without** reading them.
|
||
|
||
Confidentiality is an OPTIONAL layer that is **orthogonal to the
|
||
capability**. It wraps the payload bytes; the capability still names how
|
||
to decode the *plaintext* once recovered. A sink decrypts first, then
|
||
runs capability dispatch (§4) on the plaintext.
|
||
|
||
### 6.1 Manifest field
|
||
|
||
A manifest MAY carry a `security` object:
|
||
|
||
```json
|
||
"security": { "encryption": "mls-sframe", "kid": 0 }
|
||
```
|
||
|
||
- `security.encryption` — encryption scheme id. Absent, `null`, or
|
||
`"none"` ⇒ the payload is plaintext (the default; §1–§5 unchanged).
|
||
`"mls-sframe"` ⇒ the payload is an SFrame (RFC 9605) ciphertext object
|
||
whose group key is agreed by MLS (RFC 9420) — the
|
||
`draft-jennings-moq-e2ee-mls` binding.
|
||
- `security.kid` — the SFrame key id selecting which sender/epoch key
|
||
opens the object. It is also carried in the SFrame header; the
|
||
manifest copy lets a multiplexer route without parsing the payload.
|
||
|
||
`media`, `intent`, `conditioning.kind`, and
|
||
`model_requirement.capability` continue to describe the **plaintext**
|
||
codec. They are NOT encrypted and remain visible for routing —
|
||
confidentiality protects the *content*, not the *shape*.
|
||
|
||
### 6.2 Keys are a requirement of existence
|
||
|
||
Exactly as the model behind a neural capability is never transported
|
||
(§1), the **group key is never transported in the WAI file**. Group
|
||
membership is established out of band via MLS; each member derives the
|
||
32-byte SFrame base key from the group's exporter secret under the label
|
||
`"moq-jwp sframe base key"`. A sink that is not a group member cannot
|
||
derive the key and the file is **inert at that sink** — the
|
||
confidentiality analog of a missing capability.
|
||
|
||
### 6.3 Relay transparency and attestation
|
||
|
||
A WAI relay or multiplexer that carries an encrypted payload MUST treat
|
||
it as opaque: it MUST NOT require the plaintext to route, meter, or
|
||
attest, and MUST NOT attempt capability dispatch on ciphertext. The JWP
|
||
receipt chain ([`extensions/jwp-receipts.md`](extensions/jwp-receipts.md))
|
||
commits over the **ciphertext** content hash, so per-object delivery,
|
||
energy, and integrity are attested end-to-end without any relay holding
|
||
the key. Content secrecy (SFrame/MLS) and delivery attestation (JWP) are
|
||
independent layers over the same bytes and compose: a relay proves it
|
||
forwarded the exact sealed bytes it was given while never learning what
|
||
they say.
|
||
|
||
### 6.4 Decrypt-then-dispatch
|
||
|
||
A confidentiality-aware sink MUST, before running §4:
|
||
|
||
1. If `security.encryption` is absent / `null` / `"none"`, proceed to §4
|
||
on the payload unchanged.
|
||
2. Else, if the sink does not implement the named scheme, or holds no
|
||
key for `security.kid`, the file is **inert at this sink** — return a
|
||
clear "no key / unsupported encryption" error. It MUST NOT feed
|
||
ciphertext to a codec.
|
||
3. Else recover the plaintext payload via the named scheme (for
|
||
`mls-sframe`: SFrame `open` under the member's base key), then run §4
|
||
on the recovered plaintext.
|
||
|
||
A sink that does not implement confidentiality at all MUST refuse an
|
||
envelope whose manifest carries a non-`none` `security.encryption`
|
||
cleanly, rather than mis-decode ciphertext.
|
||
|
||
Byte-level SFrame framing, the SFrame key schedule, and the MLS binding
|
||
(including per-sender keying for multi-sender channels) are specified in
|
||
[`extensions/confidentiality.md`](extensions/confidentiality.md). The
|
||
reference implementation is the `moq-sframe` (SFrame) and
|
||
`joule-comm-mls` (MLS exporter → base key) crates, with browser bindings
|
||
in `joule-comm-mls-wasm`; `Track::e2e_encrypted` is the switch that
|
||
selects this path. Live: https://wai.transaction.science/private-channel
|
||
|
||
---
|
||
|
||
## 7. Conformance
|
||
|
||
- A **conforming sink** MUST: implement the container (§2), capability
|
||
dispatch (§4), and the mandatory floor (§5).
|
||
- A **conforming encoder** MUST emit containers (§2) that any
|
||
conforming sink can read; the payload MUST be the canonical byte
|
||
stream for the registered capability.
|
||
- Conformance is verified by **bit-exact decode-equivalence with the
|
||
reference library** named in §5 for each registered capability. The
|
||
WAI Rust reference impl in `wai-rs/` is built on those very
|
||
libraries and ships a test suite that exercises every registered
|
||
capability through the full WAI envelope (`cargo test --lib`).
|
||
|
||
### Replicate-soundness — the integer-entropy contract (normative)
|
||
|
||
`intent = replicate` claims the sink reproduces the *exact* source bytes. For a
|
||
**neural** capability that claim is only sound if the decode is byte-identical
|
||
on every machine — and that is **not** automatic. A learned codec's entropy
|
||
decode desyncs the instant the decoder's scale-bucket / σ computation drifts
|
||
from the encoder's by one float ULP: the bucket assignment flips and the rest
|
||
of the stream corrupts. So a neural decode that runs **float** inference is
|
||
reproducible only on the *same build*, never guaranteed across hardware.
|
||
|
||
Therefore a neural capability MAY back `intent = replicate` **only** if its
|
||
entire decode path — entropy parameterization *and* synthesis — is
|
||
integer / fixed-point, with no float operation anywhere (the **integer-entropy
|
||
contract**). The reference impl factors the halves into ORT-free, pure-i64
|
||
modules a codec composes: `int_entropy` (the deterministic scale→bucket step
|
||
that removes the float-σ desync), `int_synth` (integer synthesis), and the
|
||
integer rANS — assembled into a full conditional decode by `int_hyper_synth`
|
||
(`wai.neural.int_hyper`: factorized rANS-decode `z` → integer hyper-decoder
|
||
`h_s` → σ,μ → integer-σ bucket → rANS-decode residual → `y_hat = r + μ` →
|
||
integer synthesis — both bitstreams entropy-coded, no float anywhere). This is
|
||
a property of the capability, classified in the
|
||
registry as `codecs::capability_replicate_class(cap) -> ReplicateClass`:
|
||
|
||
- **`NeuralIntegerExact`** — integer by construction; byte-identical on every
|
||
machine; the only neural class that soundly backs cross-hardware `replicate`.
|
||
(`wai.neural.int_synth` is synthesis only; `wai.neural.int_hyper` is the full
|
||
conditional codec — σ source, entropy, and synthesis all integer.)
|
||
- **`GenerativeDeterministic`** — the *create*-side of byte-exact conformance.
|
||
A generator (`intent = create`) whose entire pipeline is integer/fixed-point
|
||
and pinned to `(model, prompt, seed, steps)`, so the **generated** content is
|
||
byte-identical on every machine. There is no original to reconstruct, yet the
|
||
output hash is portable and receiptable — *generation-equivalence*. The
|
||
fixed-point sampler is mandatory: a float RNG or float sampling step desyncs
|
||
the stream exactly as a float σ does. (`wai.generate.spectral`: a pure-integer
|
||
spectral synthesis — prompt+seed draw integer-LUT sinusoid components by a
|
||
`splitmix64` PRNG; the float `sin()` that bakes the LUT runs once at
|
||
model-build, never at generation.) Distinct from `Behavioral`, which conforms
|
||
by similarity and never reproduces bytes.
|
||
- **`NeuralFloat`** — runs float inference; exact only on the same build. An
|
||
encoder MUST NOT emit `intent = replicate` for one of these; `perceptual` /
|
||
"exact on this build" is the honest claim.
|
||
- **`StandardDefined`** — reconstruction is fixed by the named codec/standard
|
||
(the floor + menu codecs) or by WAI's deterministic floor (§ extensions);
|
||
the neural float hazard does not apply.
|
||
- **`Behavioral`** — a sink-generator path that conforms by similarity, not
|
||
bytes (`wai.semantic.*`).
|
||
|
||
A conforming sink that receives `intent = replicate` for a `NeuralFloat`
|
||
capability MUST refuse the replicate claim (decode as perceptual or reject).
|
||
The reference impl enforces this per-envelope in `decode_envelope_strict`, which
|
||
rejects a `replicate` envelope whose pinned prior is not integer-exact
|
||
(`DeterminismClass`) — and a `NeuralFloat` capability cannot honestly carry an
|
||
integer-exact prior. The registry class is the *static* audit of the same
|
||
property: `wai capabilities` prints it per row and reports the count of neural
|
||
integer-exact capabilities, so a deployer can require "dispatch `replicate` only
|
||
to a cross-hardware-sound decode" in code, exactly as it audits royalty status.
|
||
|
||
This is the standard fixing the one axis the learned-codec field leaves
|
||
implicit: a neural codec that is *integer all the way down* is the only one that
|
||
can put a reconstruction in a receipt and have it verify on someone else's
|
||
machine.
|
||
|
||
---
|
||
|
||
## 7.1. Multi-rendition envelope (v1.1 extension)
|
||
|
||
The v1.0 single-payload envelope is sufficient when one source produces
|
||
one rendition for one capability. v1.1 adds an OPTIONAL multi-payload
|
||
form for cases where the source emits the SAME content in multiple
|
||
renditions and lets the sink pick — typically because the sink's
|
||
compute budget, bandwidth budget, or runtime preference (browser-
|
||
native vs WebGPU vs WebNN vs native ML) differs at decode time.
|
||
|
||
The `model_requirement.fallback` field in v1.0 is **declarative** — it
|
||
names a capability the sink CAN look for. v1.1 makes fallback (and
|
||
multi-rendition selection generally) **executable** by carrying every
|
||
declared capability's payload in one envelope.
|
||
|
||
### Self-contained-ecosystem note
|
||
|
||
In a controlled-deployment ecosystem (every sink ships from one
|
||
authority and therefore has a known capability set) the multi-rendition
|
||
form is NOT a "graceful fallback for missing capability" — every sink
|
||
has every required capability. Renditions exist for **policy selection**:
|
||
high-quality on a desktop sink with WebGPU; low-quality on a phone sink;
|
||
quality-vs-latency by bandwidth headroom; native vs WebNN by which
|
||
runtime is initialized. The sink picks by deployer-defined policy, not
|
||
by which capability happens to be installed.
|
||
|
||
### v1.1 wire format
|
||
|
||
```
|
||
+--------+----------------+-------------------+----------------+----...---+
|
||
| "WAI2" | u32 man_len | manifest (JSON) | rendition table| payloads |
|
||
+--------+----------------+-------------------+----------------+----...---+
|
||
```
|
||
|
||
- Magic is `WAI2` (distinct from v1.0's `WAI1`; sinks dispatch by magic).
|
||
- Manifest is JSON with a single `renditions` array of self-contained
|
||
rendition entries, in deployer-preferred order:
|
||
```json
|
||
{
|
||
"wai": "1.1",
|
||
"media": "audio",
|
||
"intent": "replicate",
|
||
"renditions": [
|
||
{ "capability": "wai.neural.encodec32", "kind": "encodec_tokens" },
|
||
{ "capability": "wai.audio.opus", "kind": "opus" }
|
||
],
|
||
"target": { "sr": 48000, "dur": 5.0 }
|
||
}
|
||
```
|
||
Each entry has its own `capability` (the dispatch key) and `kind`
|
||
(the codec id matching the bytes in the corresponding payload).
|
||
- Rendition table: `u16 n_renditions | n × (u32 offset, u32 length)`,
|
||
offsets relative to the start of the payloads block. The table's
|
||
i-th entry corresponds to `renditions[i]` in the manifest.
|
||
- Payloads block: the rendition byte ranges, packed contiguously.
|
||
- `n_renditions` MUST equal the manifest's `renditions.length`.
|
||
|
||
### Selection algorithm
|
||
|
||
A v1.1-aware sink MUST:
|
||
|
||
1. Read the manifest, get the ordered list of `model_requirement`
|
||
entries.
|
||
2. Walk the list in order; pick the first entry whose capability the
|
||
sink either advertises OR whose declared backend the sink prefers
|
||
under its deployer policy.
|
||
3. Read the corresponding rendition's bytes from the payload block.
|
||
4. Dispatch as in v1.0 §4.
|
||
|
||
A v1.0 sink that encounters a `WAI2` envelope MUST refuse it cleanly
|
||
(unknown major). No silent fallback to the first payload — that would
|
||
hide a major-version mismatch.
|
||
|
||
### Companion components (descriptors bound to a payload)
|
||
|
||
A `WAI2` component carries an OPTIONAL `role`. Absent ⇒ `"rendition"` (a
|
||
selectable alternative of the same content — the default above).
|
||
`"companion"` marks a **descriptor applied *with* the chosen rendition, not
|
||
instead of it**, naming the component it binds to in `companion_of`. This
|
||
resolves the one media class that is not a standalone payload: **HDR dynamic
|
||
metadata** (`wai.meta.hdr10plus` / `wai.meta.dovi`, SMPTE ST 2094) and
|
||
immersive-audio metadata accompany a video/audio payload rather than replacing
|
||
it. Carried as companions, the descriptor and its target ride in the **same
|
||
envelope**, so the binding is intrinsic — not a spoofable sidecar.
|
||
|
||
The selection algorithm is unchanged: a sink picks a rendition among the
|
||
`role != "companion"` entries, then applies every companion whose
|
||
`companion_of` names the chosen component (e.g. the HDR10+ block for the AV1
|
||
video the sink picked). `pick`/`primary` never return a companion. Static HDR
|
||
characteristics (ST 2086 mastering display, HLG transfer) stay in-band in the
|
||
video bitstream / a manifest color field and need no companion.
|
||
|
||
### v1.0 compatibility
|
||
|
||
v1.0 envelopes (`WAI1`) remain valid and are unchanged. Encoders
|
||
SHOULD emit `WAI1` when only one rendition is present (simpler form,
|
||
wider sink support). `WAI2` is for sources that genuinely benefit from
|
||
shipping multiple renditions per file.
|
||
|
||
---
|
||
|
||
## 8. Versioning
|
||
|
||
- The `wai` manifest field is `MAJOR.MINOR`. A reader MUST reject an
|
||
unknown MAJOR. A reader MUST accept an unknown MINOR by ignoring
|
||
fields it does not understand, provided MAJOR matches.
|
||
- The container format (§2) and the manifest schema (§3) are frozen
|
||
for all of `1.x`.
|
||
- New capabilities (§5) MAY be added in any MINOR revision. Existing
|
||
capabilities MUST NOT be redefined — once a capability string is
|
||
registered for a codec, its payload format is fixed forever.
|
||
- Removing or repurposing an existing capability requires a new MAJOR.
|
||
|
||
---
|
||
|
||
## Appendix A — Reference implementation
|
||
|
||
`wai-rs/` (Rust). Builds as `lib`, `cdylib`, `staticlib` so the C ABI
|
||
in `wai-rs/src/ffi.rs` drops in as `libwai.dylib` / `.so` / `.dll` and
|
||
can be called from any language. The crate wraps:
|
||
|
||
- **image**: `image` crate (PNG, JPEG, AVIF via `ravif`), `jpegxl-rs`
|
||
(libjxl 0.11.x).
|
||
- **audio**: `opus` (libopus 1.x), `claxon` + `flac-bound` (libFLAC).
|
||
- **video**: `rav1e` (AV1 encode) + `dav1d` (AV1 decode).
|
||
- **text**: `zstd` (libzstd), `xz2` (liblzma).
|
||
|
||
Run `cargo test --lib` (with `RUSTFLAGS="-L /opt/homebrew/opt/flac/lib"`
|
||
on macOS, or via the committed `.cargo/config.toml`).
|
||
|
||
## Appendix B — Why a *capability menu*, not a custom codec
|
||
|
||
Earlier drafts of WAI defined custom transform + entropy stages for
|
||
each medium. That direction was dropped: re-implementing JPEG / MPEG /
|
||
Opus poorly is strictly worse than calling the field's mature
|
||
libraries. WAI's value is the envelope + capability dispatch + the
|
||
neural-shared-prior model, all of which are absent from existing
|
||
standards. The zeroth condition's purpose is **availability**, not
|
||
codec novelty.
|
||
|
||
## Appendix C — License
|
||
|
||
Apache-2.0. The standard and reference implementation are open;
|
||
royalty-free implementation is a precondition for adoption (avoiding
|
||
the H.264/H.265 royalty trap; following the VP9/AV1/AVIF/JPEG-XL open-
|
||
codec precedent).
|