debate/.planning/phases/01-core-infrastructure-security/01-03-PLAN.md
Mikkel Georgsen 262a32673b docs(01): create phase plan
Phase 01: Core Infrastructure & Security
- 5 plans in 3 waves
- 3 parallel (Wave 1-2), 1 sequential (Wave 3)
- Ready for execution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 19:59:49 +00:00

189 lines
6.2 KiB
Markdown

---
phase: 01-core-infrastructure-security
plan: 03
type: execute
wave: 2
depends_on: ["01-01", "01-02"]
files_modified:
- backend/app/main.py
- backend/app/core/security.py
- backend/app/api/deps.py
- backend/app/api/v1/endpoints/health.py
autonomous: true
must_haves:
truths:
- "Rate limiting blocks requests exceeding 100/minute"
- "CSRF tokens are validated on state-changing requests"
- "Database connectivity checked in health endpoint"
- "Security headers present in responses"
artifacts:
- path: "backend/app/core/security.py"
provides: "Rate limiting and CSRF configuration"
contains: "Limiter"
- path: "backend/app/api/deps.py"
provides: "FastAPI dependency injection"
contains: "get_db"
- path: "backend/app/main.py"
provides: "Security middleware stack"
contains: "TrustedHostMiddleware"
key_links:
- from: "backend/app/main.py"
to: "backend/app/core/security.py"
via: "limiter import"
pattern: "from app\\.core\\.security import"
- from: "backend/app/api/v1/endpoints/health.py"
to: "backend/app/api/deps.py"
via: "Depends(get_db)"
pattern: "Depends\\(get_db\\)"
---
<objective>
Implement security middleware stack with rate limiting, CSRF protection, and security headers.
Purpose: Protect the API from abuse and common web vulnerabilities (INFR-06, INFR-07).
Output: FastAPI application with layered security: rate limiting (100/min), CSRF protection, trusted hosts, CORS, and security headers.
</objective>
<execution_context>
@/home/mikkel/.claude/get-shit-done/workflows/execute-plan.md
@/home/mikkel/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/phases/01-core-infrastructure-security/01-RESEARCH.md (Pattern 3: FastAPI Security Middleware Stack)
@.planning/phases/01-core-infrastructure-security/01-01-SUMMARY.md
@.planning/phases/01-core-infrastructure-security/01-02-SUMMARY.md
</context>
<tasks>
<task type="auto">
<name>Task 1: Configure rate limiting and CSRF protection</name>
<files>
backend/app/core/security.py
backend/app/api/deps.py
</files>
<action>
Create backend/app/core/security.py:
- Import and configure slowapi Limiter:
- key_func=get_remote_address
- default_limits=["100/minute"]
- storage_uri from settings (default to memory, Redis for production)
- Configure fastapi-csrf-protect CsrfProtect:
- Create CsrfSettings Pydantic model with:
- secret_key from settings
- cookie_samesite = "lax"
- cookie_secure = True (HTTPS only)
- cookie_httponly = True
- Implement @CsrfProtect.load_config decorator
Create backend/app/api/deps.py:
- Import get_db from app.db.session
- Re-export for cleaner imports in endpoints
- Create optional dependency for CSRF validation:
```python
async def validate_csrf(csrf_protect: CsrfProtect = Depends()):
await csrf_protect.validate_csrf_in_cookies()
```
</action>
<verify>
Run: `cd /home/mikkel/repos/debate && ruff check backend/app/core/security.py backend/app/api/deps.py`
Expected: No errors.
</verify>
<done>
Rate limiter configured at 100/minute, CSRF protection configured with secure cookie settings.
</done>
</task>
<task type="auto">
<name>Task 2: Apply security middleware to FastAPI app and update health endpoint</name>
<files>
backend/app/main.py
backend/app/api/v1/endpoints/health.py
</files>
<action>
Update backend/app/main.py with middleware stack (order matters - first added = outermost):
1. TrustedHostMiddleware:
- allowed_hosts from settings.allowed_hosts
- Block requests with invalid Host header
2. CORSMiddleware:
- allow_origins from settings.allowed_origins
- allow_credentials=True
- allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"]
- allow_headers=["*"]
- max_age=600 (cache preflight for 10 min)
3. Rate limiting:
- app.state.limiter = limiter
- Add RateLimitExceeded exception handler
4. Custom middleware for security headers:
- Strict-Transport-Security: max-age=31536000; includeSubDomains
- X-Content-Type-Options: nosniff
- X-Frame-Options: DENY
- X-XSS-Protection: 1; mode=block
- Referrer-Policy: strict-origin-when-cross-origin
Update backend/app/api/v1/endpoints/health.py:
- Keep GET /health as simple {"status": "healthy"}
- Add GET /health/db that checks database connectivity:
- Depends on get_db session
- Execute "SELECT 1" query
- Return {"status": "healthy", "database": "connected"} on success
- Return {"status": "unhealthy", "database": "error", "detail": str(e)} on failure
- Add @limiter.exempt decorator to health endpoints (don't rate limit health checks)
</action>
<verify>
Start the server and test:
```bash
cd /home/mikkel/repos/debate
source .venv/bin/activate
uvicorn backend.app.main:app --host 0.0.0.0 --port 8000 &
sleep 2
# Test health endpoint
curl -s http://localhost:8000/health
# Test database health
curl -s http://localhost:8000/api/v1/health/db
# Test security headers
curl -sI http://localhost:8000/health | grep -E "(X-Content-Type|X-Frame|Strict-Transport)"
# Test rate limiting (make 110 requests)
for i in {1..110}; do curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8000/health; done | sort | uniq -c
```
Expected: First 100+ requests return 200, some return 429 (rate limited).
Kill the server after testing.
</verify>
<done>
Security middleware applied, health endpoints check database, rate limiting blocks excess requests.
</done>
</task>
</tasks>
<verification>
1. `curl -sI http://localhost:8000/health` includes security headers (X-Content-Type-Options, X-Frame-Options)
2. `curl http://localhost:8000/api/v1/health/db` returns database status
3. Rapid requests (>100/min) return 429 Too Many Requests
4. Invalid Host header returns 400 Bad Request
5. `ruff check backend/` passes
</verification>
<success_criteria>
- Rate limiting enforced at 100 requests/minute per IP (INFR-06)
- CSRF protection configured (INFR-07)
- Security headers present in all responses
- Health endpoints verify database connectivity
- All middleware applied in correct order
</success_criteria>
<output>
After completion, create `.planning/phases/01-core-infrastructure-security/01-03-SUMMARY.md`
</output>