Devboxes
Feature Catalog

Organizations, roles & access

The membership guard, session-rooted revocation, and where writes gate.

Every request into an organization resolves the caller's active membership; the role on that membership — owner, admin, or member — decides what the caller may do. Reads are open to any active member. Writes that create projects, dispatch runs, touch any credential, or control an agent session require owner or admin. Owner and admin are equivalent on those access surfaces; member is read-only, and credential reads gate the same way so secrets never reach a member. Membership privilege changes reserve the owner role itself for owners.

Access is rooted in the session rather than re-checked per request. Cookie sessions and device-flow bearer tokens share one enforcement path, so a ban — which revokes the user's sessions at the source — closes both. The only bearer tokens that can outlive a session are the short-lived JWTs, minted only from a live session and capped at 15 minutes, so a ban reaches JWT holders within that window without a separate revocation list. A user creates at most one organization and joins others by invitation; the session resolves the acting organization from the user's active memberships. Bans and impersonation are driven by a separate platform-administrator role, not by any organization role.

How to test it

SuiteProves
pnpm vp run @firops/api#testopencode-provider-credentials.integration.test.tsNon-admin credential attempts get a 403 through the real membership check, banning a user revokes bearer-session access, and JWTs mint only from a live session — a ban stops issuance while outstanding tokens expire within 15 minutes
pnpm vp run @firops/api#testrunner-machines.test.tsA device session revoked by a ban is rejected at first registration, claim run tokens bind to the machine and the task attempt, and reviving an API key under another organization is rejected

For the full backend gate, run pnpm vp run validate:full.

Decisions

Membership operationOwnerAdminMember
InviteYesYesNo
Resend invitationYesYesNo
Cancel invitationYesYesNo
Change roleYesYesNo
Remove memberYesYesNo
Rename organizationYesYesNo

Only owners can grant or remove the owner role. The server also refuses to demote or remove the last owner.

  • Revocation is session-rooted, not a per-request ban check — banning goes through the real admin flow, which revokes sessions; cookie and device-flow bearer sessions pass through the same guard, and JWTs are short-lived and issued only from live sessions. A stale ban has nowhere to slip through, and the guard stays a single membership lookup.
  • Creating organizations is capped at one; membership is not — a person creates at most one organization but can join others by invitation, so the session resolves the acting organization from the user's active memberships rather than a stored current-org pointer. A caller with more than one owner/admin organization must name it (the runner answers "Multiple owner/admin organizations are available. Pass --organization once.").
  • Writes gate at owner/admin; reads do not — any active member may view organization data, but creating projects, dispatching runs, managing every credential (repository tokens, provider credentials, environment variables and secrets), and every agent-session write require owner or admin, because those actions spend credentials or move real work.
  • Membership changes use the server permission matrix — the dashboard sends, resends, and cancels invitations and manages roles, removals, and organization names, but the server remains the authority for every operation.

Next: Transactional email — the mail that carries invitations out.

Terms of ServicePrivacy Policy

On this page