doc: add AGENTS.md
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
# AGENTS.md
|
||||
|
||||
Compact operational guide for OpenCode sessions. See `CLAUDE.md` for the prose
|
||||
overview; this file captures what an agent would otherwise get wrong.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# First-time test env (creates venv/, installs requirements.txt + requirements-test.txt)
|
||||
./setup_test_env.sh
|
||||
|
||||
# Full suite with coverage (activates venv, erases old coverage, builds htmlcov/)
|
||||
./run_tests.sh
|
||||
|
||||
# Manual, from an active venv
|
||||
python -m pytest tests/ --cov=. --cov-config=.coveragerc -v
|
||||
|
||||
# Single test
|
||||
python -m pytest tests/test_main.py::test_health_check -v
|
||||
|
||||
# Dev server (must run from repo root — see Gotchas)
|
||||
uvicorn main:app --host 0.0.0.0 --port 8000 --reload
|
||||
```
|
||||
|
||||
There is no lint, typecheck, formatter, or CI config in this repo. Do not
|
||||
claim to run `ruff`, `mypy`, `flake8`, or `black` — none are installed or
|
||||
configured. The only verification step is the pytest suite above.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Run from repo root.** `read_root()` and `favicon()` open
|
||||
`templates/index.html` / `templates/favicon.ico` via relative paths
|
||||
(`main.py:329`, `main.py:371`). Invoking uvicorn from another cwd 404s the
|
||||
frontend.
|
||||
- **`@lru_cache` on OIDC helpers.** `get_well_known_config`, `get_jwks`,
|
||||
`get_userinfo_endpoint`, `get_token_endpoint` are all `lru_cache(maxsize=1)`
|
||||
(`main.py:68-129`). When a test patches `requests` with a different
|
||||
response, call `func.cache_clear()` first or you get the previous mock's
|
||||
cached value. Existing tests do this; new tests must too.
|
||||
- **Python 3.14, not 3.7.** `.python-version` and the Dockerfile
|
||||
(`python:3.14-alpine`) target 3.14. The README's "3.7+" claim is stale.
|
||||
- **`.envrc` is gitignored and ships real credentials.** It exports a live
|
||||
`CLIENT_ID` / `CLIENT_SECRET` for direnv. Never commit it, never paste its
|
||||
values into code or commits.
|
||||
- **`CLIENT_ID` has no default.** `main.py:28` reads it from env with no
|
||||
fallback; the app and several tests need it set. `OIDC_ISSUER` defaults to
|
||||
`https://login.infomaniak.com`; `CLIENT_SECRET` defaults to `""` (breaks
|
||||
`/refresh-token` with "Client secret not configured").
|
||||
|
||||
## Architecture essentials
|
||||
|
||||
- Single-file backend `main.py` (FastAPI) + single-file frontend
|
||||
`templates/index.html`. No package layout, no `pyproject.toml`, no
|
||||
`setup.cfg`.
|
||||
- `AUTHORIZED_USERS` (`main.py:33`) is a hardcoded `{email: secret_phrase}`
|
||||
dict — the "protected resource". Not a database.
|
||||
- Token validation: `verify_token(id_token, expected_nonce=None)` does JWKS
|
||||
signature verification + audience/issuer checks. The `expected_nonce`
|
||||
param binds the id_token to the login flow (anti-replay); `/validate-token`
|
||||
forwards the nonce from the request body (`main.py:278`). Tests in
|
||||
`test_token_validation.py` and `test_main.py` cover the nonce paths — keep
|
||||
them green when touching auth.
|
||||
- Tests use `fastapi.testclient.TestClient` (sync, backed by `httpx`) and
|
||||
`unittest.mock.patch` against `main.*`. Fixtures live in `tests/conftest.py`.
|
||||
- Coverage config (`.coveragerc`) omits `venv/`, `tests/`, `.venv/`.
|
||||
Reference in New Issue
Block a user