Permissions & roles
Authentication tells the API who you are (see Authentication). Authorization tells the API what you can do — it is driven by roles assigned within each Space.
External figures (auditors, customers, suppliers) do not receive accounts and roles. They access data through a separate sharing mechanism (signed, time-limited links) — out of scope for this page.
Principles
Section titled “Principles”- Roles, not granular permissions. The API checks your role (Owner, Admin, Operator, Viewer), not individual atomic permissions.
- Two scopes. Roles are either Space-level (Owner, Admin) or Unit-level (Operator, Viewer). Space-level roles see the whole Space.
- Access gate. Without a role in a Space, you cannot read or list it.
- Structural vs compliance split. Structural operations (managing Resources, Actions, Units) are separate from compliance operations (issuing and managing Certificates).
Role hierarchy
Section titled “Role hierarchy”Owner (Space) — full superset └── Admin (Space) — everything except Space lifecycle and billing └── Operator (Unit) — compliance work on assigned Units └── Viewer (Unit) — read-only access on assigned UnitsSpace-level roles
Section titled “Space-level roles”| Role | Responsibility |
|---|---|
| Owner | Space lifecycle (create, rename, delete), billing, Admin assignment, plus everything an Admin can do |
| Admin | Structural and compliance operations across the whole Space, plus Unit role management. No billing, no Space lifecycle |
The Owner is constitutive — set at CreateSpace time and persisted as
spaces.ownerUserId. Multiple Admins per Space are allowed.
Unit-level roles
Section titled “Unit-level roles”Assigned per-Unit by an Owner or Admin. A user can hold different roles on different Units. Without any Unit role (and not being Owner/Admin), access to that Unit is denied.
| Role | Value | Responsibility |
|---|---|---|
| Operator | operator | Compliance work: issue, update, revoke Certificates, manage Attachments. Does not modify Units/Resources/Actions |
| Viewer | viewer | Read-only across all entities of the Unit |
Use-case matrix
Section titled “Use-case matrix”Space lifecycle (Owner only)
Section titled “Space lifecycle (Owner only)”| Use case | Owner | Admin | Operator | Viewer |
|---|---|---|---|---|
CreateSpace | ✓ | |||
RenameSpace | ✓ | |||
DeleteSpace | ✓ |
Admin management (Owner only)
Section titled “Admin management (Owner only)”| Use case | Owner | Admin | Operator | Viewer |
|---|---|---|---|---|
AssignSpaceAdmin | ✓ | |||
RemoveSpaceAdmin | ✓ | |||
ListSpaceAdmins | ✓ | ✓ |
Structure (Owner + Admin)
Section titled “Structure (Owner + Admin)”| Use case | Owner | Admin | Operator | Viewer |
|---|---|---|---|---|
CreateUnit / RenameUnit / DeleteUnit | ✓ | ✓ | ||
RegisterResource / UpdateResource / DeleteResource | ✓ | ✓ | ||
DefineAction / UpdateAction / DeleteAction | ✓ | ✓ | ||
AssignResourceToUnit / RemoveResourceFromUnit | ✓ | ✓ | ||
AssignActionToUnit / RemoveActionFromUnit | ✓ | ✓ |
Unit roles (Owner + Admin)
Section titled “Unit roles (Owner + Admin)”| Use case | Owner | Admin | Operator | Viewer |
|---|---|---|---|---|
AssignUnitRole | ✓ | ✓ | ||
AssignUnitRoleByEmail | ✓ | ✓ | ||
RemoveUnitRole | ✓ | ✓ | ||
ListUnitRoles | ✓ | ✓ | ||
LeaveUnit | ✓³ | ✓³ | ✓³ | ✓³ |
GetMyRole | ✓ | ✓ | ✓ | ✓ |
³ LeaveUnit removes the caller’s own assignment on the target Unit. Any role can call it on themselves; an Owner/Admin cannot “leave” (their access is not Unit-scoped).
Compliance — writes
Section titled “Compliance — writes”| Use case | Owner | Admin | Operator¹ | Viewer |
|---|---|---|---|---|
IssueCertificate | ✓ | ✓ | ✓ | |
UpdateCertificate | ✓ | ✓ | ✓ | |
RevokeCertificate | ✓ | ✓ | ✓ | |
AddAttachment / RemoveAttachment | ✓ | ✓ | ✓ |
¹ Operator can act only on entities of the Units they are assigned to.
Subscription (Owner)
Section titled “Subscription (Owner)”| Use case | Owner | Admin | Operator | Viewer |
|---|---|---|---|---|
GetSubscription | ✓ | |||
CreateCheckoutSession | ✓ | |||
CreatePortalSession | ✓ |
| Use case | Owner | Admin | Operator² | Viewer² |
|---|---|---|---|---|
CRUD reads (Get*, List*) | ✓ | ✓ | ✓ | ✓ |
GetUnitCompliance / GetResourceCompliance / GetResourceObligations | ✓ | ✓ | ✓ | ✓ |
GetComplianceGaps / GetExpiringCertificates | ✓ | ✓ | ✓ | ✓ |
GetSpaceCompliance | ✓ | ✓ |
² Operator and Viewer see only entities from Units they are assigned to. Owner and Admin see the whole Space.
Membership
Section titled “Membership”A user has access to a Space when at least one of the following holds:
- they are its Owner (
spaces.ownerUserId), - they are an Admin (via
SpaceAdminAssignment), - they have a role on at least one Unit (Operator or Viewer).
ListSpaces returns only the Spaces the caller can access.
Assigning roles
Section titled “Assigning roles”An Owner or Admin assigns a role by email. Two cases:
- Known user (registered with the IdP) → a
UnitRoleAssignmentis created immediately. - Unknown user → a
UnitRoleInvitationis created and an email is sent. When the user signs up, pending invitations are consumed intoUnitRoleAssignmentrecords.
Constraints
Section titled “Constraints”- one role per
(user, Unit)pair — assigning a new role replaces the old one, - the same user can hold different roles on different Units,
- Owner and Admin automatically see every Unit, with no explicit assignment.
Subscription gating
Section titled “Subscription gating”When a Space’s subscription is not active (expired, payment failed, etc.):
- all write operations are blocked for every role, Owner included,
- read operations remain available,
- membership is preserved — the user still sees the Space in their list,
- the Space
statusfield is independent from the subscription state.
Error responses
Section titled “Error responses”| Situation | Response |
|---|---|
| Token missing / invalid / expired | 401 Unauthorized |
| Valid token, no access to the requested Space | 403 Forbidden |
| Valid token, access to the Space, but insufficient role for the operation | 403 Forbidden (InsufficientPermissionsException) |
| Write blocked by inactive subscription | 403 Forbidden |