"""B19 wiring — Cookie-Coherence-Check (Salesforce-as-essential).""" from __future__ import annotations import html import logging from collections import Counter from compliance.services.cookie_coherence_check import check_cookie_coherence logger = logging.getLogger(__name__) def run_b19(state: dict) -> None: # Step 3 — Auto-Learning: alle deklarierten Cookies dieser Site # in cookie_behavior_audits loggen (Cross-Site-Konsens-Basis). try: from compliance.services.cookie_observation_logger import ( log_observations, ) stats = log_observations(state) logger.info("B19 observation-logger: %s", stats) except Exception as e: logger.warning("observation-logger skipped: %s", e) new = check_cookie_coherence(state) if not new: return extras = state.get("extra_findings") or [] extras.extend(new) state["extra_findings"] = extras state["cookie_coherence_html"] = _render(new) state["cookie_coherence_findings"] = new logger.info("B19 cookie-coherence: %d finding(s)", len(new)) def _render(findings: list[dict]) -> str: # Aggregate per type for the summary chip by_type = Counter(f.get("check_id") for f in findings) severity_color = { "HIGH": "#dc2626", "MEDIUM": "#f59e0b", "LOW": "#64748b", } # Show only the top 12 cards in the mail; rest goes to CSV cards = [] for f in findings[:12]: sev = (f.get("severity") or "").upper() color = severity_color.get(sev, "#475569") meta = "" if f.get("cookie_name"): meta += ( "
{html.escape(f['cookie_name'])}"
f" · Vendor: {html.escape(f.get('vendor') or '?')}"
"{html.escape(f['declared_category'])}"
+ (f" · actual (KB): {html.escape(f['actual_category'])}"
if f.get("actual_category") else "")
+ ""
f"Vergleich Site-Deklaration vs Open Cookie Database (2287) + "
f"BreakPilot-KB.
Verteilung: {type_summary}
"
f"… und {len(findings)-12} weitere — vollständige Liste "
f"in cookies-full.csv im ZIP-Anhang.