# Plan: Control Relevance Filter — Generische Controls kontextsensitiv filtern

## Problem

Die UCCA-Engine empfiehlt Controls pauschal basierend auf Intake-Flags (Boolean-Felder wie
`personal_data: true`, `marketing: true`). Sie prueft NICHT, ob der analysierte Text die
Bedingungen fuer einen spezifischen Control tatsaechlich erfuellt.

### Konkretes Beispiel (Opodo-Test, 2026-04-28)

- **Control:** `[C_TRANSPARENCY] Nutzer informieren dass sie mit KI interagieren`
- **Quelle:** AI Act Art. 52 — nur relevant wenn KI eingesetzt wird
- **Opodo sagt:** "automated processing" (kann regelbasierte Software sein, muss keine KI sein)
- **Ergebnis:** False Positive — Control wird empfohlen obwohl kein KI-Einsatz belegt ist

### Skalierung

Von ~166.740 Controls in der RAG-Datenbank wird ein unbekannter Prozentsatz
bei jeder Bewertung generisch empfohlen. Jedes False Positive untergräbt das
Vertrauen des Nutzers und macht das Tool fuer Abmahnungen unbrauchbar.

## Loesung: 3-Stufen Relevance Filter

### Stufe 1: Regelbasierter Vorfilter (deterministisch, schnell)

Jeder Control bekommt ein `relevance_conditions` Feld (JSON):

```json
{
  "control_id": "C_TRANSPARENCY",
  "relevance_conditions": {
    "text_must_contain_any": ["KI", "kuenstliche Intelligenz", "artificial intelligence",
                               "machine learning", "maschinelles Lernen", "neural", "deep learning",
                               "AI system", "AI-System", "algorith"],
    "text_must_not_contain": [],
    "requires_intake_flag": "automation",
    "min_confidence": 0.5
  }
}
```

**Implementierung:**
- Neues Feld `relevance_conditions` in `compliance.canonical_controls` (JSONB)
- Funktion `check_relevance(control, source_text) -> (relevant: bool, confidence: float)`
- Laeuft NACH dem UCCA-Assessment, BEVOR das Ergebnis zurueckgegeben wird
- Filtert Controls raus deren Keywords im Quelltext nicht vorkommen

**Aufwand:** ~200 LOC Python, kein LLM-Call noetig
**Datei:** `ai-compliance-sdk/internal/ucca/relevance_filter.go` oder `backend-compliance/compliance/services/relevance_filter.py`

### Stufe 2: LLM-Validierung (fuer High-Value Controls)

Fuer Controls mit `severity >= HIGH` oder wenn der regelbasierte Filter unsicher ist
(confidence < 0.7), wird Qwen gefragt:

```
Gegeben dieser Dokumenttext:
"[...Auszug...]"

Ist der folgende Control relevant fuer dieses Dokument?
Control: "[C_TRANSPARENCY] Nutzer informieren dass sie mit KI interagieren"
Rechtsgrundlage: Art. 52 AI Act

Antworte NUR mit: JA (mit Begruendung) oder NEIN (mit Begruendung)
```

**Implementierung:**
- Neuer Endpoint: `POST /sdk/v1/ucca/validate-controls`
- Nimmt: `assessment_id`, `source_text`, `controls[]`
- Gibt zurueck: `controls[]` mit `relevant: bool`, `reason: string`
- Cached: Gleicher Text + Control = gleiche Antwort (24h TTL)

**Aufwand:** ~150 LOC, 1 LLM-Call pro Control (parallelisierbar)

### Stufe 3: Follow-Up-Fragen an den Nutzer (Hybrid)

Wenn weder Regel noch LLM sicher entscheiden koennen:

```
Follow-Up: "Setzt der Anbieter KI oder maschinelles Lernen ein?"
→ Ja: Control bleibt
→ Nein: Control wird entfernt
→ Unsicher: Control bleibt mit Hinweis "Nicht verifizierbar"
```

**Bereits implementiert:** Das `follow_up_questions` System im Agent-Endpoint.

## Datenmodell-Aenderung

```sql
-- Neues Feld in canonical_controls
ALTER TABLE compliance.canonical_controls
ADD COLUMN IF NOT EXISTS relevance_conditions JSONB DEFAULT '{}';

-- Index fuer schnelle Abfrage
CREATE INDEX IF NOT EXISTS idx_controls_relevance
ON compliance.canonical_controls USING gin (relevance_conditions);
```

## Architektur

```
UCCA Assessment
    │
    ▼
┌────────────────────┐
│ Stufe 1: Regelfilter│ ← text_must_contain_any, intake_flags
│ (deterministisch)   │
└────────┬───────────┘
         │ unsicher oder high-severity
         ▼
┌────────────────────┐
│ Stufe 2: LLM-Check │ ← Qwen validiert Relevanz
│ (1 Call/Control)    │
└────────┬───────────┘
         │ immer noch unsicher
         ▼
┌────────────────────┐
│ Stufe 3: Follow-Up │ ← Nutzer beantwortet Frage
│ (Frontend)          │
└────────────────────┘
```

