Skip to content

Administration

One host, many organisations, each running itself. Create organisations, invite people, assign roles, connect single sign-on, send mail, and remove a leaver, from the console or the host.

Set the organisation's rules and the person's route in. The refusals are the console's own sentences. Kodela has no second factor of its own: Require MFA is checked against what the identity provider reports on an SSO sign-in.

What it is, and what it is not

An operator runs the host. Each organisation runs itself: it invites its members, assigns owner, admin, member or read-only auditor, grants repositories and AI providers per person, and sets its own security profile, egress mode and agent rules within the operator's floor. Organisations can sign in through their own Microsoft Entra ID, Google Workspace or OIDC provider.

It is not a SaaS account system. There is no self-signup, no SAML or SCIM, no native MFA or passkeys, and no way yet to delete or suspend a whole organisation.

How it works

Two platform roles
Operator (stored as admin) runs the host and sees every organisation. Developer (stored as dev) works in workspaces. An organisation role grants nothing on the host.
Four organisation roles
Ranked auditor < member < admin < owner. Owners and admins administer; auditors read; members work.
Two consoles, one shell
The operator console covers health, workspaces, organisations, credentials, cluster, settings, mail, governance, egress and audit, plus an operator-only Changelog page at /changelogs listing every release. The organisation console, scoped to one organisation, covers members, workspaces and repository access, AI keys, checks, MCP servers, plans, tasks, settings, “Why it's stuck”, Computers (members' computers), AI usage and Audit. AI usage and Audit are for owners, admins and auditors; a plain member is not offered the Audit tab. Its settings include the Where workspaces run, Workspace requests, Member requests, App feedback, Workspace Docker and Workspace languages cards.
Identity
A password (PBKDF2-SHA256, 200,000 iterations) or per-organisation OIDC. Sessions are signed, HttpOnly, SameSite=Lax cookies that last 24 hours, marked Secure when the host declares TLS, and revoked on the server at sign-out.
What each organisation role may do
In an organisationowneradminmemberauditor
Read members, invitations, the Audit and AI usage tabs, and egressyesyesnoyes
Invite, change roles, disable or offboard membersyesyes, up to adminnono
Settings, SSO, repository grants, AI credentials, create workspacesyesyesnono
Make someone an owneroperators only
Reset another member's passwordmembers onlymembers onlynono
Write anything, even in a workspace they ownyesyestheir own workno

Defaults

Identity and administration defaults
SettingScopeDefaultAllowed
Invitation lifetimeplatform7 daysset per invitation from the host
Session lifetimeplatform24 hoursfixed
Password lockoutplatform8 failures in 5 minutes per source addressfixed; held in memory
mail_driverplatformnone: every send is refusednone, console, smtp
identity_mail_per_address_per_hourplatform31 to 100
identity_mail_per_ip_per_hourplatform201 to 1000
sso_availableplatformtrue; no provider is configured for any organisationtrue, false
sso_default_link_policyplatform, copied to new organisationsdomaindomain, claim, none
personal_hosts_allowedorganisation, set by an operatoroffon, off
personal_hosts_enabled: members' own computers may host their workspacesorganisationoff until an admin turns it onon only while the operator's grant holds
Require SSO, Require MFAorganisationoff until an admin turns them onon, off
Require per-developer identityplatformoff: a shared front-door password is accepted, and is not attributable to a personon, off
max_workspacesorganisation, set by an operator0: no limit0 to 10000
policy_profile, agent_profile_floorplatformunset: no floor; the default profile is guardeda profile name
signup_modeplatforminviterecorded, not yet enforced: invitations are the only way in

Configure it

Organisations and invitations

An operator creates an organisation in the operator console under Organisations, with a slug and a name, and invites its first owner. Owners and admins then invite their own people from the organisation's Members tab. Without mail, the invitation link is shown to the person who made it, once: the server keeps only a hash.

on the host
$ bin/_store.py org-add --slug=acme --name="Acme Ltd"
# the token goes to stdout, the /portal/invite#… link to stderr
$ bin/_store.py invite --slug=acme --email=owner@example.test --org-role=owner
# cap how many workspaces the organisation may hold
$ bin/policy set --scope tenant --target acme --key max_workspaces --value 20

Single sign-on

In the organisation console, open Settings and the Single sign-on card. Register an application with your identity provider using the redirect URI the card shows, https://kodela.example.com/portal/sso/callback on your own address, with scopes openid profile email; Kodela uses the authorisation code flow with PKCE (S256).

Microsoft Entra ID
Application (client) ID, Directory (tenant) ID and client secret. The tenant is pinned: common, organizations and consumers are refused.
Google Workspace
Client ID, client secret, and the allowed domains, which Google requires.
Generic OIDC
Client ID and secret on the card. The issuer and endpoints are entered by hand and discovery is not fetched; they are not on the card yet.
Verified domains
Claim a domain, publish the DNS TXT record the card shows, then mark it verified. The domain link policy links an SSO identity to an existing account only inside a verified domain; accounts are never linked on email alone.
Require SSO
Closes password sign-in for the organisation. It is refused until the provider is enabled, a secret is saved and at least one member is exempt as break-glass.
Require MFA
Passes only if the ID token's amr or acr claim reports a second factor. Kodela has no second factor of its own.

