ReBAC Model
Relationship-based access control in Control Plane — roles, actions, and SpiceDB enforcement.
Control Plane authorization is relationship-based (ReBAC), enforced by SpiceDB. Role names like owner and member are stored as relationships; API handlers check a closed action vocabulary against resource types.
Resource types
| SpiceDB type | Maps to | Typical scope |
|---|---|---|
portal_user | Human user | Subject of all checks |
portal_account | Account (billing org) | Top-level tenant |
portal_workspace | Workspace | Data + apps boundary |
portal_environment | Environment | Deploy target (dev/staging/prod) |
Types are prefixed portal_ because SpiceDB is shared with Dataplane tenant schemas — the prefix prevents collisions.
Membership roles
Users hold roles on accounts and workspaces via SpiceDB relationships:
| Relation | On | Grants |
|---|---|---|
owner | account, workspace | Full administration |
billing_admin | account | Billing + administer |
admin | workspace | Workspace administration |
writer | workspace | Read + write + delete on data pillars |
member | account, workspace | Read access |
deployer | environment | Deploy to that environment |
The Customer Portal Members & Roles page maps to memberships rows in Postgres, which are kept in sync with SpiceDB tuples.
Closed action vocabulary
Handlers call check(action, resource_type, resource_id) with one of:
| Action | Valid on |
|---|---|
administer | account, workspace |
read | account, workspace, environment |
write | workspace |
delete | workspace |
ddl | workspace |
deploy | workspace, environment |
manage_members | account, workspace |
view_billing | account |
A 403 from the API means SpiceDB denied the action — the JWT was valid but the user lacks the relationship.
Adding a new action requires a schema change, authorization code update, and documentation — all in the same change. See SpiceDB schema.
How checks run
| Path | SpiceDB consulted? |
|---|---|
GET /v1/workspaces/{id} | Yes — per-record check |
GET /v1/workspaces (my workspaces) | Indirect — filtered via memberships table |
| Workspace pillar APIs | Yes — action per endpoint |
Control Plane talks to SpiceDB via direct gRPC — not through Dataplane.
Customer Portal mapping
| Portal area | Typical action |
|---|---|
| Accounts list | read on account |
| Create workspace | administer on account |
| Data Vault write | write on workspace |
| Secrets reveal | read + audited |
| Members add/revoke | manage_members |
Related
- SpiceDB schema — full Zed definitions
- API Authentication — JWT + 403 behavior
- Members & Roles guide — UI for grants