Files
papercrate/docs/capability_sets.md
nils 3c9a9fc060
ci / docker (backend, backend/Dockerfile, backend) (push) Failing after 13s
ci / docker (frontend, frontend/Dockerfile, frontend) (push) Failing after 12s
Initial commit
2025-12-17 13:37:31 +01:00

3.9 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: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:

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_id column (via future admin APIs or direct SQL) to reassign a user. The authentication pipeline will enforce the new capabilities automatically.
  • API tokens: POST /api/profile/api-tokens requires a capability_set_id. Tokens are bound to the selected set; raw capability arrays are no longer accepted.

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).