Skip to content
Merged
7 changes: 1 addition & 6 deletions quest/m0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,9 @@ Each lands its fixes in its own PR and plans only what needs a decision.

## Required

- [qmux 0.5 upstream](/quest/m0/qmux-credit-backport-upstream.md) - old-release publication, independent of the main fix

- [qmux release backport](/quest/m0/qmux-credit-backport.md) - adopt the 0.5 fix independently of the next breaking cut

- [CI cost and latency](/quest/m0/ci/README.md) - cloud CI runs only in the merge queue as one `just ci` pass, expensive checks run nightly and gate `release`, caches move to R2, and runners are chosen last
- [Release builds link](/quest/m0/release-link.md) - the Linux zigbuild release binaries and moq-gst packages link again after the 2026-10-11 nixpkgs bump, so the next release cut can publish
- [web-transport releases the qmux fixes](/quest/m0/qmux-credit-upstream.md) - waiting on #412 to publish the patched 0.6.x that main adopts
- [qmux credit](/quest/m0/qmux-credit.md) - main adopts qmux 0.6 credit and close fixes; the 0.5 backport is independent
- [Namespace advert errors](/quest/m0/namespace-advert-error.md) - one PUBLISH_NAMESPACE stream failing withdraws only that namespace instead of closing the Rust session
- [Broadcast epochs](/quest/m0/broadcast-epoch/README.md) - every first-party publisher that can restart mints a fresh route epoch, the newest wins a path, and only routes with the same epoch resume a subscription
- [Performance audit](/quest/m0/audit-perf.md) - benchmarks that regressed since the last run are explained, fixed, or planned, and unbenched hot paths get coverage
- [Compile time audit](/quest/m0/audit-compile-time.md) - build-time hotspots are measured against a baseline and the worst are fixed or planned
Expand Down
38 changes: 38 additions & 0 deletions quest/m0/namespace-advert-error.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# [S] One namespace's stream error ends only its own advertisement

## Goal

On moq-transport, a Rust publisher whose PUBLISH_NAMESPACE request stream
fails while it waits for the first answer withdraws just that namespace, as
JS does, and keeps advertising and withdrawing every other namespace.
Today `advertise_namespace` propagates the error with `?` out of
`run_publish_namespaces` (`rs/moq-net/src/ietf/publisher.rs`), and the
session races that loop, so one reset PUBLISH_NAMESPACE stream closes the
whole session and aborts every track on it. When the error is a
`ProtocolViolation`, moq-tokio treats it as terminal and stops reconnecting.

## Plan

