joule-moq speaks draft-ietf-moq-transport-23 (2 November 2026) beside -22, -18 and -16, in a
codec module of its own (draft23) with a bridge to the -22 model the rest of the crate is
written in, which made the smaller diff. -23 is offered and chosen first. Each change of -23's
§A.1 is implemented and tabled in the README with how the bridge carries it: the varint
control-message Length and MAX_CONTROL_MESSAGE_SIZE, FETCH answered by REQUEST_OK, REQUEST_ERROR's
Error Details, NAMESPACE's parameters, PAUSED for FORWARD, SUBSCRIBE_TRACKS_ID, the counted
FILL_PARAMETERS and the new parameter lists, non-empty Track Names, GOAWAY from a request's
receiver only, the fetch stream's new encoding (Object ID Delta + 2, delta-coded End of Range,
End of Gone Range, End of Group, End of Track), property scope and repetition, grease outside
the Mandatory range, and the session codes that replace PROTOCOL_VIOLATION.
The -23 corpus holds 119 vectors; moqt23_check.py, a second decoder written from -23's text,
reads all of them, and its 66 negative vectors (the planted faults, each -22 form a -23 endpoint
meets among them) are each refused with -23's code; joule-code-conformance runs it.
The relay bridges -23 sessions over QUIC, WebTransport and the WebSocket binding, allows a -23
session overlapping namespace subscriptions, closes one whose requester sends GOAWAY on its own
request stream, and records each session's real draft in its summary. The interop client, the
ingest gateway (`[relay] draft`) and the browser client (`setDraft`, `moqt=23`) speak -23;
local.sh runs every draft and pair on a relay bound to port 0, and counts a tampered run as
refused only on the client's own verdict. joule-moq and joule-moq-relay are clippy-clean.
Co-Authored-By: Claude Opus 5.5 <[email protected]>