feat(audit-mail): P58/P59c/P60b/P61/P62 — Mercedes-Cycle Phase 1 abgeschlossen
CI / nodejs-build (push) Has been skipped
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 38s
CI / test-python-document-crawler (push) Has been skipped
CI / detect-changes (push) Successful in 12s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / validate-canonical-controls (push) Successful in 14s
CI / loc-budget (push) Failing after 15s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
CI / nodejs-build (push) Has been skipped
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 38s
CI / test-python-document-crawler (push) Has been skipped
CI / detect-changes (push) Successful in 12s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / validate-canonical-controls (push) Successful in 14s
CI / loc-budget (push) Failing after 15s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
P58 Anti-Audit-Detection robuster (script-domain + settings-spezifisch —
war bereits im Code, jetzt sauber als completed dokumentiert).
P59c DACH-Custom-Cookies in compliance.cookie_library: Borlabs,
etracker, Matomo/Piwik, Userlike, Cookiebot/Cookieyes/Usercentrics,
Akamai/Cloudflare/Datadome Bot-Manager + HubSpot. 21 neue Eintraege
(3 von 24 schon via Open-Cookie-Database vorhanden).
Script: backend-compliance/scripts/seed_dach_cookies.py.
P60b Vendor-Pattern-Dedupe mit Fuzzy-Match (Jaccard >= 0.7) statt exakter
Tuple-Equality. Vendors mit teilweise befuellten Feldern (z.B.
Sitzland eingetragen) fallen nicht mehr aus der globalen Notice —
Bug: Amazon/Psyma/Qualtrics hatten zuvor wiederholte per-row Actions.
P61 "Untergeschobene Cookies"-Erkennung — wenn ein deklarierter Vendor
(z.B. Google Tag Manager) automatisch weitere mitbringt (GA + GCL_AU
+ DoubleClick), werden diese als separater Mail-Block (gelb) mit
COOKIE/VENDOR-Badges + Quellen-Doku ausgewiesen. Neuer Service:
compliance.services.vendor_package_cookies (8 Primary-Vendors mit
je 2-4 implicit Cookies/Vendors).
P62 Marketing-Manager-Disclaimer "Was wir sehen / nicht sehen" als
blauer Box-Block direkt unter dem Critical-Findings-Block. Erklaert
Grenzen unseres Audits (Server-Side-Tracking, Vendor-interne
Datenweitergabe, Cross-Page-Banner) und Risiko des Falschvertrauens
in einen 100%-Score. Neuer Renderer: compliance.api.scope_disclaimer.
Architektur: VVT-Tabellen-Renderer aus agent_doc_check_extras.py (552
LOC -> 242 LOC) in compliance.api.vvt_table_renderer ausgelagert, um den
500-LOC-Hardcap einzuhalten.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -231,5 +231,55 @@ def build_banner_deep_html(banner_result: dict | None) -> str:
|
||||
)
|
||||
parts.append('</ul></div>')
|
||||
|
||||
# 6) P61: Untergeschobene Cookies/Vendors (Vendor-Package)
|
||||
impl_findings = banner_result.get("implicit_vendor_findings") or []
|
||||
if impl_findings:
|
||||
# Gruppiert nach primary_vendor: pro Primary die mitgelaufenen Items
|
||||
by_primary: dict[str, list[dict]] = {}
|
||||
for f in impl_findings:
|
||||
by_primary.setdefault(f["primary_vendor"], []).append(f["implicit"])
|
||||
parts.append(
|
||||
'<div style="margin:14px 0 4px;padding:8px 12px;'
|
||||
'background:#fef3c7;border-left:3px solid #d97706;border-radius:4px">'
|
||||
'<div style="font-size:12px;color:#92400e;font-weight:600;'
|
||||
'margin-bottom:6px">Untergeschobene Cookies / Vendors '
|
||||
'(P61 — mit Hauptanbieter automatisch mitgeladen)</div>'
|
||||
'<div style="font-size:10px;color:#92400e;margin-bottom:8px">'
|
||||
'Diese Cookies/Vendors kommen automatisch mit dem deklarierten '
|
||||
'Hauptanbieter mit — Marketing-Manager waehlen sie oft nicht '
|
||||
'bewusst aus, sie sind aber zustimmungspflichtig.</div>'
|
||||
)
|
||||
for primary, impls in by_primary.items():
|
||||
parts.append(
|
||||
f'<div style="font-size:11px;color:#1e293b;margin:6px 0">'
|
||||
f'<strong>{primary}</strong> bringt automatisch:</div>'
|
||||
'<ul style="margin:0 0 8px 18px;padding:0;font-size:11px;color:#1e293b">'
|
||||
)
|
||||
for impl in impls:
|
||||
tag = ('<span style="font-size:9px;background:#dc2626;color:#fff;'
|
||||
'padding:1px 5px;border-radius:3px;margin-right:6px">'
|
||||
'COOKIE</span>' if impl["type"] == "cookie" else
|
||||
'<span style="font-size:9px;background:#7c3aed;color:#fff;'
|
||||
'padding:1px 5px;border-radius:3px;margin-right:6px">'
|
||||
'VENDOR</span>')
|
||||
cat_color = {"marketing": "#dc2626", "statistics": "#d97706",
|
||||
"functional": "#0891b2", "essential": "#16a34a"}.get(
|
||||
impl.get("category", ""), "#475569")
|
||||
parts.append(
|
||||
f'<li style="margin-bottom:5px">{tag}'
|
||||
f'<code style="font-size:10px;background:#f1f5f9;'
|
||||
f'padding:1px 4px;border-radius:2px">{impl["name"]}</code> '
|
||||
f'<span style="font-size:9px;color:{cat_color};'
|
||||
f'margin-left:4px">[{impl.get("category","?")}]</span>'
|
||||
f'<div style="font-size:10px;color:#475569;margin-top:2px">'
|
||||
f'{impl.get("why","")[:240]}</div>'
|
||||
f'<div style="font-size:9px;color:#94a3b8;font-style:italic">'
|
||||
f'Quelle: <a href="{impl.get("source_url","")}" '
|
||||
f'style="color:#94a3b8">{impl.get("source_url","")[:80]}</a>'
|
||||
f'</div></li>'
|
||||
)
|
||||
parts.append('</ul>')
|
||||
parts.append('</div>')
|
||||
|
||||
parts.append('</div>')
|
||||
return "".join(parts)
|
||||
|
||||
Reference in New Issue
Block a user