Add per-action, per-namespace restrictive scopes#2236
Draft
philipfweiss wants to merge 3 commits into
Draft
Conversation
Thread is_admin into AuthContext and short-circuit RBAC authorization for admins, approving all requests. The bypass is a single explicit check and is logged for audit, so it is easy to find and to later scope down if admins should still respect some constraints. Co-authored-by: Cursor <cursoragent@cursor.com>
Add a DEFAULT_ACCESS_ROLE setting whose scopes are evaluated as a fallback when no explicit grant matches, so deployments can express graceful defaults (e.g. read on *) without flipping the whole policy to permissive. The default role's scopes are pre-loaded into AuthContext and evaluated together with the principal's own scopes: _make_decision now gathers all candidate scopes (explicit grants + default role) and resolves them in one step, then falls back to default_access_policy. Collecting candidates before deciding (rather than a nested allow-ladder) keeps the door open for future deny/precedence rules. Co-authored-by: Cursor <cursoragent@cursor.com>
Add a RESTRICTIVE_SCOPES setting (entries like "write:namespace:finance.*") so enforcement can be scoped to specific actions and namespaces: a matching request is denied unless an explicit grant allows it, while everything else follows the permissive baseline. This enables write governance on one namespace at a time (writes restrictive there, reads and other namespaces permissive) without a global deny flip. Extracts resource matching into a shared helper and applies the restrictive check in the decision fallback, after explicit grants. No-op when restrictive_scopes is empty. Co-authored-by: Cursor <cursoragent@cursor.com>
✅ Deploy Preview for thriving-cassata-78ae72 canceled.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tracking: #2234 (step 4 of the RBAC enablement sequence).
This is the mechanism that makes write governance possible with minimal blast radius, and it avoids a global deny footgun.
Adds a
RESTRICTIVE_SCOPESsetting. Each entry isaction:scope_type:scope_value, e.g.write:namespace:finance.*. A request matching any entry is denied unless an explicit grant allows it, regardless ofdefault_access_policy; anything not matched follows the permissive baseline.This gives per-action and per-namespace enforcement in one mechanism. For example, with
restrictive_scopes=["write:namespace:finance.*","delete:namespace:finance.*","manage:namespace:finance.*"]and the default permissive policy:finance.*require an explicit grant (or ownership),finance.*stay open,So you can turn on write governance one namespace at a time instead of flipping the whole deployment to deny.
Implementation:
_resource_in_scopehelper, reused by grant checks and restrictive checks._make_decisionafter explicit grants, preserving the collect-then-decide shape from Add configurable default-access role to RBAC #2233.restrictive_scopesis empty (the default), so nothing changes today.Made with Cursor