Skip to content

feat(auth): carry typed refusal reasons and verified attribution - #5996

Merged
kixelated merged 6 commits into
mainfrom
quest/m1/refusal-reason
Oct 20, 2026
Merged

kixelated merged 6 commits into
mainfrom
quest/m1/refusal-reason

Conversation

@kixelated

@kixelated kixelated commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

The auth client discarded refusal bodies, so the relay could neither distinguish expired credentials nor attribute refusals to a verified root and tier.

Approach

Share a typed refusal between HTTP auth and embedded admission. Verify signatures, claims, and key scope before attributing a token refusal; never attribute the dialed path. Preserve legacy plain-text 401/403 refusals and map unknown reason strings to refused. Count expired refusals in metrics and per-root stats, for sessions, gateways, and the HTTP /fetch and /announced endpoints alike, and remove the completed quest.

Impact

  • Breaking Rust API: moq_auth::Error::Refused and moq_relay::auth::Error::Refused carry moq_auth::Refusal; affected serve::Refusal variants carry verified roots. Migration entries in rs/moq-auth/MIGRATE.md and rs/moq-relay/MIGRATE.md describe the changes.
  • HTTP contract: 403 JSON carries reason (refused, forbidden, expired), optional verified root, and optional tier. Typed forbidden refusals preserve HTTP 403 at relay endpoints. An expired refusal at revalidation ends the credential lease as expired.
  • Additive TypeScript API: RefusalSchema and Refusal in @moq/auth mirror the HTTP shape.
  • Stats wire: sessions_refused.expired is an additive cumulative counter. Refusal roots supply the stats label; absent roots remain unattributed. No MoQ transport framing or negotiation changes.

Alternatives

Keep all refusals generic, losing expiry information. Using the dialed path for attribution would allow unbounded attacker-chosen stats entries.

Decisions

Iterate rounds (no maintainer decision needed):

Failing Test (bursts_cross_a_transport_peer::impaired, "the route was withdrawn while the peer link was up")

  • ✅ Merge origin/main: the failure is the shaper ingress-gate flake fixed by moq-dev/moq#5943, which names this exact message and merged after this PR's run
  • Investigate as a product bug in this PR

Key::verify and the new verify_claims duplicated the decode/validate/scope steps

  • ✅ verify calls verify_claims and adds the time check, so the two cannot drift
  • Keep two copies

Expiry clock after merging moq-dev/moq#5987

  • ✅ Key::verify and serve's expired-token check both read moq_clock::wall(), as main now does
  • Keep SystemTime::now() in serve

Codex: HTTP admission recorded refusals unattributed

  • ✅ admit_http records through record_auth, with a regression test
  • Decline

Validation

  • Reproduced the original failure: a JSON expired refusal became a generic refusal error.
  • Focused Rust auth and relay tests cover actual expired-JWT QUIC refusal metrics, embedded root/tier attribution, forged and out-of-scope credentials, legacy bodies, and unknown reasons. web::tests::http_refusals_keep_the_deciders_root_and_tier fails without the HTTP fix.
  • just check after merging origin/main: 7858 Rust tests passed (31 existing skips), @moq/auth passed. Under machine load above 20, bench/relay.test.py hit its 15s wall timeout (1.3s on rerun) and an earlier run failed moq-uring clock::tests::host_tracks_moq_clock's 1ms slack (passed on rerun and in the full rerun). Neither is touched here.
  • Native interop passed earlier at 0a7b42259: just test interop --publishers rust,python,go,cpp --subscribers rust,python,go,cpp,js-native-node,js-native-bun,c,gst --timeout 30. The browser portion of --all was blocked locally by the pinned Chromium runtime missing libglib. This PR changes no MoQ wire.

Follow-ups

  • moq-uring clock::tests::host_tracks_moq_clock compares two wall-clock reads with a 1ms slack, so it fails under load.

(Written by GPT-6.1-Sol and Claude Opus 5.5)

🤖 Generated with Claude Code

kixelated and others added 4 commits October 19, 2026 13:06
Share refusal reasons and optional verified root/tier across HTTP auth and embedded admission. Keep legacy refusals unattributed, and count expired credentials in relay metrics and stats.

Co-Authored-By: GPT-6.1-Sol <noreply@openai.com>
# Conflicts:
#	quest/m1/README.md
#	rs/moq-relay/MIGRATE.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated marked this pull request as ready for review October 20, 2026 00:11
@coderabbitai

coderabbitai Bot commented Oct 20, 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 16 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: 634a21ad-58f4-4023-a24b-2904f8e8df45
📥 Commits

Reviewing files that changed from the base of the PR and between 4ec3b8e and 05ae392.

📒 Files selected for processing: 27
  • doc/bin/relay/auth.md
  • doc/concept/stats.md
  • doc/lib/rs/moq-auth.md
  • js/auth/src/contract.test.ts
  • js/auth/src/contract.ts
  • quest/m1/README.md
  • quest/m1/refusal-reason.md
  • rs/moq-auth/MIGRATE.md
  • rs/moq-auth/src/client.rs
  • rs/moq-auth/src/error.rs
  • rs/moq-auth/src/key.rs
  • rs/moq-auth/src/lib.rs
  • rs/moq-auth/src/refusal.rs
  • rs/moq-auth/src/serve.rs
  • rs/moq-auth/src/set.rs
  • rs/moq-net/src/stats/outcomes.rs
  • rs/moq-relay/MIGRATE.md
  • rs/moq-relay/benches/auth.rs
  • rs/moq-relay/src/auth.rs
  • rs/moq-relay/src/auth/refresh.rs
  • rs/moq-relay/src/cluster.rs
  • rs/moq-relay/src/refusals.rs
  • rs/moq-relay/src/shutdown.rs
  • rs/moq-relay/src/web.rs
  • rs/moq-relay/tests/integration/auth_embedder.rs
  • rs/moq-relay/tests/integration/auth_lifetime.rs
  • rs/moq-relay/tests/integration/refusals.rs
  • Autofix · 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.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-20T01:46:30.404253Z 05ae392 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4b50a4f719

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rs/moq-relay/src/refusals.rs
kixelated and others added 2 commits October 19, 2026 18:23
…r's root and tier

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 05ae3924da

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rs/moq-auth/src/client.rs
@kixelated
kixelated added this pull request to the merge queue Oct 20, 2026
Merged via the queue into main with commit 904f87b Oct 20, 2026
15 checks passed
@kixelated
kixelated deleted the quest/m1/refusal-reason branch October 20, 2026 03:13
kixelated added a commit that referenced this pull request Oct 20, 2026
Refusals always serializes all six kinds since #5996.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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