Outbound mail

Invitations work without mail. Email verification and password reset need it. Point the host at an SMTP relay on the operator console's Outbound mail page (host, port, username, password, From address, TLS mode), switch the driver, and use send test email before believing it works. Links in mail are built from AGENT_STACK_BASE_URL in the console's environment, for example https://kodela.example.com; without it, sending fails with no-base-url.

on the host
$ bin/policy set --key mail_driver --value smtp
$ bin/policy get --key mail_driver

Attributable sign-in

While the shared front-door password is accepted, a workspace session is authenticated but not tied to a person. Turn on Require per-developer identity under Governance in the operator console: the shared credential is then refused and every session belongs to a named account.

Requests from members and agents

Three cards in the organisation's settings collect requests for an owner or admin to decide. None of them changes anything by itself.

Member requests
A member asks, from Ask your org in the portal, for a repository from the organisation's catalog or for its AI model. A request grants nothing: approving it only records the decision, and the admin makes the change with the existing controls.
Workspace requests
With workspace_portal_api_enabled on (off by default), an agent in a workspace may ask for a new workspace. A request creates no workspace.
App feedback
With the same switch on, an agent records and triages what an app's users reported.

Tasks

Onboard an organisation

  1. Create it. Operator console, Organisations, new organisation acme. Result: an empty organisation, listed with its members and workspaces.
  2. Invite the owner. Only an operator can grant owner. Result: a one-time link, valid for 7 days, shown once.
  3. The owner sets up SSO and invites members from the Members tab, as admin, member or auditor.
  4. Grant work. The owner connects the organisation's GitHub App, loads repositories and grants them to members' workspaces.

Require SSO safely

  1. Configure and enable the provider, and sign in once with it yourself.
  2. Exempt a break-glass member. Pick one person who keeps a password, for when the provider is down.
  3. Turn on Require SSO. Result: password sign-in answers “Your organisation requires single sign-on” for everyone else.

Remove a leaver

  1. Offboard in the console. Members tab, the person's row, offboard. Disabling alone does not end live sessions; offboarding does.
  2. Their workspaces are archived when the owner departs, including the workspaces on their own computer if your organisation uses members' computers.
  3. On the host, a developer's Linux account is removed with its home archived first: bin/dev-offboard --dev dev01 --dry-run, then without --dry-run. Result: stop, archive, remove; exit 0.

Get an operator back in

  1. See why they cannot sign in. bin/account-recover show --email ops@example.test. Result: each login gate, ending “this account CANNOT sign in: …” or “every login gate on this account is open.”
  2. Restore the role if needed: bin/account-recover set-role --email ops@example.test --role admin. It also re-enables and approves the account.
  3. Reset the password. bin/account-recover reset-password --email ops@example.test. Result: a one-time token, shown once, valid for an hour; the account's sessions are revoked.

Verify it works

on the host
$ bin/account-recover show --email dev@example.test
$ bin/policy get-for --tenant acme --key max_workspaces
$ bin/audit-log query --stream identity --day 2026-09-28

Good looks like: every login gate open for the people who should get in; invitations, sign-ins and role changes in the identity stream, and sign-ins under People & access on the organisation's Audit tab; the Outbound mail test answering “Accepted by the relay for delivery to …”; and an SSO member signing in without a password.

Troubleshooting

no mail driver is configured

mail_driver is none. Set it to smtp and fill in Outbound mail. Hand invitation links over by hand until then.

this invitation has expired - ask for a new one

Invitations last 7 days. Mint another; the old link stays dead.

this invitation was sent to a different address

Sign in as the invited address to accept it, or invite the right one.

only a platform operator can make someone an owner

Admins may grant admin, member or auditor. Ask an operator for owner.

an organisation must keep one owner

Make someone else owner before removing or demoting the last one.

… it must keep one member who can still sign in with a password

Require SSO needs a break-glass member. Exempt one first, or turn Require SSO off.

That address is not in a domain this organisation has verified.

Verify the domain with its DNS record, or use a different link policy.

Too many failed attempts. Try again shortly.

The source address hit the lockout. It clears on its own, and on a restart, because it is held in memory.

This account is waiting to be approved.

An operator approves it; bin/account-recover set-role also approves.

creating an organisation is an operator action

Organisation admins cannot create organisations. An operator does.

What it does not do yet

  • SAML and SCIM. OIDC only, and user provisioning is by invitation.
  • A live identity provider on record. SSO is verified in code; it has not been exchanged with a customer's real IdP, including Okta through generic OIDC.
  • Native MFA or passkeys. A second factor comes only from the IdP on SSO sign-ins.
  • Sign-ins before orxy V1.7.2.2. Password and shared-credential sign-ins are recorded from orxy V1.7.2.2 on (single sign-on sign-ins are recorded as “signed in with SSO”); earlier sign-ins are not in the trail.
  • Deleting or suspending an organisation. Members can be disabled and offboarded; a whole organisation cannot yet.
  • Self-signup. signup_mode is recorded and nothing reads it yet.
  • Email before you configure SMTP, and no delivery is on record yet with the SMTP driver.
  • Rate limits on workspace creation and invitations, scheduled backups and high availability.

Verified against the main branch, 4 Oct 2026.