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.
- Login pagedev@example.test at acme
- Organisation rulesRequire SSO, break-glass exemptions
- Identity providerEntra ID, Google or OIDC; PKCE, state, nonce
- Second factorread from the IdP's token, never asked by Kodela
- Account linklink policy
domain - Sessionsigned, HttpOnly, 24 hours, revocable
Require SSO closes password sign-in for everyone except break-glass members.
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 asdev) 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
/changelogslisting 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.
| In an organisation | owner | admin | member | auditor |
|---|---|---|---|---|
| Read members, invitations, the Audit and AI usage tabs, and egress | yes | yes | no | yes |
| Invite, change roles, disable or offboard members | yes | yes, up to admin | no | no |
| Settings, SSO, repository grants, AI credentials, create workspaces | yes | yes | no | no |
| Make someone an owner | operators only | |||
| Reset another member's password | members only | members only | no | no |
| Write anything, even in a workspace they own | yes | yes | their own work | no |
Defaults
| Setting | Scope | Default | Allowed |
|---|---|---|---|
| Invitation lifetime | platform | 7 days | set per invitation from the host |
| Session lifetime | platform | 24 hours | fixed |
| Password lockout | platform | 8 failures in 5 minutes per source address | fixed; held in memory |
mail_driver | platform | none: every send is refused | none, console, smtp |
identity_mail_per_address_per_hour | platform | 3 | 1 to 100 |
identity_mail_per_ip_per_hour | platform | 20 | 1 to 1000 |
sso_available | platform | true; no provider is configured for any organisation | true, false |
sso_default_link_policy | platform, copied to new organisations | domain | domain, claim, none |
personal_hosts_allowed | organisation, set by an operator | off | on, off |
personal_hosts_enabled: members' own computers may host their workspaces | organisation | off until an admin turns it on | on only while the operator's grant holds |
| Require SSO, Require MFA | organisation | off until an admin turns them on | on, off |
| Require per-developer identity | platform | off: a shared front-door password is accepted, and is not attributable to a person | on, off |
max_workspaces | organisation, set by an operator | 0: no limit | 0 to 10000 |
policy_profile, agent_profile_floor | platform | unset: no floor; the default profile is guarded | a profile name |
signup_mode | platform | invite | recorded, 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.
$ 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 20Single 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,organizationsandconsumersare 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
domainlink 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
amroracrclaim 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.
$ bin/policy set --key mail_driver --value smtp
$ bin/policy get --key mail_driverAttributable 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_enabledon (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
- Create it. Operator console, Organisations, new organisation
acme. Result: an empty organisation, listed with its members and workspaces. - Invite the owner. Only an operator can grant owner. Result: a one-time link, valid for 7 days, shown once.
- The owner sets up SSO and invites members from the Members tab, as admin, member or auditor.
- Grant work. The owner connects the organisation's GitHub App, loads repositories and grants them to members' workspaces.
Require SSO safely
- Configure and enable the provider, and sign in once with it yourself.
- Exempt a break-glass member. Pick one person who keeps a password, for when the provider is down.
- Turn on Require SSO. Result: password sign-in answers “Your organisation requires single sign-on” for everyone else.
Remove a leaver
- Offboard in the console. Members tab, the person's row, offboard. Disabling alone does not end live sessions; offboarding does.
- Their workspaces are archived when the owner departs, including the workspaces on their own computer if your organisation uses members' computers.
- 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
- 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.” - Restore the role if needed:
bin/account-recover set-role --email ops@example.test --role admin. It also re-enables and approves the account. - 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
$ 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-28Good 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_modeis 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.
Related
Verified against the main branch, 4 Oct 2026.