Files
clubber/openspec/changes/add-graphql-member-api/specs/project-setup/spec.md
T
gurixandClaude f3f5e0282c feat: add OpenSpec proposal for GraphQL member API
Create comprehensive OpenSpec proposal for implementing a minimal GraphQL API
for member management with flexible validation requirements.

Key features:
- Only firstName required for member creation
- Conditional validation (email/phone format validated only when provided)
- Full CRUD operations via GraphQL
- SQLite database with Alembic migrations
- FastAPI + Strawberry GraphQL integration

Includes 4 capability specs:
- project-setup: Python project structure with uv dependency management
- database-layer: SQLAlchemy async models with nullable fields
- graphql-api: Strawberry schema with minimal required fields
- member-crud: Business logic with conditional validation

Implementation broken down into 20 discrete tasks across 5 phases.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 11:29:06 +01:00

8.3 KiB

Spec: Project Setup

Capability: project-setup Status: Draft Last Updated: 2025-11-20

Overview

This capability establishes the foundational Python project structure, dependency management, tooling configuration, and development environment for the Clubber application.

ADDED Requirements

Requirement: Python project structure with uv dependency management

The project MUST use Python 3.11+ with uv for fast, reliable dependency management and provide a standard src/ layout for code organization.

Scenario: Developer initializes new development environment

Given a developer has cloned the repository When they run uv sync Then all dependencies are installed in a virtual environment And the environment is ready for development within 30 seconds

Scenario: Developer runs the application

Given dependencies are installed When developer runs uv run uvicorn src.main:app --reload Then the FastAPI server starts on http://localhost:8000 And GraphQL playground is available at http://localhost:8000/graphql

Requirement: Project configuration in pyproject.toml

The project MUST define all metadata, dependencies, and tool configurations in pyproject.toml following modern Python packaging standards.

Dependencies required:

  • fastapi >= 0.104.0 (Web framework)
  • strawberry-graphql[fastapi] >= 0.215.0 (GraphQL integration)
  • sqlalchemy[asyncio] >= 2.0.0 (ORM with async support)
  • aiosqlite >= 0.19.0 (Async SQLite driver)
  • alembic >= 1.12.0 (Database migrations)
  • pydantic-settings >= 2.0.0 (Configuration management)
  • uvicorn[standard] >= 0.24.0 (ASGI server)

Development dependencies required:

  • pytest >= 7.4.0 (Test framework)
  • pytest-asyncio >= 0.21.0 (Async test support)
  • black >= 23.0.0 (Code formatting)
  • ruff >= 0.1.0 (Linting)
  • isort >= 5.12.0 (Import sorting)

Scenario: Dependencies are declared with version constraints

Given pyproject.toml exists When developer inspects [project.dependencies] Then all required packages are listed with minimum versions And version constraints allow patch/minor updates

Scenario: Development tools are configured

Given pyproject.toml contains tool configurations When developer runs black . Then code is formatted with line length 88 When developer runs ruff check . Then code is linted against configured rules

Requirement: Source directory structure following layered architecture

The project MUST organize code into src/ directory with clear separation of concerns across API, business logic, and data layers.

Required directory structure:

src/
├── __init__.py
├── main.py              # FastAPI application, startup/shutdown
├── config.py            # Settings and configuration
├── database.py          # Database connection, session factory
├── models/              # SQLAlchemy ORM models
│   ├── __init__.py
│   └── member.py
├── schemas/             # Strawberry GraphQL types
│   ├── __init__.py
│   └── member.py
└── resolvers/           # GraphQL query/mutation resolvers
    ├── __init__.py
    └── member.py

Scenario: Code is organized by architectural layer

Given the src/ directory exists When a developer navigates the codebase Then models/ contains only SQLAlchemy ORM definitions And schemas/ contains only Strawberry GraphQL type definitions And resolvers/ contains only GraphQL resolver functions And each module has clear, single responsibility

Scenario: Main application entry point is defined

Given src/main.py exists When the file is imported Then it exports a FastAPI app instance And app includes GraphQL route at /graphql And app includes startup event to verify database connection

Requirement: Testing infrastructure with pytest

The project MUST provide pytest configuration for running async tests with database fixtures and code coverage reporting.

Scenario: Async tests can be executed

Given pytest and pytest-asyncio are installed When developer runs pytest Then all tests in tests/ directory are discovered And async test functions execute correctly And test results are displayed with pass/fail status

Scenario: Database fixtures are available for tests

Given tests/conftest.py defines database fixtures When a test function requests db_session fixture Then an isolated test database session is provided And session is rolled back after test completion And no test data persists between test runs

Requirement: Code quality tooling configuration

The project MUST configure black, ruff, and isort for consistent code formatting and linting with settings in pyproject.toml.

Black configuration:

  • Line length: 88 characters
  • Target version: Python 3.11
  • Skip string normalization: false

Ruff configuration:

  • Line length: 88 characters
  • Select: E, F, W, I (pycodestyle, pyflakes, warnings, isort)
  • Ignore: E501 (line too long, handled by black)

Isort configuration:

  • Profile: black (compatible settings)
  • Multi-line output: 3 (vertical hanging indent)

Scenario: Code formatting is enforced

Given black is configured in pyproject.toml When developer runs black --check . Then all Python files are checked for formatting And exit code is 0 if all files are formatted correctly And exit code is 1 if any files need formatting

Scenario: Code quality checks pass

Given ruff is configured in pyproject.toml When developer runs ruff check . Then all Python files are linted And no errors are reported for compliant code And clear error messages are shown for violations

Requirement: Environment configuration with .env support

The project MUST support environment-based configuration using .env files with pydantic-settings for type-safe config values.

Scenario: Default configuration works for development

Given no .env file exists When application starts Then it uses default SQLite database path And it runs in debug mode And application starts successfully

Scenario: Environment variables override defaults

Given .env file contains DATABASE_URL=sqlite+aiosqlite:///./test.db When application loads configuration Then settings.database_url equals "sqlite+aiosqlite:///./test.db" And custom database path is used

Scenario: Configuration is type-safe

Given src/config.py defines Settings class When invalid configuration value is provided Then pydantic validation raises clear error And application fails fast on startup

Requirement: Development scripts for common tasks

The project MUST provide executable scripts for database seeding and common development tasks.

Required scripts:

  • scripts/seed.py - Populate database with sample member

Scenario: Seed script creates sample data

Given database schema exists from migrations When developer runs uv run python scripts/seed.py Then sample member is created in database And script is idempotent (safe to run multiple times) And success message is displayed

MODIFIED Requirements

None (new capability)

REMOVED Requirements

None (new capability)

Cross-References

Depends On

None (foundational capability)

Enables

  • database-layer - Requires project structure and dependencies
  • graphql-api - Requires FastAPI app and Strawberry installation
  • member-crud - Requires complete project infrastructure

Implementation Notes

  1. Dependency resolution: Use uv add <package> to ensure lock file is updated
  2. Python version: Minimum 3.11 for modern async features and performance
  3. Import ordering: Isort configured to work with black (no conflicts)
  4. Testing: Pytest configuration in pyproject.toml, not separate pytest.ini
  5. Scripts: Use uv run prefix to execute in correct virtual environment

Validation Checklist

  • uv sync completes without errors
  • uv run pytest discovers and runs tests (even if no tests exist yet)
  • uv run black --check . passes
  • uv run ruff check . passes
  • uv run uvicorn src.main:app --reload starts server
  • pyproject.toml includes all required dependencies
  • src/ directory structure matches specification
  • .env.example file documents available settings