4.0 KiB
Capability Sets
Capability sets are the tenant-scoped bundles of REST and WebDAV permissions. Every user membership and API token now references one of these sets, and the capability guard middleware enforces the scopes on every route.
Enumerated Capabilities
All capabilities live in the ApiCapability enum. The current list is:
documents:readdocuments:editdocuments:writedocuments:uploadfolders:readfolders:editfolders:writetags:readtags:edittags:writecorrespondents:readcorrespondents:editcorrespondents:writeprofile:readprofile:writewebdav:readwebdav:writecapability_sets:readcapability_sets:write
Default Sets
Provisioning (and the test harness) seed four system capability sets per tenant:
owner— contains the full set above. Tenant owners, admin users, and freshly minted API tokens effectively get unrestricted access.user— the default interactive role: full document/tag/correspondent/profile access, but no capability-set or WebDAV write privileges.readonly— interactive but read-only: document/folder/tag/correspondent reads plus WebDAV downloads, but no modifying routes.webdav— contains onlywebdav:read. WebDAV backup scripts can bind to this set for read-only access.
System sets are flagged with is_system = true and cannot be modified or deleted via the API.
REST API
The capability-set endpoints live at /api/capability-sets and require the new admin capabilities:
| Method & Path | Capability | Description |
|---|---|---|
GET /api/capability-sets |
capability_sets:read |
List all sets for the tenant |
POST /api/capability-sets |
capability_sets:write |
Create a new set |
GET /api/capability-sets/{id} |
capability_sets:read |
Fetch details of a specific set |
PATCH /api/capability-sets/{id} |
capability_sets:write |
Replace capabilities / rename the set |
DELETE /api/capability-sets/{id} |
capability_sets:write |
Remove a custom set (must be unused) |
Examples
Create a read-only set:
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
https://app.papercrate.org/api/capability-sets \
-d '{
"slug": "api_readonly",
"capabilities": [
"documents:read",
"folders:read",
"tags:read"
]
}'
Update an existing set:
curl -X PATCH \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
https://app.papercrate.org/api/capability-sets/$SET_ID \
-d '{
"capabilities": ["documents:read", "documents:edit"]
}'
Delete (fails if still referenced by memberships or tokens):
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
https://app.papercrate.org/api/capability-sets/$SET_ID
Assigning Sets
- User memberships: change the
capability_set_idcolumn (via future admin APIs or direct SQL) to reassign a user. The authentication pipeline will enforce the new capabilities automatically. - API tokens:
PATCH /api/profile/api-tokens/{id}accepts a capability array; underneath the token is mapped to the corresponding capability set. With the new endpoints, we can expose acapability_set_idfield to limit tokens to specific bundles.
Guard Coverage
The RequireCapabilitiesLayer middleware wraps all protected routers (documents, folders, tags, correspondents, profile, capability sets, assets). Requests missing the necessary capability now terminate with a 403 containing missing_capability details.
Integration tests in backend/tests/capability_guards_flow.rs ensure read-only users cannot upload or manage capability sets, and WebDAV tokens without webdav:read are rejected (backend/tests/api_tokens_flow.rs).