Roles, scopes, and permissions
This document describes how user are tied to workspaces, what each role can do, and how permissions are enforced in the Backup API.
For SDK examples (listing workspaces, inviting members, patching roles), see Workspaces and members.
Conceptsβ
Accounts vs workspace membershipβ
- A user is a global account (email, identities, API keys).
- A workspace is an isolated container for backups, restores, snapshots, and quotas.
- Workspace membership links a user to a workspace with exactly one role per pair (
workspace_members). The same user can belong to many workspaces with different roles in each.
Effective permissions (scopes)β
Authorization on workspace routes is not simple βrole checksβ in handlers; it is scope checks. Each request that targets a workspace runs membership resolution, which loads the caller's membership row and computes effectiveScopes:
- Start from the default scopes for the member's role (see below).
- Add every scope listed in
extra_scopes(grant more capability). - Remove every scope listed in
revoked_scopes(take capability away).
Only scopes defined in the API's scope list are valid for extra_scopes / revoked_scopes.
Rolesβ
There are four roles available for workspace members, each granting a different level of access and capabilities.
| Role | Purpose |
|---|---|
| owner | Created for the user who created the workspace. Intended as the ultimate admin; protected from removal when it would leave no owners. |
| admin | Same default powers as owner for day-to-day API operations (see scope table). |
| member | Can read/write backups and related data; cannot manage workspace settings, members, or API keys by default. |
| viewer | Read-only access to backups, restores, and snapshots (no backup writes). |
Default scopes by roleβ
| Scope | owner | admin | member | viewer |
|---|---|---|---|---|
backup:write | β | β | β | |
backup:read | β | β | β | β |
restore:write | β | β | ||
restore:read | β | β | β | β |
snapshots:read | β | β | β | β |
user:read | β | β | ||
api_keys:manage | β | β | ||
workspace:manage | β | β |
Notes
- owner and admin have the same default scope set in code. The important behavioral difference is ownership rules that is owner cannot be removed.
Fine-grained overridesβ
Admin can patch a member with:
roleβ one ofowner,admin,member,viewer.extraScopesβ array of scopes to add on top of the role defaults.revokedScopesβ array of scopes to strip from the effective set (even if the role would normally grant them).
Invalid scope names are rejected with 400.
API keys and workspacesβ
API keys belong to a user, not to a workspace. When a request uses an API key against a workspace route:
- The user must still be a member of that workspace (membership is resolved like for sessions).
- Effective scopes are computed from role + extras β revocations, as for sessions.
- Additionally, each required scope must appear on the API key itself (
keyScopes). So permission is the intersection of workspace-derived scopes and key scopes.
Session JWTs do not impose that second filter; workspace membership alone defines the envelope (unless you add key-like constraints elsewhere).
For creating and scoping keys for automation jobs, see API keys for backup jobs.
Note β There is no βpending inviteβ record, adding a member requires the email to match an existing user.