Skip to content

feat(BA-6867): add generic RBAC scoped-ops primitives#12825

Closed
jopemachine wants to merge 1 commit into
mainfrom
feat/BA-6867-rbac-scoped-ops-primitives
Closed

feat(BA-6867): add generic RBAC scoped-ops primitives#12825
jopemachine wants to merge 1 commit into
mainfrom
feat/BA-6867-rbac-scoped-ops-primitives

Conversation

@jopemachine

@jopemachine jopemachine commented Jul 14, 2026

Copy link
Copy Markdown
Member

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 — a None primary scope_ref marks a global-scoped entity (no association).
  • scope_unbinderscope_ref is Optional to 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):

  1. feat(BA-6552): add app_config_fragments DB model and Alembic migration #12306feat(BA-6552): app_config_fragments DB model and Alembic migration
  2. feat(BA-6553): add app_config_fragments repository layer #12307feat(BA-6553): repository layer
  3. refactor(BA-6619): consolidate AppConfigScopeType into common.data (single definition) #12403refactor(BA-6619): consolidate AppConfigScopeType into common.data
  4. refactor(BA-6620): ExistsQuerier ops primitive + AppConfigAllowList.exists #12405refactor(BA-6620): ExistsQuerier + AppConfigAllowList.exists
  5. feat(BA-6554): add app_config_fragment service layer #12358feat(BA-6554): AppConfigFragment service layer
  6. feat(BA-6702): move fragment rank to the allow list with scope defaults #12516feat(BA-6702): move fragment rank to the allow list with scope defaults
  7. feat(BA-6701): expose allow-list rank on the v2 API surface #12517feat(BA-6701): expose allow-list rank on the v2 API surface
  8. feat(BA-6704): cascade app config subtree deletion from the definition #12518feat(BA-6704): cascade app config subtree deletion from the definition
  9. feat(BA-6626): app_config_fragment bulk repository layer #12426feat(BA-6626): app_config_fragment bulk repository layer
  10. feat(BA-6618): app_config_fragment bulk CRUD service layer #12401feat(BA-6618): app_config_fragment bulk CRUD service layer
  11. feat(BA-6810): AppConfigFragment visible-fragments query (repository layer) #12706feat(BA-6810): AppConfigFragment visible-fragments query (repository layer)
  12. 👉 feat(BA-6867): add generic RBAC scoped-ops primitives #12825feat(BA-6867): RBAC scoped-ops primitives ← you are here
  13. feat(BA-6859): bind AppConfig fragments to their RBAC scope on write (repository layer) #12826feat(BA-6859): bind fragments to their RBAC scope on write (repository layer)
  14. feat(BA-6868): RBAC-gate AppConfig fragment single writes at the processors #12827feat(BA-6868): RBAC-gate fragment single writes at the processors
  15. feat(BA-6555): AppConfig merge engine + resolve service (service layer) #12359feat(BA-6555): AppConfig merge engine + resolve service (service layer)
  16. feat(BA-6556): AppConfig REST v2 API (raw fragments and merged read/update) #12377feat(BA-6556): AppConfig REST v2 API
  17. feat(BA-6860): RBAC-gate app_config fragment writes at the processors #12759feat(BA-6860): fragment write API routes + bulk write authz

Jira: https://lablup.atlassian.net/browse/BA-6867

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings July 14, 2026 06:33
@jopemachine jopemachine requested a review from a team as a code owner July 14, 2026 06:33
@github-actions github-actions Bot added size:L 100~500 LoC comp:manager Related to Manager component labels Jul 14, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 BulkScopeActionRBACValidator and exposed it via RBACValidators (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.

Comment on lines +111 to +114
# 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
]
Comment on lines +269 to +271
all_scope_refs = [
ref for ref in (creator.scope_ref, *creator.additional_scope_refs) if ref is not None
]
Comment on lines +20 to +22
# 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)."""
Comment on lines 145 to 146
"""Insert rows with their RBAC scope associations (each creator carries its scope)."""
return await execute_rbac_entity_creators(self._sess, creators)
Comment on lines +25 to +28
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]>
@jopemachine jopemachine force-pushed the feat/BA-6867-rbac-scoped-ops-primitives branch from 10fe99d to fbc02e4 Compare July 14, 2026 06:48
@jopemachine jopemachine marked this pull request as ready for review July 14, 2026 06:55
@jopemachine jopemachine marked this pull request as draft July 14, 2026 07:00
@jopemachine

Copy link
Copy Markdown
Member Author

Not planned — abandoning the primitives-extraction approach. Per review, we will not leak a global/None scope into the shared RBAC primitives. Instead:

  • keep RBAC scoped-ops taking a concrete scope (no scope_ref | None),
  • drop BulkScopeActionRBACValidator,
  • restrict bulk create to a single shared scope (one scope per batch),
  • handle the public (global) case with a branch in the service layer.

These changes are folded into #12826.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:manager Related to Manager component size:L 100~500 LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants