Skip to content

fix(net): accept a clear FIRST_OBJECT that starts at object 0 - #5027

Merged
kixelated merged 3 commits into
mainfrom
quest/m0/ietf-first-object-zero
Oct 8, 2026
Merged

kixelated merged 3 commits into
mainfrom
quest/m0/ietf-first-object-zero

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Summary

A draft-18+ subgroup stream with FIRST_OBJECT clear whose first Object ID is 0 is read as a whole group, in rs/moq-net and js/net. A clear bit with any other first ID is still dropped before a group exists.

The first Object ID is absolute whatever the bit says, and object IDs start at 0, so ID 0 is the head either way. This accepts a publisher that left the bit clear. next_object_id (and JS Frame.decode) still refuses a later gap.

js/net had grown the same early drop since the quest was written, so it is fixed the same way. It still has no fill or resume exception on this path.

Public API

None.

Wire

None.

Tests

  • Rust: a draft-18 stream with the bit clear and first ID 0 delivers its group. One with first ID 3 is dropped, and the next group still arrives.
  • JS: the same two cases.

just rs check-test -p moq-net passed (1554 tests). The @moq/net suite passed.

just check did not finish. After the JS checks, the Rust dependent graph failed in moq-gst because glib-sys could not find sysprof-capture-4.pc. That build does not use this change.

Quest

This completes quest/m0/ietf-first-object-zero from #5020. The quest file is not on main, so this PR leaves quest/ untouched. Delete that file once #5020 merges.

No empty-prefix behavior was changed.

(Written by Grok 4.5)

A draft-18 subgroup stream that leaves the bit clear and starts at object 0 is the whole group. Any other first ID is still dropped before a group exists.
@kixelated

Copy link
Copy Markdown
Collaborator Author

Outcome: the decided behavior is in. A draft-18+ subgroup with FIRST_OBJECT clear and first Object ID 0 is delivered as a whole group. First ID 3 is still dropped before a group exists. No public API or wire change.

just check stopped on a local moq-gst pkg-config miss (sysprof-capture-4), not on this diff. just rs check-test -p moq-net and the @moq/net suite passed.

No open decision. I recommend /quest-merge after review. The quest file stays until #5020 merges, then it should be deleted.

(Written by Grok 4.5)

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)

Reviewed commit 41610f2259fc9922f8d0734f72d911a05152d2f3.

No actionable correctness issue found in the changed Rust/TypeScript parsing paths and regression tests. Accepting object 0 while retaining sequential-ID validation is a sound compatibility fix; the Rust fill/resume exceptions and END_OF_TRACK handling remain intact.

Verification: static diff and surrounding-code review only; I did not run the suites. The reported aggregate build limitation remains unverified.

@kixelated
kixelated marked this pull request as ready for review October 8, 2026 00:10
@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 18 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 49c24bac-c4f5-413b-9e5e-0fe2dca5ba41
📥 Commits

Reviewing files that changed from the base of the PR and between b0f4a99 and f9bd584.

📒 Files selected for processing (4)
  • js/net/src/ietf/object.ts
  • js/net/src/ietf/subscriber.test.ts
  • js/net/src/ietf/subscriber.ts
  • rs/moq-net/src/ietf/subscriber.rs
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…bject-zero

# Conflicts:
#	js/net/src/ietf/subscriber.test.ts
#	js/net/src/ietf/subscriber.ts
@kixelated

Copy link
Copy Markdown
Collaborator Author

Automated review of f9bd5840 (full review; no earlier Grok review on this PR)

The change does what the quest asked: a draft-18+ subgroup with FIRST_OBJECT clear is now judged by its first Object ID, which is absolute whatever the bit says. Rust moves the drop into open_group after the existing PeekFirst peek (no second peek), and JS adds a peekU62 before the drop. Object 0 is delivered as the whole group, any other first ID or an empty stream is still dropped, and the fill and resume exceptions stay as they were. Both sides behave the same, and the new tests cover the two cases the quest named. I found no blocking issues.

