# Odudu documentation > Odudu is a self-hosted OpenID Connect and OAuth 2.0 identity provider. Each page below is plain Markdown. This file contains links to documentation sections following the llmstxt.org standard. ## Table of Contents - [Audit trail in the console](https://wizzywit.github.io/odudu/docs/admin-console/audit-trail.md): Find out who changed what and when, filter the trail, read one event in full and export the events that match. - [Clients in the console](https://wizzywit.github.io/odudu/docs/admin-console/clients.md): Register an application, set where sign-in may send people back, rotate its secret and cut off its tokens. - [Email in the console](https://wizzywit.github.io/odudu/docs/admin-console/email.md): Give a tenant a mail relay of its own, send a test message, and see which mail went out and which failed. - [Groups in the console](https://wizzywit.github.io/odudu/docs/admin-console/groups.md): Gather subjects into groups, nest groups under one another and give a group roles that all its members hold. - [Admin console](https://wizzywit.github.io/odudu/docs/admin-console.md): A guided first visit to the console, then one page for each area it manages. - [Overview in the console](https://wizzywit.github.io/odudu/docs/admin-console/overview.md): Check what needs attention in a tenant, see how big it is and copy the addresses an application needs. - [Registration tokens in the console](https://wizzywit.github.io/odudu/docs/admin-console/registration-tokens.md): Let an application register itself as a client with a token that works a set number of times and then expires. - [Roles in the console](https://wizzywit.github.io/odudu/docs/admin-console/roles.md): Create a role, nest one role in another, see who holds it, and understand which roles are really admin capabilities. - [Scopes in the console](https://wizzywit.github.io/odudu/docs/admin-console/scopes.md): Create a scope, decide which clients get it, write the text people see when they consent, and connect roles to it. - [Sessions in the console](https://wizzywit.github.io/odudu/docs/admin-console/sessions.md): See everybody who is signed in to a tenant and end one person's sessions or all of them. - [Settings in the console](https://wizzywit.github.io/odudu/docs/admin-console/settings.md): Change how long sessions and tokens last, what a password must satisfy, when an account locks, and how long the audit trail is kept. - [Sign-in flow in the console](https://wizzywit.github.io/odudu/docs/admin-console/sign-in-flow.md): Choose what a person is asked at sign-in and in what order, and make a one-time password mandatory for everyone. - [Signing keys in the console](https://wizzywit.github.io/odudu/docs/admin-console/signing-keys.md): Rotate the keys that sign a tenant's tokens without breaking the applications that verify them. - [Subjects in the console](https://wizzywit.github.io/odudu/docs/admin-console/subjects.md): Create a person, give them a first password, change their profile, groups and roles, end their sessions and delete them. - [System administrators in the console](https://wizzywit.github.io/odudu/docs/admin-console/system-administrators.md): See who can reach every tenant, give another subject that reach, and change or take it back. - [Tenants in the console](https://wizzywit.github.io/odudu/docs/admin-console/tenants.md): Create a tenant with its first administrator, export it to a file, import a file as a new tenant, disable it and delete it. - [A first visit to the console](https://wizzywit.github.io/odudu/docs/admin-console/tour.md): Sign in to the console, enter a tenant, find your way around the menu, look at one person and see the change that made them recorded. - [Clients](https://wizzywit.github.io/odudu/docs/concepts/clients.md): A client is an app registered with a tenant. It is public or confidential, uses PKCE, and may only send people back to addresses you listed. - [Consent and audit](https://wizzywit.github.io/odudu/docs/concepts/consent-and-audit.md): Consent is what a person agreed to share with an app. The audit trail is the record of what happened, kept per tenant and bounded. - [Concepts](https://wizzywit.github.io/odudu/docs/concepts.md): Tenants, clients, scopes, roles and groups, sessions, tokens, and consent and audit, each explained with a story and a diagram. - [Roles and groups](https://wizzywit.github.io/odudu/docs/concepts/roles-and-groups.md): A role says what a person may do, a group says who they are alongside. Roles reach down a tree of groups, and the groups claim does not. - [Scopes](https://wizzywit.github.io/odudu/docs/concepts/scopes.md): A scope is a named bundle of access a client asks for. It decides which claims reach each token, and what a person is asked to approve. - [Sessions](https://wizzywit.github.io/odudu/docs/concepts/sessions.md): A session records that a person signed in. It ends when idle too long, after a fixed time or on purpose. Recovery codes replace a lost second factor. - [Tenants](https://wizzywit.github.io/odudu/docs/concepts/tenants.md): A tenant is one organisation's own space in Odudu, with its own people, apps, keys and sessions, kept apart from every other tenant's. - [Tokens](https://wizzywit.github.io/odudu/docs/concepts/tokens.md): A sign-in produces three tokens. The access token goes to your API, the ID token tells your app who signed in, and the refresh token gets new ones. - [Architecture](https://wizzywit.github.io/odudu/docs/contributing/architecture.md): The five layers every package follows, the imports each may make and a map of what each directory of the repository holds. - [Contributing](https://wizzywit.github.io/odudu/docs/contributing.md): Build Odudu from source, run its tests and send a change. - [Run it from a checkout](https://wizzywit.github.io/odudu/docs/contributing/run-from-a-checkout.md): Start Odudu from the source tree, with Postgres in Docker or on your machine, and try the console, the e2e suite and the Swagger UI. - [Running the tests](https://wizzywit.github.io/odudu/docs/contributing/running-the-tests.md): What each kind of test in the repository does, how to run all of them or one, and what fails when documentation drifts. - [The phase process](https://wizzywit.github.io/odudu/docs/contributing/the-phase-process.md): How a piece of work is planned, built, reviewed and closed, in short, with a pointer to where the rules live. - [How the transcripts are captured and checked](https://wizzywit.github.io/odudu/docs/contributing/transcripts.md): How the recorded request, admin and console transcripts were captured against running stacks, and the tests that keep them true to the server. - [An admin signs in and changes a user](https://wizzywit.github.io/odudu/docs/guides/admin-signs-in-and-changes-a-user.md): Sign an administrator in to the console, check who you are, change a user with a safe update, and sign out, with the real requests. - [Protect an API](https://wizzywit.github.io/odudu/docs/guides/api.md): Decide whether to trust the access token a caller sends your API, by finding the tenant's keys and checking the token's issuer, expiry and signature. - [Guides](https://wizzywit.github.io/odudu/docs/guides.md): Sign users in from a web app, a single-page app, an API or a machine. - [Move from Keycloak](https://wizzywit.github.io/odudu/docs/guides/keycloak.md): Which Keycloak concepts Odudu has under what name, how to rebuild a realm's roles and groups as a tenant, and what does not move. - [Call an API as a service](https://wizzywit.github.io/odudu/docs/guides/machine-to-machine.md): Register a service, get an access token for it with the client credentials grant and read what it holds, with commands you can run. - [Read a refusal](https://wizzywit.github.io/odudu/docs/guides/read-a-refusal.md): What an error from Odudu looks like and why it happened: a wrong password, an unknown client, a reused token, too much scope, a stale update. - [Refresh and end a session](https://wizzywit.github.io/odudu/docs/guides/refresh-and-end-a-session.md): Keep a person signed in by rotating refresh tokens, spot a stolen one, and sign them out so no token works again. - [Sign a user in](https://wizzywit.github.io/odudu/docs/guides/sign-a-user-in.md): Send a person to Odudu to sign in and get back tokens your app can trust, with the authorization code flow and PKCE. - [Sign people in to a single-page app](https://wizzywit.github.io/odudu/docs/guides/single-page-app.md): Register a single-page or mobile app that cannot keep a secret, allow its origin to call Odudu from the browser and sign a person in with PKCE. - [Sign people in to a web app](https://wizzywit.github.io/odudu/docs/guides/web-app.md): Register a web app that keeps a secret, send a person to Odudu to sign in and swap the code you get back for tokens, with commands you can run. - [Sign in to WordPress with Odudu](https://wizzywit.github.io/odudu/docs/guides/wordpress.md): Let people sign in to a WordPress site with their Odudu account, using the OpenID Connect Generic Client plugin and one small add-on. - [Odudu next to other identity providers](https://wizzywit.github.io/odudu/docs/introduction/compare.md): What Odudu does today and where each capability is shown, what it does not do, and where to read about Keycloak, Ory, Zitadel and Authentik. - [Introduction](https://wizzywit.github.io/odudu/docs/introduction.md): What Odudu is, who it is for and how the documentation is laid out. - [The name Odudu](https://wizzywit.github.io/odudu/docs/introduction/odudu.md): What the name Odudu stands for in the product, authority held by the people who run it. - [Backups](https://wizzywit.github.io/odudu/docs/operating/backups.md): What to copy so a lost server can be rebuilt, and what the project has not yet proven. - [Production settings](https://wizzywit.github.io/odudu/docs/operating/configuration.md): Which settings the server will not start without in production, and where the full list of variables is. - [Deploying](https://wizzywit.github.io/odudu/docs/operating/deploying.md): Put Odudu on a server other people can reach, with its own Postgres, TLS in front and secrets you generated. - [Hardening](https://wizzywit.github.io/odudu/docs/operating/hardening.md): A checklist of the guards the server starts under and the settings around them, to go through before real people sign in. - [Operating Odudu](https://wizzywit.github.io/odudu/docs/operating.md): Deploy, configure, upgrade, back up and scale a running installation. - [Releasing](https://wizzywit.github.io/odudu/docs/operating/releasing.md): How a version of Odudu is published, for the people who publish one. - [Scaling](https://wizzywit.github.io/odudu/docs/operating/scaling.md): Why Odudu runs as one instance today, what that costs and where more are planned. - [Upgrading](https://wizzywit.github.io/odudu/docs/operating/upgrading.md): Move a running Odudu server to a newer version, safely and one instance at a time. - [Quick start](https://wizzywit.github.io/odudu/docs/quick-start.md): Start Odudu with Docker Compose, sign in to its console and sign a person in to an app of your own, through the console or the command line. - [Admin API: Audit](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/audit.md): 3 operations of the Odudu admin API on audit, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Clients](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/clients.md): 12 operations of the Odudu admin API on clients, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Flow](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/flow.md): 2 operations of the Odudu admin API on flow, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Groups](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/groups.md): 9 operations of the Odudu admin API on groups, each with its method, path, required capability, parameters, request body and responses. - [Admin API](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api.md): The Odudu admin API: 114 operations over HTTP and JSON, grouped by area, with authentication and the shape of an error. - [Admin API: Keys](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/keys.md): 5 operations of the Odudu admin API on keys, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Lockouts](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/lockouts.md): 1 operation of the Odudu admin API on lockouts, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Mail](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/mail.md): 1 operation of the Odudu admin API on mail, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Registration tokens](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/registration-tokens.md): 3 operations of the Odudu admin API on registration tokens, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Roles](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/roles.md): 10 operations of the Odudu admin API on roles, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Scopes](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/scopes.md): 16 operations of the Odudu admin API on scopes, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Sessions](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/sessions.md): 3 operations of the Odudu admin API on sessions, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Settings](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/settings.md): 2 operations of the Odudu admin API on settings, each with its method, path, required capability, parameters, request body and responses. - [Admin API: SMTP](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/smtp.md): 4 operations of the Odudu admin API on smtp, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Subjects](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/subjects.md): 34 operations of the Odudu admin API on subjects, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Tenants](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/tenants.md): 8 operations of the Odudu admin API on tenants, each with its method, path, required capability, parameters, request body and responses. - [Admin API: Whoami](https://wizzywit.github.io/odudu/docs/reference/generated/admin-api/whoami.md): 1 operation of the Odudu admin API on whoami, each with its method, path, required capability, parameters, request body and responses. - [Command line](https://wizzywit.github.io/odudu/docs/reference/generated/cli.md): Every command of the odudu program, with its options and an example: init, seed, reap, send-mail, console and more. - [Configuration](https://wizzywit.github.io/odudu/docs/reference/generated/configuration.md): Every environment variable the Odudu server and its commands read, with type, bounds, default, which are required and what each does. - [Endpoints](https://wizzywit.github.io/odudu/docs/reference/generated/endpoints.md): Every HTTP endpoint the Odudu server serves, with its method, path, how it authenticates and what it is for. - [Error codes](https://wizzywit.github.io/odudu/docs/reference/generated/errors.md): Every error code Odudu returns or prints: admin API problem types, OAuth and OpenID Connect errors, and server and command errors. - [Audit events](https://wizzywit.github.io/odudu/docs/reference/generated/events.md): The audit trail vocabulary: every event type, action, outcome and reason Odudu records, and what each means. - [Reference](https://wizzywit.github.io/odudu/docs/reference.md): Endpoints, configuration, commands, error codes and events, looked up by name. - [Protocol in plain words](https://wizzywit.github.io/odudu/docs/reference/protocol.md): The addresses Odudu serves for sign-in, the parameters each takes, and what it refuses, in plain words. - [DELETE /admin/tenants/{tenant}](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/delete-admintenantstenant.md): Requires manage-tenants, the capability every other route over the tenant collection takes, so only a system administrator reaches it. - [DELETE /clients/{id}](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/delete-clientsid.md): Requires manage-clients. Deletes the client and its OIDC configuration in one statement — the foreign key from client_oidc_config to clients… - [DELETE /clients/:id/grants](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/delete-clientsidgrants.md): Requires manage-sessions, the capability every other grant revocation takes. - [DELETE /keys/:id](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/delete-keysid.md): Requires manage-keys. Deletes a retired key, which is published nowhere and signs nothing, so nothing a relying party holds can still need it. - [DELETE /lockouts](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/delete-lockouts.md): Requires manage-users. Clears every subject's run of failed sign-ins, locked or still counting, as DELETE /subjects/:id/lockout clears one, and… - [DELETE /scopes/:id/clients/:clientId](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/delete-scopesidclientsclientid.md): Requires manage-tenant. Removes the client's assignment of the scope, whether it was default or optional — the inverse of PUT… - [DELETE /sessions](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/delete-sessions.md): Requires manage-sessions. Ends every live session in the tenant, each through the same endSession that DELETE /subjects/:id/sessions/:sid calls —… - [DELETE /subjects/:id](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/delete-subjectsid.md): Requires manage-users. Removes the subject; every table that names one (users, user_credentials, sessions, token_grants, subject_roles, …) cascades… - [DELETE /subjects/:id/credentials/:credentialId](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/delete-subjectsidcredentialscredentialid.md): Requires manage-users. Removes one credential — a TOTP enrolment or a WebAuthn credential, most operationally — so the subject's next login no… - [DELETE /subjects/:id/lockout](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/delete-subjectsidlockout.md): Requires manage-users. Deletes the subject's login_failures row — the same write a correct password accepted by an unlocked account makes — so the… - [DELETE /subjects/:id/recovery-codes](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/delete-subjectsidrecovery-codes.md): Requires manage-users. Revokes every recovery code the subject holds, spent ones with them, so none signs in again — the answer to a printed list… - [DELETE /subjects/:id/sessions](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/delete-subjectsidsessions.md): Requires manage-sessions, like the rest of this family. - [GET /admin/openapi.json](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-adminopenapijson.md): The reference these pages point at: an OpenAPI 3.1 description of every route above, generated from the same route table the router registers… - [GET /admin/tenants](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-admintenants.md): Lists tenants — every one, the system tenant included: hiding it would make the one tenant an operator most needs to inspect the one they cannot. - [GET /admin/tenants/count, GET /subjects/count, GET…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-admintenantscount-get-subjectscount-get-clientscount-get-rolescount-get.md): How many rows a listing would page through, without paging through them. - [GET /admin/tenants/{tenant} and PATCH…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-admintenantstenant-and-patch-admintenantstenant.md): Both require manage-tenant on the tenant named in the path — the tenant itself, not the collection, so a tenant-local admin reaches its own and a… - [GET /audit](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-audit.md): Requires view-audit, which carries no manage- counterpart: nothing ever amends a row here, only reap deletes one once it is older than the tenant's… - [GET /audit/count and GET /audit/export](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-auditcount-and-get-auditexport.md): Requires view-audit. Both take GET /audit's filters, and the same refusals of them. - [GET /clients, POST /clients and GET /clients/{id}](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-clients-post-clients-and-get-clientsid.md): The client transcripts here and under PATCH, DELETE and POST …/secret predate service_account_admin_reach; each such response now carries it. - [GET /clients/:id/evaluate](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-clientsidevaluate.md): Requires manage-clients and view-users, since what it answers is the subject's data; without the second it is refused with 403 and a… - [GET /clients/:id/installation](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-clientsidinstallation.md): Requires manage-clients. What a relying party is configured with: the issuer and its discovery URL, as this request's own host names them — the… - [GET /clients/:id/logout-deliveries](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-clientsidlogout-deliveries.md): Requires manage-clients. The Back-Channel Logout Tokens queued for the client, most recent first and cursored: pending, delivered, or failed once… - [GET /export](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-export.md): GET /admin/tenants/{tenant}/export requires manage-tenant and manage-clients — the second because the document carries every client, which every… - [GET /flow/executions and PUT /flow/executions](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-flowexecutions-and-put-flowexecutions.md): Both require manage-tenant. GET reads the tenant's whole authentication flow — the ordered list authn-flows's executor dispatches against — as… - [GET /groups, POST /groups, GET /groups/:id, PATCH…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-groups-post-groups-get-groupsid-patch-groupsid-and-delete-groupsid.md): All five require manage-tenant; the list, GET /groups, is also readable with view-users (below). - [GET /groups/:id/roles and PUT /groups/:id/roles](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-groupsidroles-and-put-groupsidroles.md): Both require manage-tenant. The write replaces the group's role mapping wholesale — a role left out of the list is one the caller clears, not one… - [GET /keys, POST /keys, POST /keys/:id/promote and POST…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-keys-post-keys-post-keysidpromote-and-post-keysidretire.md): All four require manage-keys, never manage-tenant — a tenant admin who may reconfigure clients need not also be trusted to rotate what signs their… - [GET /mail](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-mail.md): Requires manage-tenant, the capability SMTP is configured with. - [GET /registration-tokens, POST /registration-tokens and…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-registration-tokens-post-registration-tokens-and-delete-registration.md): All three require manage-clients, the same capability the client routes above need — an initial access token is configuration for dynamic… - [GET /roles, POST /roles, GET /roles/:id, PATCH /roles/:id…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-roles-post-roles-get-rolesid-patch-rolesid-and-delete-rolesid.md): All five require manage-tenant; the list, GET /roles, is also readable with view-users (below). - [GET /roles/:id/composites and DELETE…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-rolesidcomposites-and-delete-rolesidcompositeschildid.md): Both require manage-tenant. The read answers the role's direct children only, each in the same shape GET /roles/:id answers, ordered by name — not… - [GET /scopes, POST /scopes, GET /scopes/:id, PATCH…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-scopes-post-scopes-get-scopesid-patch-scopesid-and-delete-scopesid.md): All five require manage-tenant. include_in_id_token and include_in_access_token (both default true) decide which token a scope's claims land in… - [GET /scopes/:id/clients](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-scopesidclients.md): Requires manage-tenant, the capability that arranges scopes — not the manage-clients a client's own representation needs. - [GET /scopes/:id/impact, GET /scopes/builtins and POST…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-scopesidimpact-get-scopesbuiltins-and-post-scopesrestore-builtins.md): All three require manage-tenant. They support deleting a built-in scope: what it takes, which built-ins are missing, and how to restore them… - [GET /scopes/:id/mappers and PUT /scopes/:id/mappers](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-scopesidmappers-and-put-scopesidmappers.md): Both require manage-tenant. GET returns available — every mapper name the process's ClaimMapperRegistry carries, the same registry ID token and… - [GET /scopes/:id/roles and PUT /scopes/:id/roles](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-scopesidroles-and-put-scopesidroles.md): Both require manage-tenant. The write replaces the scope's role mapping wholesale, the same replace-all shape PUT /groups/:id/roles uses. - [GET /sessions, GET /sessions/count and GET…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-sessions-get-sessionscount-and-get-clientsidsessions.md): Requires manage-sessions. Every live session in the tenant, whoever holds it, in id order and cursored, each naming its subject and that subject's… - [GET /settings and PATCH /settings](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-settings-and-patch-settings.md): The 36 columns tenants carries beyond identity — everything odudu seed tenant --set can already change — read and amended through one map… - [GET /smtp, PUT /smtp, DELETE /smtp and POST /smtp/test](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-smtp-put-smtp-delete-smtp-and-post-smtptest.md): All four require manage-tenant. DELETE removes the tenant's own row, so its mail falls back to the deployment's ODUDU_SMTP_ sender and then the… - [GET /subjects](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjects.md): Requires view-users, and manage-users reaches it too: every manage-* role is composited to its view-* counterpart through role_composites. - [GET /subjects/:id](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsid.md): Requires view-users, the same capability the listing does. - [GET /subjects/:id/admin-capabilities](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsidadmin-capabilities.md): Requires view-users. The admin capabilities the subject holds, each as the effective role it is, with every path it is held by (direct, group… - [GET /subjects/:id/consents and DELETE…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsidconsents-and-delete-subjectsidconsentsclientid.md): The read requires view-users, the delete manage-users. - [GET /subjects/:id/credentials](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsidcredentials.md): Requires view-users. Metadata only — type, created_at, and, for a password credential, whether it is expired under the tenant's password_max_age_days. - [GET /subjects/:id/effective-roles](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsideffective-roles.md): Requires view-users. Every role the subject holds — the set token issuance and authorization read (effectiveRoles, @odudu/domain-authz), not only… - [GET /subjects/:id/grants and DELETE…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsidgrants-and-delete-subjectsidgrantsclientid.md): Requires manage-sessions: a grant is what a token is presented under, so it is a session's concern, and ending one is the same capability's. - [GET /subjects/:id/groups and PUT /subjects/:id/groups](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsidgroups-and-put-subjectsidgroups.md): The read requires view-users; the write requires manage-users. - [GET /subjects/:id/lockout](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsidlockout.md): Requires view-users. The subject's run of failed sign-ins as the lockout reads it: failure_count, last_failure_at, locked_until, and locked —… - [GET /subjects/:id/profile and PATCH /subjects/:id/profile](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsidprofile-and-patch-subjectsidprofile.md): Reading a subject's profile requires view-users, and changing it requires manage-users. - [GET /subjects/:id/required-actions and PUT…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsidrequired-actions-and-put-subjectsidrequired-actions.md): Reading a subject's required actions requires view-users, and replacing them requires manage-users. - [GET /subjects/:id/roles and PUT /subjects/:id/roles](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsidroles-and-put-subjectsidroles.md): The read requires view-users. The write requires manage-users, and enforces a capability ceiling beyond it: a caller may never assign authority it… - [GET /subjects/:id/sessions and DELETE…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsidsessions-and-delete-subjectsidsessionssid.md): Both require manage-sessions; there is no view-sessions, the same reasoning that leaves clients with no view-clients — a session is reached only by… - [GET /subjects/username-policy](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-subjectsusername-policy.md): Requires view-users. Whether this tenant accepts a rename — its username_editable setting, alone, for whoever can read subjects: GET /settings holds… - [GET /whoami](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/get-whoami.md): The identity probe: what an operator reaches for when a token is not working and they need to know what the server thinks it is, before debugging… - [Getting the token](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/getting-the-token.md): odudu seed admin creates the system tenant, its odudu-admin client and its signing key, and a subject holding tenant-admin there — which composites… - [Admin paths](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths.md): The admin API, route by route: the request each endpoint takes and the response it answers, run against a real stack. - [PATCH /clients/{id}](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/patch-clientsid.md): Requires manage-clients, as every client route does. - [PATCH /subjects/:id](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/patch-subjectsid.md): Requires manage-users. Amends email and enabled — and username, where the tenant allows it (below) — the only general fields a subject exposes… - [POST /admin/tenant-imports](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/post-admintenant-imports.md): POST /admin/tenant-imports requires manage-tenants and always creates a new tenant, from a document GET /export answered. - [POST /admin/tenants](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/post-admintenants.md): Creates a tenant: the row, its browser authentication flow (provisionTenant, @odudu/authn-flows) and its built-in admin client… - [POST /clients/{id}/secret](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/post-clientsidsecret.md): Requires manage-clients. Rotates a confidential client's secret: generates a fresh one, stores only its hash, and returns the plaintext exactly… - [POST /roles/:id/composites](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/post-rolesidcomposites.md): Requires manage-tenant, and enforces the same capability ceiling PUT /subjects/:id/roles does: nesting child_role_id under the role named by :id… - [POST /subjects](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/post-subjects.md): Requires manage-users. Creates a type: "user" subject: the subject itself, its users row and the tenant's default_for_new_subjects roles — the same… - [POST /subjects/bulk](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/post-subjectsbulk.md): Requires manage-users. Applies one action to at most 100 subjects: disable, enable, delete, or end-sessions, which additionally requires… - [POST /subjects/:id/actions-email](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/post-subjectsidactions-email.md): Requires manage-users. The body names the required actions the link takes the subject through — {"actions": […]}, at least one of update-password… - [POST /subjects/:id/password-reset and POST…](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/post-subjectsidpassword-reset-and-post-subjectsidverification.md): Requires manage-users. Each queues a link to the subject's own address, minted and mailed by the same write the self-service door makes… - [POST /subjects/:id/password](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/post-subjectsidpassword.md): Requires manage-users, and takes no body. An administrator restoring a subject's access never chooses the password: the server generates one — the… - [PUT /groups/:id/default](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/put-groupsiddefault.md): Requires manage-tenant. The body is {"default": true} or {"default": false}, and the answer is the group with its ETag; the group's… - [PUT /roles/:id/default](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/put-rolesiddefault.md): Requires manage-tenant. The body is {"default": true} or {"default": false}, and the answer is the role with its ETag. - [PUT /scopes/:id/clients/:clientId](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/put-scopesidclientsclientid.md): Requires manage-tenant. Assigns the scope to the client as default or optional, narrowing or widening any existing assignment rather than colliding… - [Admin API: the shape of it](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/the-shape-of-it.md): Most of the admin endpoint lives under /admin/tenants/{tenant}/, mirroring the protocol surface's own /tenants/{tenant}/ convention: the tenant… - [Admin API: what to do next](https://wizzywit.github.io/odudu/docs/reference/transcripts/admin-paths/what-to-do-next-from-wherever-you-are.md): From here, for anything these pages do not yet cover — creating a client, rotating a signing key, editing a tenant's authentication flow —… - [A path that escapes /admin/](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/a-path-that-escapes-admin.md): The proxy resolves the path it would forward, dot segments included, and refuses with a 404 before it reads the session. - [A refresh that cannot take the lock](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/a-refresh-that-cannot-take-the-lock.md): A refresh waits at most five seconds for the session's row lock, so two refreshes of one session never present its refresh token twice. - [A refresh the server refuses](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/a-refresh-the-server-refuses.md): When the server refuses a refresh, the grant is revoked, the next call answers a session-ended 401 and clears its cookie, and the row is gone. - [A refresh](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/a-refresh.md): Within 30 seconds of expiry the gateway refreshes the access token as odudu-admin before it forwards a call; the browser sees no difference. - [Following the logout redirect](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/following-the-logout-redirect.md): After a console logout the browser follows the redirect, and the console cookie it held from before the logout is an ended session. - [GET /console/](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/get-console.md): The logout's 302 lands on the console shell. Every path under /console/ that neither the API nor the sign-in routes claim answers the shell, with… - [GET /console/api/admin/tenants/{tenant}/subjects](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/get-consoleapiadmintenantstenantsubjects.md): Anything under /console/api/admin/ is forwarded to /admin/ with the session's access token. - [GET /console/api/session](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/get-consoleapisession.md): The console session endpoint answers with the tenant, subject and username of the signed-in administrator, and no token. - [GET /console/api/tenants/{tenant}/discovery, GET…](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/get-consoleapitenantstenantdiscovery-get-consoleapitenantstenantjwks.md): Read-only mirrors of the tenant's own public discovery document and JWKS (the request paths' GET… - [GET /console/auth/callback, refused](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/get-consoleauthcallback-refused.md): A callback whose state does not match the login cookie restarts the sign-in once; a second refusal inside the minute shows a page that links back. - [GET /console/auth/callback, restarted](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/get-consoleauthcallback-restarted.md): A refused callback no longer ends on a refusal page: it restarts the sign-in once, for the tenant its state is bound to, with a fresh state. - [GET /console/auth/callback](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/get-consoleauthcallback.md): The console callback that takes the tenant sign-in redirect, ends the login cookie and starts the console session. - [GET /console/auth/login](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/get-consoleauthlogin.md): The console's sign-in starts here. return_to is where the callback sends the browser afterwards, and must be a /console/ path. - [Console paths](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths.md): The routes under /console that sign an administrator in, keep the tokens on the server and forward the console’s calls, run against a stack. - [PATCH /console/api/admin/tenants/{tenant}/subjects/{id}](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/patch-consoleapiadmintenantstenantsubjectsid.md): A write through the console proxy carries If-Match and names the session's subject in the X-Odudu-Console-Subject header. - [POST …/subjects, refused as cross-site](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/post-consoleapiadmintenantstenantsubjects-refused-as-cross-site.md): A write to /console/api/ or /console/auth/ is refused with a 403 unless it carries the base's own Origin and the X-Odudu-Console: 1 header. - [POST …/subjects, refused for another principal](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/post-consoleapiadmintenantstenantsubjects-refused-for-another-principal.md): Every tab shares the console cookie, so another tab's sign-in can replace the session; the console names the subject it expects on each request. - [POST /console/auth/logout](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/post-consoleauthlogout.md): A console logout ends the console session. It is sent with no body, under the same CSRF guard as every other write. - [The gateway is a confidential client](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/the-gateway-is-a-confidential-client.md): The gateway signs an RFC 7523 assertion with the console's key for the code exchange, the refresh and the revocation; without one they are refused. - [The tenant's own sign-in](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/the-tenants-own-sign-in.md): The two requests between the gateway's redirect and its callback are the tenant's authorization endpoint and sign-in form, which… - [What these runs do not show](https://wizzywit.github.io/odudu/docs/reference/transcripts/console-paths/what-these-runs-do-not-show.md): The console gateway behaviours that tests cover and that no recorded run on a running stack shows. - [First start](https://wizzywit.github.io/odudu/docs/reference/transcripts/first-start.md): The Compose stack and odudu init as run on a real stack, with every refusal and exit status, and what each leaves on disk. - [Transcripts](https://wizzywit.github.io/odudu/docs/reference/transcripts.md): The full, recorded runs behind the guides: every request and response, grouped into request paths, admin paths and console paths. - [Bootstrap](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/bootstrap.md): A tenant, its first user and its signing key are created by the server's seed command — the only way to create the first of anything, since the… - [Brute-force lockout](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/brute-force-lockout.md): Five consecutive wrong credentials lock an account — passwords, and after a correct one the codes of a second factor (below) — and the tenant ships… - [CORS: the preflight and the request differ](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/cors-the-preflight-and-the-request-differ.md): A browser single-page client is the reader ## Path A above walks through, and until this section landed its preflight failed: /token and /userinfo… - [Enrolling a passkey](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/enrolling-a-passkey.md): POST /tenants/{tenant}/login-actions/required-action?action=configure-passkey enrols a WebAuthn credential for the subject the authentication… - [Following a required-actions link](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/following-a-required-actions-link.md): An administrator's POST /admin/tenants/{tenant}/subjects/{id}/actions-email (the admin paths) mails a link to the same… - [Request paths](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths.md): Every request a client or a browser makes to the protocol endpoints, run against a real stack, with the exact response that came back. - [One sign-in's audit trail, read through the admin API](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/one-sign-ins-audit-trail-read-through-the-admin-api.md): The sections above read audit_events with psql, one door at a time. - [Password expiry, and changing a password](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/password-expiry-and-changing-a-password.md): A tenant's password_max_age_days ages a password out. - [Password reset](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/password-reset.md): GET/POST /tenants/{tenant}/login-actions/reset-password is the third account-lifecycle setting, reset_password_allowed — off by default, like… - [Path A, as a confidential client](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/path-a-as-a-confidential-client.md): Path A ran demo-spa, which is public. The other common deployment shape is a server-side web application that holds a secret, and a reader who is… - [Path A: authorization code with PKCE](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/path-a-authorization-code-with-pkce.md): The full interactive flow. Every client uses PKCE, public and confidential alike, with no exception and no per-client opt-out (ADR 0016). - [Path B: refresh rotation](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/path-b-refresh-rotation.md): Refresh tokens rotate: every successful refresh consumes the presented token and returns a new one. - [Path C: client_credentials](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/path-c-client_credentials.md): No user, no browser, no PKCE, no redirect. A confidential client authenticates as itself and gets a token for its own service account. - [Path D: token exchange](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/path-d-token-exchange.md): RFC 8693's grant runs against a tenant of its own, exdoc, so the clients this exercises — one registered for the grant, one registered for it but… - [Recovery codes](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/recovery-codes.md): Enrolling a TOTP creates a way to be locked out: lose the phone and the password alone no longer signs anybody in. - [Retention: what odudu reap removes](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/retention-what-odudu-reap-removes.md): Everything above leaves rows behind, and nothing in any repository deletes one. - [RP-initiated logout](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/rp-initiated-logout.md): GET/POST /tenants/{tenant}/protocol/openid-connect/logout implements OpenID Connect RP-Initiated Logout 1.0. - [Self-registration](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/self-registration.md): GET/POST /tenants/{tenant}/login-actions/registration is the first way a user reaches a tenant without an administrator seeding them in. - [Sending queued mail: odudu send-mail](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/sending-queued-mail-odudu-send-mail.md): No request in these pages sends mail. Address verification, self-registration and password reset each write the message to email_outbox in the… - [Signing in with a passkey, and no username](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/signing-in-with-a-passkey-and-no-username.md): An enrolled passkey is a first factor on its own. The login page offers it beside the password fields, and pressing it asks for nothing typed: - [The branches](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/the-branches.md): This is the most security-sensitive ordering decision in the server. - [The documentation under /docs](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/the-documentation-under-docs.md): The image carries its own copy of the documentation, built at the version the image is, and the server answers it from its own origin at /docs/. - [The shape of it](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/the-shape-of-it.md): A tenant has its own users, clients, signing keys and sessions, isolated in the database by PostgreSQL row-level security (ADR 0009). - [Two-factor authentication with TOTP](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/two-factor-authentication-with-totp.md): A tenant's otp_required decides whether every subject in it is expected to hold a second factor. - [What to do next, from wherever you are](https://wizzywit.github.io/odudu/docs/reference/transcripts/request-paths/what-to-do-next-from-wherever-you-are.md): From a rendered error page at /authorize. The client never sees it. - [Roadmap](https://wizzywit.github.io/odudu/docs/roadmap.md): What Odudu does today, what comes next and in what order, what is planned for later, and what it will never do. - [Disclosure](https://wizzywit.github.io/odudu/docs/security/disclosure.md): How to report a security problem in Odudu privately, and what to expect after you do. - [Security](https://wizzywit.github.io/odudu/docs/security.md): How Odudu protects credentials, sessions and tenants, and how to report a problem. - [The threat model](https://wizzywit.github.io/odudu/docs/security/threat-model.md): What Odudu protects, who it assumes an attacker is, how each defence works, where each one stops and what is not covered at all. ## Machine-readable references - [Admin API OpenAPI document](https://wizzywit.github.io/odudu/openapi/admin.json): The OpenAPI 3.1 description of the admin API, as JSON.