Files
papercrate/docs/capability_sets.md
T
2025-11-05 14:10:57 +01:00

101 lines
4.0 KiB
Markdown

# 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:read`
- `documents:edit`
- `documents:write`
- `documents:upload`
- `folders:read`
- `folders:edit`
- `folders:write`
- `tags:read`
- `tags:edit`
- `tags:write`
- `correspondents:read`
- `correspondents:edit`
- `correspondents:write`
- `profile:read`
- `profile:write`
- `webdav:read`
- `webdav:write`
- `capability_sets:read`
- `capability_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 only `webdav: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:
```bash
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:
```bash
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):
```bash
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
https://app.papercrate.org/api/capability-sets/$SET_ID
```
## Assigning Sets
- **User memberships**: change the `capability_set_id` column (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 a `capability_set_id` field 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`).