Files
authentik/AGENTS.md
Dominic Roy 15aa5e86a9 website: mdx (#25246)
* website: mdx

* oh right

* fixup
2026-08-25 15:50:06 +00:00

172 lines
13 KiB
Markdown

## 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)
# eslint-config / prettier-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/`** + **`tenants/`** — branding/theming and multi-tenancy (`django-tenants`).
- **`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, an integration guide, or a glossary term | `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
```
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 <https://docs.goauthentik.io/docs/developer-docs/>:
- `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 (multi-tenant via `django-tenants`) |
| 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."