Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ surface and zero-copy texture import, land before the cut.
- [Release audit findings](/quest/m1/release-audit/README.md) - resolve newly identified resource, parser, playback, and interoperability risks before the cut
- [Pre-cut audit findings](/quest/m1/cut-audit/README.md) - fix the crashes, hostile-input costs, and correctness bugs the 2026-10-24 audit of main found
- [Cancelled moq-transport requests stop](/quest/m1/ietf-request-cancel.md) - a cancelled request releases its state even when the peer withholds credit
- [Datagrams past object 0 never pose as object 0](/quest/m1/datagram-object-drop.md) - a hop or reader that cannot carry an Object ID delivers only object 0 of a moq-transport datagram group
- [Empty segments refused](/quest/m1/empty-segments.md) - `room//cam` fails loud instead of naming `room/cam`
- [In-band auth](/quest/m1/auth/README.md) - a session tells its peer what it may publish and subscribe to, unions tokens presented in band, and fails loud on an out-of-scope publish
- [Cluster routing](/quest/m1/cluster-routing/README.md) - prove shared routing contracts, implement per-origin routes, and connect outbound local clusters
Expand Down
54 changes: 54 additions & 0 deletions quest/m1/datagram-object-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# [S] Datagrams past object 0 never pose as object 0

## Goal

A moq-transport datagram group with several objects reaches every surface
that keeps Object IDs intact, and every surface that cannot carry an Object ID
delivers only object 0. Today a moq-lite hop without the `ietf` extension
forwards every object as a plain datagram at the same sequence, and the
plain Rust datagram reader hands out every object's payload at one sequence
with no way to tell them apart. If object 0 is lost or arrives late, object 1
is delivered as the group's datagram, which is silent substitution, not loss.

Out of scope: exposing an Object ID on the public `Datagram` in Rust, JS, or
the bindings; refusing the track; a dropped-datagram stat; multi-object
datagram support in JS.

## Plan

Decided 2026-10-26 (maintainer, importing
[moq-dev/moq#6885](https://github.com/moq-dev/moq/issues/6885)):

- Keep the passthrough from
[moq-dev/moq#5494](https://github.com/moq-dev/moq/pull/5494). Rust relays
already carry Object IDs between moq-transport peers and across a lite-07
hop with the `ietf` extension. The report was against release 0.17, whose
IETF ingress still dropped every object past 0. Rejected: refusing at
ingress everywhere, which deletes that passthrough.
- Drop, don't refuse. A hop that cannot carry the Object ID sends only
object 0, matching how a hop drops an oversized datagram or a status object
it cannot carry. The rest of the track keeps flowing. Rejected: aborting the
track with `Unsupported`, which would also cost the lite viewer object 0.
- Surfaces:
- `Subscription::serve_datagram` (`rs/moq-net/src/lite/publisher.rs`),
when `ietf` is off: skip a datagram whose `wire.object_id` is past 0, as
it already skips a status.
- `track::Subscriber::poll_recv_datagram` (`rs/moq-net/src/model/track.rs`):
skip a stored datagram past object 0, as it already skips a status.
- JS's IETF subscriber already drops past object 0 and needs no change.
- Debug log like the other per-hop drops; no new stat.
- Fix the docs inline: `doc/concept/standard.md` (the objects and datagrams
bullet says plain readers and lite peers see "normal datagram payloads")
and the `model/datagram.rs` module doc. The cursor's private
`poll_recv_datagram` comment says ranges match "by Object ID", which the
code does not do; make it say what the code does.
- Test both surfaces with a group carrying objects 0 to 2, including object
0 arriving last and object 0 never arriving.

## Closes

- [#6885](https://github.com/moq-dev/moq/issues/6885) - moq-relay silently drops datagram objects after object 0 in a group

## Related

- [moq-transport 18 and 22 only](/quest/m1/ietf-drop/README.md) - the reporter's draft 16 is among the drafts that quest deletes
1 change: 1 addition & 0 deletions quest/m1/ts-reliability/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ catalog linger (#5305).
- [PAT changes](/quest/m1/ts-reliability/pat-lifecycle.md) - a revised PAT never leaves a broadcast meaning another program
- [TS workflow passes](/quest/m1/ts-reliability/validation-green.md) - the scheduled TS lanes pass on main again, with no lane loosened
- [Export SI order](/quest/m1/ts-reliability/export-si-order.md) - a TS export sends SI and media after its PMT and a PCR interval, so a hop keeps first emissions
- [A stitched switch keeps playing the old instance](/quest/m1/ts-reliability/epoch-switch-drain.md) - `export ts --stitch` plays the old epoch until the new one's clock is acquired, so a backup starting leaves no hole

## Related

Expand Down
50 changes: 50 additions & 0 deletions quest/m1/ts-reliability/epoch-switch-drain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# [M] A stitched switch keeps playing the old instance

## Goal

When `moq export ts --stitch` follows a newer epoch, the output keeps playing
the old instance until the new one's clock is acquired, then switches with the
marked program discontinuity it has today. A switch away from a healthy leg,
such as a redundant importer starting or restarting, leaves no hole in the
output. A switch after a failure costs only what the failed leg did not
deliver. Today `Export::followed`
(`rs/moq-mux/src/container/ts/export.rs`) replaces the whole export on a
switch, discarding the old leg's held backlog (up to one `--delay`) and
holding output while the new clock is acquired.

Out of scope: changing route order, timestamp continuity across epochs, and
hitless failover between importers.

## Plan

Decided 2026-10-26 (maintainer, importing
[moq-dev/moq#6877](https://github.com/moq-dev/moq/issues/6877)):

- Routing stays as decided on 2026-10-19: the newest epoch wins, so starting
or restarting a backup importer is a switch. Rejected: a standby epoch that
routes only when no live epoch remains (a second, publisher-declared
selection policy ahead of epoch on the wire), and receiver-select in the CLI
(a multi-broadcast `export ts`). Separate paths chosen by the subscriber
stay documented in `doc/setup/redundancy.md`.
- The new instance opens a new jitter generation instead of a new export,
reusing the generation machinery `rs/moq-mux/src/jitter.rs` already has for
in-source timeline restarts: generations go out in turn, and the new clock
is never ahead of a deadline already given out.
- The old instance's subscription keeps feeding its generation until the new
generation is acquired, bounded by the `--follow` window, then stops.
Rejected: playing out only what the buffer holds at the switch.
- Distinct epochs promise no timestamp relation, so the switch stays a program
change: new PMT version, every PID flagged, PCR discontinuity. Do not align
the legs' timestamps; that is the cross-importer alignment dropped on
2026-10-19.
- The redundant failover integration test in
`rs/moq-cli/tests/integration/export.rs` prints each switch's output gap
without asserting it. Assert that a switch away from a healthy leg leaves
no gap, behind a bufferbloat impairment.
- Fix inline: `doc/setup/redundancy.md` and `doc/bin/cli.md` say the switch
is not hitless and that starting a backup causes it; say what a switch now
costs.

## Closes

- [#6877](https://github.com/moq-dev/moq/issues/6877) - a redundant ingest pair: a follower switches without emptying its delay (the standby-epoch ask is declined)
Loading