Skip to content

control-plane-api: extract Authority on every route - #3405

Open
bbartman wants to merge 4 commits into
bmb/3376-stack-3-authority-extractorfrom
bmb/3376-stack-4-authority-migration
Open

control-plane-api: extract Authority on every route#3405
bbartman wants to merge 4 commits into
bmb/3376-stack-3-authority-extractorfrom
bmb/3376-stack-4-authority-migration

Conversation

@bbartman

@bbartman bbartman commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Part of #3376 (task 3b). Stacked on #3404 (task 3a); review only the last three commits.

The mechanical call-site migration, with zero behavior change:

  • All ten REST handler signatures swap Envelope for Authority, decomposed structurally in the manner of axum's Statecrate::Authority { envelope: env, .. } binds env, so handler bodies are unchanged.
  • graphql_handler decomposes the extracted Authority and injects the Envelope and the bearer's CapabilityMask as separate context data: resolvers read the Envelope exactly as before (their ~52 pulls are untouched), while authorization chokepoints will consume the mask on their own in the next PR, without every resolver having to care that it exists. The agent GraphQL test harness mirrors the same decomposition via Authority::from_envelope, the same evaluation HTTP extraction performs.
  • Envelope keeps its FromRequestParts impl as the inner extraction Authority composes over (now written in axum's async fn style).
  • The authorization chokepoint helpers (verify_authorization, storage-mappings') keep their &Envelope parameters: the extractor carries the bearer's mask on every request, but nothing consumes it yet — every chokepoint stays pinned to ALL_CAPABILITIES from tables: capability-mask-aware user grant walk #3397. Live mask threading is the next stacked PR (task 3c).

Every route now evaluates its Requirement at extraction (all routes are NoRequirement today, which is vacuous), so response behavior is byte-identical — pinned by the existing route-level test suites, which pass unchanged.

@bbartman bbartman changed the title control-plane-api: migrate handlers and resolvers to Authority control-plane-api: extract Authority on every route Aug 26, 2026
@bbartman
bbartman force-pushed the bmb/3376-stack-4-authority-migration branch from c69f919 to 6a57e7a Compare August 27, 2026 10:50
@bbartman
bbartman force-pushed the bmb/3376-stack-4-authority-migration branch from 6a57e7a to 8327516 Compare August 27, 2026 12:12
@bbartman
bbartman force-pushed the bmb/3376-stack-4-authority-migration branch 2 times, most recently from 9de5b8a to d8c9f47 Compare August 28, 2026 12:17
@bbartman
bbartman force-pushed the bmb/3376-stack-4-authority-migration branch from d8c9f47 to f3d4380 Compare August 28, 2026 16:59
@bbartman
bbartman force-pushed the bmb/3376-stack-4-authority-migration branch from f3d4380 to 07e7aba Compare August 31, 2026 12:45
Mechanical call-site migration with zero behavior change (task 3b of
#3376): every REST handler signature and GraphQL resolver pull swaps
Envelope for Authority, decomposed structurally in the manner of
axum's State to grab the envelope member — binding `env` so handler
and resolver bodies are unchanged. graphql_handler injects the whole
Authority into request data, and the agent GraphQL harness assembles
one via Authority::from_envelope, the same evaluation HTTP extraction
performs.

Envelope keeps its FromRequestParts impl as the inner extraction that
Authority composes over (now in axum's async fn style), and the
authorization chokepoint helpers keep their &Envelope parameters: the
extractor carries the bearer's mask on every request, but nothing
consumes it yet — live mask threading is the next stacked PR.
from_envelope already returns Result<Self, Rejection>, so the
Ok(...?) round trip was a no-op.
…L data

Rather than putting Authority itself into the GraphQL context, the
handler decomposes it and injects the Envelope and the bearer's
capability mask as separate context data: resolvers read the Envelope
exactly as before (their ~52 pulls revert unchanged), while
authorization chokepoints will consume the mask on their own, without
every resolver having to care that it exists. The agent harness
mirrors the same decomposition.
The /admin endpoints authorize via SQL internal.user_roles rather than
the snapshot walk, so the bearer's capability mask has no effect there
until their authorization is refactored onto the snapshot — say so on
each handler.

Also rewrite two migration-era comments to state what is rather than
what was: the Authority type doc's handler rule, and graphql_handler's
rationale for injecting Envelope and mask as separate context data.
@bbartman
bbartman force-pushed the bmb/3376-stack-4-authority-migration branch from 07e7aba to 520f432 Compare September 1, 2026 13:08
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