d720db07dd
Firmen-tauglicher Bericht aus den Snapshot-Modulergebnissen (kein Re-Crawl, kein LLM): Einleitung, Testumfang+Methodik, Management-Summary (4-Status), Detail- befunde je Modul, Maßnahmen, Rechtlicher Hinweis. Co-Pilot-Tonalität, Tracking- statt Cookie-Rohzahl, Norm nur referenziert (kein Normtext). - audit_report.py: assemble_report (pur) + render_markdown + render_pdf (reportlab) - snapshot_check_routes: GET /report (struktur+md) + GET /report.pdf - Frontend: AuditReportTab + Proxys (report, report/pdf) + "Bericht"-Tab - Tests: 5 Assembler (compliance/tests → CI-geprüft) + 1 Vitest Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
66 lines
2.8 KiB
Python
66 lines
2.8 KiB
Python
"""Audit-Report-Assembler (pur) — Sektionen, 4-Status-/Severity-Zählung,
|
|
Co-Pilot-Tonalität, kein Normtext."""
|
|
|
|
from compliance.services.audit_report import assemble_report, render_markdown
|
|
|
|
META = {"site_label": "BMW", "site_domain": "bmw.de",
|
|
"created_at": "2026-06-11T14:15:00", "check_id": "508983ec"}
|
|
MODULES = {
|
|
"cookie": {"findings": [
|
|
{"title": "Cookie als notwendig deklariert, real Marketing",
|
|
"severity": "HIGH", "legal_ref": "§ 25 TDDDG",
|
|
"measure": "Als einwilligungspflichtig (§ 25) einstufen."},
|
|
{"title": "Laufzeit überschreitet Empfehlung", "severity": "LOW"},
|
|
]},
|
|
"impressum": {"findings": [
|
|
{"title": "Vertretungsberechtigte fehlen", "severity": "MEDIUM",
|
|
"status": "APPLICABLE", "recommendation": "Vertretungsberechtigte ergänzen."},
|
|
], "status": "APPLICABLE", "confidence": 0.8},
|
|
"browser": {"cross_findings": [
|
|
{"title": "Tracking vor der Einwilligung — in allen Browsern",
|
|
"severity": "HIGH", "detail": "Chrome + Firefox setzen Tracker vor Consent",
|
|
"measure": "Tracking-Skripte erst nach aktiver Einwilligung laden."},
|
|
]},
|
|
}
|
|
|
|
|
|
def test_sections_present():
|
|
r = assemble_report(META, MODULES)
|
|
titles = [s["title"] for s in r["sections"]]
|
|
for t in ["Einleitung", "Testumfang & Methodik", "Management-Summary",
|
|
"Detailbefunde", "Empfohlene Maßnahmen", "Rechtlicher Hinweis"]:
|
|
assert t in titles, f"Sektion fehlt: {t}"
|
|
|
|
|
|
def test_severity_counts():
|
|
r = assemble_report(META, MODULES)
|
|
c = r["totals"]["by_severity"]
|
|
assert c["HIGH"] == 2 and c["MEDIUM"] == 1 and c["LOW"] == 1
|
|
assert r["totals"]["findings"] == 4
|
|
|
|
|
|
def test_markdown_has_header_findings_and_copilot_disclaimer():
|
|
md = render_markdown(assemble_report(META, MODULES))
|
|
assert "Compliance-Audit-Bericht — BMW" in md
|
|
assert "Tracking vor der Einwilligung" in md # Browser-Cross-Finding
|
|
assert "Vertretungsberechtigte ergänzen" in md # Maßnahme aus recommendation
|
|
assert "DSB" in md and "Anwalt" in md # Co-Pilot-Disclaimer
|
|
assert "Wahrscheinlichkeit" in md # keine Garantie
|
|
assert "BreakPilot" in md
|
|
|
|
|
|
def test_empty_modules_graceful():
|
|
r = assemble_report({"site_domain": "example.com"}, {})
|
|
assert r["totals"]["findings"] == 0
|
|
md = render_markdown(r)
|
|
assert "keine wesentlichen auffälligkeiten" in md.lower()
|
|
# Auch ohne Befunde: Disclaimer + Methodik vorhanden.
|
|
assert "Rechtlicher Hinweis" in md
|
|
|
|
|
|
def test_essential_cookie_framing_in_methodik():
|
|
# Tonalität/Recht: technisch notwendige Cookies ausgenommen (§ 25 Abs. 2).
|
|
md = render_markdown(assemble_report(META, MODULES))
|
|
assert "§ 25 Abs. 2" in md
|
|
assert "nicht-essentielle" in md.lower()
|