3. Add Permission-bitmask resolution repository function clipped by scope-entity cap
- Dominant language
- Python
- Stars
- 670
- Forks
- 183
- Avg merge
- 15h 13m
- Merged PRs (30d)
- 368
Description
Background
Add a new permission-resolution repository function that operates on the Permission bitmask grant column, resolves via a 1-hop direct-scope query, and enforces the scope-entity cap by clipping edge-derived permissions. This is purely additive: the existing operation-based resolution (recursive scope walk + self-scope union) stays in place and is not modified or removed.
Resolution Model: 1-hop direct-scope query (no scope walk)
The new bitmask-based function resolves permissions by querying only the scopes the target entity is directly associated with in scope_entities (1-hop). It does not use the recursive scope walk; the existing _build_scope_walk_cte and the AUTO-seeded direct-scopes machinery remain untouched for the existing function. Premise: RBAC entity creation paths associate each entity directly with all of its effective scopes (primary + additional scope refs), so multi-hop traversal over scope-to-scope edges is redundant for the new path.
Cap Semantics
The grant (permissions.permission) and the cap (scope_entities.permission_cap) share the Permission IntFlag type, so clipping is a single bitwise AND per edge: effective = granted AND edge.permission_cap, with a NULL cap meaning "no ceiling". A permission resolved via one edge is never reduced by another edge's cap. Entity-scope direct grants (Layer 1, scope == entity) bypass cap entirely. No assignment is rejected.
Scope
Add a new function in repositories/permission_controller/db_source/db_source.py that resolves effective permissions via:
(a) a 1-hop branch: join the entity's direct scope_entities edges to permissions on the Permission bitmask column, clipping each edge-derived permission by that edge's permission_cap (NULL = full);
(b) a Layer-1 self-scope branch (entity-as-scope match), evaluated independently and never clipped.
The function reads the Permission bitmask column and uses bitwise predicates (permission & bit != 0); any operation filter is expressed as a bitwise predicate.
Do not modify or remove the existing operation-based resolution path (_resolve_permissions_via_direct_scope_walk, _build_scope_walk_cte, the recursive walk machinery, or the existing operation readers). They continue to serve current callers until later stories migrate over.
New behavior (deliberate, in the new function only): REF edges contribute as direct edges with cap clipping — the holder's own scope permissions apply to the referenced entity up to the edge cap (e.g., read-only through an invitation ref edge).
Out of Scope
Switching existing callers / removing the operation-based resolution path (later stories).
Write-path rejection of over-cap assignment (dropped; enforcement is resolution-time clipping).
API exposure (BA-6351); per-operation row collapse and operation column removal (BA-6352); object_permissions/ObjectPermissionRow query removal (BA-4360).
Depends On
BA-6349: Permission bitmask column on permissions and permission_cap stamping on new ref edges (granter) must exist first.
Success Criteria
The new function returns, for AUTO-edge setups, permission decisions identical to the existing resolution (parity on the additive path).
A permission resolved through a REF / low-cap edge is clipped to the edge cap (new-behavior tests — REF edges previously contributed nothing via resolution).
A permission resolved via an un-capped (NULL) edge is not reduced; no edge's cap affects another edge's contribution.
An entity-scope direct grant (e.g. invitation write) is not clipped by any edge cap.
The existing operation-based resolution path is unchanged and its behavior/tests still pass.
pants lint/check/test pass for affected packages.
JIRA Issue: BA-6350
Contributor guide
Research direction
Start in repositories/permission_controller/db_source/db_source.py and read the existing _resolve_permissions_via_direct_scope_walk and _build_scope_walk_cte paths without changing them. Add the separate bitmask-resolution function with direct scope_entities edges, cap clipping, REF handling, and an uncapped self-scope branch. Done means the stated AUTO parity, REF-cap, NULL-cap, independent-edge, self-scope, and existing-path checks pass, along with pants lint/check/test for affected packages.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- authorization, backend, databases
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100