porchlight/CLAUDE.md
2026-06-29 09:18:37 +02:00

6.5 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Commands

# 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)

# 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).

Beads Issue Tracker

This project uses bd (beads) for issue tracking. Run bd prime to see full workflow context and commands.

Quick Reference

bd ready              # Find available work
bd show <id>          # View issue details
bd update <id> --claim  # Claim work
bd close <id>         # Complete work

Rules

  • Use bd for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists
  • Run bd prime for detailed command reference and session close protocol
  • Use bd remember for persistent knowledge — do NOT use MEMORY.md files

Architecture in one line: issues live in a local Dolt DB; sync uses refs/dolt/data on your git remote; .beads/issues.jsonl is a passive export. See https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md for details and anti-patterns.

Agent Context Profiles

The managed Beads block is task-tracking guidance, not permission to override repository, user, or orchestrator instructions.

  • Conservative (default): Use bd for task tracking. Do not run git commits, git pushes, or Dolt remote sync unless explicitly asked. At handoff, report changed files, validation, and suggested next commands.
  • Minimal: Keep tool instruction files as pointers to bd prime; use the same conservative git policy unless active instructions say otherwise.
  • Team-maintainer: Only when the repository explicitly opts in, agents may close beads, run quality gates, commit, and push as part of session close. A current "do not commit" or "do not push" instruction still wins.

Session Completion

This protocol applies when ending a Beads implementation workflow. It is subordinate to explicit user, repository, and orchestrator instructions.

  1. File issues for remaining work - Create beads for anything that needs follow-up
  2. Run quality gates (if code changed) - Tests, linters, builds
  3. Update issue status - Close finished work, update in-progress items
  4. Handle git/sync by active profile:
    # Conservative/minimal/default: report status and proposed commands; wait for approval.
    git status
    
    # Team-maintainer opt-in only, unless current instructions forbid it:
    git pull --rebase
    git push
    git status
    
  5. Hand off - Summarize changes, validation, issue status, and any blocked sync/commit/push step

Critical rules:

  • Explicit user or orchestrator instructions override this Beads block.
  • Do not commit or push without clear authority from the active profile or the current user request.
  • If a required sync or push is blocked, stop and report the exact command and error.