feat: /v1/role list, get, create, update and delete. Reassign members on delete. Write-time validation (ValidateGrants, duplicates, typed keys against real content types). Name uniqueness (role_name_taken), role_locked, role_has_members, role_conflict on version mismatch. No-escalation: nobody grants a permission they don't hold, and roles.edit_owner_only guards the Owner role. Activity events for role changes. Typed-key exposure in /auth/me. Cleanup of typed rows when a content type is deleted. | Backend only. Will carry the deferred ListGrants decision.

This commit is contained in:
Florian Sylvain committed 2026-10-27 00:45:24 +01:00
1 parent a043f7f41a
commit 094df63a7f
51 files changed
+4822 -115

No files matched your search

@@ -152,7 +152,7 @@ Feature: Roles and permissions content scope: own and all enforcement on article
Given a role repository that counts calls and a user repository that counts calls
When a gated request is sent with a session cookie
Then the user repository Get is called at most once for the whole request, and the role repository Get (or GetByName for the legacy fallback) exactly once
And ListGrants is called zero times by the permission check and by GetMyAccessUseCase
And List is called zero times by the permission check and by GetMyAccessUseCase (ListGrants was removed by roles_permissions_roles_api)
And with an API key the user repository Get is called at most twice (key authentication plus one request-scoped load)
And the status codes and the order of checks of the enforcement feature are unchanged
And a request-scoped current-user holder is filled by the first middleware that loads the user, so RequireCurrentToken, RequireVerifiedUser, the permission gate and AuditContext do not each reload it
@@ -456,9 +456,9 @@ Feature: Roles and permissions content scope: own and all enforcement on article
Given a custom role with a duplicate row content.update=own and content.update=all, and a hand-placed settings.delete_site=all
When the client sends GET /v1/auth/me
Then access.permissions holds content.update at own and no settings.delete_site
And typed grants are not listed in this slice
And typed grants are not listed in this slice (superseded by roles_permissions_roles_api: typed entries, scope none included, are listed)
Scenario: Out of scope here
Then there is no /v1/role CRUD, no no-escalation rule, no role change or ownership transfer, no SPA change and no schedule route
And typed grants are written by slice 3 and exposed to the SPA by a later slice
And rows of deleted content types in typed grants are cleaned up by slice 3
And typed grants are written by slice 3 and exposed to the SPA by a later slice (done by roles_permissions_roles_api: the API writes them and /auth/me lists them)
And rows of deleted content types in typed grants are cleaned up by slice 3 (done by roles_permissions_roles_api)