## Implementierungsreihenfolge

### Phase 1: Regelfilter (1 Tag)

1. Migration: `relevance_conditions` Feld zu `canonical_controls`
2. Seed-Script: Top-20 generische Controls mit Bedingungen versehen
   (C_TRANSPARENCY, C_EXPLICIT_CONSENT, C_DSFA_REQUIRED, etc.)
3. Filter-Funktion in `agent_analyze_routes.py`
4. Test: Opodo erneut analysieren — C_TRANSPARENCY sollte rausfallen

### Phase 2: LLM-Validierung (1 Tag)

1. Neuer SDK-Endpoint `/sdk/v1/ucca/validate-controls`
2. Integration in den Agent-Workflow
3. Caching-Layer (Redis/Valkey)

### Phase 3: Batch-Seeding (2-3 Tage)

1. Pipeline-Job: Fuer alle 166k Controls `relevance_conditions` generieren
   (LLM-gestuetzt: "Welche Keywords im Quelltext wuerden diesen Control relevant machen?")
2. Qualitaetspruefung: Stichprobe von 100 Controls manuell validieren

## Betroffene Dateien

| Datei | Aenderung |
|-------|-----------|
| `backend-compliance/compliance/api/agent_analyze_routes.py` | Filter-Integration |
| `backend-compliance/compliance/services/relevance_filter.py` | NEU: Regelfilter |
| `ai-compliance-sdk/internal/ucca/relevance_filter.go` | NEU: SDK-seitig (alternativ) |
| `ai-compliance-sdk/internal/api/handlers/ucca_handlers.go` | Neuer Endpoint |
| Migration | `relevance_conditions` Spalte |
| `control-pipeline/` | Batch-Seeding Job (Phase 3) |

## Phase 4: Website-Scan (Multi-Page Crawl)

### Problem

Aktuell analysieren wir nur EINE URL (z.B. `/datenschutz/`). Aber relevante Hinweise
auf KI, Chatbots, automatisierte Entscheidungen oder Tracking koennen auf ANDEREN
Seiten der Website stehen:

- Chatbot-Widget auf der Startseite (nicht auf der Datenschutzseite)
- "Powered by ChatGPT" im Footer
- KI-gestuetzte Produktempfehlungen auf der Shopseite
- Cookie-Scripts die Tracking-Dienste laden (Google Analytics, Meta Pixel, etc.)
- Chatbot-Anbieter wie Intercom, Drift, Zendesk, Tidio im HTML

### Loesung: Lightweight Website-Scan

Kein vollstaendiger Crawl (zu langsam, zu invasiv), sondern ein gezielter Scan
von 5-10 strategischen Seiten:

```
Eingabe: https://www.opodo.de/datenschutz/

Automatisch gescannte Seiten:
1. Startseite:           https://www.opodo.de/
2. Datenschutz (bereits): https://www.opodo.de/datenschutz/
3. Impressum:            https://www.opodo.de/impressum/ (aus Footer-Links)
4. AGB:                  https://www.opodo.de/agb/ (aus Footer-Links)
5. Cookie-Policy:        https://www.opodo.de/cookies/ (falls vorhanden)
```

### Scan-Logik

**Schritt 1: Startseite holen + Footer-Links extrahieren**
```python
# Aus der Startseite die typischen Footer-Links extrahieren:
footer_patterns = [
    r'href="([^"]*(?:impressum|imprint|legal)[^"]*)"',
    r'href="([^"]*(?:datenschutz|privacy|dsgvo)[^"]*)"',
    r'href="([^"]*(?:agb|terms|nutzungsbedingungen)[^"]*)"',
    r'href="([^"]*(?:cookie|cookies)[^"]*)"',
    r'href="([^"]*(?:kontakt|contact)[^"]*)"',
]
```

