# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview **DirektVermittlungDe (DVD)** is a document-centric communication platform between citizens and German authorities. It eliminates the "phone hunt" by: 1. Citizens upload a document or provide an *Aktenzeichen* (reference number) 2. The system auto-routes to the responsible unit 3. Opens an interaction thread for direct clarification ## Current Development Status **⚠️ IMPORTANT**: This repository is currently in transition from prototype phase to main production codebase. - **Current State**: Three prototype implementations (chatgpt5, geminiNbt3pro, grok4.1) in `/prototype-*` directories - **Target State**: Unified production codebase in `/src` with TDD-driven development - **Active Workplan**: See `docs/WORKPLAN_MainCodebase_Integration.md` for detailed migration plan **When working on this codebase:** - Check the workplan to understand which phase we're in - Follow TDD practices: write tests first, then implementation - Reference ADRs for architectural decisions (see below) - New code goes in `/src`, not prototypes ## Repository Structure (Target State) ``` / ├── docs/ │ ├── architecture/ │ │ ├── adr/ # Individual ADR files (0001-*.md) │ │ │ ├── 0001-split-payload-model.md │ │ │ ├── 0002-stateless-authentication.md │ │ │ └── ... │ │ ├── architecture-overview.md │ │ └── design-patterns.md │ ├── api/ │ │ ├── openapi.yaml │ │ └── api-scenarios.md │ ├── development/ │ │ ├── testing-strategy.md │ │ ├── agentic-coding-guide.md │ │ └── setup-guide.md │ └── WORKPLAN_MainCodebase_Integration.md ├── src/ │ ├── domain/ # Pure business logic (TDD tested) │ ├── adapters/ # External integrations (mocked in tests) │ ├── service/ # Application services (TDD tested) │ ├── api/ # FastAPI routes (integration tested) │ └── workers/ # Background jobs ├── tests/ │ ├── unit/ # TDD unit tests │ ├── integration/ # Integration tests │ └── fixtures/ # Test data and mocks ├── scripts/ # Utility scripts ├── prototype-*/ # ARCHIVED prototypes (reference only) ├── pyproject.toml # Dependencies & tool config └── pytest.ini # Test configuration ``` ## Development Commands ### Setup and Run (Main Codebase) ```bash # Install dependencies (from repo root) pip install -e ".[dev]" # Initialize database metadata python -m scripts.init_db # Run development server uvicorn src.main:app --reload # View API docs # http://localhost:8000/docs ``` ### Testing (TDD Workflow) ```bash # Run all tests pytest # Run with coverage report pytest --cov=src --cov-report=html # Run only unit tests pytest tests/unit/ # Run only integration tests pytest tests/integration/ # Run specific test file pytest tests/unit/domain/test_document_metadata.py -v # Watch mode (requires pytest-watch) ptw ``` ### Code Quality ```bash # Lint and format with ruff ruff check src/ tests/ ruff format src/ tests/ # Type checking with mypy mypy src/ # Run pre-commit hooks manually pre-commit run --all-files ``` ## Key Architectural Patterns ### 1. Split-Payload Model (ADR-001) **Critical**: Documents use a split design to enable both encryption and routing: - **metadata** (plaintext JSON): authorityId, referenceNumber, docType, issuedAt - **encryptedPayload** (encrypted blob): actual PDF/scan content The backend can route based on metadata without decrypting the payload. This is the core architectural constraint. When working with documents: - NEVER attempt to decrypt `encryptedPayload` in the main service - The backend treats encrypted content as opaque - Routing logic operates only on metadata fields ### 2. Hybrid Concurrency Pattern (ADR-007) Python's GIL requires careful concurrency handling: - **I/O operations** (DB, network): Use native `async`/`await` - **CPU operations** (crypto, PDF): Offload to `ProcessPoolExecutor` Example pattern: ```python cpu_pool = ProcessPoolExecutor(max_workers=4) async def handler(): # I/O: async/await data = await db.fetch() # CPU: executor loop = asyncio.get_running_loop() result = await loop.run_in_executor(cpu_pool, heavy_function, data) ``` ### 3. Cursor-Based Pagination (ADR-003) For message threads, use cursor-based pagination (timestamp) instead of offset-based: - Ensures consistent performance regardless of thread length - Prevents duplicate/missing messages during real-time updates - Target: <300ms response time (NFR-1) ### 4. Async Export Pattern (ADR-004) Data exports use async request-reply: 1. POST `/exports` → 202 Accepted + jobId 2. Background worker processes via message queue 3. Client polls status endpoint or receives webhook ### 5. Stateless Authentication (ADR-002) OAuth2/JWT with scopes: - `citizen:write`: Document submission, thread creation - `official:read`: View assigned cases - `official:write`: Respond to inquiries JWTs enable horizontal scaling without session affinity. ### 6. GDPR-Compliant Retention (ADR-006) Documents have `retention_date` field: - Default: `closedAt + gracePeriod` - Personal archive: `null` or extended date - Automated cleanup via TTL engine ## API Structure The API follows document-centric REST hierarchy: - `/documents` - Root envelope (FR-1: Document intake) - `/documents/{id}/threads` - Sub-resource for communication (FR-3) - `/threads/{threadId}/messages` - Message exchange - `/exports` - Async data export for authority systems (FR-7) ## Critical Domain Models Located in `src/domain/models.py` (target) or `prototype-chatgpt5/src/app/domain/models.py` (reference): **Enums:** - **ThreadType**: TEXT_CHAT, CALLBACK_REQUEST, APPOINTMENT - **SenderRole**: CITIZEN, OFFICIAL, SYSTEM - **ExportJobStatus**: QUEUED, RUNNING, COMPLETED, FAILED **Core Models:** - **DocumentMetadata**: authorityId, referenceNumber, docType, issuedAt - Validation: authorityId (1-50 chars), referenceNumber required - **DocumentCreateRequest**: metadata, encryptedPayload (base64) - **DocumentCreatedResponse**: id, status, assignedUnit - **ThreadCreateRequest**: type, initialMessage, preferredTimeSlot - **MessageDto**: id, senderRole, content (encrypted), timestamp ## Performance Targets (NFR) - Core operations: <300ms response time - Document upload routing: <500ms - Concurrent sessions: 10k+ per region - Availability: ≥99.5% ## Security Constraints - E2E encryption required for sensitive data (NFR-5) - Backend cannot decrypt document payloads - Least-privilege access via OAuth scopes (NFR-6) - No PII in plaintext application logs ## TDD Development Workflow **CRITICAL**: This project follows a strict Test-Driven Development approach. ### The Red-Green-Refactor Cycle 1. **RED**: Write a failing test that defines desired behavior 2. **GREEN**: Write minimal code to make the test pass 3. **REFACTOR**: Improve code while keeping tests green ### Example TDD Workflow ```python # Step 1: Write failing test (tests/unit/domain/test_document_metadata.py) def test_document_metadata_validates_authority_id(): with pytest.raises(ValidationError): DocumentMetadata( authorityId="", # Empty should fail referenceNumber="123/456", docType="NOTICE", issuedAt=datetime.now() ) # Step 2: Run test (it fails) # $ pytest tests/unit/domain/test_document_metadata.py # Step 3: Implement validation (src/domain/models.py) class DocumentMetadata(BaseModel): authorityId: str = Field(..., min_length=1, max_length=50) # ... rest of fields # Step 4: Run test again (it passes) # Step 5: Refactor if needed, ensure tests still pass ``` ### Agentic TDD Pattern When asking Claude to implement features, use this pattern: ``` "Write a test for [feature] that verifies [specific behavior]. Use pytest and follow the pattern in tests/unit/[module]/. Reference ADR-[number] for architectural constraints." ``` Example: ``` "Write a test for document routing that verifies documents with docType='NOTICE' are routed to the NoticeTeam. Mock the routing adapter using the protocol defined in src/adapters/protocols.py. Follow ADR-0001 split-payload constraints." ``` See `docs/development/agentic-coding-guide.md` for comprehensive examples. ## Documentation References ### Architecture & Decisions - **Workplan**: `docs/WORKPLAN_MainCodebase_Integration.md` - Current migration plan - **ADRs**: `docs/architecture/adr/` - Individual decision records - `0001-split-payload-model.md` - Core constraint: metadata vs encrypted payload - `0002-stateless-authentication.md` - OAuth2/JWT architecture - `0003-cursor-based-pagination.md` - Performance-optimized pagination - `0004-async-export-workflow.md` - Background job pattern - `0005-rest-resource-structure.md` - API design hierarchy - `0006-gdpr-retention-model.md` - Data lifecycle management - `0007-hybrid-concurrency-pattern.md` - Python GIL mitigation - `0008-agentic-tdd-workflow.md` - LLM-driven development process - **Overview**: `docs/architecture/architecture-overview.md` - System design - **Patterns**: `docs/architecture/design-patterns.md` - Common patterns ### API Documentation - **OpenAPI**: `docs/api/openapi.yaml` - Full API specification - **Scenarios**: `docs/api/api-scenarios.md` - Real-world usage examples ### Development Guides - **Testing**: `docs/development/testing-strategy.md` - TDD practices - **Agentic Coding**: `docs/development/agentic-coding-guide.md` - AI-assisted development - **Setup**: `docs/development/setup-guide.md` - Environment setup ### Legacy (Prototypes) - `prototype-chatgpt5/README.md` - Reference implementation (ARCHIVED) - `docs/decisions.md` - Original ADRs (DEPRECATED, see /docs/architecture/adr/) ## Database Schema Key tables (PostgreSQL): - **documents**: id, reference_number, authority_id, status, storage_path, retention_date - **threads**: id, document_id, type, assigned_official_id, last_activity_at - **messages**: id, thread_id, sender_role, content_blob, created_at Indexes: - `idx_docs_authority` on documents(authority_id, status) - `idx_msgs_thread_time` on messages(thread_id, created_at DESC) ## Technology Stack - **Language**: Python 3.11+ - **Framework**: FastAPI + Uvicorn - **ORM**: SQLAlchemy (async) - **Database**: PostgreSQL 15+ - **Blob Storage**: S3-compatible (MinIO/AWS S3) - **Task Queue**: ARQ (Redis-based, async) or Celery - **Auth**: OAuth2/JWT (stateless) - **Testing**: pytest + pytest-asyncio + pytest-cov - **Linting**: ruff (fast, replaces flake8/isort/pyupgrade) - **Type Checking**: mypy (strict mode) - **CI/CD**: GitHub Actions ## Workplan & Phase Tracking **Active Workplan**: `docs/WORKPLAN_MainCodebase_Integration.md` ### Current Phase Status To check which phase we're in: 1. Open `docs/WORKPLAN_MainCodebase_Integration.md` 2. Look for checked `[x]` items in each phase section 3. Focus development on uncompleted `[ ]` items in the current phase ### How to Contribute **Before implementing any feature:** 1. Check if it's in the current phase of the workplan 2. Read the relevant ADR(s) in `docs/architecture/adr/` 3. Write tests first (TDD approach) 4. Implement to make tests pass 5. Ensure all quality gates pass (pytest, mypy, ruff) **When adding new architectural decisions:** 1. Create a new ADR file in `docs/architecture/adr/` 2. Use the template in `0000-template.md` 3. Number sequentially (next available number) 4. Update the ADR index in `docs/architecture/adr/README.md` ## Common Gotchas 1. **Stream large files**: Use `aiobotocore` to stream uploads to S3, don't load entire payloads into memory 2. **ProcessPoolExecutor**: CPU-heavy operations MUST be offloaded to avoid blocking the event loop 3. **Metadata separation**: The routing engine needs plaintext metadata - design API contracts accordingly 4. **Retention dates**: Always set `retention_date` on document creation for GDPR compliance 5. **Cursor pagination**: Use timestamp-based cursors for message history, not offset-based