Skip to content

Users and organisations ​

An application user is a member of organisations. Organisations own guilds, secrets, connector logins, model keys, and usage. How a request becomes a user depends on AUTH_MODE (apps/orchestrator/src/http/identity.ts).

Identity ​

A user has an id, a globally unique name, an optional email, an optional image path, an optional IANA timezone, and an optional identity color (a 6-digit lowercase hex). Names match ^[a-z][a-z0-9-]{0,62}$. The name user is reserved so @user stays the group-chat tag for every operator of a guild. GET /api/auth/me returns the user with platform_admin, which is true for the instance admin. PATCH /api/auth/me takes name, timezone, color, or any of them (timezone and color may be null; a field left out keeps its value), from the Settings page; a name another user holds is 409. The Routine tab pre-fills random windows with the timezone, falling back to the browser's. The colour, returned on /api/auth/me and the organisation's member list, tints the person's messages and avatar.

Core implements two modes, and its configuration accepts no other. Before anyone is identified the app reads GET /api/auth/config, which names the mode. An edition built on core may add a mode of its own by supplying an identity provider (Extension points); a server in a mode with no provider signs no one in (401).

AUTH_MODEProofTypical box
compat-cookieX-Guilds-User or guilds_userLocal Compose; the default
trusted-headerProxy email header (TRUSTED_HEADER_EMAIL, default X-Forwarded-Email) + X-Guilds-Proxy-SecretBehind the operator's own authenticating proxy

compat-cookie: whoever reaches the port is the operator. One user and no header selects that user; several users and no header is 400; an unknown id is 404. The UI boots from GET /api/users and remembers the chosen id in localStorage.

The user directory is GET /api/users, POST /api/users (a name and an optional email; creates the user plus a personal organisation), PATCH /api/users/:id (sets the email, or clears it with null), and DELETE /api/users/:id. On compat-cookie it takes no current-user header and answers whoever reaches the box. On trusted-header it answers the instance admin and is 404 to anyone else. A mode an edition adds has no directory. An email is stored trimmed and in lower case, and two users cannot hold the same one (409).

trusted-header: the reverse proxy exclusively determines the email, and the request's user is the one who holds it; an email no user holds is 401, as is a header without TRUSTED_PROXY_SECRET. Boot gives the seeded operator the address in OPERATOR_EMAIL, which the mode does not start without, and refuses to start when another user holds it. The operator gives anyone else an account through the user directory (Remote access).

Organisations ​

text
instance → organisation → guild → agent

Organisation is the ownership root. org_members carries an owner, admin, or member role. A new user gets a personal organisation with themselves as owner; it stays visually implicit while it is the user's only membership. Guild names are unique within an organisation; agent names are globally unique.

The selected organisation is X-Guilds-Org or guilds_org. One membership and no header selects that organisation; several memberships and no header is 400. Lists return that organisation's visible guilds (org-visible plus the private guilds the current user operates), secrets, and connector logins. Cross-organisation reads and writes return 404. Every member lists every secret of the organisation (metadata, never a value); owners and admins manage any secret and decide who gets it, and a member manages only secrets granted inside guilds they can see (Secrets and access).

Organisation routes: GET /api/orgs, POST /api/orgs (name, slug; anyone on compat-cookie, the instance admin otherwise), GET /api/orgs/:id, PATCH /api/orgs/:id (name, slug), members (GET /api/orgs/:id/members, POST /api/orgs/:id/members with user_id and role, PATCH/DELETE /api/orgs/:id/members/:user_id; owners change owners, admins the rest), usage (GET /api/usage: the current organisation's guilds the caller may see, by guild and agent), and model keys (GET /api/orgs/:id/model-providers for every member, PUT/DELETE /api/orgs/:id/model-providers/:provider for owners and admins; Tools and connectors).

An organisation's limits (how many agents, browser agents, coding agents, and guilds it may hold, how many generations run at once, and a monthly spend) come from the organisation policy. Core's policy sets none of them; the instance-wide ceiling on concurrent generations is MAX_CONCURRENT_GENERATIONS (Configure). An edition may supply a policy of its own (Extension points).

Instance admin is who administers the instance: the connector catalog, instance-level access, and new organisations. Core's rule is an owner of the seed organisation org_home; an edition may replace the rule. The instance admin reaches /api/admin/mcp/* (the connector catalog), GET /api/platform (the instance-level access view), and the Admin entry in the account menu (Operator app).

Group chat snapshots the current user's name on each post; agents see it as the post's author. A guild's operators (Guilds and agents) are tagged by name, and @user tags all of them. Neither selects an agent.

A user can be removed from an organisation, or deleted, only while every guild they administer has another admin.

Seed identity ​

On a box with no user at all, boot (seedOperator) inserts one user row and the organisation it owns:

IdNameEmailImage
user_operatoroperatornone, or OPERATOR_EMAIL when it is setnone

Organisation org_home (name Home, slug home): operator is the owner and has no second personal organisation. The seed user cannot be deleted. Once the box has a user the seed never runs again, so a renamed operator or organisation keeps its name. An edition that seeds its own first user before core looks gets no operator.

A user has no portrait upload path; the account button shows initials.

Delete ​

DELETE /api/users/:id refuses a seed user, and refuses a user who is the last owner of an organisation that still has guilds. The UI has no delete control.

Deleting a user does not cascade organisation-owned data. The instance usage view lists every organisation's lifetime totals; an organisation's counter drops when that organisation is deleted, and the global total stays.

Free software under the GNU Affero General Public License, version 3 only.