feat(BA-6867): add generic RBAC scoped-ops primitives#12825
Conversation
There was a problem hiding this comment.
Pull request overview
Adds foundational, entity-agnostic RBAC “scoped ops” primitives to the manager repository layer, enabling creation/purge flows that also manage scope associations, plus a new bulk validator variant for actions whose targets are scopes (not entities). This is groundwork intended to be reused by future entity-specific work (e.g., AppConfig fragments).
Changes:
- Added
RBACWriteOps.create_scoped()/purge_scoped()wrappers for single-row scoped create/purge execution. - Made RBAC scope binding/unbinding primitives accept
scope_ref: Optional[...]to represent “global-scoped” entities with no scope association rows. - Introduced
BulkScopeActionRBACValidatorand exposed it viaRBACValidators(as an optional field).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/ai/backend/manager/repositories/ops/rbac/provider.py | Adds single-entity scoped create/purge entry points on RBACWriteOps. |
| src/ai/backend/manager/repositories/base/rbac/scope_unbinder.py | Allows scope_ref=None and short-circuits RBAC association deletion for global-scoped entities. |
| src/ai/backend/manager/repositories/base/rbac/entity_creator.py | Allows scope_ref=None and skips association inserts when no scopes exist. |
| src/ai/backend/manager/actions/validators/rbac/bulk_scope.py | Adds bulk RBAC validator for scope-targeted bulk actions, checking permission on the action’s entity type. |
| src/ai/backend/manager/actions/validators/rbac/init.py | Exposes the new bulk-scope validator via RBACValidators (optional). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # A None primary scope marks a global-scoped entity: no association row. | ||
| all_scope_refs = [ | ||
| ref for ref in (creator.scope_ref, *creator.additional_scope_refs) if ref is not None | ||
| ] |
| all_scope_refs = [ | ||
| ref for ref in (creator.scope_ref, *creator.additional_scope_refs) if ref is not None | ||
| ] |
| # Optional so the many test fixtures that build RBACValidators without it keep working; | ||
| # production (the composer) always sets it. | ||
| bulk_scope: BulkScopeActionRBACValidator | None = None |
| self, | ||
| creator: RBACEntityCreator[TRow], | ||
| ) -> RBACEntityCreatorResult[TRow]: | ||
| """Insert one row with its RBAC scope association (the creator carries its scope).""" |
| """Insert rows with their RBAC scope associations (each creator carries its scope).""" | ||
| return await execute_rbac_entity_creators(self._sess, creators) |
| class BulkScopeActionRBACValidator(BulkActionValidator): | ||
| """Bulk analog of ``ScopeActionRBACValidator``: authorize a bulk action at each of its | ||
| scope targets by the caller's permission on the action's *own* entity type. | ||
|
|
Entity-agnostic RBAC write primitives extracted so any entity can reuse them: - RBACWriteOps.create_scoped / purge_scoped: single scoped create/purge that also writes/clears the entity's scope association in the same transaction. - entity_creator: a None primary scope_ref marks a global-scoped entity (no association). - scope_unbinder: scope_ref is Optional to support global-scoped entities. - BulkScopeActionRBACValidator: per-scope RBAC validation for bulk scope actions. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
10fe99d to
fbc02e4
Compare
|
Not planned — abandoning the primitives-extraction approach. Per review, we will not leak a global/None scope into the shared RBAC primitives. Instead:
These changes are folded into #12826. |
Summary
Foundational, entity-agnostic RBAC write primitives extracted from the AppConfig fragment work so any entity can reuse them.
RBACWriteOps.create_scoped/purge_scoped— single scoped create/purge that writes/clears the entity's scope association in the same transaction.entity_creator— aNoneprimaryscope_refmarks a global-scoped entity (no association).scope_unbinder—scope_refisOptionalto support global-scoped entities.BulkScopeActionRBACValidator— per-scope RBAC validation for bulk scope actions.📚 Stacked PRs
Part of the AppConfigFragment / AppConfig stack under BEP-1052 (epic BA-5781). Merge in order (#12801 was split into #12825 / #12826 / #12827):
feat(BA-6552): app_config_fragments DB model and Alembic migrationfeat(BA-6553): repository layerrefactor(BA-6619): consolidate AppConfigScopeType into common.datarefactor(BA-6620): ExistsQuerier + AppConfigAllowList.existsfeat(BA-6554): AppConfigFragment service layerfeat(BA-6702): move fragment rank to the allow list with scope defaultsfeat(BA-6701): expose allow-list rank on the v2 API surfacefeat(BA-6704): cascade app config subtree deletion from the definitionfeat(BA-6626): app_config_fragment bulk repository layerfeat(BA-6618): app_config_fragment bulk CRUD service layerfeat(BA-6810): AppConfigFragment visible-fragments query (repository layer)feat(BA-6867): RBAC scoped-ops primitives ← you are herefeat(BA-6859): bind fragments to their RBAC scope on write (repository layer)feat(BA-6868): RBAC-gate fragment single writes at the processorsfeat(BA-6555): AppConfig merge engine + resolve service (service layer)feat(BA-6556): AppConfig REST v2 APIfeat(BA-6860): fragment write API routes + bulk write authzJira: https://lablup.atlassian.net/browse/BA-6867
🤖 Generated with Claude Code