claude.md

This commit is contained in:
2026-02-01 19:40:55 +01:00
parent 0ff43b1a9c
commit ce24e0caa0

228
CLAUDE.md Normal file
View File

@@ -0,0 +1,228 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Architecture Overview
**Container-per-session architecture** for Norwegian legal research chat interface:
- **session-manager**: FastAPI service managing OpenCode container lifecycles (one per user session)
- **OpenCode containers**: Isolated chat environments with MCP integration
- **Lovdata MCP server**: External Norwegian legal research server (15+ tools for law search, provisions, cross-references)
- **Caddy**: Reverse proxy with dynamic session-based routing
### Session Manager Components
The session-manager is built with a layered architecture:
```
main.py → FastAPI endpoints, session lifecycle orchestration
docker_service.py → Docker abstraction layer (testable, mockable)
async_docker_client.py → Async Docker operations
database.py → PostgreSQL session persistence with asyncpg
session_auth.py → Token-based session authentication
container_health.py → Health monitoring and auto-recovery
resource_manager.py → CPU/memory limits, throttling
http_pool.py → Connection pooling for container HTTP requests
host_ip_detector.py → Docker host IP detection (host.docker.internal fallback)
logging_config.py → Structured JSON logging with context
```
**Key design patterns:**
- **Dependency injection**: SessionManager receives DockerService via constructor (enables testing with MockDockerService)
- **Service abstraction**: Clean separation between business logic (main.py) and infrastructure (docker_service.py)
- **Async-first**: All I/O operations use asyncio (Docker, HTTP, database)
- **Database persistence**: Sessions survive manager restarts via PostgreSQL
### MCP Integration
OpenCode containers connect to two MCP servers:
1. **lovdata MCP server**: Norwegian legal tools (configured via `MCP_SERVER` env var)
2. **sequential-thinking**: Local MCP for reasoning (optional)
Configuration: `config_opencode/opencode.jsonc`
Skills: `config_opencode/skills/norwegian-legal-queries/`
## Development Commands
### Running the stack
```bash
# Start all services (session-manager, docker-daemon, caddy)
docker-compose up --build
# Start in background
docker-compose up -d --build
# View logs
docker-compose logs -f session-manager
# Stop services
docker-compose down
```
### Session management (API)
```bash
# Create session
curl http://localhost/api/sessions -X POST
# List sessions
curl http://localhost/api/sessions
# Get session info
curl http://localhost/api/sessions/{session_id}
# Delete session
curl http://localhost/api/sessions/{session_id} -X DELETE
# Manual cleanup
curl http://localhost/api/cleanup -X POST
# Health check
curl http://localhost/api/health
```
### Running session-manager locally (without Docker)
```bash
cd session-manager
# Install dependencies
pip install -r requirements.txt
# Run directly (requires Docker socket or TLS connection)
uvicorn main:app --reload --host 0.0.0.0 --port 8000
```
### Testing
Test scripts in `docker/scripts/`:
```bash
# Test Docker service abstraction
python docker/scripts/test-docker-service.py
# Test async Docker operations
python docker/scripts/test-async-docker.py
# Test resource limits
python docker/scripts/test-resource-limits.py
# Test session authentication
python docker/scripts/test-session-auth.py
# Test database persistence
python docker/scripts/test-database-persistence.py
# Test container health monitoring
python docker/scripts/test-container-health.py
# Test HTTP connection pooling
python docker/scripts/test-http-connection-pool.py
# Test host IP detection
python docker/scripts/test-host-ip-detection.py
# Test structured logging
python docker/scripts/test-structured-logging.py
```
All test scripts are self-contained and can run independently.
### Building the OpenCode image
```bash
# Build with custom MCP server
make build MCP_SERVER=http://your-lovdata-server:8001
# Run container interactively
make run
# Clean up image
make clean
```
## Environment Configuration
Required environment variables (see `.env.example`):
```bash
MCP_SERVER=http://localhost:8001 # External Lovdata MCP server URL
# Docker TLS (if using TLS instead of socket)
DOCKER_TLS_VERIFY=1
DOCKER_CERT_PATH=/etc/docker/certs
DOCKER_HOST=tcp://host.docker.internal:2376
# Optional LLM keys (at least one required for chat functionality)
OPENAI_API_KEY=...
ANTHROPIC_API_KEY=...
GOOGLE_API_KEY=...
```
## Security
**Current setup uses Docker socket mounting** (`/var/run/docker.sock`) which grants root access. TLS-based Docker API access is implemented but not enabled by default.
To enable TLS (recommended for production):
```bash
# Generate certificates
cd docker
DOCKER_ENV=production ./scripts/generate-certs.sh
# Configure Docker daemon
./scripts/setup-docker-tls.sh
# Update docker-compose.yml to use TLS instead of socket
```
**Session isolation:**
- Each session gets dedicated container
- Resource limits: 4GB RAM, 1 CPU core per container
- Max 3 concurrent sessions (configurable in resource_manager.py)
- Auto-cleanup after 60 minutes inactivity
## Session Data Persistence
Sessions are stored in PostgreSQL with the following schema:
- Session ID, container ID, status, timestamps
- Survives session-manager restarts
- Health monitoring tracks container state
Session working directories: `./sessions/` (bind-mounted into containers)
## Container Health Monitoring
Automatic health checks run every 30 seconds:
- Restart unhealthy containers (max 3 attempts)
- Mark failed sessions for cleanup
- Track health history for debugging
## Implementation Documentation
Detailed implementation guides in `docker/`:
- `ASYNC_DOCKER_IMPLEMENTATION.md` - Async Docker client
- `CONTAINER_HEALTH_MONITORING_IMPLEMENTATION.md` - Health checks
- `DATABASE_PERSISTENCE_IMPLEMENTATION.md` - Session database
- `HOST_IP_IMPLEMENTATION.md` - Host IP detection
- `HTTP_CONNECTION_POOLING_IMPLEMENTATION.md` - HTTP pooling
- `RESOURCE_LIMITS_IMPLEMENTATION.md` - Resource management
- `SESSION_AUTHENTICATION_IMPLEMENTATION.md` - Auth tokens
- `STRUCTURED_LOGGING_IMPLEMENTATION.md` - JSON logging
## Common Pitfalls
1. **MCP_SERVER must point to external server**: The lovdata-ai MCP server is NOT part of this stack, configure URL in `.env`
2. **Docker socket permissions**: Session-manager needs access to Docker socket or TLS certificates
3. **Port conflicts**: Session-manager uses ports 8000, Caddy uses 80/443, docker-daemon uses 2376
4. **Container cleanup**: Failed containers may linger, use `/api/cleanup` to force cleanup
5. **Resource exhaustion**: Default limit is 3 concurrent sessions, increase in resource_manager.py if needed
6. **Database connection**: PostgreSQL connection configured in database.py, defaults to localhost:5432