fix: false positive findings + restore docs-src + §312k ecommerce filter

1. Intake prompt: "BETREIBER verarbeitet" statt "Text erwaehnt".
   IHK berichtet ueber Gesundheitsdaten → false. Vorher: true.
2. §312k Check: nur bei E-Commerce/Abo-Websites (Warenkorb, Shop, PayPal etc.)
   IHK hat keine Vertraege → kein Kuendigungsbutton noetig.
3. docs-src/ restored from commit 9824304

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-02 08:26:59 +02:00
parent e318215cc5
commit 0f3ec9061e
2 changed files with 35 additions and 19 deletions
@@ -18,27 +18,34 @@ OLLAMA_URL = os.environ.get("OLLAMA_URL", "http://host.docker.internal:11434")
OLLAMA_MODEL = os.environ.get("OLLAMA_MODEL", "qwen3.5:35b-a3b") OLLAMA_MODEL = os.environ.get("OLLAMA_MODEL", "qwen3.5:35b-a3b")
EXTRACTION_PROMPT = """/no_think EXTRACTION_PROMPT = """/no_think
Analysiere den folgenden Text (Datenschutzerklaerung oder Website-Inhalt) und Du analysierst eine Datenschutzerklaerung oder Website. Bestimme ob der
bestimme fuer JEDES der folgenden Flags ob es zutrifft (true/false). BETREIBER DIESER WEBSITE die folgenden Daten AKTIV VERARBEITET.
WICHTIG: Setze ein Flag NUR auf true wenn der Websitebetreiber diese Daten
SELBST erhebt, speichert oder verarbeitet. NICHT wenn die Website nur
UEBER solche Themen BERICHTET oder informiert.
Beispiel: Eine IHK-Website die UEBER Datenschutz im Gesundheitswesen
berichtet → health_data: false (die IHK verarbeitet keine Gesundheitsdaten)
Flags: Flags:
- personal_data: Werden personenbezogene Daten verarbeitet? - personal_data: Erhebt der Betreiber personenbezogene Daten (Name, Email, IP)?
- customer_data: Werden Kundendaten (Name, Email, Adresse) gespeichert? - customer_data: Speichert der Betreiber Kundendaten (Registrierung, Konto)?
- payment_data: Werden Zahlungsdaten (Kreditkarte, IBAN, PayPal) verarbeitet? - payment_data: Verarbeitet der Betreiber Zahlungsdaten (Shop, Buchung)?
- location_data: Werden Standort-/GPS-Daten erhoben? - location_data: Erhebt der Betreiber GPS/Standortdaten der Nutzer?
- biometric_data: Werden biometrische Daten verarbeitet? - biometric_data: Verarbeitet der Betreiber biometrische Daten?
- minor_data: Werden Daten von Kindern/Minderjaehrigen verarbeitet? - minor_data: Richtet sich die Website gezielt an Kinder/Minderjaehrige?
- health_data: Werden Gesundheitsdaten verarbeitet? - health_data: Verarbeitet der Betreiber Gesundheitsdaten seiner Nutzer?
- marketing: Werden Daten fuer Werbung/Marketing/Newsletter genutzt? - marketing: Nutzt der Betreiber Nutzerdaten fuer eigene Werbung/Newsletter?
- profiling: Findet Profiling, Scoring oder Personalisierung statt? - profiling: Erstellt der Betreiber Nutzerprofile oder Scoring?
- automated_decisions: Werden automatisierte Einzelentscheidungen getroffen (Art. 22)? - automated_decisions: Trifft der Betreiber automatisierte Einzelentscheidungen?
- third_party_sharing: Werden Daten an Dritte/Partner weitergegeben? - third_party_sharing: Gibt der Betreiber Nutzerdaten an Dritte weiter?
- cross_border_transfer: Findet Datentransfer ausserhalb EU/EWR statt? - cross_border_transfer: Uebermittelt der Betreiber Daten ausserhalb EU/EWR?
- tracking: Werden Cookies/Tracking-Pixel/Analytics eingesetzt? - tracking: Setzt der Betreiber Cookies/Tracking/Analytics ein?
- ai_usage: Wird KI/Machine Learning/Algorithmen eingesetzt? - ai_usage: Setzt der Betreiber KI/Machine Learning ein?
Antworte NUR mit einem JSON-Objekt, keine Erklaerung: Antworte NUR mit einem JSON-Objekt, keine Erklaerung:
{"personal_data": true, "customer_data": true, ...} {"personal_data": true, "customer_data": false, ...}
""" """
@@ -28,7 +28,16 @@ async def check_website_compliance(
html_lower = html.lower() html_lower = html.lower()
base_domain = re.sub(r"https?://([^/]+).*", r"\1", url) base_domain = re.sub(r"https?://([^/]+).*", r"\1", url)
# --- §312k BGB: Kündigungsbutton --- # E-Commerce detection — §312k only applies to sites with online contracts
ecommerce_indicators = [
r"warenkorb", r"cart", r"shop", r"bestell", r"order",
r"checkout", r"kasse", r"kaufen", r"add.?to.?cart",
r"stripe|paypal|klarna|mollie|adyen",
r"abo", r"mitgliedschaft", r"subscription", r"premium",
]
is_ecommerce = any(re.search(p, html_lower) for p in ecommerce_indicators)
# --- §312k BGB: Kündigungsbutton (NUR bei E-Commerce/Abo-Websites) ---
cancel_patterns = [ cancel_patterns = [
r'href="[^"]*(?:kuendig|kündig|cancel|vertrag.?beenden|abo.?beenden|mitgliedschaft.?beenden)[^"]*"', r'href="[^"]*(?:kuendig|kündig|cancel|vertrag.?beenden|abo.?beenden|mitgliedschaft.?beenden)[^"]*"',
r'(?:kündigen|kuendigen|vertrag beenden|abo beenden|mitgliedschaft kündigen)', r'(?:kündigen|kuendigen|vertrag beenden|abo beenden|mitgliedschaft kündigen)',
@@ -52,7 +61,7 @@ async def check_website_compliance(
except Exception: except Exception:
continue continue
if not has_cancel_link: if not has_cancel_link and is_ecommerce:
findings.append( findings.append(
"[§312k BGB] Kein oeffentlich sichtbarer Kuendigungsbutton gefunden. " "[§312k BGB] Kein oeffentlich sichtbarer Kuendigungsbutton gefunden. "
"Seit 01.07.2022 muessen online geschlossene Vertraege mit max. 2 Klicks kuendbar sein." "Seit 01.07.2022 muessen online geschlossene Vertraege mit max. 2 Klicks kuendbar sein."