From cc6f53528b97bc5a4f79ea7ae61bb4622588fcef Mon Sep 17 00:00:00 2001 From: Edouard Vanbelle Date: Wed, 17 Jun 2026 23:35:58 +0200 Subject: [PATCH] feat(role): reflect ReBAC doc with changes --- docs/architecture/rebac-authorization.md | 12 ++++++++- docs/plan/drive.md | 8 ++++++ ...plan-ReBAC-Permissions-Grants-Cascading.md | 27 ++++++++++++------- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/docs/architecture/rebac-authorization.md b/docs/architecture/rebac-authorization.md index ca5c927e..2a1d70d9 100644 --- a/docs/architecture/rebac-authorization.md +++ b/docs/architecture/rebac-authorization.md @@ -107,9 +107,19 @@ storage.access_grants expires_at TIMESTAMPTZ NULL ``` -One row per `(subject, permission, resource)` triple. An "admin role on folder +One row per `(subject, permission, resource)` triple. An "owner role on folder X for user Y" is 6 rows; a "viewer role" is 1 row. +> **Note (D-Prep, 2026-06-17):** the role assignment has since pivoted into +> a separate `storage.role_grants` table that stores **one row per role +> assignment** rather than one per permission. `access_grants` stays +> populated via dual-write during the transition; the engine reads the +> role-keyed table for authz decisions. The cleanup PR drops +> `access_grants` after the dual-write window. The historical role name +> `Admin` was renamed to `Owner` at the same time, to disambiguate from +> `UserRole::Admin` (user-account privilege) and match Drive plan +> terminology. + Cleanup is trigger-driven (`trg_cleanup_grants_folder`, …): when a resource or subject is deleted, all referencing grants disappear in the same transaction. diff --git a/docs/plan/drive.md b/docs/plan/drive.md index d94ec018..e567c00f 100644 --- a/docs/plan/drive.md +++ b/docs/plan/drive.md @@ -44,6 +44,14 @@ recognise it instantly. ## Prerequisite — PR D-Prep: `access_grants → role_grants` +**Status (2026-06-17): scope complete, ready to PR.** The schema migration +runs cleanly against real sandbox data (38 role_grants rows produced, +matching the audit's 29 viewer / 5 editor / 4 owner distribution, zero +bundle mismatches). End-to-end Hurl test (`tests/api/role_grants.hurl`) +covers create / atomic role update / revoke with both the canonical +`"owner"` and the legacy `"admin"` compat wire format. Engine reads +pivot to `role_grants` for authz decisions; `access_grants` stays +populated via dual-write as the safety net for one release cycle. **Ratified 2026-06-16.** A separate PR lands BEFORE D0 that refactors `storage.access_grants` into `storage.role_grants` with role-bundle semantics: diff --git a/docs/plan/plan-ReBAC-Permissions-Grants-Cascading.md b/docs/plan/plan-ReBAC-Permissions-Grants-Cascading.md index 5a0a6506..9a55d1cb 100644 --- a/docs/plan/plan-ReBAC-Permissions-Grants-Cascading.md +++ b/docs/plan/plan-ReBAC-Permissions-Grants-Cascading.md @@ -602,20 +602,29 @@ impl Role { pub fn expand(self) -> &'static [Permission] { match self { Role::Viewer => &[Permission::Read], - Role::Commenter => &[Permission::Read, Permission::Comment], - Role::Editor => &[Permission::Read, Permission::Comment, - Permission::Create, Permission::Update], - Role::Manager => &[Permission::Read, Permission::Comment, - Permission::Create, Permission::Update, - Permission::Share], - Role::Admin => &[Permission::Read, Permission::Comment, - Permission::Create, Permission::Update, - Permission::Share, Permission::Delete], + Role::Commenter => &[Permission::Read, Permission::Comment], + Role::Contributor => &[Permission::Read, Permission::Create], + Role::Editor => &[Permission::Read, Permission::Comment, + Permission::Create, Permission::Update], + Role::Owner => &[Permission::Read, Permission::Comment, + Permission::Create, Permission::Update, + Permission::Share, Permission::Delete, + Permission::Manage], } } } ``` +> **Note (D-Prep, 2026-06-17):** the `Manager` role was retired before shipping +> (its bundle was a strict subset of `Owner`); the historical `Admin` role was +> renamed to `Owner` to disambiguate from `UserRole::Admin` (the user-account +> privilege) and match Drive plan terminology. `Contributor` is the new +> drop-zone role. The actual on-the-wire enum lives in +> `src/application/dtos/grant_dto.rs`; that file is the canonical source of +> truth for bundle expansion. The pivot to role-keyed storage (`role_grants` +> table) also happened in D-Prep — see +> `docs/architecture/rebac-authorization.md` for the dual-write timeline. + ### `POST /api/grants` accepts either shape ```json