12 KiB
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:
- Citizens upload a document or provide an Aktenzeichen (reference number)
- The system auto-routes to the responsible unit
- 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
/srcwith TDD-driven development - Active Workplan: See
docs/WORKPLAN_MainCodebase_Integration.mdfor 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)
# 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)
# 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
# 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
encryptedPayloadin 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:
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:
- POST
/exports→ 202 Accepted + jobId - Background worker processes via message queue
- Client polls status endpoint or receives webhook
5. Stateless Authentication (ADR-002)
OAuth2/JWT with scopes:
citizen:write: Document submission, thread creationofficial:read: View assigned casesofficial: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:
nullor 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
- RED: Write a failing test that defines desired behavior
- GREEN: Write minimal code to make the test pass
- REFACTOR: Improve code while keeping tests green
Example TDD Workflow
# 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 records0001-split-payload-model.md- Core constraint: metadata vs encrypted payload0002-stateless-authentication.md- OAuth2/JWT architecture0003-cursor-based-pagination.md- Performance-optimized pagination0004-async-export-workflow.md- Background job pattern0005-rest-resource-structure.md- API design hierarchy0006-gdpr-retention-model.md- Data lifecycle management0007-hybrid-concurrency-pattern.md- Python GIL mitigation0008-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_authorityon documents(authority_id, status)idx_msgs_thread_timeon 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:
- Open
docs/WORKPLAN_MainCodebase_Integration.md - Look for checked
[x]items in each phase section - Focus development on uncompleted
[ ]items in the current phase
How to Contribute
Before implementing any feature:
- Check if it's in the current phase of the workplan
- Read the relevant ADR(s) in
docs/architecture/adr/ - Write tests first (TDD approach)
- Implement to make tests pass
- Ensure all quality gates pass (pytest, mypy, ruff)
When adding new architectural decisions:
- Create a new ADR file in
docs/architecture/adr/ - Use the template in
0000-template.md - Number sequentially (next available number)
- Update the ADR index in
docs/architecture/adr/README.md
Common Gotchas
- Stream large files: Use
aiobotocoreto stream uploads to S3, don't load entire payloads into memory - ProcessPoolExecutor: CPU-heavy operations MUST be offloaded to avoid blocking the event loop
- Metadata separation: The routing engine needs plaintext metadata - design API contracts accordingly
- Retention dates: Always set
retention_dateon document creation for GDPR compliance - Cursor pagination: Use timestamp-based cursors for message history, not offset-based