FastStack is a hybrid FastAPI framework (runtime core + CLI generator) replacing a legacy cookiecutter template. The repo is greenfield — only docs exist. We need to build the entire framework across 6 phases (~40 items, ~63 files). All design decisions are captured in docs/design/fastapi-generator-plan.md and 7 ADRs in docs/architecture/adr/.
Goal: A user can pip install faststack, run faststack init my-app, define entities in YAML, and get a complete async FastAPI project with protocol-based testing, structured logging, and RFC 7807 errors.
Before any code, create the package structure.
- Package:
faststack, Python>=3.12 - Runtime deps:
fastapi,sqlalchemy[asyncio],asyncpg,pydantic>=2.0,alembic,click,jinja2,inflect,uvicorn,python-json-logger - Dev deps:
pytest,pytest-asyncio,polyfactory,ruff,black,aiosqlite,httpx,mypy - Entry point:
[tool.poetry.scripts] faststack = "cli:cli" - Ruff/black/pytest config sections
faststack_core/{__init__,base/,exceptions/,database/,logging/,middleware/,health/,settings/}
cli/__init__.py
templates/{project/,simple/}
tests/{__init__,test_core/,test_cli/,test_templates/}
Common development commands (~15 targets):
install # poetry install
test # pytest
test-verbose # pytest -v
test-single # pytest tests/ -k "$(K)" (usage: make test-single K=test_name)
lint # ruff check . && black --check .
format # ruff check --fix . && black .
typecheck # mypy faststack_core/ cli/
check # lint + typecheck + test (CI gate)
clean # remove __pycache__, .pytest_cache, .coverage, htmlcov, dist, *.egg-info
help # list all targets with descriptions
Depends on: Phase 0
Critical files: repository.py (Protocol + SqlAlchemyRepository), entity.py, service.py
faststack_core/base/entity.py— Entity, AuditedEntity, SoftDeleteEntity, FullAuditedEntitytests/test_core/test_base_entity.py
faststack_core/exceptions/domain.py— DomainError + 8 subclasses + EXCEPTION_MAPfaststack_core/exceptions/handlers.py— RFC 7807 handlertests/test_core/test_exceptions.py
faststack_core/database/session.py— DatabaseConfig, async get_dbfaststack_core/base/permissions.py— @require_permission, @require_role
faststack_core/base/repository.py— Repository Protocol[T], SearchableRepository, SqlAlchemyRepositorytests/test_core/test_repository.py— Protocol conformance, async CRUD, soft-deletefaststack_core/base/service.py— CrudService with 6 async lifecycle hookstests/test_core/test_crud_service.py— hooks fire, NotFoundError, fake repo in tests
Depends on: Phase 1
Critical file: setup.py (integrates everything)
faststack_core/logging/config.py— log settingsfaststack_core/logging/masking.py— recursive sensitive data maskingfaststack_core/logging/structured_logger.py— dual-format (JSON file + colored console)
faststack_core/middleware/correlation_id.py— UUID per request via contextvarsfaststack_core/middleware/request_logging.py— method/path/status/durationfaststack_core/middleware/security_headers.py— HSTS, X-Content-Type-Options, etc.
faststack_core/health/endpoints.py— /health + /health/detailedfaststack_core/settings/config.py— FastStackConfig dataclass
faststack_core/setup.py—setup_app(app, config)one-call registration- Tests: test_logging.py, test_middleware.py, test_health.py, test_setup.py
Depends on: Phase 1 (for entity types)
Critical files: model_introspector.py (HIGHEST RISK), yaml_parser.py
cli/__init__.py— Click CLI group with versioncli/field_mappings.py— 13-type YAML → SQLAlchemy → Pydantic mapcli/yaml_parser.py— EntityDefinition/FieldDefinition dataclasses, parse_entities_yaml(), relationship resolutiontests/test_cli/test_field_mappings.py,tests/test_cli/test_yaml_parser.py
cli/model_introspector.py— AST-based model reader (parses Mapped[], mapped_column(), relationship())tests/test_cli/test_model_introspector.py— test with string model files written to temp
Risk mitigation for introspector: Only support patterns FastStack generates. Test-driven against known model files.
Verify: pytest tests/test_cli/ -v, cross-check: YAML parse → generate model → introspect model → same EntityDefinition
Depends on: Phases 1-3
templates/project/pyproject.toml.j2templates/project/main.py.j2— imports setup_app, registers entity routerstemplates/project/config.py.j2— Pydantic BaseSettingstemplates/project/Dockerfile.j2templates/project/docker-compose.yml.j2templates/project/alembic.ini.j2templates/project/alembic_env.py.j2— async engine, auto-model-discoverytemplates/project/conftest.py.j2— async fixtures, test DB
cli/cmd_init.py—faststack initcommand (uses templates + yaml_parser)tests/test_cli/test_init.py— scaffold to temp dir, verify structuretests/test_templates/test_project_templates.py— render + ast.parse
Verify: faststack init test-project in temp dir, all generated files parse as valid Python/TOML/YAML
Depends on: Phases 1-4
Critical file: model.py.j2 (must handle all 13 types + 3 relationship types)
templates/simple/model.py.j2— SQLAlchemy model with enums, relationships, FKs, junction tablestemplates/simple/schema.py.j2— Pydantic v2 Create/Update/Response/DetailResponsetemplates/simple/repository.py.j2— extends SqlAlchemyRepositorytemplates/simple/service.py.j2— extends CrudService with hook placeholderstemplates/simple/router.py.j2— FastAPI CRUD endpoints, flat routes, query param filteringtemplates/simple/factory.py.j2— polyfactory ModelFactorytemplates/simple/fake_repository.py.j2— in-memory dict-based, satisfies Protocoltemplates/simple/test_unit_service.py.j2— service tests with faketemplates/simple/test_integration.py.j2— API tests with httpx.AsyncClient
tests/test_templates/test_simple_mode.py— render all 9 for User/Post/Category, verify valid Python, cross-template consistency
Verify: Render all templates for User entity, ruff check + black --check on output, fake satisfies Protocol
Depends on: Phases 1-5
cli/cmd_migrate.py— Alembic wrapper (generate/upgrade/downgrade)cli/cmd_list.py— entity status table with staleness detectiontests/test_cli/test_migrate.py,tests/test_cli/test_list.py
- Registry generation logic (dependencies.py template, router registration in main.py)
cli/cmd_add_entity.py— add-entity (interactive, --fields, --from-yaml, --update)cli/cmd_generate.py— regenerate REGENERATABLE files from model, skip PRESERVED, hash trackingtests/test_cli/test_add_entity.py,tests/test_cli/test_generate.py
faststack init blog-app --entities fixtures/blog.yaml
cd blog-app
# Verify User + Post + Category generated
# Modify User model (add bio field)
faststack generate User # schemas updated, service preserved
faststack list # shows staleness correctly
faststack add-entity Comment --fields "body:text:required,post_id:uuid"
# Verify Comment entity, dependencies.py updated
pytest # all generated tests pass
ruff check . && black --check . # clean output| Risk | Severity | Phase | Mitigation |
|---|---|---|---|
| AST introspection of Mapped[] syntax | HIGH | 3 | Test-driven, only support patterns FastStack generates |
| model.py.j2 correctness (13 types x 3 relationships) | HIGH | 5 | Test every type+relationship combo with User/Post/Category fixture |
| Protocol[T] + Generic[T] type checker compat | MEDIUM | 1 | Add runtime_checkable, test with mypy |
| --update mode AST rewriting | MEDIUM | 6 | v1: append fields to class end, not merge. Print diff for review. |
| BaseHTTPMiddleware streaming issues | LOW | 2 | Verify Starlette version compat, use raw ASGI if needed |
docs/design/fastapi-generator-plan.md— all code examples serve as implementation referencedocs/architecture/adr/— 7 ADRs with constraints and alternatives- Design plan YAML example (User + Post + Category) — golden test fixture for all template testing