add uncommitted plans and CLAUDE.md
This commit is contained in:
parent
6b4cbdc152
commit
fb133f9cba
10 changed files with 5241 additions and 0 deletions
99
CLAUDE.md
Normal file
99
CLAUDE.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# Format
|
||||
make reformat # uv run ruff format src/ tests/
|
||||
|
||||
# Lint (with auto-fix)
|
||||
make lint # uv run ruff check src/ tests/ --fix
|
||||
|
||||
# Type checking
|
||||
make typecheck # uv run ty check src/
|
||||
|
||||
# Tests
|
||||
make test # uv run python -m pytest -v
|
||||
uv run pytest tests/test_foo.py::test_specific # single test
|
||||
|
||||
# All checks
|
||||
make check
|
||||
|
||||
# Dev server
|
||||
OIDC_OP_ISSUER=http://localhost:8000 OIDC_OP_DEBUG=true \
|
||||
uv run uvicorn porchlight.app:create_app \
|
||||
--factory --host 127.0.0.1 --port 8000 --reload --reload-dir src
|
||||
```
|
||||
|
||||
### End-to-end tests (Playwright/Node)
|
||||
|
||||
```bash
|
||||
# One-time setup
|
||||
cd tests/e2e && npm install && npm run setup && cd ../..
|
||||
|
||||
# Run e2e tests (starts/stops the server automatically)
|
||||
./tests/e2e/run.sh
|
||||
|
||||
# Run a specific spec
|
||||
./tests/e2e/run.sh tests/e2e/login.spec.js
|
||||
|
||||
# Run with visible browser
|
||||
E2E_HEADLESS=0 ./tests/e2e/run.sh
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
Porchlight is an OpenID Connect (OIDC) Provider + user management app built on **FastAPI** with **idpyoidc** for the OIDC protocol layer. UI is server-side **Jinja2** templates with **HTMX** for interactivity. Storage defaults to **SQLite** via `aiosqlite`.
|
||||
|
||||
### Request flow
|
||||
|
||||
```
|
||||
Browser/RP → FastAPI routes → Service classes → Repository layer → SQLite
|
||||
↕
|
||||
idpyoidc (OIDC protocol)
|
||||
```
|
||||
|
||||
### Module layout
|
||||
|
||||
- `src/porchlight/app.py` — FastAPI app factory (`create_app()`), lifespan, middleware stack
|
||||
- `src/porchlight/config.py` — Settings loaded from env vars (`OIDC_OP_*` prefix) and optional TOML file
|
||||
- `src/porchlight/models.py` — Pydantic domain models (`User`, `WebAuthnCredential`, `MagicLink`, `Consent`)
|
||||
- `src/porchlight/validation.py` — Form-validation models (`ProfileUpdate` with email/phone/URL validation)
|
||||
- `src/porchlight/dependencies.py` — FastAPI dependency injection helpers
|
||||
- `src/porchlight/csrf.py` — Synchronizer-token CSRF middleware (exempt: `/token`, `/userinfo`)
|
||||
- `src/porchlight/authn/` — Password (`argon2`) and WebAuthn (`fido2`) authentication services + routes
|
||||
- `src/porchlight/manage/` — Authenticated user credential & profile management routes
|
||||
- `src/porchlight/admin/` — Admin user management routes (user list, invite creation, profile editing)
|
||||
- `src/porchlight/invite/` — Magic-link invitation service (proquint tokens, time-limited)
|
||||
- `src/porchlight/oidc/` — OIDC endpoints (discovery, JWKS, `/authorization`, `/token`, `/userinfo`)
|
||||
- `src/porchlight/store/` — Repository pattern: `protocols.py` defines interfaces; `sqlite/` has the concrete implementation; `mongodb/` is a stub
|
||||
- `src/porchlight/cli.py` — Typer CLI (`create-invite`, `initial-admin`)
|
||||
|
||||
### Storage layer
|
||||
|
||||
`store/protocols.py` defines `UserRepository`, `CredentialRepository`, `MagicLinkRepository`, and `ConsentRepository` as Protocol classes. The SQLite implementation lives in `store/sqlite/repositories.py`. Migrations run automatically on startup from `store/sqlite/migrations/*.sql`.
|
||||
|
||||
### Configuration
|
||||
|
||||
All settings use the `OIDC_OP_` env-var prefix (see `config.py`). Key vars:
|
||||
|
||||
| Variable | Notes |
|
||||
|---|---|
|
||||
| `OIDC_OP_ISSUER` | **Required.** Must match the public-facing URL. |
|
||||
| `OIDC_OP_SESSION_SECRET` | Session signing key |
|
||||
| `OIDC_OP_DEBUG` | Enables Swagger UI |
|
||||
| `OIDC_OP_SQLITE_PATH` | DB file path (default `data/oidc_op.db`) |
|
||||
| `OIDC_OP_CONFIG_FILE` | Optional TOML file for clients and advanced config |
|
||||
|
||||
OIDC relying parties (clients) are defined in the TOML config file under `[clients.<id>]`.
|
||||
|
||||
### Test fixtures
|
||||
|
||||
`tests/conftest.py` provides:
|
||||
- `settings` — in-memory SQLite, test issuer
|
||||
- `client` — async `httpx.AsyncClient` with ASGI transport
|
||||
- CSRF token extraction helper
|
||||
|
||||
Unit and integration tests use in-memory SQLite; e2e tests use a seeded file-based DB (`tests/e2e/setup_db.py`).
|
||||
Loading…
Add table
Add a link
Reference in a new issue