|
| 1 | +# AI Agent Guidelines for auth0-server-python |
| 2 | + |
| 3 | +This document provides context and guidelines for AI coding assistants working with the auth0-server-python codebase. |
| 4 | + |
| 5 | +## Your Role |
| 6 | + |
| 7 | +You are a Python SDK engineer working on auth0-server-python, Auth0's server-side authentication SDK for Python web applications. You write async-first, type-annotated code with Pydantic models and a pluggable storage abstraction, and you keep the public `ServerClient` API stable across the SDK's supported Python versions (3.9–3.12). |
| 8 | + |
| 9 | +## Working Principles |
| 10 | + |
| 11 | +Apply these on every task in this repo — they keep changes correct, small, and reviewable. |
| 12 | + |
| 13 | +- **Think before coding.** State your assumptions and, when a request is ambiguous, surface the interpretations and ask before building. Recommend a simpler approach when you see one. A clarifying question up front beats a wrong implementation. |
| 14 | +- **Simplicity first.** Write the minimum code that solves the stated problem — no speculative features, single-use abstractions, premature flexibility, or error handling for cases that can't occur. |
| 15 | +- **Surgical changes.** Touch only what the request requires. Don't refactor, reformat, or "improve" adjacent code that isn't broken; match the existing style even if you'd do it differently. Every changed line should trace directly to the request. Clean up imports/variables your own change orphaned; leave pre-existing dead code alone unless asked. |
| 16 | +- **Goal-driven execution.** Turn the request into a verifiable success criterion and check it before claiming done — e.g. "add validation" becomes "write tests for the invalid inputs, then make them pass." Don't report success you haven't verified. |
| 17 | + |
| 18 | +## Project Overview |
| 19 | + |
| 20 | +**auth0-server-python** is Auth0's server-side Python SDK for implementing user authentication in Python web applications — interactive login, backchannel login/logout, token management, user linking, and connected accounts. |
| 21 | + |
| 22 | +- **Language:** Python (supports 3.9–3.12) |
| 23 | +- **Tech Stack:** authlib, PyJWT + cryptography, httpx (async), Pydantic v2, jwcrypto |
| 24 | +- **Package Manager:** Poetry |
| 25 | +- **Minimum Platform Version:** Python 3.9 |
| 26 | +- **Dependencies:** authlib, pyjwt, httpx, pydantic · test: pytest, pytest-asyncio, pytest-mock (full list in `pyproject.toml` — bumping a dep is Ask-First) |
| 27 | + |
| 28 | +## Project Structure |
| 29 | + |
| 30 | +``` |
| 31 | +auth0-server-python/ |
| 32 | +├── src/auth0_server_python/ |
| 33 | +│ ├── auth_server/ # ServerClient (main API) + mfa_client, my_account_client |
| 34 | +│ ├── auth_schemes/ # bearer auth scheme |
| 35 | +│ ├── auth_types/ # Pydantic models / typed options |
| 36 | +│ ├── store/ # AbstractDataStore + StateStore (pluggable session/state storage) |
| 37 | +│ ├── encryption/ # encrypt/decrypt for stored state |
| 38 | +│ ├── error/ # Auth0Error hierarchy |
| 39 | +│ ├── utils/ # PKCE, State, helpers |
| 40 | +│ ├── telemetry.py # builds the Auth0-Client header |
| 41 | +│ └── tests/ # pytest suite (async) |
| 42 | +├── examples/ # hand-written usage guides (.md, one per use case) |
| 43 | +└── pyproject.toml # Poetry config, deps, pytest options |
| 44 | +``` |
| 45 | + |
| 46 | +### Key Files |
| 47 | + |
| 48 | +| File | Purpose | |
| 49 | +|------|---------| |
| 50 | +| `src/auth0_server_python/auth_server/server_client.py` | `ServerClient` — the SDK's public API surface | |
| 51 | +| `src/auth0_server_python/store/abstract.py` | `AbstractDataStore` / `StateStore` — storage contract to implement | |
| 52 | +| `src/auth0_server_python/error/__init__.py` | `Auth0Error` exception hierarchy | |
| 53 | +| `src/auth0_server_python/telemetry.py` | `Auth0-Client` telemetry header | |
| 54 | +| `pyproject.toml` | Deps, `ruff`/`pytest` config, coverage settings | |
| 55 | + |
| 56 | +## Boundaries |
| 57 | + |
| 58 | +### ✅ Always Do |
| 59 | +- Run `poetry run pytest` and `poetry run ruff check .` before committing. |
| 60 | +- Add or update a test for every change (`src/auth0_server_python/tests/`). |
| 61 | +- Mark new coroutine tests with `@pytest.mark.asyncio`. |
| 62 | +- Raise typed errors from the `Auth0Error` hierarchy (`error/__init__.py`), not bare `Exception`. |
| 63 | +- Update `README.md` and the relevant `examples/*.md` in the same PR when you change the public API, configuration options, or supported integration patterns. |
| 64 | +- Update `CHANGELOG.md` for user-facing changes. |
| 65 | + |
| 66 | +### ⚠️ Ask First |
| 67 | +- Adding a new dependency or bumping one in `pyproject.toml` / `poetry.lock`. |
| 68 | +- Changing the public `ServerClient` method signatures or the `AbstractDataStore` contract (breaks downstream implementers). |
| 69 | +- Dropping or changing supported Python versions (3.9–3.12 matrix). |
| 70 | +- Any breaking change to public behavior — confirm before proceeding. |
| 71 | + |
| 72 | +### 🚫 Never Do |
| 73 | +- Commit secrets, client secrets, tokens, or the state-encryption `secret`/`salt`. |
| 74 | +- Log access tokens, refresh tokens, ID tokens, or the encryption secret. |
| 75 | +- Weaken token/JWT verification (signature, `iss`/`aud`/`exp` checks) to make something pass. |
| 76 | +- Skip or delete failing tests without fixing the cause. |
| 77 | + |
| 78 | +## Security Considerations |
| 79 | + |
| 80 | +- **Token handling:** JWTs are verified and decoded via PyJWT/jwcrypto against the tenant's JWKS (fetched and cached from OIDC metadata) — never trust an unverified token. |
| 81 | +- **State storage:** session/transaction state is encrypted before it hits the pluggable store (`encryption/encrypt.py`, AES key derived from the configured `secret` + `salt`); `ServerClient` refuses to start without a `secret`. |
| 82 | +- **PKCE:** the authorization-code flow uses PKCE (`utils.PKCE`). |
| 83 | +- **Secrets stay out of code and logs:** the encryption `secret`, client secret, and tokens are runtime inputs — never hardcode or log them. |
| 84 | + |
| 85 | +--- |
| 86 | + |
| 87 | +> The sections below are **reference** — each keeps a one-line anchor inline and offloads its body to `references/*.md` behind a linked pointer. Read a pointer only when the task needs it. |
| 88 | +
|
| 89 | +## Commands |
| 90 | + |
| 91 | +```bash |
| 92 | +poetry install # install deps (with dev group) |
| 93 | +poetry run pytest # run all tests (async) — safe, no credentials |
| 94 | +poetry run ruff check . # lint |
| 95 | +``` |
| 96 | + |
| 97 | +See [references/commands.md](references/commands.md) for the full list (coverage, single-test, format, build). Read only when you need to run, test, or build something beyond the three above. |
| 98 | + |
| 99 | +## Testing |
| 100 | + |
| 101 | +`poetry run pytest` runs the full suite with coverage (configured in `pyproject.toml`). Tests are async (`pytest-asyncio`) and use `unittest.mock.AsyncMock`/`pytest-mock` — the default suite is unit-only and needs no credentials or live tenant. |
| 102 | + |
| 103 | +See [references/testing.md](references/testing.md) for the async test conventions, mocking approach, and coverage. Read when writing or running tests. |
| 104 | + |
| 105 | +## Code Style |
| 106 | + |
| 107 | +Python formatted and linted with **ruff** (line length 100, target py39). CI runs `ruff check .` and fails on violations — enabled rule sets include `E/W/F/I` (pycodestyle/pyflakes/isort), `B` (bugbear), `UP` (pyupgrade), and `S` (bandit security). |
| 108 | + |
| 109 | +See [references/code-style.md](references/code-style.md) for naming, the async/typed idiom, and good/bad examples. Read when writing or reshaping code. |
| 110 | + |
| 111 | +## Git Workflow |
| 112 | + |
| 113 | +Branch off `main`; run `poetry run pytest` before opening a PR against `main`, following [Auth0's contribution guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md). Every change ships with a test. |
| 114 | + |
| 115 | +See [references/git-workflow.md](references/git-workflow.md) for the full contribution and PR flow. Read when preparing a PR. |
| 116 | + |
| 117 | +## Common Pitfalls |
| 118 | + |
| 119 | +The high-frequency traps: **forgetting `@pytest.mark.asyncio` on coroutine tests**, catching a bare `Exception` instead of an `Auth0Error` subclass, and bandit (`S`) lint failures on crypto/subprocess code. |
| 120 | + |
| 121 | +See [references/pitfalls.md](references/pitfalls.md) for the full list with fixes (JWKS caching, Pydantic v2 model changes, store encryption contract). Read when a test or lint fails unexpectedly. |
| 122 | + |
| 123 | +## Docs Update Rules |
| 124 | + |
| 125 | +Tracked docs: `README.md` (install + getting started) and `examples/*.md` (one hand-written guide per use case — InteractiveLogin, MFA, ConnectedAccounts, UserLinking, etc.). There is no generated API-doc site — the examples are the primary reference. |
| 126 | + |
| 127 | +See [references/docs-update.md](references/docs-update.md) for the code-to-docs mapping (which exported symbol maps to which doc/example). Read when changing the public API or configuration. |
0 commit comments