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
33 changes: 22 additions & 11 deletions quest/m1/auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ that predates the stream. Node-bound peer grants for direct sessions belong to

Decisions settled while planning, recorded so review does not relitigate them:

- **Per-request boundary (2026-10-12).** Request tokens are an experimental
Rust interoperability hook with application-owned verification, retaining
renewal. They are not a complete authentication scheme or a relay feature.
Local session permission may admit an incoming request; grants received
from the peer may not. The shared acceptor queue distinguishes session and
request events with separate acceptance handles. This is an intentional
Rust API change, not an optional scope field on the existing acceptor.
Per-request relay integration, JS APIs, CLI, and bindings are deferred;
session AUTH work continues. Document the hook only in minimal API comments,
with no feature page or guide. The relay request-lease quest is related
future work, no longer required to complete this epic.
- **One AUTH stream per token, opened by whoever presents it.** Either side of
a session may open one; the acceptor answers with the grant that token
earns. A moq-net session opens one on both sides right after SETUP with an
Expand Down Expand Up @@ -88,8 +99,9 @@ Decisions settled while planning, recorded so review does not relitigate them:
SUBSCRIBE_OK. Rust is `moq_net::auth` with `auth::Grant`, `auth::Handle`,
`auth::Token`, and `auth::Request`; JS mirrors as `connection.auth`.

Everything here is additive: `Session::auth()` is new, and the relay derives
the grant from the origin handles it already scopes. Decided 2026-10-05: wire
`Session::auth()` is additive, while the request-token hook intentionally
changes the Rust acceptor API as described above. The relay derives the grant
from the origin handles it already scopes. Decided 2026-10-05: wire
work targets the wip lite version until the maintainer cuts it, never a
published version in place, so AUTH lands in `moq-lite-07-wip` (or whichever
version is wip then), not lite-06. The UNAUTHORIZED stream code stays on lite-06
Expand All @@ -102,17 +114,10 @@ because `main` assigned 0x3A to NOT_FETCHABLE first.
- [AUTH violations](/quest/m1/auth/violations.md) - every AUTH protocol violation closes the session in Rust and JS, lite and IETF
- [Relay tokens](/quest/m1/auth/relay-refresh.md) - the relay verifies tokens
sent in band, unions their grants, and cancels only work that loses access
- [Request-token decode](/quest/m1/auth/request-token-decode.md) - an
`AUTHORIZATION TOKEN` on a moq-transport request decodes by the draft's
rules, closing the session on the forms the draft forbids
- [Setup extensions](/quest/m1/auth/extensions.md) - a side declares which
Setup extensions it offers with one `Extensions` struct
- [Request tokens](/quest/m1/auth/request-token.md) - a token on a
moq-transport request authorizes that request and renews it in band
- [Request tokens](/quest/m1/auth/request-token.md) - an experimental Rust
verifier hook confines a token's authority to its request and renews it
- [Request gate](/quest/m1/auth/request-gate.md) - every incoming request is
refused up front and held to the grant through a gate its dispatcher owns
- [Request leases](/quest/m1/auth/request-lease.md) - moq-relay honors a
request token with a lease of its own
- [Expired token error](/quest/m1/auth/expired-error.md) - an expired token
reports `Error::Expired`, not `Unauthorized`, in Rust, JS, and the bindings
- [Bindings](/quest/m1/auth/bindings.md) - grants and tokens reach every
Expand All @@ -123,6 +128,12 @@ because `main` assigned 0x3A to NOT_FETCHABLE first.

## Related