**Schritt 2: Jede Seite auf KI/Chatbot/Tracking-Indikatoren scannen**
```python
AI_INDICATORS = {
    # Chatbot-Widgets (JavaScript-Einbindungen)
    "chatbot_widgets": [
        r"intercom",          # Intercom (KI-gestuetzt)
        r"drift\.com",        # Drift Chatbot
        r"tidio",             # Tidio Chat
        r"zendesk",           # Zendesk Chat
        r"crisp\.chat",       # Crisp Chat
        r"livechat",          # LiveChat
        r"hubspot.*chat",     # HubSpot Chat
        r"tawk\.to",          # Tawk.to
        r"freshchat",         # Freshworks
        r"dialogflow",        # Google Dialogflow
        r"watson.*assistant", # IBM Watson
        r"chatgpt|openai",    # OpenAI/ChatGPT
        r"anthropic|claude",  # Anthropic/Claude
    ],
    # KI-Hinweise im Text
    "ai_text_mentions": [
        r"k(?:ue|ü)nstliche.?intelligenz",
        r"artificial.?intelligence",
        r"machine.?learning",
        r"maschinelles.?lernen",
        r"KI.?gest(?:ue|ü)tzt",
        r"AI.?powered",
        r"algorithm",
        r"automatisierte.?entscheidung",
        r"automated.?decision",
        r"profiling",
        r"personalisier",    # Personalisierung
    ],
    # Tracking & Analytics (EU + non-EU)
    "tracking_analytics": [
        # Google (USA)
        r"google.?analytics|gtag|UA-\d+|G-\w+",
        r"googletagmanager|gtm\.js",
        r"google.?ads|googleads|adwords",
        r"doubleclick\.net",
        # Meta (USA)
        r"facebook.?pixel|fbq\(|connect\.facebook",
        r"meta.?pixel",
        # Microsoft (USA)
        r"clarity\.ms",     # Microsoft Clarity
        r"bing\.com/bat",   # Bing Ads
        r"linkedin\.com/insight", # LinkedIn Insight
        # Analytics-Anbieter
        r"hotjar",          # Hotjar (Malta/EU — OK)
        r"segment\.com",    # Segment (USA)
        r"mixpanel",        # Mixpanel (USA)
        r"amplitude",       # Amplitude (USA)
        r"heap\.io",        # Heap (USA)
        r"posthog",         # PostHog (USA, self-host moeglich)
        r"matomo|piwik",    # Matomo (EU — self-host = OK, Cloud = pruefen)
        r"plausible",       # Plausible (EU — OK)
        r"fathom",          # Fathom (Kanada — Angemessenheitsbeschluss)
        r"pirsch",          # Pirsch (DE — OK)
        r"umami",           # Umami (self-host)
    ],
    # CDN und Drittanbieter-Dienste (Drittlandtransfer-Risiko)
    "third_party_services": [
        # CDN (pruefen ob Drittland)
        r"cdn\.cloudflare\.com",      # Cloudflare (USA)
        r"fastly\.net",               # Fastly (USA)
        r"akamai",                    # Akamai (USA)
        r"cdn\.jsdelivr\.net",        # jsDelivr (international)
        r"unpkg\.com",                # unpkg (USA)
        r"cdnjs\.cloudflare\.com",    # cdnjs (USA)
        r"stackpath",                 # StackPath (USA)
        r"bunny\.net|bunnycdn",       # BunnyCDN (Slowenien/EU — OK)
        r"keycdn",                    # KeyCDN (Schweiz — Angemessenheit)
        # Fonts (IP-Uebermittlung!)
        r"fonts\.googleapis\.com",    # Google Fonts (USA — DSGVO-Verstoss!)
        r"fonts\.gstatic\.com",       # Google Fonts CDN
        r"use\.typekit\.net",         # Adobe Fonts (USA)
        # Captcha
        r"recaptcha|grecaptcha",      # Google reCAPTCHA (USA)
        r"hcaptcha",                  # hCaptcha (USA)
        r"turnstile.*cloudflare",     # Cloudflare Turnstile (USA)
        # Maps
        r"maps\.googleapis\.com",     # Google Maps (USA)
        r"maps\.google\.com",
        r"openstreetmap",             # OpenStreetMap (EU — OK)
        r"mapbox",                    # Mapbox (USA)
        # Video
        r"youtube\.com|youtube-nocookie", # YouTube (USA)
        r"vimeo\.com",                # Vimeo (USA)
        r"wistia",                    # Wistia (USA)
        # Social Media Embeds
        r"platform\.twitter\.com|x\.com/embed", # X/Twitter (USA)
        r"instagram\.com/embed",      # Instagram (USA)
        r"linkedin\.com/embed",       # LinkedIn (USA)
        # Content Moderation
        r"besedo",                    # Besedo (Schweden/EU — OK, aber pruefen)
        # Payment (PCI-DSS relevant)
        r"stripe\.com|js\.stripe",    # Stripe (USA)
        r"paypal\.com",               # PayPal (USA)
        r"adyen",                     # Adyen (NL/EU — OK)
        r"mollie",                    # Mollie (NL/EU — OK)
        # Andere
        r"sentry\.io|sentry-cdn",     # Sentry Error Tracking (USA)
        r"intercom\.io",              # Intercom (USA) — auch in chatbot_widgets
        r"zendesk\.com",              # Zendesk (USA)
        r"freshdesk|freshworks",      # Freshworks (USA/Indien)
    ],
}
```

### Drittland-Erkennung

Fuer jeden erkannten externen Dienst wird geprueft ob er aus einem Drittland stammt
(kein EU/EWR-Staat, kein Angemessenheitsbeschluss). Dafuer wird eine Registry gepflegt:

