Meta Authorization¶
Sforza authorizes access to its own administrative APIs using the same SFBAC model — Sforza is a client of itself. The entities involved are ordinary resources and operations, registered automatically at startup.
Meta resources and operations¶
| Resource | Operation | Grants |
|---|---|---|
role |
role:read |
Read roles. |
role |
role:write |
Create / update / delete roles. |
role |
role:assign |
Assign roles to users. |
operation |
operation:read |
Read operations. |
operation |
operation:write |
Create / update / delete operations. |
operation |
operation:assign |
Assign (operation, scope) to roles or users. |
resource |
resource:read |
Read resources. |
resource |
resource:write |
Create / update / delete resources. |
user |
user:read |
Read users and their effective permissions. |
The API reference lists the exact meta operation each endpoint requires.
FULL scope is required
Administrative endpoints operate on whole collections, so a meta
permission only takes effect at FULL scope. RESTRICTED and EMPTY
grants on meta operations deny access.
Tenant scoping¶
Meta permissions live in tenant databases like any other permission. A
user with role:write in tenant-a cannot touch roles in tenant-b
unless granted there too.
Bootstrap administrator¶
On startup Sforza:
- registers the meta resources and operations in the shared database;
- creates the
authorization:adminrole in every tenant, containing every meta operation atFULLscope; - creates the user configured as
bootstrap.admin-suband assigns it the role in every tenant.
bootstrap:
admin-sub: admin-user-sub
The process is idempotent — restarting never duplicates anything, and the admin role is re-asserted even if it was modified.
Delegating administration¶
Because meta operations are ordinary operations, delegation is just another grant. Give a team lead read-only visibility:
curl -X PUT -H 'X-Tenant-ID: tenant-a' ... \
-d '{"scope":"FULL"}' \
localhost:8080/api/v1/roles/team-lead/permissions/role:read
Or query which meta operations a user holds:
GET /api/v1/me/meta-operations
GET /api/v1/users/{sub}/meta-operations # requires user:read