- CLAUDE.md: add step 5 to infrastructure protocol (tear down after testing) - .claude/settings.local.json: add git push, docker compose, docker run to allowed commands accumulated during this session Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.1 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Stack
| Layer | Tech |
|---|---|
| Backend | FastAPI (async), SQLAlchemy 2 (async), Alembic, PostgreSQL |
| Auth | JWT via python-jose, bcrypt via bcrypt (direct, no passlib) |
| Frontend | React 18, TypeScript, Vite, React Router v6, TanStack Query, Axios |
| Dev DB | PostgreSQL 16 via Docker Compose |
Commands
Backend (run from backend/)
# Install
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
# Run dev server
uvicorn app.main:app --reload
# Lint / format
ruff check . && ruff format .
# Tests
pytest
pytest tests/test_auth.py # single file
# Migrations
alembic revision --autogenerate -m "describe change"
alembic upgrade head
alembic downgrade -1
Frontend (run from frontend/)
npm install
npm run dev # Vite dev server at :5173, proxies /api → :8000
npm run build
npm run typecheck
npm run lint
Full stack via Docker
cp .env.example backend/.env
docker compose up --build
Architecture
Request flow
Browser → Vite dev server (:5173)
/api/* → proxy → FastAPI (:8000)
→ router → dependency injection (get_db, get_current_user)
→ SQLAlchemy async session → PostgreSQL
Backend layout
app/main.py— FastAPI app, CORS, router registrationapp/core/config.py— all settings viapydantic-settings(reads.env)app/core/security.py— password hashing and JWT encode/decodeapp/database.py— async engine,AsyncSessionLocal,Base(all models inherit from here)app/models/— SQLAlchemy ORM models; import them all in__init__.pyso Alembic detects themapp/schemas/— Pydantic request/response models (separate from ORM models)app/routers/— one file per resource; mount inmain.pyapp/deps.py— FastAPI dependencies:get_current_uservalidates JWT and returnsUser
Frontend layout
src/api/client.ts— single Axios instance; all API calls live here, token injected via interceptorsrc/hooks/useAuth.ts— token state (localStorage),login,logout; consumed by pages andApp.tsxsrc/pages/— one file per route; data fetching via TanStack Querysrc/App.tsx— route tree;PrivateRoutewrapper redirects to/loginwhen no token
Auth flow
POST /api/auth/loginreturns a JWT bearer token- Token stored in
localStorage, attached to every request by the Axios interceptor - Protected routes call
GET /api/users/me;get_current_userdep validates the token on the server
Git convention
Always run git push immediately after every git commit.
Infrastructure change protocol
After any change to Dockerfiles, docker-compose*.yml, nginx.conf, setup scripts, or installation / usage procedures:
- Update
README.md— keep the Containers table, ports, image names, and Current State section accurate. - Spin up the dev stack and verify that login and registration work end-to-end:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build - Spin up the prod stack and run the same checks:
docker compose up --build -d - Confirm each container is running as a non-root user (
docker inspect <container> --format '{{.Config.User}}'). - Tear down after testing — stop and remove all containers, networks, and volumes:
docker compose down --volumes --remove-orphans # or for dev stack: docker compose -f docker-compose.yml -f docker-compose.dev.yml down --volumes --remove-orphans
Security hook
A pre-commit hook lives in .githooks/pre-commit and runs scripts/security_check.py inside a Docker container. It is registered via git config core.hooksPath .githooks (already set in this repo).
The hook checks staged files for:
- Hardcoded credentials / secrets
- Dangerous patterns (
eval,exec,shell=True,pickle) - Weak cryptography (MD5, SHA1, DES)
- SQL injection risk
- Debug flags left in code
banditstatic analysis on all Python files
New clones must run git config core.hooksPath .githooks to activate the hook.
Changelog convention
Every time files are added or modified, append an entry to the relevant file in changelog/ (one file per date, named YYYY-MM-DD_<slug>.md). If a file for today already exists, append to it rather than creating a new one.
Each entry must include:
- A heading with the date and a short description
**Timestamp:**in ISO-8601 format- A Summary sentence
- A Files Added / Modified / Deleted list with one-line descriptions
The README.md Current State section should be kept up to date whenever significant features are added or removed.
Adding a new resource
- Add ORM model in
app/models/, import it inapp/models/__init__.py - Run
alembic revision --autogenerate -m "add <resource>"+alembic upgrade head - Add Pydantic schemas in
app/schemas/ - Add router in
app/routers/, mount it inapp/main.py - Add API function(s) to
src/api/client.ts, add page/component, register route inApp.tsx