docs: Master Controls spec for document checker — 80-100 specific check criteria

Detailed requirements for the pipeline session:
- Binary yes/no check_question per control
- Concrete pass_criteria + fail_criteria (not 'check completeness')
- correction_template from our Template Generator
- 8 document types: DSI, Cookie, Impressum, Widerruf, AGB, DSFA, AVV, Loeschkonzept
- ~80-100 total controls (not 25K generic ones)
- Examples for DSI, Cookie, Impressum with exact field expectations

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-07 07:53:36 +02:00
parent a680276c86
commit e19d9ca532
@@ -0,0 +1,191 @@
# Anforderung: Master Controls fuer Dokumentenpruefung
## Kontext
Der Compliance Agent prueft rechtliche Dokumente (DSI, AGB, Impressum, Cookie-Richtlinie,
Widerrufsbelehrung) gegen Pflichtangaben. Aktuell nutzen wir Regex-Patterns fuer die
Grundpruefung (9 Art. 13 DSGVO Felder) — das funktioniert gut fuer "ist X erwaehnt?".
Der naechste Schritt ist: **Nicht nur pruefen OB etwas erwaehnt wird, sondern ob es
KORREKT und VOLLSTAENDIG ist.** Dafuer brauchen wir Master Controls als Pruefkriterien.
## Das Problem mit den aktuellen Controls
Die 294K Atomic Controls in `canonical_controls` sind zu allgemein:
```
Titel: "Informationspflicht des Verantwortlichen gegenueber betroffenen Personen"
test_procedure: [
"Ueberpruefung der Datenschutzerklaerung auf Vollstaendigkeit",
"Pruefung ob Name und Kontaktdaten des Verantwortlichen angegeben sind",
"Verifizierung ob Kontaktdaten des DSB vorhanden sind",
]
```
Wenn wir das LLM fragen "Erfuellt der IHK-Text diesen Control?", sagt es "Nein"
weil der Control zu vage ist — "Vollstaendigkeit" ist subjektiv.
## Was wir brauchen
Master Controls mit **konkreten, binaerenr Pruefkriterien** pro Dokumenttyp.
Jeder Control muss eine **JA/NEIN Frage** sein die das LLM eindeutig beantworten kann.
### Beispiel: DSI (Datenschutzinformation nach Art. 13 DSGVO)
```yaml
master_control:
id: "MC-DSI-001"
title: "Vollstaendige Angabe des Verantwortlichen"
doc_type: "dse"
regulation: "DSGVO Art. 13(1)(a)"
check_question: >
Ist der Verantwortliche mit vollstaendigem Namen, Rechtsform,
Anschrift (Strasse, PLZ, Ort), E-Mail-Adresse UND Telefonnummer
angegeben?
pass_criteria:
- "Name des Verantwortlichen mit Rechtsform (z.B. GmbH, e.V., AG)"
- "Vollstaendige Postanschrift (Strasse + Hausnummer + PLZ + Ort)"
- "E-Mail-Adresse"
- "Telefonnummer"
fail_criteria:
- "Nur Firmenname ohne Anschrift"
- "Nur 'Kontaktieren Sie uns' ohne konkrete Daten"
- "Postfach statt Strasse (bei Pflicht zur ladungsfaehigen Anschrift)"
correction_template: >
Verantwortlicher im Sinne der DSGVO:
{{COMPANY_NAME}}
{{STREET}} {{HOUSE_NUMBER}}
{{ZIP}} {{CITY}}
E-Mail: {{EMAIL}}
Telefon: {{PHONE}}
Vertretungsberechtigte: {{REPRESENTATIVES}}
```
### Beispiel: Cookie-Richtlinie (§25 TDDDG)
```yaml
master_control:
id: "MC-COOKIE-003"
title: "Zweckbeschreibung pro Cookie-Kategorie"
doc_type: "cookie"
regulation: "TDDDG §25"
check_question: >
Wird fuer JEDE Cookie-Kategorie (notwendig, funktional, statistik,
marketing) ein konkreter Zweck beschrieben — nicht nur der
Kategoriename sondern WAS damit gemacht wird?
pass_criteria:
- "Pro Kategorie mindestens ein Satz der den Zweck beschreibt"
- "'Statistik-Cookies helfen uns zu verstehen wie Besucher die Seite nutzen'"
- "'Marketing-Cookies werden fuer personalisierte Werbung verwendet'"
fail_criteria:
- "Nur Kategorienamen ohne Erklaerung"
- "'Wir verwenden Cookies' ohne Differenzierung"
- "Zweck nur als 'notwendig fuer den Betrieb' ohne Spezifikation"
```
### Beispiel: Impressum (§5 TMG)
```yaml
master_control:
id: "MC-IMP-002"
title: "Handelsregister und USt-IdNr"
doc_type: "impressum"
regulation: "TMG §5(1) Nr. 4-6"
check_question: >
Sind Handelsregister (Registergericht + HRB/HRA-Nummer) UND
Umsatzsteuer-Identifikationsnummer angegeben (falls vorhanden)?
pass_criteria:
- "Registergericht benannt (z.B. 'Amtsgericht Konstanz')"
- "Registernummer (z.B. 'HRB 12345')"
- "USt-IdNr. im Format DE + 9 Ziffern"
fail_criteria:
- "Nur 'im Handelsregister eingetragen' ohne Details"
- "USt-IdNr. fehlt bei offensichtlichem Gewerbebetrieb"
```
## Gewuenschte Dokumenttypen + Anzahl Controls
| Dokumenttyp | Regulation | Geschaetzte Anzahl Controls |
|-------------|-----------|---------------------------|
| DSI (Datenschutzinformation) | DSGVO Art. 13, Art. 14 | 15-20 |
| Cookie-Richtlinie | TDDDG §25, ePrivacy Art. 5(3) | 8-12 |
| Impressum | TMG §5, MStV §18 | 8-10 |
| Widerrufsbelehrung | BGB §355, §312g | 6-8 |
| AGB | BGB §305, §307, §309 | 10-15 |
| DSFA | DSGVO Art. 35, Landes-Listen | 12-15 |
| AVV | DSGVO Art. 28 | 10-12 |
| Loeschkonzept | DSGVO Art. 5(1)(e), DIN 66398 | 8-10 |
**Gesamt: ca. 80-100 Master Controls** — nicht 25.000, sondern die spezifischen
Pruefkriterien fuer die Dokumentenpruefung.
## Technische Anforderungen
### Felder die der Doc-Checker braucht
```sql
-- Pro Master Control:
id UUID
doc_type VARCHAR -- 'dse', 'cookie', 'impressum', 'widerruf', 'agb', 'dsfa', 'avv'
regulation VARCHAR -- 'DSGVO Art. 13(1)(a)', 'TDDDG §25'
title VARCHAR -- Kurztitel fuer die Checkliste
check_question TEXT -- Die Frage die das LLM beantwortet (JA/NEIN)
pass_criteria JSONB -- Was muss im Text stehen (konkret)
fail_criteria JSONB -- Was darf NICHT stehen / was fehlt
correction_template TEXT -- Korrekturvorschlag mit Platzhaltern
severity VARCHAR -- 'HIGH', 'MEDIUM', 'LOW'
```
### Wie der Doc-Checker sie nutzt
```python
# 1. Query: Alle Controls fuer doc_type='dse'
controls = db.query(MasterControl).filter(doc_type='dse').all()
# 2. Fuer jeden Control: LLM fragen
prompt = f"""
{control.check_question}
PASS wenn: {control.pass_criteria}
FAIL wenn: {control.fail_criteria}
DOKUMENTTEXT:
{document_text[:5000]}
Antworte mit JSON: {{"passed": true/false, "evidence": "textstelle", "issue": "problem"}}
"""
# 3. Bei FAIL: correction_template als Korrekturvorschlag anbieten
```
### Wo die Controls liegen sollen
Entweder:
- **Neue Tabelle** `compliance.doc_check_controls` (saubere Trennung)
- **Oder** in `canonical_controls` mit `doc_type` Feld + Flag `is_doc_check = true`
- **Oder** in `master_controls` mit `lifecycle_phase = 'document_check'`
Die einfachste Variante ist eine neue Tabelle — keine Vermischung mit den
294K bestehenden Controls.
## Zusammenfassung
Wir brauchen **~80-100 hochspezifische Pruefkriterien** die:
1. Einem konkreten Dokumenttyp zugeordnet sind
2. Eine binaere JA/NEIN Frage stellen
3. Konkrete pass_criteria haben (nicht "Vollstaendigkeit pruefen")
4. Konkrete fail_criteria haben (typische Fehler)
5. Einen Korrekturvorschlag mitliefern (aus unseren Templates)
Das LLM (Qwen 3.5:35b) kann dann jede Frage zuverlaessig beantworten
weil die Frage praezise genug ist.