agentleFS
motola10motola10/claude-code-base/.claude/skills/fastapi-standards/SKILL.md

fastapi-standards

Skill1 starsChanged 5 months agoMITView on GitHub

Best-practice coding standards for FastAPI services (FastAPI app, APIRouter, Pydantic v2). OVERLAY — load python-standards FIRST, then apply these. Covers project structure, async, dependency injection, Pydantic models, JWT auth, URI versioning, SQLAlchemy/Alembic, testing. Used by the review agents on FastAPI code. Do NOT use for non-Python web frameworks.

The file

Show its rules and text

We split this skill into the rules it gives an agent

14 rules. About 0 are common, 3 are distinctive, and 11 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 11

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    FASTAPI-STRUCT-4 (SHOULD NOT): Put blocking work, DB calls, or business logic directly in a path operation function — delegate to the …

    line 78
  2. Very specific:

    FASTAPI-MODEL-1 (MUST): Every request body is a Pydantic BaseModel (not a raw dict).

    line 90
  3. Very specific:

    FASTAPI-MODEL-3 (MUST): Use separate input and output schemas (e.g.

    line 97
  4. Distinctive:

    Never accept or echo server-controlled fields (id, timestamps, roles) through the input model.

    line 98
  5. Very specific:

    FASTAPI-MODEL-5 (SHOULD): Use Pydantic v2 idioms — @field_validator/@model_validator, model_dump()/model_validate(), model_config.

    line 102
  6. Very specific:

    FASTAPI-DEP-1 (MUST): Use Depends for shared cross-cutting concerns — DB sessions, the current authenticated user, pagination, settings.

    line 124
  7. Very specific:

    FASTAPI-DEP-2 (SHOULD): Use the Annotated[T, Depends(...)] style (optionally a shared type alias) rather than the legacy default-value = …

    line 127
  8. Very specific:

    FASTAPI-ASYNC-1 (MUST): Use async def for path operations and dependencies that perform I/O with async libraries.

    line 138
  9. Distinctive:

    FASTAPI-ASYNC-2 (MUST): If an operation must call blocking code, either define it as a plain

    line 141
  10. Very specific:

    FASTAPI-ASYNC-3 (SHOULD): Use an async HTTP client (httpx.AsyncClient) for outbound calls, constructed once (lifespan/dependency) and …

    line 144
  11. Very specific:

    FASTAPI-ERR-3 (MUST): Do not leak internals — unhandled exceptions return a generic 500 with no traceback/secret to the client (fulfils …

    line 156
  12. Very specific:

    FASTAPI-ERR-4 (SHOULD): Use accurate, semantic status codes via the status module (status.HTTP_404_NOT_FOUND), and set status_code= on …

    line 158
  13. Very specific:

    FASTAPI-SEC-5 (SHOULD): Don't expose interactive docs (/docs, /redoc) or the OpenAPI schema on untrusted/production surfaces without …

    line 178
  14. Very specific:

    FASTAPI-TEST-1 (MUST): Test endpoints with FastAPI's TestClient (or httpx.AsyncClient + ASGITransport) at the app boundary, covering …

    line 204

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

FastAPI Coding Standard (v1.0 — LOCKED)

Status: ✅ Locked — all review questions resolved (decision log at end). An overlay that builds on the locked Python core (codebase-standards/python.md v1.0) the way Next.js builds on React. A FastAPI service is first a Python service — every PY-* rule applies (3.12 floor, mypy --strict, uv, Ruff, Google docstrings, ≥80% changed-code coverage). This document adds only the web-framework specifics (FASTAPI-* rules). Same constraint language, rule-ID format, and severity mapping as the template.

On adoption this becomes .claude/skills/fastapi-standards/SKILL.md + references/*.md.

Toolchain verified current as of 2026-06-13 (via Context7 + PyPI): FastAPI 0.136.x, Pydantic v2 (2.13.x), Starlette 1.3.x, Uvicorn 0.49.x, pydantic-settings 2.14.x, httpx 0.28.x. Rules are written version-agnostically; these are reference points, not pins.


How to read this document

Constraint language (RFC 2119)

  • MUST / MUST NOT — hard requirement; a violation is a blocking issue.
  • SHOULD / SHOULD NOT — strong recommendation; deviate only with a written # Justification:.
  • MAY — optional.

Rule IDs

Stable FASTAPI-AREA-NUMBER (e.g. FASTAPI-ERR-2). The reviewer MUST cite the rule ID. Never renumber; add new numbers. PY-* IDs from the Python core still apply and are cited as-is.

Severity mapping

This document says…Reviewer severityGate
MUST/MUST NOT in SecurityCriticalBlocks merge
MUST/MUST NOT elsewhereCritical / Warning (by impact)Blocks if it risks correctness/data loss
SHOULD without justificationWarningShould fix
MAY / stylisticSuggestionNice to have

Scope & Assumptions

  1. Target: HTTP APIs and services built on FastAPI (Pydantic v2, served by Uvicorn).
  2. Inherits the Python core in full — this overlay never relaxes a PY-* rule, only adds to it.
  3. Pydantic v2 is assumed. v1-only syntax (@validator, .dict(), Config class) is treated as legacy; use v2 (@field_validator, .model_dump(), model_config).
  4. Custom overrides: the project's custom-standards skill overrides this document on conflict.

How this overlay extends the Python core

Python core ruleFastAPI mechanism that fulfills/strengthens it
PY-SEC-1 (validate all inbound)Pydantic request models + Query()/Path() constraints + extra="forbid"
PY-ERR-3/5 (typed errors, no leaks)HTTPException + registered exception handlers with a stable error shape
PY-CONF-1/2 (single validated config)pydantic-settings BaseSettings, validated at startup
PY-STRUCT-2 (layering)APIRouter (transport) → service functions (logic) → repository (data)
PY-SEC-5 (password hashing)FastAPI security deps + Argon2/bcrypt/pwdlib (per PY-SEC-5)

1. Application & Project Structure

  • FASTAPI-STRUCT-1 (MUST): Split routes into APIRouter modules by feature and include_router them on the app — do not define all endpoints on a single FastAPI() instance. Keep the layering of PY-STRUCT-2: routers handle transport only (parse request, call a service, shape response); business logic lives in service functions; data access is isolated.
  • FASTAPI-STRUCT-2 (SHOULD): Build the app in an app factory (create_app() -> FastAPI) so it can be constructed with test/overridden config. Register routers, middleware, and exception handlers there.
  • FASTAPI-STRUCT-3 (MUST): Manage startup/shutdown with the lifespan async context manager (not the deprecated @app.on_event). Open pools/clients on startup and close them on shutdown — this is how PY-level graceful shutdown is realized for the service.
  • FASTAPI-STRUCT-4 (SHOULD NOT): Put blocking work, DB calls, or business logic directly in a path operation function — delegate to the service layer.
  • FASTAPI-STRUCT-5 (SHOULD): Access relational data through a mature ORM with versioned migrations, kept behind the repository/data layer (never raw SQL strings in handlers — see PY-SEC-2). Recommended default: SQLAlchemy 2.0 (async) + Alembic migrations (or SQLModel, the FastAPI-author's SQLAlchemy+Pydantic layer). The ORM library is recommended, not mandated — but migrations and the data-layer boundary are required.

2. Request & Response Models

  • FASTAPI-MODEL-1 (MUST): Every request body is a Pydantic BaseModel (not a raw dict). Path/query/header params use typed parameters with validation (Annotated[int, Path(gt=0)], Annotated[str, Query(max_length=50)]).
  • FASTAPI-MODEL-2 (MUST): Declare an explicit response_model (or a typed return annotation) on operations that return data. FastAPI filters the response to that schema — this is the enforcement point for PY-level "never serialize secrets": MUST NOT return ORM/DB objects directly; map to a response schema that omits sensitive fields.
  • FASTAPI-MODEL-3 (MUST): Use separate input and output schemas (e.g. UserCreate vs UserRead). Never accept or echo server-controlled fields (id, timestamps, roles) through the input model.
  • FASTAPI-MODEL-4 (SHOULD): Reject unknown fields on request models with model_config = {"extra": "forbid"} (mirrors PY-SEC-1). Add field constraints with Field(..., gt=, max_length=, pattern=) rather than hand-rolled checks.
  • FASTAPI-MODEL-5 (SHOULD): Use Pydantic v2 idioms — @field_validator/@model_validator, model_dump()/model_validate(), model_config. Flag v1 @validator, .dict(), inner Config.
class UserCreate(BaseModel):
    model_config = {"extra": "forbid"}          # FASTAPI-MODEL-4
    email: EmailStr
    password: str = Field(min_length=12)

class UserRead(BaseModel):                       # FASTAPI-MODEL-3: no password field
    id: int
    email: EmailStr

@router.post("/users", response_model=UserRead, status_code=status.HTTP_201_CREATED)
async def create_user(payload: UserCreate, svc: Annotated[UserService, Depends(get_user_service)]):
    return await svc.create(payload)             # returns a UserRead-shaped object, never the ORM row

3. Dependency Injection

  • FASTAPI-DEP-1 (MUST): Use Depends for shared cross-cutting concerns — DB sessions, the current authenticated user, pagination, settings. MUST NOT reach for module-level globals or construct these inline in each handler.
  • FASTAPI-DEP-2 (SHOULD): Use the Annotated[T, Depends(...)] style (optionally a shared type alias) rather than the legacy default-value = Depends(...) form.
  • FASTAPI-DEP-3 (MUST): Acquire and release per-request resources (DB sessions, transactions) via a dependency with yield, so cleanup runs even on error.
  • FASTAPI-DEP-4 (SHOULD): Enforce authentication/authorization through dependencies (route- or router-level dependencies=[...]), not ad-hoc checks inside handlers.

4. Async & Concurrency

  • FASTAPI-ASYNC-1 (MUST): Use async def for path operations and dependencies that perform I/O with async libraries. Inside them, never block the event loop (PY-ASYNC-1) — no sync DB drivers, requests, time.sleep, or CPU-heavy loops.
  • FASTAPI-ASYNC-2 (MUST): If an operation must call blocking code, either define it as a plain def (FastAPI runs def endpoints in a threadpool) or offload via run_in_threadpool / asyncio.to_thread — do not call blocking code from inside an async def path operation.
  • FASTAPI-ASYNC-3 (SHOULD): Use an async HTTP client (httpx.AsyncClient) for outbound calls, constructed once (lifespan/dependency) and reused — not a new client per request, and not requests.

5. Error Handling

  • FASTAPI-ERR-1 (MUST): Raise HTTPException (or a subclass) for expected client-facing errors with the correct status code — don't return {"error": ...} dicts with a 200.
  • FASTAPI-ERR-2 (MUST): Map domain exceptions to HTTP responses in registered exception handlers (@app.exception_handler(...)), not by try/except in every handler. Provide a consistent error response shape across the API.
  • FASTAPI-ERR-3 (MUST): Do not leak internals — unhandled exceptions return a generic 500 with no traceback/secret to the client (fulfils PY-ERR-5); full detail is logged server-side.
  • FASTAPI-ERR-4 (SHOULD): Use accurate, semantic status codes via the status module (status.HTTP_404_NOT_FOUND), and set status_code= on operations that aren't a plain 200.

6. Security (violations here are Critical / blocking)

  • FASTAPI-SEC-1 (MUST): Protect non-public endpoints with auth enforced via dependencies (route/router dependencies=[...]). Verify the credential and check authorization (scopes/roles), not just authentication. Default scheme: stateless JWT bearer tokens via OAuth2PasswordBearer (token in the Authorization: Bearer header). Sanctioned alternatives, by context: httpOnly session cookies for browser-first apps (token not exposed to JS), or an external IdP / OAuth2 provider (Keycloak, Auth0, etc.) for larger systems. Whatever the scheme, it MUST be enforced centrally via dependencies, not ad-hoc per handler.
  • FASTAPI-SEC-2 (MUST): Configure CORS deliberately via CORSMiddleware — an explicit origin allowlist; MUST NOT combine allow_origins=["*"] with allow_credentials=True.
  • FASTAPI-SEC-3 (MUST): Apply rate limiting to public/auth/webhook endpoints (e.g. slowapi, or the API gateway/reverse proxy). Cap request body size.
  • FASTAPI-SEC-4 (MUST): Hash passwords with Argon2/bcrypt per PY-SEC-5 (argon2-cffi, bcrypt, or pwdlib); store only hashes; use secrets/crypto for tokens. Never log credentials or tokens.
  • FASTAPI-SEC-5 (SHOULD): Don't expose interactive docs (/docs, /redoc) or the OpenAPI schema on untrusted/production surfaces without protection — disable or gate them as appropriate.

7. Configuration

  • FASTAPI-CONF-1 (MUST): Load configuration with pydantic-settings BaseSettings, exposed as a cached dependency (@lru_cache get_settings), validated at startup — fulfils PY-CONF-1/2. Read config through the settings object/dependency, not scattered os.environ access.

8. API Design & Documentation

  • FASTAPI-DOC-1 (SHOULD): Lean on FastAPI's auto OpenAPI — give operations tags, summary, and response models so the generated schema is accurate and useful. Keep it in sync by construction.
  • FASTAPI-DOC-2 (SHOULD): Version the public API with a URI prefix (/v1) on the router (APIRouter(prefix="/v1")) — URI versioning is the standard. Keep URL/resource naming consistent (plural nouns, no verbs in paths). Header/media-type versioning is an acceptable alternative if a team standardizes on it; internal-only APIs MAY defer versioning until a v2 is actually needed.

9. Testing

  • FASTAPI-TEST-1 (MUST): Test endpoints with FastAPI's TestClient (or httpx.AsyncClient + ASGITransport) at the app boundary, covering success, validation (422), auth (401/403), and error paths.
  • FASTAPI-TEST-2 (MUST): Isolate external systems in tests with dependency overrides (app.dependency_overrides) — e.g. swap the DB/session or auth dependency — rather than monkey-patching internals. Carries PY-TEST-2 (isolation) and PY-TEST-5 (meaningful assertions) into the web layer.

10. Serving & Lifecycle

  • FASTAPI-RUN-1 (MUST): Serve with Uvicorn (an ASGI server); in production run under a process manager/container with multiple workers. Do not use the dev --reload server in production.
  • FASTAPI-RUN-2 (MUST): Expose a health/readiness endpoint, and ensure the lifespan shutdown path drains in-flight work and closes pools/clients (ties to FASTAPI-STRUCT-3).

Resolved Decisions

Settled per the verified cross-platform best practice (kept consistent with nodejs.md v1.1):

#AxisDecision
Q1ORM / data layer✅ SQLAlchemy 2.0 (async) + Alembic recommended (or SQLModel); ORM recommended not mandated, but migrations + the data-layer boundary are required (FASTAPI-STRUCT-5).
Q2Auth scheme✅ Stateless JWT bearer (OAuth2PasswordBearer) as the default, enforced via dependencies; httpOnly session cookies (browser apps) and external IdP/OAuth2 (larger systems) are sanctioned alternatives (FASTAPI-SEC-1).
Q3API versioning✅ URI versioning /v1 via APIRouter(prefix="/v1") for public APIs; header/media-type acceptable; internal APIs may defer (FASTAPI-DOC-2).
Q4Depth✅ Lean, consistent with the other standards.

Inherited from the Python core: 3.12 floor, mypy --strict, uv, Ruff, Google docstrings, ≥80% changed-code coverage + flag weak tests, FRAMEWORK-AREA-N IDs + severity mapping.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.