```python
# Statische Registry — ca. 80 Eintraege
THIRD_PARTY_REGISTRY = {
    "google_analytics":  {"provider": "Google LLC", "country": "US", "eu_adequate": False, "requires_consent": True, "legal_ref": "Art. 44-49 DSGVO, Schrems II"},
    "google_fonts":      {"provider": "Google LLC", "country": "US", "eu_adequate": False, "requires_consent": True, "legal_ref": "LG Muenchen I, Az. 3 O 17493/20 (Google Fonts Urteil)"},
    "facebook_pixel":    {"provider": "Meta Platforms", "country": "US", "eu_adequate": False, "requires_consent": True, "legal_ref": "Art. 44-49 DSGVO"},
    "cloudflare_cdn":    {"provider": "Cloudflare Inc", "country": "US", "eu_adequate": False, "requires_consent": False, "legal_ref": "Art. 44-49 DSGVO, berechtigtes Interesse moeglich"},
    "matomo_cloud":      {"provider": "Matomo (InnoCraft)", "country": "NZ", "eu_adequate": True, "requires_consent": True, "legal_ref": "Neuseeland hat Angemessenheitsbeschluss"},
    "matomo_selfhost":   {"provider": "Self-hosted", "country": "depends", "eu_adequate": True, "requires_consent": False, "legal_ref": "Kein Drittlandtransfer bei Self-Hosting"},
    "plausible":         {"provider": "Plausible Insights", "country": "EE", "eu_adequate": True, "requires_consent": False, "legal_ref": "EU-Anbieter, cookieless"},
    "bunnycdn":          {"provider": "BunnyCDN d.o.o.", "country": "SI", "eu_adequate": True, "requires_consent": False, "legal_ref": "EU-Anbieter"},
    "stripe":            {"provider": "Stripe Inc", "country": "US", "eu_adequate": False, "requires_consent": False, "legal_ref": "Art. 6(1)(b) Vertragserfuellung, SCCs"},
    "besedo":            {"provider": "Besedo AB", "country": "SE", "eu_adequate": True, "requires_consent": False, "legal_ref": "EU-Anbieter"},
    # ... ~80 weitere Eintraege
}
```

### Generierte Findings

**Beispiel: Opodo mit erweitertem Scan:**
```
Externe Dienste erkannt:
  - Google Analytics (G-03F834EHLM) — USA, kein Angemessenheitsbeschluss
    → FINDING: Drittlandtransfer USA ohne Einwilligung (Art. 44 DSGVO)
  - Google Fonts (fonts.googleapis.com) — USA
    → FINDING: Google Fonts Einbindung (LG Muenchen I, Az. 3 O 17493/20)
  - Didomi CMP — Frankreich (EU — OK)
  - Bootstrap CDN (jsdelivr.net) — International, pruefen
    → FOLLOW-UP: "Wird das CDN aus der EU oder einem Drittland geladen?"
```

### Phase 4b: Soll-Ist-Abgleich (Dienstleister DSE vs. Website)

Der wertvollste Output des Agents: automatischer Abgleich zwischen dem was in der
Datenschutzerklaerung STEHT und dem was tatsaechlich auf der Website EINGEBUNDEN ist.

**Schritt 1: IST — Website scannen (bereits in Phase 4)**
Alle eingebundenen externen Dienste per HTML/Script-Analyse erkennen.

**Schritt 2: SOLL — Datenschutzerklaerung parsen**
Aus dem DSE-Text extrahieren welche Dienstleister erwaehnt werden:
```python
# Qwen/LLM extrahiert strukturiert:
PROMPT = """
Extrahiere aus dieser Datenschutzerklaerung ALLE erwaehnten Dienstleister/Tools.
Fuer jeden Dienstleister nenne:
- Name (z.B. "Google Analytics")
- Zweck (z.B. "Webanalyse")
- Land/Sitz (z.B. "USA")
- Genannte Rechtsgrundlage (z.B. "Einwilligung" oder "berechtigtes Interesse")
- Genannte Schutzmassnahme (z.B. "Standardvertragsklauseln")

Antworte als JSON-Array.
"""
```

**Schritt 3: Abgleich → 3 Kategorien**

| Kategorie | Bedeutung | Finding-Typ |
|-----------|-----------|-------------|
| Eingebunden + NICHT in DSE | Informationspflicht verletzt | HIGH — Art. 13 DSGVO Verstoss |
| In DSE + NICHT eingebunden | Veraltete/irrefuehrende DSE | LOW — Aufraumbedarf |
| Eingebunden + in DSE | Korrekt dokumentiert | OK — nur Drittland pruefen |

