Skip to main content

Admin permissions

The RolePermission table is editable at runtime. Only a system_admin can mutate it; mutations invalidate the global permission cache so changes take effect on the next request.

Endpoints

GET    /api/admin/permissions
POST /api/admin/permissions body { scope, role, resourceType, action, ownOnly? }
PATCH /api/admin/permissions/:id body { ownOnly }
DELETE /api/admin/permissions/:id

All four require requireAdmin (i.e., systemRole = 'system_admin'). The non-admin response is 403 from requireAdmin, not 404.

List

curl --cookie cookies.txt http://localhost:3001/api/admin/permissions
# [
# {"id":"...","scope":"system","role":"user","resourceType":"video","action":"read","ownOnly":false,...},
# {"id":"...","scope":"project","role":"annotator","resourceType":"annotation","action":"create","ownOnly":true,...},
# ...
# ]

Sorted by (scope, role, resourceType, action). The default production seed has on the order of 100 rows.

Create

curl -X POST --cookie cookies.txt http://localhost:3001/api/admin/permissions \
-H 'Content-Type: application/json' \
-d '{"scope":"project","role":"curator","resourceType":"claim","action":"update","ownOnly":false}'
# 201 Created

The unique key is (scope, role, resourceType, action). A duplicate returns 409.

Patch

curl -X PATCH --cookie cookies.txt http://localhost:3001/api/admin/permissions/<id> \
-H 'Content-Type: application/json' \
-d '{"ownOnly":true}'

Only ownOnly is mutable. The route refuses to change scope, role, resourceType, or action because those columns are the unique key; changing them would silently re-identify the row. To move a permission, delete it and create a new row.

Delete

curl -X DELETE --cookie cookies.txt http://localhost:3001/api/admin/permissions/<id>
# 204 No Content

Cache invalidation

Every mutation calls invalidatePermissionCache(), which clears the global matrix cache and every per-user ability cache. Subsequent requests rebuild from the updated matrix. Do not rely on the 5-minute TTL fallback for revocation; the explicit invalidation is the contract.

See also