lablup / lablup/backend.ai

5. Collapse per-operation permission rows into bitmask and drop operation column

Open
#12,028 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
670
Forks
183
Avg merge
15h 13m
Merged PRs (30d)
368

Description

Background

Finalize the migration by collapsing per-operation rows into a single bitmask row per (role, scope, entity) and removing the legacy operation column.

Scope

Alembic migration: for each (role_id, scope_type, scope_id, entity_type), aggregate per-operation rows into a single row whose Permission bitmask is the OR of the group's operations; delete the redundant rows.

Replace the unique constraint uq_permissions_role_scope_entity_op (role, scope, entity, operation) with one on (role, scope, entity); drop the `operation` column and its StrEnum usage.

Remove operation-unit logic from the write path (PermissionRow.from_input, PermissionCreator, update_role_permissions, bulk add/remove, base/rbac/granter.py, base/rbac/revoker.py, and the vfolder share level change / unshare flows).

Idempotent per the alembic README backport strategy; downgrade restores per-operation rows and the operation column.

Revoke Semantics (partial revoke must NOT be a row DELETE)

Today each row carries exactly one operation, so revoking a subset of operations == deleting the matching rows. After the collapse a row carries the full bitmask, so a naive translation (DELETE WHERE permission & revoked_bits != 0) deletes the whole grant and over-revokes the remaining bits (e.g., an rw -> ro share downgrade would remove read access entirely).

Partial revoke becomes an atomic bitwise clear executed in SQL: UPDATE permissions SET permission = permission & ~revoked_bits WHERE ...; then DELETE rows whose mask reached NONE (do not keep empty grants).

No fetch-modify-write in Python: with per-operation rows, concurrent grant/revoke of different operations touched different rows; after the collapse they contend on one row, so the bit update must be a single SQL statement to avoid lost updates (READ COMMITTED is sufficient with atomic updates).

Entity-keyed full deletes (entity purge, full unshare with operations=None) are unaffected.

Grant Semantics (OR-merge upsert)

Replace ON CONFLICT DO NOTHING on (role, scope, entity, operation) with an OR-merge upsert on the new (role, scope, entity) constraint: ON CONFLICT DO UPDATE SET permission = permissions.permission | EXCLUDED.permission. Keeping DO NOTHING would make permission upgrades (e.g., ro -> rw re-share) silently no-op.

Depends On

Resolution switch story and API exposure story (resolution and API must use the Permission column only). Related: BA-4622 RBAC legacy cleanup; BA-4360 object_permissions removal should land before/with this story so the operation StrEnum can be fully retired.

Success Criteria

after migration, at most one permissions row exists per (role, scope, entity); the bitmask equals the OR of the previous per-operation grants.

the operation column and uq_permissions_role_scope_entity_op are removed; the write path no longer references operation.

partial revoke clears only the targeted bits (remaining bits keep working); a row whose mask reaches NONE is deleted. Covered by tests.

re-granting over an existing row ORs the new bits in (e.g., ro -> rw upgrade works). Covered by tests.

permission resolution results unchanged versus the resolution-switch story (regression parity).

pants lint/check/test pass for affected packages.

JIRA Issue: BA-6352

Contributor guide

Open the contributing guide

Research direction

Start with the Alembic migration and the named write-path entry points: PermissionRow.from_input, PermissionCreator, update_role_permissions, bulk add/remove, base/rbac/granter.py, and base/rbac/revoker.py. Run the affected Pants lint/check/test targets and trace the vfolder share and unshare flows. Done means one bitmask row per role, scope, and entity, atomic partial revokes, OR-merge grants, and successful downgrade parity.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, sql
Domain
authorization, backend, databases
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.