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

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