11 KiB
11 KiB
Project Context
Purpose
This project provides a toolset for managing members of a non-profit society. It consists of a graphql api. A simple MCP server that connects to the graphql api provides the tools for AI agents to manage the society administration.
Tech Stack
Core Framework
- Python 3.11+ - Primary language
- uv - Fast Python package and project manager
- FastAPI - Async web framework and HTTP layer
- Strawberry GraphQL - Schema-first GraphQL with Python type hints
Data Layer
- SQLAlchemy 2.0 - ORM with modern async support
- Alembic - Database migration management
- SQLite - Development and testing database
- PostgreSQL - Production database (future)
Integration Layer
- MCP Server (Python) - AI assistant integration
- httpx - HTTP client for GraphQL queries
Project Conventions
Code Style
Formatting
- Black - Code formatting (line length: 88)
- isort - Import sorting (Black-compatible profile)
- ruff - Fast linting and additional formatting
Type Hints
- Use type hints extensively for all function signatures
- Leverage Strawberry's type system for GraphQL schema
- SQLAlchemy models should use Mapped[] type annotations
- Prefer explicit types over Any where possible
Naming Conventions
- Files: lowercase_with_underscores.py
- Classes: PascalCase (e.g., MemberModel, MemberType)
- Functions/Variables: snake_case (e.g., get_member, member_id)
- Constants: UPPER_SNAKE_CASE (e.g., MAX_MEMBERS)
- GraphQL Types: PascalCase matching domain entities
- GraphQL Fields: camelCase (Strawberry default)
Code Organization
- Keep modules focused and single-purpose
- Prefer flat structure until complexity requires hierarchy
- Group related functionality (models, resolvers, services)
- Avoid circular dependencies through clear layering
Dependency Management
- uv for all Python package management
uv pip install <package>- Install packagesuv pip compile requirements.in -o requirements.txt- Lock dependenciesuv venv- Create virtual environmentsuv run- Run commands in virtual environment
- pyproject.toml - Project metadata and dependencies
- requirements.txt or uv.lock - Locked dependency versions
- Pin major versions, allow minor/patch updates
- Regular dependency updates for security patches
- Separate dev dependencies from production dependencies
Documentation
- README.md - Primary project documentation
- Project overview and purpose
- Quick start guide
- Installation instructions (uv setup)
- Basic usage examples
- Links to OpenSpec documentation
- Contributing guidelines
- License information
- Keep README.md up-to-date with major changes
- README is the entry point for new developers and AI assistants
- For detailed specs, refer to
openspec/directory
Architecture Patterns
Layered Architecture
API Layer (FastAPI + Strawberry)
↓
Service Layer (Business Logic)
↓
Data Layer (SQLAlchemy Models)
↓
Database (SQLite/PostgreSQL)
GraphQL Schema Design
- Type hints as schema: Use Python types to define GraphQL schema
- Simple, consistent filters: Prefer explicit arguments over complex nested filters
- Good:
members(status: MemberStatus, joinedAfter: Date) - Avoid:
members(where: {and: [{status: {eq: ACTIVE}}]})
- Good:
- Introspection-friendly: Design schema for AI consumption via introspection
- Field descriptions: Document all fields for self-describing API
Database Patterns
- Database-agnostic code: Write portable SQLAlchemy code for SQLite/PostgreSQL
- Connection string switching: Same code works with different databases
- Alembic migrations: All schema changes via migrations
- Async operations: Use async SQLAlchemy patterns where beneficial
Authentication
- JWT tokens at HTTP layer (FastAPI middleware)
- Service account for MCP server (admin privileges)
- GraphQL resolvers assume authenticated context
- Future: User-specific MCP instances
Simplicity Principles
- Default to single-file implementations (<100 lines)
- Avoid frameworks/abstractions without clear justification
- Choose boring, proven patterns
- Add complexity only with:
- Performance data showing need
- Concrete scale requirements
- Multiple proven use cases
Testing Strategy
Testing Pyramid
- Unit Tests: Core business logic and utilities
- Integration Tests: Database operations and GraphQL resolvers
- E2E Tests: Complete GraphQL query/mutation flows
- MCP Tests: Tool definitions and API integration
Framework & Tools
- pytest - Test runner with async support
- pytest-asyncio - Async test support
- httpx - Test client for FastAPI/GraphQL
- SQLAlchemy test fixtures - In-memory SQLite for fast tests
Test Organization
tests/
├── unit/ # Pure logic tests
├── integration/ # Database + resolver tests
├── e2e/ # Full API tests
└── mcp/ # MCP server tests
Coverage Goals
- Aim for >80% coverage on business logic
- 100% coverage on critical paths (payments, memberships)
- Focus on behavior, not implementation details
- Test error cases and edge conditions
Testing Conventions
- One test file per module:
test_<module>.py - Descriptive test names:
test_member_creation_with_valid_data - Use fixtures for common setup (db session, test data)
- Clean database state between tests
- Mock external services (future: email, payment providers)
Git Workflow
Branching Strategy with Worktrees
- main - Production-ready code (primary worktree)
- Feature branches -
feature/<description>or<change-id>from OpenSpec - Hotfix branches -
hotfix/<issue> - Use git worktrees for parallel development:
- Each branch gets its own directory
- Work on multiple features simultaneously
- No need to stash or switch contexts
- Example:
git worktree add ../clubber-feature-payments feature/payments
- Keep branches short-lived (1-3 days max)
- Remove worktree and delete branch after merge
Commit Conventions
- Use conventional commits format:
feat:- New featuresfix:- Bug fixesrefactor:- Code refactoringdocs:- Documentation changestest:- Test additions/changeschore:- Build, config, dependencies
- Examples:
feat: add member payment trackingfix: correct member status calculationrefactor: simplify GraphQL resolver logic
Pull Request Process
- Create worktree for feature branch from main
- Implement changes with tests in worktree
- Run tests and linting locally
- Create PR with clear description
- Link to OpenSpec change if applicable
- Review and address feedback
- Squash merge to main
- Remove worktree:
git worktree remove <path>
Pre-commit Checks
- Black formatting
- isort import sorting
- ruff linting
- Type checking (mypy)
- Tests pass
Domain Context
Non-Profit Society Management
This system manages members of a registered non-profit society (Verein/club).
Core Entities
-
Members: Individuals who belong to the society
- Active, inactive, honorary members
- Membership start/end dates
- Contact information
- Payment status
-
Memberships: The relationship between members and the society
- Annual/lifetime memberships
- Membership fees
- Payment tracking
- Status changes over time
-
Payments: Financial transactions
- Membership fees
- Donations
- Event fees
- Payment methods and tracking
-
Events (future): Society activities and meetings
- Member participation
- Registration and attendance
Business Rules
- Members must have valid contact information
- Membership status changes based on payment history
- Privacy considerations for member data (GDPR compliance)
- Financial records must be auditable
- Society governance (board members, voting rights)
Common Operations
- Add new members
- Track membership payments
- Generate membership lists
- Send payment reminders
- Export reports for annual meetings
- Member communication
Important Constraints
Technical Constraints
- Database portability: Code must work with both SQLite and PostgreSQL
- Async-first: Use async patterns for scalability
- Single-server deployment: No distributed systems initially
- Limited resources: Optimize for small-scale (<1000 members initially)
- Python-only: Keep the stack simple with one primary language
Business Constraints
- Data privacy: GDPR compliance for EU member data
- Right to access (export member data)
- Right to deletion (full data removal)
- Consent tracking for communications
- Data minimization principles
- Audit trail: Financial transactions must be traceable
- Offline capability: Export functionality for offline access to critical data
- Non-profit requirements: Transparent financial reporting
AI Integration Constraints
- Schema introspection: GraphQL schema must be AI-readable
- Simple query patterns: Avoid complex nested filters
- Service account authentication: MCP server uses admin credentials
- Rate limiting: Protect against excessive API usage (future)
- Query complexity limits: Prevent resource-intensive operations
Development Constraints
- Simplicity first: Avoid premature optimization
- Incremental delivery: Start with core features, expand gradually
- Solo developer: Optimize for maintainability over cleverness
- Open source ready: Clean, documented code for potential future contributors
External Dependencies
Current Dependencies
- Python Package Index (PyPI): Package registry (managed via uv)
- strawberry-graphql
- fastapi
- sqlalchemy
- alembic
- httpx
- pytest and testing tools
- uv: Fast package installer and resolver
Future/Planned Dependencies
-
Email Service (future): Transactional emails
- Payment reminders
- Membership notifications
- Board communications
- Consider: SMTP, SendGrid, or similar
-
Payment Processing (future): Online payment collection
- Bank transfers (EU SEPA)
- Credit card processing
- Payment reconciliation
- Consider: Stripe, PayPal, or EU-specific providers
-
Document Storage (future): Member documents and files
- Meeting minutes
- Member applications
- Financial reports
- Consider: Local filesystem, S3-compatible storage
-
Backup Service (future): Automated backups
- Database backups
- Document backups
- Disaster recovery
MCP Integration
- Claude AI API: For AI assistant features via MCP
- MCP Protocol: Standard protocol for AI tool integration
- GraphQL Introspection: Self-documenting API for AI consumption
Development Tools
- Git: Version control
- GitHub (optional): Code hosting and collaboration
- Docker (optional): Containerization for deployment
- CI/CD (future): Automated testing and deployment