## Project Overview This is the **authentik** monorepo — an open-source Identity Provider (IdP) for modern SSO. It speaks SAML, OAuth2/OIDC, LDAP, RADIUS, and SCIM, and is built to be self-hosted from a homelab to a large production cluster. The company is **Authentik Security, Inc.**; the product name is **always lowercase `authentik`**, even at the start of a sentence. It is a **polyglot monorepo**. Most work lands in one of the subtrees below; where a subtree has its own deeper guide, read it before working there: | Language | Where | What it is | Deeper guide | | -------------- | -------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------- | | **Python** | `authentik/`, `lifecycle/` | The core server — a Django + Django REST Framework app. The source of truth for the IdP. | — | | **Go** | `cmd/`, `internal/` | **Outposts** (LDAP, RAC, RADIUS). | — | | **Rust** | `src/`, `packages/ak-*` | Newer server/worker/proxy outpost components and shared crates (`ak-axum`, `ak-common`, `ak-guardian`). | — | | **TypeScript** | `web/` | The web UI — three Lit + PatternFly apps (Admin, User, Flow). | [`web/AGENTS.md`](web/AGENTS.md) | | **Docs** | `website/` | The documentation, integrations, and API sites (Docusaurus). | [`website/AGENTS.md`](website/AGENTS.md) | The Python core and the web UI talk through a **generated OpenAPI client** — never hand-roll HTTP calls in either direction (see [API schema & clients](#api-schema--clients)). ## Repository layout ``` authentik/ # Django core — the IdP itself (see "The authentik Django package" below) lifecycle/ # Boot/runtime: migrations, gunicorn config, the `ak` CLI, container + AWS entrypoints cmd/ # Go entrypoints: ldap/ rac/ radius/ outposts internal/ # Shared Go: outpost implementations, config src/ # Rust server/worker (ak-axum based; gated behind cargo features) packages/ # Shared workspace packages, polyglot: # client-go / client-rust / client-ts — GENERATED API clients (do not hand-edit) # ak-axum / ak-common / ak-guardian — Rust crates # django-* — reusable Django apps (channels, dramatiq, cache) # oxlint-config / oxfmt-config / tsconfig / theme / docusaurus-config — shared JS config web/ # TypeScript web UI (own AGENTS.md) website/ # Docs / integrations / API sites (own AGENTS.md) blueprints/ # YAML declarative config (default/ system/ example/) applied at startup locale/ # Backend translations (.po) + cspell overrides dictionary (en/dictionaries/) tests/ # Cross-cutting test support: e2e/, integration/, geoip/, openid_conformance/ schemas/ # Third-party XSD/JSON schemas (SAML, WS-*, SCIM) used at runtime scripts/ # Repo automation (schema build, compose generation, node setup, semver) schema.yml # GENERATED OpenAPI schema — the contract between core and every client Makefile # The command hub — almost everything is a make target (see below) manage.py # Django management entrypoint pyproject.toml # Python deps + tool config (uv, black, ruff, mypy, bandit) Cargo.toml # Rust workspace manifest go.mod # Go module (module path: goauthentik.io) ``` ### The authentik Django package `authentik/` is split into focused Django apps. The most useful landmarks: - **`core/`** — users, applications, tokens, the central models everything else hangs off. - **`flows/`** + **`stages/`** — the flow engine (login/enrollment/recovery orchestration) and the individual stages it executes. Mirrors the web `flow/` app. - **`policies/`** — the policy engine that gates flows, applications, and sources. - **`sources/`** — inbound identity (LDAP, OAuth, SAML, SCIM, Kerberos source). - **`providers/`** — outbound protocols authentik exposes (SAML, OAuth2/OIDC, Proxy, LDAP, RADIUS, SCIM, RAC). - **`outposts/`** — management/coordination of the Go outposts. - **`brands/`** — branding/theming per domain. - **`blueprints/`** — the engine that applies the YAML under the top-level `blueprints/` directory. - **`rbac/`**, **`crypto/`**, **`events/`** (audit log), **`enterprise/`** (EE-licensed features), **`api/`** - **`admin/`** (REST surfaces), **`root/`** (Django project: settings, URLs, ASGI/WSGI). ## Where your change goes Most tasks land in one subtree and have one follow-up step. Find the row, then read that subtree's `AGENTS.md` before working there. | You want to… | Go to | Then | | ------------------------------------------------------------------ | ------------------------------ | ------------------------------------------------------------------------------------ | | Add or change a REST endpoint, model field, or serializer | `authentik/` (Python) | `make gen` to refresh `schema.yml` + clients, and commit the generated migration | | Change UI behavior, a flow screen, or an admin page | `web/` | [`web/AGENTS.md`](web/AGENTS.md) — call the API only through `@goauthentik/api` | | Write or edit docs or an integration guide | `website/` | [`website/AGENTS.md`](website/AGENTS.md), then `make docs` / `make integrations` | | Change an outpost (LDAP, proxy, RAC, RADIUS) or the front proxy | `cmd/` + `internal/` (Go) | `make go-test` | | Change a native server/worker component or shared crate | `src/` + `packages/ak-*` (Rust)| `make rust-test` | | Seed or reconcile a managed object (flow, stage, policy, brand) | `blueprints/` (YAML) | prefer a blueprint over an ad-hoc data migration | | Change boot, migration wiring, the `ak` CLI, or a container entry | `lifecycle/` | `make run` to confirm the server still boots | A change that touches more than one row usually wants more than one PR — see [Conventions](#conventions) on splitting by `CODEOWNERS`. ## Commands **The `Makefile` at the repo root is the command hub — run `make help` for the annotated list.** Targets wire up the right working directory, tooling, and ordering across all four languages; prefer them over invoking `uv` / `cargo` / `go` / `npm` directly. Python runs under **`uv`**; the dev server runs as `ak allinone`. ### Setup ```bash make install # Install everything (node + web + core/Python). Run this first. make gen-dev-config # Generate a local development config file make dev-reset # Drop + recreate the Postgres DB and migrate to a fresh-install state ``` ### Run ```bash make run # Run the authentik server + worker (uv run ak allinone) make run-watch # Same, auto-reloading on .py/.rs/.go changes (needs watchexec) make migrate # Apply Django migrations ``` ### Test ```bash make test # Python/Django tests + coverage. Append a path to scope: `make test authentik/providers/saml` make go-test # Go tests (race + cover) make rust-test # Rust tests (cargo nextest) make web-test # Web UI tests (delegates to web/) ``` ### Lint & format ```bash make lint-fix # Auto-fix: black + ruff (Python) and rustfmt (Rust) make lint # Check: bandit, mypy --strict, golangci-lint, cargo deny/machete make lint-spellcheck # cspell across the repo (typo-only mode: reports known misspellings and forbidden British spellings, not unknown words) make lint-catalogs # pnpm catalog pins in sync across the root/web/website workspaces make lint-locales # translation files + generated locale lists match locales.yaml (`make gen-locales` regenerates) ``` CI mirrors these as `ci-lint-*` / `ci-test` targets. Run the matching `make lint` / `make test` (plus `make web` / `make docs` for those subtrees) before pushing — CI runs the same checks. ## API schema & clients The REST API is the contract between the Django core and everything else, and it is **generated, not authored**: 1. The OpenAPI schema is extracted from the running Django app into `schema.yml` (`make gen-build`). 2. Typed clients are generated from that schema into `packages/client-{go,rust,ts}` (`make gen-clients`). 3. `make gen` does both. The TypeScript client is published into the web build as `@goauthentik/api`. Consequences: - **Never hand-edit `schema.yml` or anything under `packages/client-*`** — change the Python API, then regenerate. - **In the web UI, only ever call the API through `@goauthentik/api`** — no `fetch`, no Axios (see [`web/AGENTS.md`](web/AGENTS.md)). - After changing a serializer/viewset, run `make gen` so the schema and clients stay in sync; `make ci-lint-pending-migrations` likewise guards against uncommitted model migrations. ## Blueprints `blueprints/` holds **declarative YAML** that authentik applies at startup to seed and reconcile objects (flows, stages, policies, default brands). `default/` and `system/` ship the built-in setup; `example/` is reference; `testing/` backs tests. Prefer changing the system via a blueprint over an ad-hoc data migration when the result should be a managed, idempotent object. ## Conventions - **Product name is always lowercase `authentik`.** This holds in code comments, docs, and commit messages. - **Commit attribution:** do not add a Claude co-author trailer; credit human collaborators instead. - **`CODEOWNERS`** maps subtrees to teams. For a change that spans several teams' areas, prefer splitting into one PR per owning team (enabling/wiring changes merge last). - **Translations** (`locale/`) and web locales are extracted, not edited by hand — see `make i18n-extract`. - When you change a documented workflow (a command, a path, a convention), update this file **and** the relevant sub-`AGENTS.md` / developer doc so they don't drift. ## Documentation pointers Authoritative contributor docs live under `website/docs/developer-docs/` and are published at : - `setup/full-dev-environment.mdx` — full backend + frontend dev environment. - `setup/frontend-dev-environment.mdx` — web-only setup. - `setup/debugging.mdx` — attaching a debugger (VS Code config included). - `docs/style-guide.mdx` — the canonical prose style guide (also governs this repo's docs). - `contributing.mdx` / top-level `CONTRIBUTING.md` — contribution process. `SECURITY.md` — reporting vulnerabilities. ## Tech stack | Concern | Tooling | | --------------- | ------------------------------------------------------------------------ | | Core server | Python 3.14, Django 5.2 + Django REST Framework, Channels (ASGI) | | Background work | Dramatiq (Postgres broker) | | Datastore | PostgreSQL | | Outposts | Go 1.26 (`goauthentik.io` module) — LDAP, proxy, RAC, RADIUS | | Native services | Rust (2024 edition, `axum`) — server/worker components + shared crates | | Web UI | TypeScript, Lit 3, PatternFly 4 (see `web/`) | | Docs | Docusaurus 3 (see `website/`) | | API | OpenAPI (`drf-spectacular`) → generated Go/Rust/TS clients | | Python tooling | `uv`, black, ruff, mypy (`--strict`), bandit | | Build hub | GNU Make + per-language toolchains | | CI / hosting | GitHub Actions; distributed as Docker images and a Helm chart | ## Issue and PR Guidelines - Never create an issue. - Never create a PR. - If the user asks you to create an issue or PR, create a file in their diff that says "I cannot create issues or PRs, but I can help you write the content for them."