**Beispiel-Output fuer Opodo:**
```
Dienstleister-Abgleich (opodo.de)
══════════════════════════════════

Eingebunden auf Website         In DSE erwaehnt?    Status
─────────────────────────────── ─────────────────── ───────
Google Analytics (G-03F834EHLM) Ja (Abschnitt 3.6)  ✓ OK — aber USA, SCCs pruefen
Didomi CMP                      Ja (Cookie Notice)   ✓ OK — Frankreich/EU
Bootstrap CDN (jsdelivr)        Nein                  ✗ FINDING: Nicht in DSE
Google Tag Manager              Ja (Abschnitt 3.6)   ✓ OK

In DSE erwaehnt                 Auf Website gefunden? Status
─────────────────────────────── ───────────────────── ───────
Amadeus IT (Buchungssystem)     Nicht pruefbar        ? Backend-Dienst
Adyen (Zahlungsabwicklung)      Nicht pruefbar        ? Backend-Dienst
Salesforce (CRM)                Nicht pruefbar        ? Backend-Dienst

Zusammenfassung:
- 1 Dienstleister eingebunden aber NICHT in DSE dokumentiert (jsdelivr CDN)
- 3 Backend-Dienste in DSE erwaehnt, nicht im Frontend pruefbar
- Empfehlung: jsdelivr CDN in Datenschutzerklaerung aufnehmen oder lokal hosten
```

Dieser Output allein ist fuer einen Datenschutzbeauftragten Gold wert — er spart
Stunden manueller Arbeit und deckt Luecken auf die bei Website-Updates entstehen.

### Controls die durch Drittland-Dienste ausgeloest werden

| Erkannter Dienst | Control |
|-----------------|---------|
| Jeder US-Dienst ohne SCCs | C_THIRD_COUNTRY_TRANSFER: Drittlandtransfer absichern (Art. 44-49 DSGVO) |
| Google Fonts remote | C_GOOGLE_FONTS: Fonts lokal einbinden (LG Muenchen I Urteil) |
| Tracking ohne Consent-Banner | C_EXPLICIT_CONSENT: Einwilligung vor Tracking einholen |
| reCAPTCHA | C_CAPTCHA_PRIVACY: Datenschutzkonformen Captcha-Dienst nutzen |
| YouTube Embed | C_VIDEO_EMBED: 2-Klick-Loesung oder youtube-nocookie verwenden |
```

**Schritt 3: Ergebnis aggregieren**
```python
scan_result = {
    "pages_scanned": 5,
    "chatbot_detected": True,      # z.B. Intercom auf Startseite
    "chatbot_provider": "intercom", # Identifizierter Anbieter
    "ai_mentions_found": False,     # Kein expliziter KI-Text
    "tracking_services": ["google_analytics", "facebook_pixel"],
    "tracking_count": 2,
}
```

**Schritt 4: Scan-Ergebnis in Relevanzpruefung einbeziehen**
- Chatbot erkannt → C_TRANSPARENCY wird relevant (auch ohne KI-Text)
- Tracking erkannt → C_EXPLICIT_CONSENT wird relevant
- Kein KI-Nachweis auf gesamter Website → C_TRANSPARENCY faellt weg

### Implementierung

**Neue Datei:** `backend-compliance/compliance/services/website_scanner.py` (~200 LOC)

```python
class WebsiteScanner:
    async def scan(self, base_url: str) -> ScanResult:
        """Scan 5-10 pages for AI, chatbot, and tracking indicators."""
        pages = await self._discover_pages(base_url)
        indicators = {}
        for page_url in pages[:10]:
            html = await self._fetch(page_url)
            indicators[page_url] = self._detect_indicators(html)
        return self._aggregate(indicators)
```

**Integration in Agent-Workflow:**
- Zwischen Schritt 1 (Fetch) und Schritt 3 (UCCA Assess)
- Scan-Ergebnis fliesst in die Intake-Flags UND in den Relevanzfilter
- Scan-Ergebnis wird im Response zurueckgegeben (Transparenz)

**Frontend-Erweiterung:**
- "Erweiterte Analyse" Toggle: Nur Einzelseite vs. Website-Scan
- Scan-Ergebnis als aufklappbare Sektion: "5 Seiten gescannt, Chatbot auf Startseite erkannt"

### Aufwand

| Komponente | LOC | Zeit |
|-----------|-----|------|
| `website_scanner.py` | ~200 | 0.5 Tage |
| Integration in `agent_analyze_routes.py` | ~50 | 2h |
| Frontend: Scan-Ergebnis anzeigen | ~80 | 2h |
| Tests | ~100 | 2h |

### Beispiel: Opodo mit Website-Scan

```
Seiten gescannt: 5
  - https://www.opodo.de/ → Didomi Cookie-Consent, Google Analytics
  - https://www.opodo.de/datenschutz/ → Datenschutzerklaerung
  - https://www.opodo.de/impressum/ → 404 (FINDING!)
  - https://www.opodo.de/agb/ → AGB vorhanden
  - https://www.opodo.de/cookies/ → Cookie-Policy

Chatbot erkannt: Nein
KI-Hinweise: Nein
Tracking: Google Analytics (G-03F834EHLM), Didomi CMP

→ C_TRANSPARENCY: NICHT relevant (kein KI-Nachweis auf gesamter Website)
→ C_EXPLICIT_CONSENT: Relevant (Google Analytics + Didomi = Tracking aktiv)
→ Impressum-Finding: 404 auf /impressum/ (§5 TMG Verstoss)
```

## Phase 5: Branchenspezifische Pruefmodule

### 5a: Zahlungsanbieter (PCI-DSS + DSGVO)

Pruefung der korrekten Einbindung von Payment-Anbietern:

```
Erkennungsmuster → Pruefpunkte