Found by [#5998](https://github.com/moq-dev/moq/pull/5998), which handles
GOAWAY throughout IETF request lifetimes; the bug predates it. Decided
2026-10-20 (maintainer): m0, since a single hostile or buggy peer stream ends
the session on main. JS already contains the failure per namespace
(`#advertise` in `js/net/src/ietf/publisher.ts`); match it.

- Separate a request's own failure (its stream reset or ended, a refusal)
from a session failure (the control stream, a protocol violation that
closes the session at the source). The first ends that namespace's request
and leaves the loop running; the second still ends the loop.
- Re-offer a namespace whose request failed on the same backoff #5998 added
for a draft-18+ stream that ends while idle (100 ms, doubling to 5 s), so a
peer that resets every advertisement gets backed-off re-offers, not a
request loop.
- Regression test: two namespaces advertised, the peer resets the first's
request stream before answering; the second is still answered and
withdrawn normally, and the first is offered again after the wait.

Public API: none. Wire: none.

## Related

- [Drain cleanup](/quest/m1/drain-cleanup.md) - what a drain does to sessions at its deadline
12 changes: 0 additions & 12 deletions quest/m0/qmux-credit-backport-upstream.md

This file was deleted.

22 changes: 0 additions & 22 deletions quest/m0/qmux-credit-backport.md

This file was deleted.

12 changes: 0 additions & 12 deletions quest/m0/qmux-credit-upstream.md

This file was deleted.

63 changes: 0 additions & 63 deletions quest/m0/qmux-credit.md

This file was deleted.

9 changes: 6 additions & 3 deletions quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,16 @@ lands before the cut.

- [Epoch correctness](/quest/m0/broadcast-epoch/README.md) - publisher identity, duplicate suppression, and catalog pinning gate the breaking cut
- [Release builds](/quest/m0/release-link.md) - package artifacts can be built
- [qmux credit](/quest/m0/qmux-credit.md) - dropped/stopped streams return credit and close is delivered

- [moq-net follows announced instances](/quest/m1/net-announced-follow.md) - the Rust equivalent of JS `request(path, { announced: true })`, replacing the follow loops in moq-ffi and moq-c
- [Sink restart follow](/quest/m1/sink-restart-follow.md) - moq-cli's server and push sinks follow an epochless `Restart` where their output can mark it, and fail loud otherwise
- [Cluster routing](/quest/m1/cluster-routing/README.md) - prove shared routing contracts, implement per-origin routes, and connect outbound local clusters
- [Routing guide](/quest/m1/routing-guide.md) - concepts and practical outbound federation setup
- [Controlled time](/quest/m1/time/README.md) - every crate and package reads time through moq-clock or @moq/clock, with regression tests for the changed contracts
- [Own the QUIC stack](/quest/m1/quic/README.md) - quinn hard-forked in-tree as `moq-quic`, carrying BBR, reliable reset, hierarchical scheduling, peer limits, and endpoint sharding
- [TS qmux in the monorepo](/quest/m1/ts-qmux.md) - `@moq/qmux` moves into `js/` and `js/net` stops depending on moq-dev/web-transport
- [qmux on the QUIC stream state machine](/quest/m1/quic-qmux.md) - qmux runs in-tree over `moq-quic`'s stream state machine, returning credit for every byte and delivering its close frame
- [Drop moq-native's noq feature](/quest/m1/native-noq-feature.md) - the empty default `noq` feature is removed
- [Finalize moq-lite-07](/quest/m1/lite07-finalize.md) - when the maintainer cuts it, lite-07 negotiates as `moq-lite-07` and the next release ships it
- [moq-transport passthrough](/quest/m1/ietf-extension/README.md) - object IDs, properties, end status, datagram objects, and unknown track properties survive moq-transport -> moq-relay (and a relay cluster) -> moq-transport; moxygen's moq-test sections 1-7 pass nightly, except cases that use a subgroup other than 0
- [Refresh](/quest/m1/refresh/README.md) - a join asks for a fresh group once the current group's deltas exceed a publisher-advertised byte ratio, at every hop; replaces `Demand::used`/`unused` and moq-json's `delta_ratio`
Expand Down Expand Up @@ -91,11 +93,12 @@ lands before the cut.
- [Handshake deadline covers admission](/quest/m1/handshake-admission-deadline.md) - `listen.timeout` bounds a connection through auth admission on both listeners, replacing the hardcoded admission timeout
- [Restart reset](/quest/m1/stateless-reset-key.md) - a relay restarted with the same `listen.reset_key` stateless-resets its predecessor's connections, so clients reconnect within an RTT instead of the idle timeout
- [Drain cleanup](/quest/m1/drain-cleanup.md) - sessions force-closed at the drain deadline record their lease end and bytes before the relay or CLI exits, while unfinished handshakes stay bounded
- [GOAWAY coverage](/quest/m1/goaway-coverage.md) - every IETF request stream handles GOAWAY, a closed control stream is a violation, and the draft-18 cutoff is honored
- [Rust redirect loops](/quest/m1/tokio-redirect-loop.md) - moq-tokio escalates its backoff when GOAWAY redirects bounce between peers, as JS does
- [JS request owner](/quest/m1/js-request-owner.md) - every JS IETF request stream has one owning handle with an `ended` promise and one closer
- [Container reads drop backfill](/quest/m1/read-backfill.md) - the JS container consumer drops groups below its read cursor like Rust
- [Rust request credit](/quest/m1/rs-request-credit.md) - a moq-net request fails at once without stream credit instead of waiting
- [A stalled subscriber holds bounded state](/quest/m1/egress-held-state.md) - group machines and bytes a credit-withholding downstream makes a publisher hold plateau at what its credit and the latency budget allow, on lite and moq-transport
- [qmux no-wait opens](/quest/m1/qmux-no-wait.md) - @moq/qmux rejects an over-limit create when waitUntilAvailable is false, like Chrome
- [qmux no-wait opens](/quest/m1/qmux-no-wait.md) - the in-tree @moq/qmux rejects an over-limit create when waitUntilAvailable is false, like Chrome
- [Timed-out requests clean up](/quest/m1/legacy-request-timeout-cleanup.md) - on drafts 14-16, Rust and JS send PUBLISH_NAMESPACE_DONE or UNSUBSCRIBE_NAMESPACE for a timed-out request before its local reset
- [TS fidelity and recovery](/quest/m1/ts-reliability/README.md) - both modes have explicit profiles, automated validation, loss tests, and a dedicated guide
- [Resume reorder](/quest/m1/resume-reorder.md) - a group whose stream header arrives after its successor's still resumes on failover; only a dropped or long-gone group fails
Expand Down
3 changes: 2 additions & 1 deletion quest/m1/audit-deps.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ duplicates are ecosystem transitions owned upstream:
webpki-roots 0.26). winit 0.30 holds rustix 0.38, x11rb 0.13, and objc2 0.5
until 0.31 leaves beta.
- Our own crates: web-transport-iroh 0.8.3 holds kio 0.5 (main already takes
0.6, waiting on a moq-dev/web-transport release), moq-vaapi holds bindgen
0.6; iroh is an accepted exception to moq taking no new work in
moq-dev/web-transport, so this lasts until that crate is released on its own), moq-vaapi holds bindgen
0.70, libloading 0.8, and thiserror 1, and mp4-atom holds thiserror 1.
- Bun has no dedupe, so same-major duplicates (`@babel/types`,
`@vue/shared`, `minimatch`, `picomatch`, `yaml`) persist until a parent
Expand Down
36 changes: 0 additions & 36 deletions quest/m1/goaway-coverage.md

