Skip to main content

Accounts and access

Who can get into the instance, and what they can do once in, is controlled at three levels: whether someone can make an account at all, what role their account holds inside a workspace, and what a token or agent acting on their behalf is allowed to touch.

Getting an account

Accounts are created by signing up. Whether signup is open is a single setting, PUBLIC_SIGNUP_ENABLED, and in a production build it is closed by default. That's the safe default for anything reachable beyond your own hands: nobody makes an account unless you let them.

The intended flow after first setup is invites, not open signup. As the operator you mint a sign-up invite from the admin console; the person follows the link and registers into the workspace you pointed them at. To open the door wide (a household instance where signup being on is harmless), set PUBLIC_SIGNUP_ENABLED=true and bring the stack up.

Roles inside a workspace

Every membership in a workspace carries a role, from most to least authority: owner, admin, editor, member, guest. Owners and admins run the workspace; editors work in it; members and guests start with almost nothing and see only what you grant.

Below those broad roles, permissions are individual capabilities (adjust stock, create a part, run a specific action). You grant them to a person one at a time, or bundle them into a custom role you define and assign. What someone lacks the capability for is both hidden in the interface and refused by the server, and the two decisions come from the same source, so the UI never shows something the server would block. The full treatment is in People and permissions.

Above every workspace sits the operator tier: the person hosting the instance, named by email in SUPERADMIN_EMAILS, who gets the cross-workspace admin console. That's a separate layer from the per-workspace roles, described in Self-hosting.

Sessions

Logging in creates a signed session that lasts SESSION_TTL_DAYS, 30 days by default and configurable in .env. Sessions are signed with JWT_SECRET; rotate that secret and every session is invalidated at once, which is the blunt way to sign everyone out if you suspect a token leaked. Individual sessions can be revoked without touching the secret.

API tokens for scripts and agents

People log in; scripts and agents use API tokens. A token is minted from your account settings, tied to your user, and shown once at creation (only a hash is stored, so it can't be recovered later, only replaced). Tokens can carry an expiry, and you can revoke one at any time.

Two properties matter for keeping a token narrow:

  • Scopes are deny-by-default. A token minted with a scope can reach only the endpoints that scope allows, and nothing else, even though it carries your identity. A token scoped to one job (say, feeding an edge bridge, or driving your open browser tab) cannot read workspace data or mint more tokens. A token minted with no scope is unrestricted, so scope the ones you hand to automation.
  • Driving is its own grant. The token scope that lets an assistant operate your open Cobblr tab (drive:control) navigates the interface and reads or writes no data on its own; it's also gated by a per-workspace toggle that is off by default. Connecting an assistant this way is covered in Connecting Claude.

Recovering access

Because you own the box, being locked out is always fixable with an .env edit and a restart. If signup is closed and there's no account at all, set PUBLIC_SIGNUP_ENABLED=true, run docker compose up -d, register, then close it again. If you have an account but no admin console, add that account's email to SUPERADMIN_EMAILS and bring the stack up; the operator check reads the list live, so the existing account is granted the tier retroactively. The step-by-step version is in Operating.