8e3d05f172
- tests/test_elli_gt_coverage.py: 7 Charakterisierungstests die
einen synthetischen Elli-State konstruieren und sicherstellen,
dass die 5 neuen Detektoren (B13-B16 + B9-Cleanup) genau die
erwarteten GT-IDs fangen. Regressionsschutz.
- zeroclaw/docs/audits/2026-06-06-elli-gt-coverage-sprint.md:
Sprint-Zusammenfassung mit GT-Bilanz (12/13 voll, 1/13 wartet
auf #7), Commit-Liste und Morgen-Agenda-Kandidaten.
Combined Sprint-Test-Run: 72/72 grün.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
211 lines
9.4 KiB
Python
211 lines
9.4 KiB
Python
"""GT-Coverage-Integration-Test gegen den Elli-Audit (2026-06-06).
|
|
|
|
Charakterisierungstest für die 5 GT-Lücken die in diesem Sprint
|
|
geschlossen wurden. Konstruiert einen synthetischen `state`-dict, der
|
|
Elli's reale Befunde widerspiegelt, und stellt sicher, dass jeder
|
|
der neuen B13-B16 + B9-Cleanup Detektoren genau die erwarteten
|
|
GT-IDs fängt.
|
|
|
|
Ground-Truth-Quelle: zeroclaw/docs/ground-truth/elli_eco_2026-06-06.json
|
|
"""
|
|
|
|
from compliance.services.ai_legal_basis_check import check_ai_legal_basis
|
|
from compliance.services.impressum_multi_entity_check import (
|
|
check_multi_entity_impressum,
|
|
)
|
|
from compliance.services.retention_conflict_check import (
|
|
check_retention_conflicts,
|
|
)
|
|
from compliance.services.url_slug_drift_check import check_url_slug_drift
|
|
from compliance.services.widerrufsbelehrung_reachability_check import (
|
|
check_widerrufsbelehrung_reachability,
|
|
)
|
|
|
|
|
|
# Elli-Fixture: minimaler State mit den Datenfeldern die jeder Check
|
|
# braucht. Texte sind verdichtet, enthalten aber jedes prüf-relevante
|
|
# Signal (Vertex AI / lit. f, Logfile-Widerspruch, B2C-Shop, etc.).
|
|
_ELLI_IMPRESSUM = """
|
|
Impressum
|
|
|
|
Volkswagen Group Charging GmbH
|
|
Karl-Liebknecht-Str. 32, 10178 Berlin
|
|
Amtsgericht Charlottenburg HRB 208967 B
|
|
Geschäftsführer: Giovanni Palazzo, Mark Möller
|
|
Telefon: 00800 3554 1111
|
|
|
|
Elli Mobility GmbH
|
|
Karl-Liebknecht-Str. 32, 10178 Berlin
|
|
Amtsgericht Charlottenburg HRB 274616 B
|
|
USt-IdNr.: DE814424009
|
|
Geschäftsführer: Joschi Jennermann, Sebastian Steffen
|
|
"""
|
|
|
|
_ELLI_DSE = """
|
|
Datenschutzerklärung der Elli Mobility GmbH.
|
|
|
|
Server-Logfiles: Bei jedem Zugriff werden Logfiles gespeichert.
|
|
Die Logfiles werden für 7 Tage gespeichert. Bei Sicherheitsvorfällen
|
|
werden Logfiles bis zu 30 Tage aufbewahrt.
|
|
|
|
AI Assistant: Für unseren Chatbot setzen wir Google Vertex AI ein.
|
|
Rechtsgrundlage ist Art. 6 Abs. 1 lit. f DSGVO (berechtigtes
|
|
Interesse). Speicherdauer 6 Monate.
|
|
|
|
Newsletter-Abonnement: Wir speichern Anmeldedaten 24 Monate ab
|
|
Abmeldung.
|
|
"""
|
|
|
|
_ELLI_HOMEPAGE = (
|
|
"Elli — Charging Solutions. In den Warenkorb. Lieferzeit 2 Tage. "
|
|
"Preis inkl. MwSt. Wallbox. Naturstrom. Ladetarif buchen."
|
|
)
|
|
|
|
|
|
def _build_elli_state(widerruf_reachable: bool = False) -> dict:
|
|
doc_entries = [
|
|
{"doc_type": "impressum",
|
|
"url": "https://www.elli.eco/de/impressum",
|
|
"text": _ELLI_IMPRESSUM,
|
|
"auto_discovered": True,
|
|
"discovery_attempted": True},
|
|
{"doc_type": "dse",
|
|
"url": "https://www.elli.eco/de/datenschutz",
|
|
"text": _ELLI_DSE,
|
|
"auto_discovered": True,
|
|
"discovery_attempted": True},
|
|
{"doc_type": "cookie",
|
|
"url": "https://www.elli.eco/de/cookies",
|
|
"text": "x" * 600,
|
|
"auto_discovered": True,
|
|
"discovery_attempted": True},
|
|
{"doc_type": "widerruf",
|
|
"url": "https://www.elli.eco/de/widerruf" if widerruf_reachable
|
|
else "",
|
|
"text": ("x" * 600) if widerruf_reachable else "",
|
|
"auto_discovered": widerruf_reachable,
|
|
"discovery_attempted": True},
|
|
]
|
|
return {
|
|
"doc_entries": doc_entries,
|
|
"doc_texts": {
|
|
"impressum": _ELLI_IMPRESSUM,
|
|
"dse": _ELLI_DSE,
|
|
},
|
|
"home_text": _ELLI_HOMEPAGE,
|
|
}
|
|
|
|
|
|
# ────────────────────────────────────────────────────────────────────────
|
|
# B9 cleanup — IMPRESSUM-001
|
|
# ────────────────────────────────────────────────────────────────────────
|
|
|
|
class TestImpressum001Coverage:
|
|
def test_per_entity_ust_id_detected(self):
|
|
state = _build_elli_state()
|
|
findings = check_multi_entity_impressum(state)
|
|
ust = [f for f in findings
|
|
if f["check_id"] == "IMPRESSUM-MULTI-UST_ID"]
|
|
assert len(ust) == 1
|
|
assert ust[0]["entities_missing"] == [
|
|
"Volkswagen Group Charging GmbH",
|
|
]
|
|
assert ust[0]["entities_present"] == ["Elli Mobility GmbH"]
|
|
|
|
|
|
# ────────────────────────────────────────────────────────────────────────
|
|
# B13 — WIDERRUFSBELEHRUNG-001
|
|
# ────────────────────────────────────────────────────────────────────────
|
|
|
|
class TestWiderrufsbelehrung001Coverage:
|
|
def test_b2c_strong_high_finding(self):
|
|
state = _build_elli_state(widerruf_reachable=False)
|
|
findings = check_widerrufsbelehrung_reachability(state)
|
|
assert len(findings) == 1
|
|
assert findings[0]["check_id"] == "WIDERRUF-REACH-001"
|
|
assert findings[0]["severity"] == "HIGH"
|
|
assert findings[0]["b2c_scope"] == "b2c_strong"
|
|
|
|
def test_widerruf_reachable_suppresses_finding(self):
|
|
state = _build_elli_state(widerruf_reachable=True)
|
|
assert check_widerrufsbelehrung_reachability(state) == []
|
|
|
|
|
|
# ────────────────────────────────────────────────────────────────────────
|
|
# B14 — TH-RETENTION-001
|
|
# ────────────────────────────────────────────────────────────────────────
|
|
|
|
class TestTHRetention001Coverage:
|
|
def test_logfile_7_vs_30_finding(self):
|
|
state = _build_elli_state()
|
|
findings = check_retention_conflicts(state)
|
|
log = [f for f in findings if f["category"] == "logfile"]
|
|
assert len(log) == 1
|
|
assert 7.0 in log[0]["values_days"]
|
|
assert 30.0 in log[0]["values_days"]
|
|
|
|
|
|
# ────────────────────────────────────────────────────────────────────────
|
|
# B15 — AI-ACT-RISK-001
|
|
# ────────────────────────────────────────────────────────────────────────
|
|
|
|
class TestAIActRisk001Coverage:
|
|
def test_vertex_ai_lit_f_finding(self):
|
|
state = _build_elli_state()
|
|
findings = check_ai_legal_basis(state)
|
|
assert len(findings) == 1
|
|
assert findings[0]["check_id"] == "AI-LEGAL-BASIS-001"
|
|
assert "Vertex" in findings[0]["provider"]
|
|
|
|
|
|
# ────────────────────────────────────────────────────────────────────────
|
|
# B16 — URL-STRUCTURE-001
|
|
# ────────────────────────────────────────────────────────────────────────
|
|
|
|
class TestURLStructure001Coverage:
|
|
def test_cookie_richtlinie_404_emits_finding(self):
|
|
# Mock _head_status: alle Standard-Slugs ausser dem discovered
|
|
# liefern 404 — Elli's reale Lage.
|
|
from unittest.mock import patch
|
|
state = _build_elli_state()
|
|
with patch(
|
|
"compliance.services.url_slug_drift_check._head_status",
|
|
return_value=404,
|
|
):
|
|
findings = check_url_slug_drift(state)
|
|
cookie_findings = [f for f in findings if f["doc_type"] == "cookie"]
|
|
assert len(cookie_findings) == 1
|
|
assert cookie_findings[0]["severity"] == "LOW"
|
|
assert "cookie-richtlinie" in cookie_findings[0]["alt_slugs_404"]
|
|
|
|
|
|
# ────────────────────────────────────────────────────────────────────────
|
|
# All-Detector-Smoke — sicherstellen, dass die 5 Checks zusammen
|
|
# gegen Elli mindestens 5 unterschiedliche Finding-IDs ergeben.
|
|
# ────────────────────────────────────────────────────────────────────────
|
|
|
|
class TestElliFullCoverage:
|
|
def test_all_five_detectors_fire(self):
|
|
from unittest.mock import patch
|
|
state = _build_elli_state(widerruf_reachable=False)
|
|
all_findings: list[dict] = []
|
|
all_findings.extend(check_multi_entity_impressum(state))
|
|
all_findings.extend(check_widerrufsbelehrung_reachability(state))
|
|
all_findings.extend(check_retention_conflicts(state))
|
|
all_findings.extend(check_ai_legal_basis(state))
|
|
with patch(
|
|
"compliance.services.url_slug_drift_check._head_status",
|
|
return_value=404,
|
|
):
|
|
all_findings.extend(check_url_slug_drift(state))
|
|
check_ids = {f["check_id"] for f in all_findings}
|
|
expected = {
|
|
"IMPRESSUM-MULTI-UST_ID",
|
|
"WIDERRUF-REACH-001",
|
|
"RETENTION-CONFLICT-001",
|
|
"AI-LEGAL-BASIS-001",
|
|
"URL-SLUG-DRIFT-001",
|
|
}
|
|
missing = expected - check_ids
|
|
assert not missing, f"GT-Lücken nicht gefangen: {missing}"
|