Skip to main content

Personas & Access

What this covers / who it's for. The two user populations (client users vs central operators), how each signs in, the MFA and step-up model, and how a tenant's team works — invitations, seats, member management, and per-tenant roles. For anyone reasoning about "who can do what, and what stands between them and a sensitive action".

Two populations, fully separate

Client userCentral operator
WhoA person inside one tenant workspace (owner, admin, approver, member, or a custom role)Stables staff: support, compliance, platform admin
SurfaceThe tenant SPA — every request carries the workspace identityThe operator backoffice
ScopeSees only their own tenant's data (database-enforced isolation)Central — works across tenants
RolesPer-tenant roles (defaults + custom)Global operator roles
Provisioned bySelf-service registration (the first owner) or a team invitationA super-admin bootstrap command or an operator invitation
Account statesactive / suspended / deactivated — only active can sign inSame three states, same rule

They are distinct account records on distinct sign-in systems. The same person (even the same email) holding both has two separate identities — separate passwords, separate MFA enrolments, separate sessions. Record specifics: identity README; flow specifics: authentication README.

The client sign-in journey (email-first)

A client user never types a workspace identifier. Sign-in is email-first:

  • Discovery resolves which tenant(s) an email belongs to, so one email can hold memberships in several workspaces.
  • Login happens inside one identified workspace. If the user has MFA enrolled, credentials alone do not sign them in — the session is deferred until a second factor is verified. Five failed challenge attempts void the pending login.
  • Registration, discovery, login, and password-reset endpoints are bot-protected (Cloudflare Turnstile) and rate-limited.

Supporting flows:

FlowBehavior
Self-service registrationCreates a brand-new workspace plus its first user (the owner) in one step. See Tenant lifecycle.
Email verificationCode-based (short-lived, attempt-limited codes); resending is throttled. Verification advances the new workspace's lifecycle.
Password resetCode-based, scoped to the identified workspace. Authenticated password change requires the current password.
Session identityGET /me returns who you are plus a live abilities snapshot (permissions + entitlements + step-up freshness) so the app can show/hide UI truthfully.

MFA — enrolment, challenge, and recovery

Both populations use the same MFA surface. Three factor kinds are supported:

MethodWhat it is
Authenticator app (TOTP)Time-based one-time codes
Platform authenticator (WebAuthn)Face ID / Touch ID / Windows Hello on the user's device
Security keyA roaming hardware key (e.g. YubiKey)
  • Confirming a first factor issues a set of recovery codes — shown exactly once — and marks the account MFA-enrolled; from then on every login includes an MFA challenge (a recovery code can substitute for a lost factor).
  • For a new workspace's first user, confirming the first factor also advances the workspace lifecycle (see Tenant lifecycle).
  • Users self-manage their credentials: list, add, and remove factors, and regenerate recovery codes.

Step-up (sudo) for sensitive actions

Being signed in is not enough for dangerous operations. Actions marked as sensitive — changing a member's roles, deactivating a member, creating/editing/deleting roles, and (for operators) compliance actions like freezing an account — are refused with a STEP_UP_REQUIRED signal until the user re-confirms a factor, which opens a short freshness window (default 5 minutes). When the window lapses, the next sensitive action prompts again; the abilities feed reflects the lapse immediately so the UI never pretends a sudo window is still open.

Central operators

Operators sign in on the central backoffice surface — no workspace context. Differences from clients:

  • Provisioning is never self-service: the first operator comes from the stables:create-super-admin bootstrap command; further operators are invited by existing staff (the backoffice invitation flow).
  • MFA enrolment is forced — an operator cannot settle into the backoffice without a factor.
  • Passkey passwordless login: operators can additionally sign in with a passkey alone (no password), on top of the shared password + MFA-challenge path.
  • Operator roles are global (platform-wide), managed in the backoffice; see Operator backoffice.

Teams — membership inside a tenant

The first user of a workspace is its owner. Everyone else arrives by invitation. Full specifics: team README.

Invitations & seats

  • Inviting requires an available seat — seats are a hard per-tier cap (a limit, not a resetting quota; see Plans & entitlements). Today's caps: starter 3 / growth 10 / elite 50 (placeholder magnitudes, not committed pricing).
  • The seat is checked at invite time but consumed at accept time. There is no reservation: an owner near the cap can over-issue invites, and the last joiner to accept is the one refused (LIMIT_REACHED, with guidance to ask an administrator to free a seat or upgrade). This is a deliberate trade-off.
  • Accepting is public — the single-use invitation token is the credential. The new member is created active with the invited role, then runs their own email-verification + MFA journey.
  • Pending invitations can be listed and revoked.

Member management

  • Role changes, deactivation, reactivation all require step-up MFA.
  • Deactivating a member frees their seat and revokes their sessions immediately; reactivating re-consumes a seat (and can itself hit the cap).
  • The last-owner guard: the only remaining owner can never be demoted or deactivated (refused with LAST_OWNER) — a workspace cannot orphan itself.

Roles — per-tenant vocabulary of a global language

  • The permission vocabulary is global (the same catalog of permission keys platform-wide), but roles are per-tenant: each workspace composes its own bundles of permissions.
  • Every workspace is provisioned with four protected defaultsowner, admin, approver, member — which can be assigned but never edited or deleted.
  • Custom roles (create / edit / delete, all step-up-gated) are a premium capability — gated on the team.advanced-roles feature, granted on the top tier only today.
  • No privilege escalation: a member can only grant permissions they themselves hold — a narrow role-manager cannot mint a stronger role and assign it to themselves.
  • Deleting a role that members still hold is refused unless the deletion names a reassignment target role, in which case holders are moved over first.
  • Some permissions depend on others (you cannot invite to a team you cannot see); dependencies are auto-completed when a role is composed, so an impossible role cannot exist.

What stands between a user and an action (the gate stack)

For any client action, in order: a live session in the right workspace → account active → workspace not compliance-frozen/closed (see Tenant lifecycle) → the required permission (via a role) → the required entitlement (jurisdiction + tier, see Plans & entitlements) → for sensitive actions, a fresh step-up. Every layer fails closed.


← Product wiki index