This file was deleted.

26 changes: 26 additions & 0 deletions quest/m1/js-request-owner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# [S] Every JS request stream has one owner and one closer

## Goal

In `js/net`'s IETF adapter, each request stream has a single handle that
owns its reader and exposes a terminal `ended` promise every consumer races,
so no request reader can be left detached, and each request closes through a
single per-request closer, so request tasks stop closing a session or stream
twice with competing codes.

## Plan

Follow-ups of [#5998](https://github.com/moq-dev/moq/pull/5998). Today no
reader is detached, but nothing prevents it: each request type wires its own
read loop and close path, and #5998's unit harness has to assert that every
close carries one code because the transport keeps the first.

- Add the handle internally in `js/net/src/ietf/` and move SUBSCRIBE, FETCH,
TRACK_STATUS, SUBSCRIBE_NAMESPACE, SUBSCRIBE_TRACKS and PUBLISH_NAMESPACE
(both sides) onto it.
- Check whether the Rust request tasks close twice the same way and give
them the same single closer if so; mirror the shape in both languages.
- Internal refactor: deleting the per-request read and close code it
replaces is the measure of success.

Public API: none. Wire: none.
18 changes: 18 additions & 0 deletions quest/m1/native-noq-feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# [XS] moq-native drops its empty noq feature

## Goal

`rs/moq-native` no longer declares the empty `noq = []` feature it enables
by default, and every reference to it (other crates' feature lists, docs,
CI matrices) is gone.

## Plan

Found 2026-10-20 auditing dependencies on the web-transport repo, noq and
quinn after the maintainer decided moq's own QUIC stack, `moq-quic`, powers
everything. The feature gates nothing.

- Removing a feature is breaking for anyone who names it: add an entry
under `## Unreleased` in moq-native's `MIGRATE.md`.

Public API: the `noq` Cargo feature is removed. Wire: none.
11 changes: 9 additions & 2 deletions quest/m1/qmux-no-wait.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@
`@moq/qmux` (the WebSocket fallback, and so Safari) rejects
`createBidirectionalStream` and `createUnidirectionalStream` at once when
`waitUntilAvailable` is false and the peer has granted no stream credit, as
Chrome's WebTransport does, instead of queueing the create. Released from
moq-dev/web-transport and bumped in `js/net/package.json`.
Chrome's WebTransport does, instead of queueing the create. The change lands
in the in-tree package.

## Plan

Decided 2026-10-07: JS requests pass the flag and otherwise rely on their
10 s timer to bound the queue.
Match the rejection Chrome raises so `@moq/net` handles both the same way.

Decided 2026-10-20 (maintainer): patched in-tree after
[TS qmux](/quest/m1/ts-qmux.md), not upstream in moq-dev/web-transport.

## Required

- [TS qmux](/quest/m1/ts-qmux.md) - `@moq/qmux` lives in `js/`
Loading
Loading