MarioGLealPandClaude Sonnet 5 c78d271132
CI / lint · types · tests (push) Successful in 8s
rework into a clean, runnable sample
Restructure the take-home into a small package with tests and fix the
bugs that stopped it running:

- app/ package: main, routes, models, documents (was json_load)
- fix the search route — it built the Response envelope positionally and
  never actually returned; now returns ListResponse[Ok, DocumentId]
- Literal domain types (Role, Department) so bad input is a 422
- load + validate docs.json in one TypeAdapter call
- PEP 695 type aliases / generics; Annotated query params
- pyproject: fix the [tool.ty.src] typo, drop the unfixable list that
  disabled every autofix, move ruff/ty to a dev group
- add 5 end-to-end tests, wire pytest into CI, add MIT LICENSE, real README

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01BmZpbtmZGQw931W7wzFeLH
2026-09-06 18:17:27 +01:00
2026-09-06 18:17:27 +01:00
2026-08-25 22:04:38 +01:00
2026-08-25 22:04:38 +01:00
2026-09-06 18:17:27 +01:00
2026-09-06 18:17:27 +01:00
2026-09-06 18:17:27 +01:00

fastapi-rbac-search

A small, fully typed FastAPI service: keyword search over a document repository that only returns the documents the caller's role is allowed to see.

It is deliberately compact — a sample of how I structure a typed Python API, not a product.

What it shows

  • Generic response envelopes — Response[S, D] and ListResponse[S, D] (app/models.py) give every endpoint the same { "status": ..., "data": ... } shape while keeping the payload type checked.
  • Literal domain types — Role and Department are closed sets, so an unknown role is a 422 from FastAPI's request validation rather than a branch in the handler.
  • Pydantic v2 models with a camelCase alias generator for the wire format, and a TypeAdapter that loads and validates the whole docs.json in one call.
  • Tooling: uv for environments, ruff for lint + format, ty for type checking, pytest for the tests — all wired into CI.

Run it

uv run uvicorn app.main:app --reload
# docs: http://127.0.0.1:8000/docs
curl 'http://127.0.0.1:8000/documents?q=rollback&role=ops'
# {"status":"ok","data":["doc-001"]}

curl -i 'http://127.0.0.1:8000/documents?q=rollback&role=hr'
# 404 — "hr" is not on doc-001's permission list

Develop

uv sync
uv run ruff format --check && uv run ruff check
uv run ty check
uv run pytest

Layout

app/
  main.py        FastAPI app + router wiring
  routes.py      GET /documents — the role-filtered search
  models.py      response envelopes, Literal domain types, the Document model
  documents.py   loads + validates app/docs.json into a list[Document]
  docs.json      the sample repository (12 documents)
tests/           end-to-end tests against the app via TestClient
S
Description
Small, fully typed FastAPI service: document search that only returns what the caller's role may see
Readme MIT
77 KiB
0 Stars 1 Watchers 0 Forks
Languages
Python 100%