Permissions
Admin-only endpoints to inspect and edit user permissions stored in MongoDB. The public API seeds the permission catalog on startup so the service and consent flows can reference known nodes right away.
Auth
All routes require a valid API JWT and are currently restricted to the super-admin user.
List permission nodes
GET /v1/admin/permissions
Response:
{
"items": [
{ "id": "671f5b8a7a8a3e6f6e6d6e6d", "node": "profile:read" },
{ "id": "671f5b9e7a8a3e6f6e6d6e6e", "node": "totem:write" }
]
}List user permissions
GET /v1/admin/users/{userId}/permissions
Response:
{
"userId": "c959d9f9-dcbd-4054-8c4c-d5c305997bc0",
"items": [
{
"node": "profile:read",
"negated": false,
"expiresAt": "2026-01-15T12:00:00Z",
"value": { "value": 20, "unit": "gib" }
}
]
}value is optional and allows permissions to carry quantitative limits ("power"/quotas). Supported shapes:
{ "value": 20, "unit": "gib" }10Units (case-insensitive): bytes, kib, mib, gib, tib, seconds, minutes, hours, days, years, count, messages (common aliases like gb are accepted and mapped).
Quota nodes
Some permission nodes are treated as quantitative limits by specific endpoints. Examples:
social:friends.max(unit:countor unit-less number): maximum number of friends a user can have.profile-share.max(unit:countor unit-less number): maximum number of active profile shares a user can create.
Upsert user permission
POST /v1/admin/users/{userId}/permissions
Body:
{
"node": "profile:read",
"negated": false,
"expiresAt": "2026-01-15T12:00:00Z",
"value": { "value": 20, "unit": "gib" }
}Response:
{
"userId": "c959d9f9-dcbd-4054-8c4c-d5c305997bc0",
"node": "profile:read",
"negated": false,
"expiresAt": "2026-01-15T12:00:00Z",
"value": { "value": 20, "unit": "gib" }
}expiresAt is optional. When omitted, the grant/deny does not expire. value is optional. When omitted, it is not changed. To clear an existing value, send null:
{ "node": "profile:read", "value": null }Delete user permission
DELETE /v1/admin/users/{userId}/permissions/{node}
Response:
{ "removed": 1 }