Docs
Open in panel → /app · general
Members & Invitations
A workspace has exactly one membership table: workspace_members(user_id, role). Roles are ranked (viewer < operator < admin < owner) for write
gating; the API server enforces them via requireMembership(userId, minRole).
Role matrix
| Role | Read | Operator actions | Admin/Owner-only |
|---|---|---|---|
| viewer | yes | no | no |
| operator | yes | create domain, register IP, register node, send | no |
| admin | yes | yes | manage members |
| owner | yes | yes | invite, delete workspace |
Invitation flow
- Owner (or admin) submits
POST /v1/panel/invitations { email, role }. - The API returns an invite token + the URL
/accept-invite?token=.... - Recipient opens the link, signs up/in, then the page POSTs to
/v1/panel/invitations/accept { token }. - On success the user is added to
workspace_memberswith the assigned role and can sign into/app.
Related
- docs/build/access.md — API/SMTP credential scope.
- docs/build/getting-started.md — first member (owner) bootstraps the workspace via the wizard.
Last verified: Sat Jul 11 2026 17:00:00 GMT-0700 (Pacific Daylight Time). Cross-link maintained byscripts/check-docs-drift.sh (M54).