From 53c997313ae8eebcdede6d6381a9a2e4ce268f6b Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Fri, 25 Sep 2026 15:42:31 -0700 Subject: [PATCH 1/2] quest(auth): path patterns join the line so AUTH ships with pattern grants Co-Authored-By: Claude Opus 5.5 --- quest/m1/README.md | 1 - quest/m1/auth/README.md | 5 +++-- quest/m1/{path-patterns.md => auth/patterns.md} | 15 ++++++++++----- quest/m1/auth/relay-refresh.md | 2 +- quest/m1/bench-coverage.md | 2 +- quest/m1/epoch.md | 2 +- quest/m1/wildcard/README.md | 8 ++++---- 7 files changed, 20 insertions(+), 15 deletions(-) rename quest/m1/{path-patterns.md => auth/patterns.md} (85%) diff --git a/quest/m1/README.md b/quest/m1/README.md index 93cb6d3458..1ea9de74ad 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -46,7 +46,6 @@ transport, benchmark tooling); worktrees isolate commits, not semantics. - [Archive](/quest/m1/archive/README.md) - record selected tracks to any object_store and replay them over FETCH or derived HLS, on the catalog and store the release ships - [Wildcard](/quest/m1/wildcard/README.md) - a relay resolves subscriptions against advertised prefixes, a service claims the prefix it could serve and refuses the rest instead of enumerating broadcasts, and the browser player treats a covering claim as availability - [Tooling](/quest/m1/tooling/README.md) - justfiles become a one-line menu over `sh/`, one impact map scopes CI, and every workflow step runs a recipe -- [Path patterns](/quest/m1/path-patterns.md) - one matcher for every predicate over broadcast paths: tokens, origins, interest - [In-band auth](/quest/m1/auth/README.md) - a session tells its peer what it may publish and subscribe to, unions tokens presented in band, and fails loud on an out-of-scope publish - [Decoded frame ownership](/quest/m1/decoded-frames.md) - retain moq-video Frames across bindings, with native views or CPU conversion as needed - [C++ through moq-ffi](/quest/m1/cpp/README.md) - generated C++ over moq-ffi with futures and expected-style errors, shipped as a tarball, vcpkg, and Conan, and adopted by the OBS plugin diff --git a/quest/m1/auth/README.md b/quest/m1/auth/README.md index f2e080d67e..0ea3337811 100644 --- a/quest/m1/auth/README.md +++ b/quest/m1/auth/README.md @@ -47,7 +47,7 @@ Decisions settled while planning, recorded so review does not relitigate them: root, and every token in a union shares the connection's root. Unscoped permission is `**`; an empty union grants nothing. Legacy AUTH wire codecs explicitly convert representable prefix unions, where `[""]` means all, - and refuse patterns they cannot represent. [Pattern interest](/quest/m1/path-patterns.md) + and refuse patterns they cannot represent. [Pattern interest](/quest/m1/auth/patterns.md) upgrades AUTH and ANNOUNCE_REQUEST wire fields together without changing the public pattern-valued grant type. - **Fail loud by aborting the session.** A publisher whose origin announces a @@ -93,6 +93,8 @@ existing lite-06 ALPN. each AUTH cell's grant and that a publish outside it fails loud - [Unauthorized reset](/quest/m1/auth/unauthorized.md) - a subscription that loses access resets with a dedicated UNAUTHORIZED stream code +- [Path patterns](/quest/m1/auth/patterns.md) - one matcher for every path + predicate, and AUTH_OK carries pattern grants from AUTH's first release - [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 - [Bindings](/quest/m1/auth/bindings.md) - grants and tokens reach every @@ -107,7 +109,6 @@ existing lite-06 ALPN. - [Origin narrowing](/quest/m1/origin-narrowing.md) - resizes a live session when the union shrinks, for revalidation and token expiry alike -- [Pattern interest](/quest/m1/path-patterns.md) - moves AUTH's legacy wire prefixes to patterns along with ANNOUNCE_REQUEST - [Expiring media grants](/quest/m1/processor/grant-lease.md) - a worker's lease renewal is a new in-band token - [P2P](/quest/m1/p2p/README.md) - the first consumer of hop-bound peer grants diff --git a/quest/m1/path-patterns.md b/quest/m1/auth/patterns.md similarity index 85% rename from quest/m1/path-patterns.md rename to quest/m1/auth/patterns.md index 76180c91e5..31dfef10cd 100644 --- a/quest/m1/path-patterns.md +++ b/quest/m1/auth/patterns.md @@ -82,11 +82,16 @@ keeps patterns off the announce wire, so ANNOUNCE_REQUEST and SUBSCRIBE_NAMESPACE carry the prefix the caller asked for and a wildcard is an optional filter on the consume side. -Replace lite-06 AUTH grant prefixes with patterns in Rust and JavaScript in -the same change. Update the lite draft and version-gated fixtures together. -Authorize by exact containment in the subscriber's v1 grant. Older moq-lite -versions keep their existing prefix wire and behavior; a grant they cannot -represent is refused, not narrowed. Cluster peers adopt nothing as a side +AUTH has not shipped in a release yet: it lives on this line. Land patterns +here, before the line merges, so AUTH_OK carries pattern grants (wildcards and +literals alike) from its first release and never ships a prefix-only encoding. +Today's encoder refuses any grant that is not a subtree +(`rs/moq-net/src/lite/auth.rs`), so a literal grant such as `b1.hang` reaches +the client as no grant at all while the relay's origin enforces it correctly; +this quest removes that gap rather than widening the grant to a covering +prefix. Replace the AUTH grant prefixes with patterns in Rust and JavaScript in +the same change, and update the lite draft and fixtures together. Authorize by +exact containment in the subscriber's v1 grant. Cluster peers adopt nothing as a side effect of this wire work. Test Rust and JavaScript interop, leading wildcards, `**` zero-segment diff --git a/quest/m1/auth/relay-refresh.md b/quest/m1/auth/relay-refresh.md index c0607f0f01..8c319a7883 100644 --- a/quest/m1/auth/relay-refresh.md +++ b/quest/m1/auth/relay-refresh.md @@ -83,6 +83,6 @@ Additive. ## Required - [Origin narrowing](/quest/m1/origin-narrowing.md) - the live re-scope a shrinking token union needs, so no temporary close-on-shrink policy ships -- [Pattern interest](/quest/m1/path-patterns.md) - AUTH can represent the complete grants relay revalidation returns +- [Pattern interest](/quest/m1/auth/patterns.md) - AUTH can represent the complete grants relay revalidation returns - [Unauthorized reset](/quest/m1/auth/unauthorized.md) - the code this relay's revocations reset with diff --git a/quest/m1/bench-coverage.md b/quest/m1/bench-coverage.md index 05d5b3077a..9adb4c4a30 100644 --- a/quest/m1/bench-coverage.md +++ b/quest/m1/bench-coverage.md @@ -17,7 +17,7 @@ and update, `moq-auth` token verification, and `moq-pattern` path matching. size. The in-band token path gets its bench with [In-band token](/quest/m1/auth/token-in-band.md), not here. - `moq-pattern`: matching swept over pattern count and path depth. Coordinate - with [Path patterns](/quest/m1/path-patterns.md) so the matcher gets one + with [Path patterns](/quest/m1/auth/patterns.md) so the matcher gets one bench, not two. Anything that fans out gets a sweep over both axes. Name each target after diff --git a/quest/m1/epoch.md b/quest/m1/epoch.md index d829397624..4e78ce8492 100644 --- a/quest/m1/epoch.md +++ b/quest/m1/epoch.md @@ -21,7 +21,7 @@ line builds on, and it replaces the e2ee-local `moq_e2ee::Epoch`. like `@alice` is valid today and stays valid: strict parsing already keeps it from reading as an epoch. Rejecting it instead would break the path contract and land on `dev`. Check how the split interacts with - [path patterns](/quest/m1/path-patterns.md) and + [path patterns](/quest/m1/auth/patterns.md) and hidden broadcasts (a leading `.`, see `doc/concept/moq-lite.md`). - `moq-e2ee` uses the shared type. Update [draft-lcurley-moq-e2ee](/drafts/draft-lcurley-moq-e2ee.md) so the path is diff --git a/quest/m1/wildcard/README.md b/quest/m1/wildcard/README.md index e7be970d69..130cf72dd9 100644 --- a/quest/m1/wildcard/README.md +++ b/quest/m1/wildcard/README.md @@ -47,7 +47,7 @@ production cost: zero for a live publish, something large for a standby that would have to start working (a cold transcoder)" (`drafts/draft-lcurley-moq-lite.md`). `moq_auth::Claims.publish` and `origin::Producer` gain versioned patterns through -[Path patterns](/quest/m1/path-patterns.md), so advertisements reuse the +[Path patterns](/quest/m1/auth/patterns.md), so advertisements reuse the same exact containment check. `Cost { warm, cold }` (`rs/moq-net/src/model/origin.rs:426`) is the route cost since [#2925](https://github.com/moq-dev/moq/pull/2925). @@ -84,7 +84,7 @@ field. ### Decisions - **One prefix on the wire, one pattern in the token and the filter.** An - advertisement is a path prefix; the [path-patterns](/quest/m1/path-patterns.md) + advertisement is a path prefix; the [path-patterns](/quest/m1/auth/patterns.md) dialect is what tokens and the consume-side filter use, matched by the shared matcher, so nothing resembles a second grammar and nothing on the wire spells a wildcard. @@ -192,7 +192,7 @@ field. - **Patterns are independent of clustering.** The `moq-pattern` crate owns the matching semantics tokens and filters share, with no draft of its own; no announce message carries a pattern on either protocol (AUTH grants on - lite-06 do, per [Path patterns](/quest/m1/path-patterns.md)). moq-cluster adds hop + lite-06 do, per [Path patterns](/quest/m1/auth/patterns.md)). moq-cluster adds hop lists, costs, pool selection, and request resolution to prefix advertisements. @@ -266,7 +266,7 @@ than announce state. ## Related -- [path-patterns](/quest/m1/path-patterns.md) - owns the pattern dialect +- [path-patterns](/quest/m1/auth/patterns.md) - owns the pattern dialect and the shared matcher advertisements reuse - [archive](/quest/m1/archive/README.md) - an archive advertises the catch-all pattern, and its catalog names the generations a wildcard cannot From b47ee9f9fe1fb4c0cefb2311203fd524f183e285 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Fri, 25 Sep 2026 17:11:47 -0700 Subject: [PATCH 2/2] quest(auth): AUTH_OK ships patterns and announce stays a prefix The grant decision still described a prefix-only AUTH codec and a joint ANNOUNCE_REQUEST upgrade, which contradicts the patterns plan. --- quest/m1/auth/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/quest/m1/auth/README.md b/quest/m1/auth/README.md index 0ea3337811..1330f9854d 100644 --- a/quest/m1/auth/README.md +++ b/quest/m1/auth/README.md @@ -45,11 +45,12 @@ Decisions settled while planning, recorded so review does not relitigate them: - **A public grant contains publish patterns, subscribe patterns, and an expiry**, in the presenter's own root; the presenter never sees the relay-side root, and every token in a union shares the connection's root. Unscoped - permission is `**`; an empty union grants nothing. Legacy AUTH wire codecs - explicitly convert representable prefix unions, where `[""]` means all, - and refuse patterns they cannot represent. [Pattern interest](/quest/m1/auth/patterns.md) - upgrades AUTH and ANNOUNCE_REQUEST wire fields together without changing - the public pattern-valued grant type. + permission is `**`; an empty union grants nothing. [Path patterns](/quest/m1/auth/patterns.md) + ships with AUTH, so AUTH_OK carries those patterns, wildcards and literals + alike, from the first release. There is no prefix-only AUTH_OK and no + covering-prefix workaround. Announce stays a prefix: ANNOUNCE_REQUEST and + SUBSCRIBE_NAMESPACE do not gain patterns in that change. The public grant + type stays pattern-valued. - **Fail loud by aborting the session.** A publisher whose origin announces a broadcast outside the union aborts the session with `Unauthorized`, naming the path. The check runs against the grants in hand once the tokens the