Repository navigation
Conversation
Quest-Claim: d555294ecf6247f9
A claim covers every path beneath its prefix, and an announce stream presents the most specific claim at or above the requested prefix at that prefix itself. A source's covering claim for `src` and a derivative's own claim for `src/derived` therefore looked alike to a viewer requesting `src/derived`, and the order the relay listed them in, by node id, decided which one it asked. The source's publisher refuses a path it does not serve, so a viewer reached the derivative on some runs and got `unroutable` on others. ANNOUNCE_START, ANNOUNCE_UPDATE and ANNOUNCE_RESTART carry `Above`: how many segments broader than the requested prefix the claim is. A stream presenting a broader claim at a narrower prefix adds the distance, and a receiver ranks the lowest `Above` first, so a claim exactly at the path shadows every broader one at any cost, as the draft says. A receiver refuses an `Above` on a claim that is not at the requested prefix, or larger than its path has segments. The wire change is to the unpublished moq-lite-07-wip, mirrored in js/net and the draft. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…prefix A claim shown above its own prefix is filed deeper than it is, so a broad claim shown at a deep prefix could still beat a more specific claim filed shallower. Selection now ranks by the claim's own depth (the filed prefix less Above) across every covering prefix, in Rust and JS. A relay forwards a claim it learned from a narrower stream at a deeper suffix of a broader request, so a receiver accepts Above on any claim, up to the path's segments, instead of only at the requested prefix. A publisher holds Above to what its handle's root leaves of the path, so a claim above a rooted export is no broader than the peer's path. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A node's most specific claims are its whole answer: the broadcast that refuses a path no longer falls through to a broader claim shown at the same prefix. Rust restricts the serving candidates to the winning tier, and JS's local-wins check lets an exact broadcast beat a broader received claim. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Finishes quest/m1/transcode-unroutable.md, which this PR deletes.
Summary
A viewer subscribing to
src.hang/transcode.hangwas sometimes refused withunroutable.A claim covers every path beneath its prefix, so the source's publisher claims
src.hang, and so alsosrc.hang/transcode.hang, which it refuses. An announce stream answering a request for exactlysrc.hang/transcode.hangpresents the most specific claim at or above the requested prefix at the requested prefix itself. The derivative's own claim and the source's covering claim therefore reached the viewer as two claims for the same path, ranked alike. Nothing but the order the relay listed them in, by node id, then decided which one the viewer asked, and a node id changes on every run. When the source's claim won, its publisher answeredunroutable.The draft already says the more specific claim wins "at any cost". The wire lost the specificity, so the receiver could not apply it.
moq-net): ANNOUNCE_START, ANNOUNCE_UPDATE and ANNOUNCE_RESTART carryAbove, how many segments broader than the requested prefix the claim is. A stream presenting a broader claim at a narrower prefix adds the distance (route::Item::lowered), androute_orderranks the lowestAbovefirst. A receiver refuses (PROTOCOL_VIOLATION) anAboveon a claim that is not at the requested prefix, or larger than the claim's path has segments.js/net): the same codec, the same lowering infloors.tsandinternal.tspresented, the same validation in the subscriber, the same leading comparison incompareRouteCandidates.rs/moq-net/tests/integration/nested_claim.rs, which fails without the fix), the pinned announce bytes, the shared corpus and golden streams moved with the codec, andAbovehas unit tests in Rust and JS.Public API and wire impact
Aboveafter the Announce Cost and before the optional Lite-06 Chain. Earlier versions are unchanged.route::ItemandLane.aboveare crate-private.@internalClaimtype andWireRoute(local ranking state) gainabove; the announce codec'sAnnounceBroadcastgains an optionalabove.Models
Size: S
Implementer: Claude, claude-sonnet-5-5, unknown effort (arm B)
Validation
test/portrait/relay.toml,ffmpegintomoq import avc3,moq transcode --encoder software --decoder software, then twomoq exportviewers atsrc.hang/transcode.hang): the relay loggedunroutablein about 60% of runs; with each side's trace logs the viewer asked the source's node for the derivative whenever the source's node id sorted ahead.moq-relayandmoq(built withtranscode,openh264): 8 of 8 runs delivered video to both viewers, with nounroutablein the relay or either viewer log.nested_claim::a_nested_broadcast_wins_over_the_claim_above_itruns a source, a derivative, a relay and a viewer over lite-07 sessions, sweeps both node-id orderings, and asserts the viewer reads the derivative's frame. It failed on the pre-fix code and passes now.cargo nextest run -p moq-net --all-features: 3992 passed.just check: passed (Rust, JS 3344bun test, biome, drafts, quest).just test interop --all: all checks passed, including the JS to Rust compress, drop and claims runs on moq-lite-07-wip and the Python sockets.Caused by
Decisions
Choices made without the maintainer, each one a review can undo:
Aboveleadsroute_order, ahead of drain, availability, priority and cost. The draft says an exact claim shadows broader ones "at any cost", so a cheaper or non-draining broader claim must not win. The alternative is ranking it after drain and availability, so a draining exact claim loses to a live broader one that then refuses the path.Aboveis always present on a lite-07 message, zero for a claim at or inside the prefix, not an optional field. An optional field would need a flag, and a flag needs a second code path in every codec.Abovethat cannot be true, instead of clamping it, as it does for other wire fields the peer fixes (Announce ID and Route ID).Lane.aboveis au8(a path has at most 32 segments), so the route entry stays inside clippy'slarge_enum_variantbudget inietf/publisher.rs. The alternative is boxingNamespaceWork::Apply.!since the wire changes, though only for the unpublished lite-07-wip.Follow-ups
None.
🤖 Generated with Claude Code
(Written by Claude Sonnet 5.5)
Review
Rewritten by
quest reviewafter each round.Head: 6959dd1, named in full once no reviewer reports a finding
Base: origin/main at 6656f32
Risk: high,
The wire-protocol routing changes affect interoperability for publishers and relays; reverting restores the implementation but cannot undo interrupted sessions or misrouted requests.Classified: medium by default
Reviewer: Codex, gpt-6.1-sol, medium effort
Session:
01a1dfcc-ae6a-72f0-8060-2538ba7293b1, round 3Score: 8/10,
The Rust refusal fallback is fixed, but the JS counterpart still allows a broader claim to supersede an exact broadcast through epoch comparison.Raised the risk to high:
The wire-protocol routing changes affect interoperability for publishers and relays; reverting restores the implementation but cannot undo interrupted sessions or misrouted requests.Rounds: 3; first round 3 (high 1, medium 2); findings 5 (high 1, medium 4): fixed 4, refuted 0, open 1
Findings, open until the next round settles them:
js/net/src/origin.ts:1186:Apply specificity before epoch supersessionThe last round's findings, at 2cd6abd:
rs/moq-net/src/model/origin.rs:6110:Restrict serving candidates to the winning specificity tier;RouteTable::best_route now restricts serving, epoch supersession, and ranking to candidates matching the winning specificity, so a refusing exact broadcast cannot fall through to a broader claim.Reviewer: Codex, gpt-6.1-sol, low effort, shadow
Session:
01a1dfcc-ae6a-7830-9841-a9783fb5b782Rounds: 2; first round 1 (medium 1); findings 1 (medium 1): fixed 1, refuted 0, open 0