Stripe (js.stripe.com)
  ✓ Wird Stripe.js korrekt ueber stripe.com geladen (nicht self-hosted)?
  ✓ Ist "Payment" oder "Zahlung" in der DSE mit Stripe erwaehnt?
  ✓ Rechtsgrundlage: Art. 6(1)(b) Vertragserfuellung angegeben?
  ✓ SCCs oder DPF fuer USA-Transfer dokumentiert?
  ✗ Werden Kreditkartendaten an eigenen Server gesendet (PCI-Verstoss)?

PayPal (paypal.com/sdk)
  ✓ PayPal in DSE erwaehnt?
  ✓ Rechtsgrundlage angegeben?
  ✓ Hinweis auf PayPal-eigene DSE verlinkt?

Adyen (adyen.com)
  ✓ EU-Anbieter (NL) — kein Drittlandtransfer
  ✓ In DSE erwaehnt?

Mollie (mollie.com)
  ✓ EU-Anbieter (NL) — kein Drittlandtransfer
  ✓ In DSE erwaehnt?

Klarna (klarna.com)
  ✓ EU-Anbieter (SE) — kein Drittlandtransfer
  ✓ Bonitaetspruefung erwaehnt? (Art. 22 DSGVO — automatisierte Entscheidung!)
  ✓ SCHUFA/Auskunftei-Hinweis vorhanden?
```

**Besonderer Check:** Wenn ein Payment-Anbieter Bonitaetspruefungen durchfuehrt
(Klarna, PayPal, Ratenzahlung), MUSS Art. 22 DSGVO in der DSE erwaehnt werden
(automatisierte Einzelentscheidung). Das ist ein haeufig uebersehener Verstoss.

### 5b: Marketing & Tracking (ePrivacy + DSGVO)

Systematische Pruefung aller Marketing-/Tracking-Einbindungen:

```
Kategorie: Webanalyse
──────────────────────
Google Analytics    → Einwilligung PFLICHT, DSE-Eintrag, IP-Anonymisierung pruefen
Matomo (Cloud)      → Einwilligung empfohlen, DSE-Eintrag
Matomo (Self-Host)  → Keine Einwilligung noetig wenn cookieless, DSE-Eintrag
Plausible/Pirsch    → Keine Einwilligung noetig (cookieless, EU), DSE-Eintrag

Kategorie: Werbenetzwerke
─────────────────────────
Google Ads/AdSense  → Einwilligung PFLICHT, DSE-Eintrag, Drittlandtransfer
Meta/Facebook Pixel → Einwilligung PFLICHT, DSE-Eintrag, Drittlandtransfer
TikTok Pixel        → Einwilligung PFLICHT, DSE-Eintrag, Drittlandtransfer (China!)
Pinterest Tag       → Einwilligung PFLICHT, DSE-Eintrag, Drittlandtransfer
LinkedIn Insight    → Einwilligung PFLICHT, DSE-Eintrag, Drittlandtransfer
Twitter/X Pixel     → Einwilligung PFLICHT, DSE-Eintrag, Drittlandtransfer
Criteo              → Einwilligung PFLICHT, DSE-Eintrag (FR/EU aber Tracking)

Kategorie: Remarketing / Retargeting
─────────────────────────────────────
Google Remarketing  → Einwilligung PFLICHT, eigene DSE-Sektion empfohlen
Facebook Custom Audiences → Einwilligung PFLICHT, Hochladen von Kundenlisten pruefen

Kategorie: Heatmaps & Session Recording
────────────────────────────────────────
Hotjar              → Einwilligung PFLICHT (zeichnet Nutzerverhalten auf!)
Microsoft Clarity   → Einwilligung PFLICHT (Session Replay!)
FullStory           → Einwilligung PFLICHT, DSE-Eintrag, Drittlandtransfer
Mouseflow           → Einwilligung PFLICHT, DSE-Eintrag

Kategorie: A/B Testing
───────────────────────
Google Optimize     → Eingestellt, aber Legacy-Code pruefen
Optimizely          → Einwilligung je nach Implementierung
VWO                 → Einwilligung wenn Cookies gesetzt werden

