Files
breakpilot-compliance/backend-compliance/compliance/services/doc_checks/agb_checks.py
T
Benjamin Admin b363c28539 feat: Add 76 Level-2 regex checks for document correctness verification
Split dsi_document_checker.py (466 LOC) into doc_checks/ package (9 files).
Two-pass L1→L2 logic: L1 checks "Is it mentioned?", L2 checks "Is it correct?"
(e.g. controller has full address, specific Art. 6 lit., concrete time periods).

138 total checks (62 L1 + 76 L2) across 7 doc types:
- DSE Art. 13: 31, Impressum §5 TMG: 16, Cookie §25 TDDDG: 15
- Widerruf §355: 15, AGB §305ff: 21, Social Media Art. 26: 20, DSFA Art. 35: 18

Frontend: hierarchical L1→L2 display with dual progress bars
(green=completeness, blue=correctness).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-07 12:37:03 +02:00

262 lines
9.8 KiB
Python

"""
AGB checks — §305ff BGB.
Level 1: Pflichtangabe erwaehnt?
Level 2: Pflichtangabe korrekt/vollstaendig?
"""
AGB_CHECKLIST = [
# ── L1: Geltungsbereich ───────────────────────────────────────────
{
"id": "scope",
"label": "Geltungsbereich",
"level": 1, "parent": None,
"patterns": [
r"geltungsbereich", r"geltung", r"scope",
r"diese\s+(?:agb|bedingungen)\s+gelten",
],
"severity": "HIGH",
},
{
"id": "incorporation_clause",
"label": "Einbeziehungsklausel (§305 BGB)",
"level": 2, "parent": "scope",
"patterns": [
r"einbezieh", r"bestandteil\s+des\s+vertrag",
r"(?:mit|durch)\s+(?:der\s+)?bestellung.*(?:anerkennen|akzeptieren|zustimm)",
r"§\s*305",
],
"severity": "MEDIUM",
},
# ── L1: Vertragsschluss ───────────────────────────────────────────
{
"id": "contract",
"label": "Vertragsschluss",
"level": 1, "parent": None,
"patterns": [
r"vertragsschluss", r"zustandekommen",
r"contract\s+formation", r"angebot\s+und\s+annahme",
],
"severity": "HIGH",
},
# ── L1: Haftung ───────────────────────────────────────────────────
{
"id": "liability",
"label": "Haftung / Haftungsbeschraenkung",
"level": 1, "parent": None,
"patterns": [
r"haftung", r"liability",
r"schadensersatz", r"haftungsbeschr(?:ae|ä)nkung",
],
"severity": "HIGH",
},
# ── L1: Gerichtsstand / Anwendbares Recht ─────────────────────────
{
"id": "jurisdiction",
"label": "Gerichtsstand / Anwendbares Recht",
"level": 1, "parent": None,
"patterns": [
r"gerichtsstand", r"anwendbares\s+recht",
r"jurisdiction", r"governing\s+law",
],
"severity": "MEDIUM",
},
{
"id": "dispute_odr_link",
"label": "ODR-Plattform-Link (EU-Verordnung 524/2013)",
"level": 2, "parent": "jurisdiction",
"patterns": [
r"ec\.europa\.eu.*odr",
r"(?:os|odr)[\-\s]plattform",
r"(?:online[\-\s]?streitbeilegung|online\s+dispute\s+resolution)",
],
"severity": "MEDIUM",
},
{
"id": "choice_of_law_specific",
"label": "Konkretes Recht benannt (z.B. deutsches Recht)",
"level": 2, "parent": "jurisdiction",
"patterns": [
r"(?:deutsches|(?:oe|ö)sterreichisches|schweizerisches)\s+recht",
r"recht\s+der\s+bundesrepublik",
r"german\s+law|law\s+of\s+germany",
r"un[\-\s]kaufrecht.*(?:ausgeschlossen|findet\s+keine\s+anwendung)",
],
"severity": "LOW",
},
# ── L1: Zahlungsbedingungen ───────────────────────────────────────
{
"id": "payment",
"label": "Zahlungsbedingungen",
"level": 1, "parent": None,
"patterns": [
r"zahlungsbedingung", r"payment\s+terms",
r"(?:preis|kosten|entgelt|verg(?:ue|ü)tung)",
r"zahlungsweise", r"rechnungsstellung",
],
"severity": "MEDIUM",
},
{
"id": "payment_methods",
"label": "Konkrete Zahlungsarten benannt",
"level": 2, "parent": "payment",
"patterns": [
r"(?:vorkasse|nachnahme|lastschrift|sepa|(?:ue|ü)berweisung|kreditkarte|paypal|sofort(?:ue|ü)berweisung|klarna|rechnung|giropay|apple\s*pay|google\s*pay)",
],
"severity": "LOW",
},
{
"id": "payment_due_date",
"label": "Faelligkeit/Zahlungsziel angegeben",
"level": 2, "parent": "payment",
"patterns": [
r"(?:f(?:ae|ä)llig|zahlbar|zahlungsziel)\s+(?:sofort|innerhalb|nach|bei|mit)",
r"(?:netto|brutto)\s*\d+\s+tage",
r"zahlungsfrist",
],
"severity": "LOW",
},
# ── L1: Lieferung ─────────────────────────────────────────────────
{
"id": "delivery",
"label": "Lieferung / Leistungserbringung",
"level": 1, "parent": None,
"patterns": [
r"lieferung", r"leistungserbringung", r"delivery",
r"lieferfrist", r"bereitstellung",
r"(?:zugang|zugriff).*(?:dienst|leistung)",
],
"severity": "MEDIUM",
},
{
"id": "delivery_timeframe",
"label": "Konkrete Lieferzeit/Frist angegeben",
"level": 2, "parent": "delivery",
"patterns": [
r"(?:lieferzeit|lieferfrist|versanddauer)\s*(?:betr(?:ae|ä)gt|von|ca\.?|circa)",
r"\d+[\-\s]+(?:\d+\s+)?(?:werk)?tage.*(?:liefer|versand)",
r"(?:liefer|versand).*\d+[\-\s]+(?:\d+\s+)?(?:werk)?tage",
],
"severity": "LOW",
},
# ── L1: Gewaehrleistung ───────────────────────────────────────────
{
"id": "warranty",
"label": "Gewaehrleistung / Maengelrechte",
"level": 1, "parent": None,
"patterns": [
r"gew(?:ae|ä)hrleistung", r"m(?:ae|ä)ngelrecht",
r"warranty", r"sachm(?:ae|ä)ngel",
r"gew(?:ae|ä)hrleistungsfrist",
],
"severity": "MEDIUM",
},
{
"id": "warranty_period",
"label": "Gewaehrleistungsfrist angegeben",
"level": 2, "parent": "warranty",
"patterns": [
r"(?:gew(?:ae|ä)hrleistungsfrist|verj(?:ae|ä)hrungsfrist)\s*(?:betr(?:ae|ä)gt|von|:)",
r"(?:2|zwei)\s+jahre.*(?:gew(?:ae|ä)hrleistung|m(?:ae|ä)ngel|verj(?:ae|ä)hrung)",
r"(?:gew(?:ae|ä)hrleistung|m(?:ae|ä)ngel|verj(?:ae|ä)hrung).*(?:2|zwei)\s+jahre",
],
"severity": "LOW",
},
# ── L1: Kuendigung ────────────────────────────────────────────────
{
"id": "termination",
"label": "Kuendigung / Vertragsbeendigung",
"level": 1, "parent": None,
"patterns": [
r"k(?:ue|ü)ndigung", r"vertragsbeendigung",
r"termination", r"laufzeit.*(?:vertrag|abo)",
r"k(?:ue|ü)ndigungsfrist",
],
"severity": "MEDIUM",
},
{
"id": "termination_period",
"label": "Kuendigungsfrist angegeben",
"level": 2, "parent": "termination",
"patterns": [
r"k(?:ue|ü)ndigungsfrist\s+(?:von|betr(?:ae|ä)gt)",
r"\d+\s+(?:tage?|wochen?|monate?).*(?:k(?:ue|ü)ndig|frist)",
r"(?:k(?:ue|ü)ndig|frist).*\d+\s+(?:tage?|wochen?|monate?)",
],
"severity": "LOW",
},
{
"id": "termination_form",
"label": "Formvorschrift fuer Kuendigung",
"level": 2, "parent": "termination",
"patterns": [
r"k(?:ue|ü)ndigung.*(?:schriftlich|textform|per\s+(?:brief|e-?mail|fax))",
r"(?:schriftlich|textform).*k(?:ue|ü)ndigung",
],
"severity": "LOW",
},
# ── L1: Datenschutzhinweis in AGB ─────────────────────────────────
{
"id": "data_protection",
"label": "Datenschutzhinweis in AGB",
"level": 1, "parent": None,
"patterns": [
r"datenschutz.*(?:agb|bedingung)",
r"(?:agb|bedingung).*datenschutz",
r"personenbezogen.*daten.*(?:agb|vertrag)",
r"dsgvo.*(?:agb|vertrag)",
],
"severity": "LOW",
},
# ── Neue L1: Salvatorische Klausel ────────────────────────────────
{
"id": "salvatory_clause",
"label": "Salvatorische Klausel",
"level": 1, "parent": None,
"patterns": [
r"salvatorische",
r"(?:unwirksamkeit|nichtigkeit)\s+(?:einer|einzelner)\s+(?:bestimmung|klausel|regelung)",
r"(?:sollte|sofern).*(?:bestimmung|klausel).*(?:unwirksam|nichtig)",
r"(?:uebrigen|übrigen)\s+bestimmungen.*(?:unberuehrt|unberührt|wirksam|bestehen)",
],
"severity": "LOW",
},
# ── Neue L1: Aenderungsklausel ────────────────────────────────────
{
"id": "amendment_clause",
"label": "Aenderungsklausel fuer AGB",
"level": 1, "parent": None,
"patterns": [
r"(?:ae|ä)nderung.*(?:agb|bedingung)",
r"(?:agb|bedingung).*(?:ae|ä)nder",
r"(?:anpassung|aktualisierung).*(?:agb|bedingung|geschaeftsbedingung|geschäftsbedingung)",
r"(?:neue\s+fassung|neufassung).*(?:agb|bedingung)",
],
"severity": "LOW",
},
# ── Neue L1: Verbraucherrechte §309 ───────────────────────────────
{
"id": "consumer_rights",
"label": "Verbraucherrechte nicht eingeschraenkt (§309 BGB)",
"level": 1, "parent": None,
"patterns": [
r"§\s*309",
r"verbraucherrecht",
r"(?:gesetzlich|zwingende)\w*\s+recht\w*.*(?:unberuehrt|unberührt|bestehen\s+bleiben)",
r"(?:verbrauch|konsument).*(?:recht|anspruch|schutz)",
],
"severity": "LOW",
},
]