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

+1
View File
@@ -51,6 +51,7 @@ Go only, no SPA. Package `test` (black-box). New files: `test/activity_producers
34. Secret sweep: after exercising every producer, marshal every stored event, the `/v1/activity` response and the `/v1/activity/export` file; assert none contains the password, hash, verification code, invite code, raw API key, article body, file bytes, asset URL or staging path. The log buffer is free of them too.
35. Allowlist: every `Change.Field` is in `{title, online, body, filename, display_name}` and every kind is `text` or `body`.
36. Read-back: list by `category=articles|media|users|system` and `outcome=failed`; compare action sets with the feature tables.
Superseded in part by roles_permissions_roles_api: the closed category list also holds `roles` (target `role`) and the actions are `role.create`, `role.edit`, `role.delete` and `role.reassign`, covered in test/roles_api_*_test.go.
## G. Mutation guard (gremlins stays clean)
37. `task mutate` scope is `./internal/infrastructure/useCases`. Each new branch needs a killing assertion: every no-op guard (body, online, filename, display name) with equal and differing values; delta sign and rune-versus-byte count; success versus failed outcome and recorded once after the change (event count and order against the repository call); every `errors.Is` row of the reason map plus the generic fallback; every `ctx` forwarding; the system-actor defaults. Bare-bool conditions produce no mutant, so cover both branches with tests regardless.