Files
Ebbe BaßandClaude Sonnet 5.5 f8b0584687 feat: add Django project scaffold, configuration and container
Environment-variable configuration that fails fast, database-only health
check, JSON request logs with a request id, security headers with a strict
CSP, and a multi-stage non-root Docker image with compose file. Ticket 1.1.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sk72AxLwQnYttF6VFSxQLt
2026-10-15 13:44:07 +02:00

40 lines
1.3 KiB
Python

import pytest
@pytest.mark.django_db
def test_security_headers_present(client):
response = client.get("/healthz")
csp = response["Content-Security-Policy"]
assert "script-src 'self'" in csp
assert "default-src 'self'" in csp
assert "frame-ancestors 'none'" in csp
assert "unsafe-inline" not in csp
assert "http" not in csp
assert response["X-Content-Type-Options"] == "nosniff"
assert response["X-Frame-Options"] == "DENY"
assert response["Referrer-Policy"] == "same-origin"
assert response["X-Request-ID"]
def test_headers_also_on_error_responses(client):
response = client.get("/missing")
assert response.status_code == 404
assert "Content-Security-Policy" in response
assert response["X-Request-ID"]
def test_valid_incoming_request_id_is_kept(client):
response = client.get("/missing", headers={"X-Request-ID": "abc12345-req"})
assert response["X-Request-ID"] == "abc12345-req"
def test_invalid_incoming_request_id_is_replaced(client):
response = client.get("/missing", headers={"X-Request-ID": "bad id\twith junk"})
assert response["X-Request-ID"] != "bad id\twith junk"
def test_csp_on_bad_host_response(client):
response = client.get("/healthz", HTTP_HOST="unlisted.example")
assert response.status_code == 400
assert "script-src 'self'" in response["Content-Security-Policy"]