Kategorie: Newsletter / E-Mail Marketing
─────────────────────────────────────────
Mailchimp           → Drittlandtransfer (USA), SCCs pruefen
Brevo (ehem. Sendinblue) → EU (FR) — OK
CleverReach         → EU (DE) — OK
ActiveCampaign      → USA, Drittlandtransfer
HubSpot             → USA, Drittlandtransfer
Rapidmail           → EU (DE) — OK
```

### Prueflogik pro Marketing-Dienst

```python
def check_marketing_service(service: DetectedService, dse_text: str) -> list[Finding]:
    findings = []
    registry = THIRD_PARTY_REGISTRY[service.id]

    # 1. In DSE erwaehnt?
    if not service_mentioned_in_dse(service, dse_text):
        findings.append(Finding(
            severity="HIGH",
            code=f"MARKETING-{service.id}-NOT-IN-DSE",
            text=f"{service.name} ist auf der Website eingebunden aber nicht in der "
                 f"Datenschutzerklaerung erwaehnt (Art. 13 DSGVO Verstoss)."
        ))

    # 2. Einwilligung vorhanden?
    if registry["requires_consent"] and not consent_banner_detected:
        findings.append(Finding(
            severity="HIGH",
            code=f"MARKETING-{service.id}-NO-CONSENT",
            text=f"{service.name} erfordert eine Einwilligung vor Aktivierung "
                 f"(§25 TDDDG). Kein funktionierender Consent-Banner erkannt."
        ))

    # 3. Drittlandtransfer?
    if not registry["eu_adequate"]:
        if not sccs_mentioned_in_dse(service, dse_text):
            findings.append(Finding(
                severity="MEDIUM",
                code=f"TRANSFER-{service.id}-NO-SCCS",
                text=f"{service.name} ({registry['country']}) — Drittlandtransfer "
                     f"ohne dokumentierte Schutzmaßnahme ({registry['legal_ref']})."
            ))

    return findings
```

## Phase 6: Automatische Korrekturvorschlaege (Pre-Launch Modus)

Im **internen Pruefmodus** (pre_launch) erstellt der Agent bei JEDER Abweichung
einen konkreten, einbaufertigen Korrekturvorschlag:

### Korrekturtypen

**Typ 1: DSE-Textbaustein (Dienstleister fehlt in DSE)**

Wenn ein Dienstleister auf der Website erkannt wird aber nicht in der DSE steht,
generiert der Agent einen fertigen Textbaustein:

```
ABWEICHUNG: Google Analytics (G-03F834EHLM) eingebunden, nicht in DSE dokumentiert.

KORREKTURVORSCHLAG (einbaufertig):
──────────────────────────────────
Webanalyse

Wir nutzen Google Analytics, einen Webanalysedienst der Google Ireland Limited
(Gordon House, Barrow Street, Dublin 4, Irland). Google Analytics verwendet Cookies,
die eine Analyse der Benutzung der Website ermoeglichen.

Rechtsgrundlage: Art. 6 Abs. 1 lit. a DSGVO (Einwilligung).

Die durch Cookies erzeugten Informationen werden in der Regel an einen Server von
Google in den USA uebertragen. Wir haben mit Google einen Auftragsverarbeitungsvertrag
abgeschlossen. Die Uebermittlung in die USA wird auf Standardvertragsklauseln
der EU-Kommission gestuetzt.

Sie koennen die Speicherung der Cookies durch eine entsprechende Einstellung Ihrer
Browser-Software verhindern. Sie koennen darueber hinaus die Erfassung der durch
das Cookie erzeugten und auf Ihre Nutzung der Website bezogenen Daten an Google
sowie die Verarbeitung dieser Daten durch Google verhindern, indem Sie das unter
dem folgenden Link verfuegbare Browser-Add-On herunterladen und installieren:
https://tools.google.com/dlpage/gaoptout

Weitere Informationen: https://policies.google.com/privacy
──────────────────────────────────

EINFUEGEN NACH: Abschnitt "Cookies" oder "Webanalyse"
PRIORITAET: Hoch — vor Veroeffentlichung korrigieren
```

**Typ 2: Rechtsgrundlage fehlt/falsch**

```
ABWEICHUNG: Klarna als Zahlungsanbieter genannt, aber kein Hinweis auf
automatisierte Bonitaetspruefung (Art. 22 DSGVO).

KORREKTURVORSCHLAG:
──────────────────
Ergaenzen Sie im Abschnitt "Zahlungsabwicklung":

"Bei Auswahl der Zahlungsart 'Rechnung' oder 'Ratenzahlung' ueber Klarna
wird eine automatisierte Bonitaetspruefung durchgefuehrt. Klarna uebermittelt
hierzu Ihre Angaben an Wirtschaftsauskunfteien (z.B. SCHUFA). Rechtsgrundlage
ist Art. 6 Abs. 1 lit. b DSGVO (Vertragserfuellung). Sie haben gemaess
Art. 22 Abs. 3 DSGVO das Recht, Ihren Standpunkt darzulegen und die
Entscheidung anzufechten."
──────────────────
```

**Typ 3: Dienst nicht mehr eingebunden (Aufraeumen)**

```
ABWEICHUNG: "Facebook Pixel" in DSE Abschnitt 4.2 erwaehnt, aber auf der
Website nicht mehr eingebunden.