Non-blocking

  1. A clear-bit stream whose peek fails now leaves a failed group behind. Before this PR, a FIRST_OBJECT-clear stream with no fill and no resume was dropped before anything was read, so group N never showed up in the track. Now the peek runs first. If the publisher resets the stream before its first object, or the first object's extension block is too large, Rust's Err arm in open_group (rs/moq-net/src/ietf/subscriber.rs:2867-2877) calls create(track) and aborts group N. JS does the same through open().close(e) (js/net/src/ietf/subscriber.ts:1160) when peekU62 (:1085) throws something other than UnexpectedEnd. Readers now see group N fail where they used to see no group at all. That's probably harmless, but if you want to keep the old behavior, skip the create in that arm when the bit is clear and neither a fill nor a resume applies.
  2. One behavior change has no test. A clear-bit stream whose first object is END_OF_TRACK at object 0 now ends the track at group N, since Rust checks Opened::EndOfTrack (:2879) before the bit, and the JS peek passes ID 0 through to frame.endOfTrack (:1114). Before, it was dropped. That follows from treating ID 0 as absolute and looks right, but it's untested. So is a clear-bit stream with no objects, which is still dropped on both sides. A small case for each in stitch_tests and subscriber.test.ts would pin both down.

Cross-PR

CI was still pending when I checked this head.

Verdict: MERGE once CI is green.

This is an automated review, not the maintainer's decision
(Written by Grok)

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)

Reviewed commit f9bd58409a104f5a1b640811f4aefaedc3713df5, comparing against my prior review of 41610f2259fc9922f8d0734f72d911a05152d2f3 and separating the main merge from PR-specific changes.

No new actionable correctness bugs found. The Rust regression fixture now supplies timestamps required by the merged timed-track validation; the JS conflict resolution preserves both object-zero acceptance and the older-draft headless-group handling. The narrow compatibility fix remains sound, with sequential-ID checks intact and no broader redesign needed. My earlier review had no unresolved findings.

The clear-bit END_OF_TRACK/empty-stream coverage suggestions are already recorded in the independent review; I am not duplicating them inline.

Verification: GitHub-only static diff and surrounding-code review. I did not run tests. Checks for this head are still queued/running, so this is not a test-pass claim.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Merge summary: I merged main and resolved conflicts with #5019 in js/net/src/ietf/subscriber.ts and its tests. The object-0 peek stays, and so does #5019's drop for pre-bit drafts with a non-zero first delta. All three tests are kept. Merged main's timed-track validation broke the new Rust draft18_subgroup fixture, so the fixture now stamps each object's Timestamp. cargo test -p moq-net ietf::, bun test src/ietf, and just test interop --all pass locally. The OpenAI review of f9bd584 found nothing new.

Re the Grok notes: (1) a clear-bit stream whose peek fails now surfaces as a failed group instead of a missing one. That matches how a stream failing before its first object is already reported, so I left it. (2) The END_OF_TRACK at object 0 and empty-stream cases are reasonable extra coverage, but I'm leaving them as a follow-up rather than restarting review. Enabling auto-merge.

(Written by Claude Opus 5.5)

@kixelated
kixelated enabled auto-merge (squash) October 8, 2026 02:37
@kixelated
kixelated merged commit fdfdf9a into main Oct 8, 2026
11 checks passed
@kixelated
kixelated deleted the quest/m0/ietf-first-object-zero branch October 8, 2026 03:04
kixelated added a commit that referenced this pull request Oct 8, 2026
Backport of #5027 to release. A draft-18+ subgroup stream with FIRST_OBJECT
clear whose first Object ID is 0 is the whole group, so it is delivered
instead of dropped; any other first ID is still dropped.

Adapted to release: there is no resumed-subscription path, and the draft-18
test helper uses release's encoding API.

(cherry picked from commit fdfdf9a)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated added a commit that referenced this pull request Oct 9, 2026
#5027) (#5069)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@moq-bot moq-bot Bot mentioned this pull request Oct 9, 2026
kixelated added a commit that referenced this pull request Oct 9, 2026
Conflicts in js/net/src/ietf/subscriber.ts, js/net/src/ietf/subscriber.test.ts, and rs/moq-net/src/ietf/subscriber.rs resolve to main: release's side is the #5069 backport of #5027, which main already carries in full, including the resume.is_none() guard the backport dropped and the newer Encoder and moq_net_sim test harness.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@moq-bot moq-bot Bot mentioned this pull request Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant