"""Statische Schutztests für den Docker-Compose-Deploymentvertrag.""" from pathlib import Path import yaml ROOT = Path(__file__).resolve().parents[1] def load_compose() -> dict: return yaml.safe_load((ROOT / "compose.yaml").read_text(encoding="utf-8")) def test_compose_uses_external_ollama_network_and_tailscale_bind(): compose = load_compose() service = compose["services"]["pv-agent"] assert service["networks"] == ["ollama"] assert compose["networks"]["ollama"] == { "external": True, "name": "ollama_default", } assert "100.103.83.12:${PV_PORT:-8080}:8080" in service["ports"] assert service["environment"]["OLLAMA_URL"] == ( "${OLLAMA_URL:-http://ollama:11434}" ) def test_compose_requires_auth_and_limits_container_privileges(): service = load_compose()["services"]["pv-agent"] assert ":?" in service["environment"]["PV_API_KEY"] assert "env_file" not in service assert service["read_only"] is True assert service["security_opt"] == ["no-new-privileges:true"] assert service["cap_drop"] == ["ALL"] assert "./data:/app/data" in service["volumes"] assert "./wissensbasis:/app/wissensbasis:ro" in service["volumes"] assert service["environment"]["PV_AUDIT_ENABLED"] == "${PV_AUDIT_ENABLED:-true}" assert service["environment"]["PV_AUDIT_DB_PATH"] == "/app/data/audit.db" assert service["logging"]["options"] == {"max-size": "50m", "max-file": "5"} def test_docker_context_excludes_secrets_and_runtime_data(): ignored = set( (ROOT / ".dockerignore").read_text(encoding="utf-8").splitlines() ) assert {".env", "data", ".lexis360", ".rechtsprechung", "wissensbasis"} <= ignored dockerfile = (ROOT / "Dockerfile").read_text(encoding="utf-8") assert "requirements-runtime.txt" in dockerfile assert "COPY agent/" in dockerfile assert "COPY web/" in dockerfile assert "python -m agent.bootstrap" in dockerfile assert "COPY ." not in dockerfile