
# [Service Name]

A single-purpose FastAPI service. Async by default. Postgres for state. Dockerized.

## Source of truth
Production runs as a container on Fly or Railway. The `Dockerfile` + locked `requirements.txt` define what runs. Local mirrors via `docker compose up`.

## Tech stack
Python 3.13 + FastAPI 0.115 + Uvicorn. Pydantic v2 for request and response schemas. SQLAlchemy 2.x with the async API. Alembic for migrations. `structlog` for JSON logs. `pytest` + `httpx` for tests (real ASGI calls, no test client wrapping). `uv` for dependency management (way faster than pip).

## Deploy
Build the Docker image, push to Fly or Railway. Health check at `/healthz`. Graceful shutdown via SIGTERM (FastAPI handles it).

## File map
- `app/main.py` FastAPI app + route mounting
- `app/api/` routers, one per resource
- `app/schemas/` Pydantic models (request, response)
- `app/models/` SQLAlchemy ORM models
- `app/db.py` engine + session factory
- `app/deps.py` reusable dependencies (auth, db session)
- `app/settings.py` Pydantic Settings (env loading)
- `alembic/` migration history
- `tests/` pytest specs
- `Dockerfile` slim Python image, multi-stage

## .env keys
- `DATABASE_URL` `postgresql+asyncpg://...`
- `API_KEY` shared secret for inbound auth (if no JWT)
- `LOG_LEVEL`
- `SENTRY_DSN` optional

## Hard rules
- Every endpoint declares response_model. No untyped JSON dicts.
- DB sessions via FastAPI `Depends`. Never instantiate `AsyncSession` in a handler.
- Migrations via Alembic auto-generate + manual review. Never edit applied migrations.
- Settings via Pydantic Settings class. No `os.environ.get` in business code.
- `pytest` runs against a throwaway Postgres in CI. No mocks for the DB layer.
- All structured logs include `request_id` set in middleware.

## Recent significant changes
- 2026-05-06: Scaffolded. Locked: Pydantic v2 (faster), SQLAlchemy 2.x async (not Tortoise), uv (not poetry).

## Next session: start here
1. `uv venv && uv sync` to install.
2. Create Postgres locally with `docker compose up db`.
3. `alembic upgrade head` to apply schema.
4. `uvicorn app.main:app --reload`.
5. Test `/healthz`, then implement the first business route.