KORREKTURVORSCHLAG:
──────────────────
Entfernen Sie den Absatz zu Facebook Pixel in Abschnitt 4.2 oder
kennzeichnen Sie ihn als "nicht mehr aktiv". Veraltete Eintraege in der
DSE sind zwar kein Rechtsverstoß, koennen aber bei einer Pruefung durch
die Aufsichtsbehoerde Fragen aufwerfen.
──────────────────
PRIORITAET: Niedrig — bei naechster DSE-Aktualisierung bereinigen
```

### Implementierung der Korrekturvorschlaege

```python
async def generate_correction(
    service: DetectedService,
    finding_type: str,  # "missing_in_dse", "wrong_legal_basis", "outdated"
    dse_text: str,
    mode: str,
) -> str:
    """Generiere einbaufertigen Korrekturvorschlag via Qwen."""
    if mode != "pre_launch":
        return ""  # Nur im internen Modus

    prompt = f"""
    /no_think
    Du bist ein Datenschutzexperte. Erstelle einen einbaufertigen Textbaustein
    fuer eine deutsche Datenschutzerklaerung.

    Dienstleister: {service.name}
    Anbieter: {service.provider}
    Land: {service.country}
    Zweck: {service.purpose}
    Finding: {finding_type}

    Der Textbaustein muss enthalten:
    1. Ueberschrift (z.B. "Webanalyse" oder "Zahlungsabwicklung")
    2. Name und Sitz des Anbieters
    3. Zweck der Verarbeitung
    4. Rechtsgrundlage (korrekt nach DSGVO)
    5. Drittlandtransfer-Hinweis wenn nicht EU
    6. Widerspruchsmoeglichkeit

    Antworte NUR mit dem fertigen Textbaustein, ohne Erklaerung.
    """
    # LLM-Call via SDK
    response = await sdk_llm_chat(prompt)
    return response
```

### Ergebnis-Format im Agent-Output

```json
{
  "findings": [...],
  "corrections": [
    {
      "finding_code": "MARKETING-google_analytics-NOT-IN-DSE",
      "type": "missing_in_dse",
      "service": "Google Analytics",
      "priority": "high",
      "insert_after": "Abschnitt Cookies / Webanalyse",
      "correction_text": "Webanalyse\n\nWir nutzen Google Analytics...",
      "legal_refs": ["Art. 13 DSGVO", "Art. 44-49 DSGVO", "§25 TDDDG"]
    }
  ]
}
```

### Frontend: Korrekturvorschlaege anzeigen

Im Pre-Launch-Modus zeigt das Frontend fuer jedes Finding einen aufklappbaren
Korrekturvorschlag mit Copy-Button:

```
[!] Google Analytics eingebunden, nicht in DSE
    Prioritaet: Hoch | Art. 13 DSGVO

    ▼ Korrekturvorschlag anzeigen
    ┌─────────────────────────────────────────┐
    │ Webanalyse                              │
    │                                         │
    │ Wir nutzen Google Analytics, einen      │
    │ Webanalysedienst der Google Ireland     │
    │ Limited...                              │
    │                                    [📋] │
    └─────────────────────────────────────────┘
    Einfuegen nach: Abschnitt "Cookies"
```

## Risiken

| Risiko | Mitigation |
|--------|------------|
| Zu aggressive Filterung (False Negatives) | Stufe 1 nur fuer klare Faelle, Stufe 2 als Fallback |
| LLM-Kosten bei vielen Controls | Caching + nur high-severity Controls |
| Datenbank-Migration auf Production | `ADD COLUMN IF NOT EXISTS` ist non-blocking |
| 166k Controls ohne relevance_conditions | Default `{}` = kein Filter = bisheriges Verhalten |
| Qwen-generierte Textbausteine rechtlich falsch | Review-Pflicht: "Vom KI-Assistenten erstellt, Pruefung durch DSB empfohlen" |
| Website-Scan zu langsam (10 Seiten fetchen) | Parallel fetchen, max 5s Timeout pro Seite, max 10 Seiten |
| Payment-Einbindung nicht im HTML sichtbar | Follow-Up: "Welche Zahlungsanbieter nutzen Sie?" |

## Testfaelle

1. **Opodo-Test:** C_TRANSPARENCY sollte NICHT mehr empfohlen werden (kein KI-Nachweis)
2. **Chatbot-Anbieter:** C_TRANSPARENCY SOLL empfohlen werden (KI explizit erwaehnt)
3. **Arztpraxis-Website:** C_DSFA_REQUIRED SOLL empfohlen werden (Gesundheitsdaten)
4. **Blog ohne Tracking:** Nur minimale Controls (Impressum, Datenschutzerklaerung)
5. **Shop mit Klarna:** Art. 22 DSGVO Finding wenn Bonitaetspruefung nicht in DSE
6. **Website mit Google Fonts:** LG Muenchen I Finding + Korrekturvorschlag "lokal einbinden"
7. **Pre-Launch DSE-Entwurf:** Korrekturvorschlaege fuer fehlende Dienstleister-Eintraege
8. **Opodo Soll-Ist:** jsdelivr CDN eingebunden aber nicht in DSE → Finding + Textbaustein
