feat(cookie): A — Findings auditfest an Controls verdrahten
Jeder Cookie-Befund traegt jetzt ein strukturiertes control-Feld (control_id aus doc_check_controls + regulation + article) statt nur hardcodeter Strings: vague_duration->AUTH-2051-A03 (Art.5(1)e+13), tracker_as_necessary->DATA-2851-A05 (§25 TDDDG), third_country-> DATA-1624-A04 (Art.44). Kette Regulation->Article->Control->Finding. Frontend zeigt die Rechtsgrundlage je Befund. (Controls tragen regulation/article noch NULL -> hier mitgeliefert bis gepflegt.) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ export interface CookieFinding {
|
||||
declared: string
|
||||
library_purpose: string
|
||||
remediation: string
|
||||
control?: { control_id?: string | null; regulation?: string; article?: string }
|
||||
}
|
||||
|
||||
interface CheckData {
|
||||
@@ -71,6 +72,12 @@ export function CookieFindingList({ data }: { data: CheckData }) {
|
||||
<div className="text-xs text-gray-500">Library-Zweck: {f.library_purpose}</div>
|
||||
)}
|
||||
<div className="text-xs text-gray-700">{f.remediation}</div>
|
||||
{f.control?.regulation && f.control.regulation !== '—' && (
|
||||
<div className="text-[10px] text-gray-400">
|
||||
Rechtsgrundlage: {f.control.regulation} {f.control.article}
|
||||
{f.control.control_id && ` · Control ${f.control.control_id}`}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -22,6 +22,19 @@ from compliance.services.cookie_knowledge_db import lookup_cookie
|
||||
|
||||
_TRACKER_CATS = {"marketing", "statistics", "social_media", "targeting"}
|
||||
|
||||
# A — auditfeste Verdrahtung: jeder Befund-Typ → echter Control (control_id aus
|
||||
# doc_check_controls) + legal_basis. Die Controls tragen regulation/article noch
|
||||
# NULL, daher liefern wir die Rechtsgrundlage hier strukturiert mit (bis sie in
|
||||
# den Controls gepflegt ist). Kette: Regulation → Article → Control → Finding.
|
||||
_CONTROL_MAP = {
|
||||
"vague_duration": {"control_id": "AUTH-2051-A03", "regulation": "DSGVO", "article": "Art. 5 Abs. 1 lit. e + Art. 13"},
|
||||
"excessive_lifetime": {"control_id": "AUTH-2051-A02", "regulation": "DSGVO", "article": "Art. 5 Abs. 1 lit. e"},
|
||||
"tracker_as_necessary": {"control_id": "DATA-2851-A05", "regulation": "TDDDG", "article": "§ 25 Abs. 1"},
|
||||
"missing_purpose": {"control_id": "AUTH-2053-A05", "regulation": "DSGVO", "article": "Art. 13"},
|
||||
"third_country": {"control_id": "DATA-1624-A04", "regulation": "DSGVO", "article": "Art. 44 ff."},
|
||||
"eu_alternative": {"control_id": None, "regulation": "—", "article": "kommerzielle Empfehlung"},
|
||||
}
|
||||
|
||||
|
||||
def load_big_library(db, names: list[str]) -> dict:
|
||||
"""Batch-Lookup der grossen Open-Cookie-Database (compliance.cookie_library,
|
||||
@@ -219,6 +232,9 @@ def analyze_cookies(vendors: list[dict], big_lib: dict | None = None) -> dict:
|
||||
),
|
||||
})
|
||||
|
||||
# A: jeden Befund an seinen Control + Rechtsgrundlage haengen (auditfest).
|
||||
for f in findings:
|
||||
f["control"] = _CONTROL_MAP.get(f["type"], {})
|
||||
findings.sort(key=lambda f: _SEV_ORDER.get(f["severity"], 3))
|
||||
return {
|
||||
"summary": {
|
||||
|
||||
@@ -79,6 +79,21 @@ def test_excessive_lifetime():
|
||||
assert el and "Art. 5" in el[0]["remediation"]
|
||||
|
||||
|
||||
def test_findings_carry_control_and_legal_basis():
|
||||
# A: jeder Befund traegt control_id + Rechtsgrundlage (auditfest).
|
||||
out = analyze_cookies([{
|
||||
"name": "Google", "category": "necessary",
|
||||
"cookies": [{"name": "_ga", "purpose": "x",
|
||||
"expiry": "Wird solange gespeichert, bis es deaktiviert wird."}],
|
||||
}])
|
||||
assert out["findings"], "es sollte Befunde geben"
|
||||
for f in out["findings"]:
|
||||
assert "control" in f
|
||||
vd = next(f for f in out["findings"] if f["type"] == "vague_duration")
|
||||
assert vd["control"]["control_id"] == "AUTH-2051-A03"
|
||||
assert "Art. 5" in vd["control"]["article"]
|
||||
|
||||
|
||||
def test_vague_duration_flagged_concrete_ok():
|
||||
# User-Beispiel Salesforce: "bis der Nutzer es deaktiviert" = vage.
|
||||
out = analyze_cookies([{
|
||||
|
||||
Reference in New Issue
Block a user