- [Request leases](/quest/m3/auth-request-lease.md) - deferred relay
integration, to revisit when a consumer needs per-request verification
- [#5107](https://github.com/moq-dev/moq/pull/5107) - landed request-token
decoding, including session-fatal REQUEST_UPDATE decode failures
- [#5106](https://github.com/moq-dev/moq/pull/5106) - landed setup extension
configuration
- [Malformed grant](https://github.com/moq-dev/moq/pull/5256) - a malformed or
non-canonical grant pattern, or an out-of-range `Expires`, closes the
session with PROTOCOL_VIOLATION in Rust and JS
Expand Down
4 changes: 4 additions & 0 deletions quest/m1/auth/bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ one without the plugin reconnecting.

## Plan

This quest exposes session AUTH only. Per-request setters and verifier APIs
remain deferred until a consumer needs them (confirmed 2026-10-12); do not
export the experimental Rust request hook through the bindings here.

- `MoqSession` in `rs/moq-ffi/src/session.rs` gains `auth()` returning an
`Arc<MoqAuth>` object, the shape `publisher()` uses, with `grant() ->
Option<MoqGrant>` (a record: publish patterns, subscribe patterns, expiry
Expand Down
32 changes: 0 additions & 32 deletions quest/m1/auth/extensions.md

This file was deleted.

16 changes: 13 additions & 3 deletions quest/m1/auth/relay-refresh.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ expiry, an expiry that leaves the union intact ends only that token, and

## Plan

- Coordinate shared plumbing with [Request tokens](/quest/m1/auth/request-token.md)
and #5148. The 2026-10-12 request-token plan chooses one queue with explicit
session/request event variants and distinct acceptance handles. The relay
accepts session events here and explicitly refuses request verification
as `Unsupported`; it must never attach a request token as a session grant.
Share cancellation, pending-work bounds, and persistent connection handles
whichever implementation lands first. #5282 already implements this shared
plumbing; its separate open API and limit-policy decisions remain open.
- `Connection::run` in `rs/moq-relay/src/connection.rs` takes `requests()`
from `moq_net::server::Handshake::auth()` before `.ok()`, so the relay owns
the initial empty AUTH too and the driver's fallback never races it.
Expand Down Expand Up @@ -71,9 +79,11 @@ expiry, an expiry that leaves the union intact ends only that token, and
- Bound pending tokens: `auth::Handle::requests()` hands out an unbounded
queue today, and a closed AUTH stream leaves its request queued, so a peer
that finishes AUTH streams faster than the relay verifies them grows it
without limit (Codex security review on #4039). This quest is the first
consumer, so bound it per session here and refuse what overflows; dropping a
`Request` already refuses its token.
without limit (Codex security review on #4039). Bound it per session and
refuse what overflows; share the bound and withdrawal support with the
request-token hook whichever lands first. Neither consumer may land with
unbounded pending verification. Dropping a `Request` already refuses its
token.
- Docs: `doc/bin/relay/auth.md` gains an "in-band tokens" section beside
revalidation stating that grants union, that a token needs the admitted
root, what an expiry does to the union today, and that the grant's expiry
Expand Down
6 changes: 5 additions & 1 deletion quest/m1/auth/request-gate.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ Decisions settled while planning (2026-10-09):
was rejected because it loses those graceful refusals.
- **Rust and JS together**, so the shape and names stay mirrored.
- **Effective authorization.** Land after request-token support. Dispatch
uses session-first admission or the admitted request grant, preserving
uses independently verified local session permission first, then the
admitted request grant; peer-issued AUTH_OK grants cannot authorize incoming
requests. Preserve
renewal, revocation, expiry and the session ceiling. Do not reject a valid
token-only request merely because it is outside the session union. Joining
FETCH follows the named subscription's live authorization and ends with
Expand All @@ -32,6 +34,8 @@ Decisions settled while planning (2026-10-09):
request-token setter/acceptor.
- **Structure only.** Finding new gaps is not the goal, but any request type
the refactor shows was ungated gets a regression test in the same PR.
Initial verification already consumes request capacity and observes
cancellation in the request-token hook; those fixes must not wait here.

Today `auth::Gate` is built inside each handler: the IETF publisher's
SUBSCRIBE, standalone FETCH, and TRACK_STATUS; the IETF subscriber; and the
Expand Down
63 changes: 0 additions & 63 deletions quest/m1/auth/request-token-decode.md

This file was deleted.

Loading
Loading