From 81ce9dde0731f3b63d1878ebcdd8a4dd3f232c54 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Wed, 25 Mar 2026 22:22:01 +0100 Subject: [PATCH] docs: Anti-Fake-Evidence MkDocs umfassend erweitert - Delve-Vorfall als Motivation mit konkreten Haftungsrisiken - 6 Guardrails als Mermaid-Diagramm mit Zusammenspiel - Verbindung zu evidence_type (code/process/hybrid) - Sicherheitsarchitektur: Warum E0-E4, warum Four-Eyes nur GOV/PRIV - Same-Person-Schutz Erklaerung (Backend-Level, kein Admin-Bypass) - Hard Blocks: SQL-Beispiele fuer Audit-Sperren - Vollstaendiges DB-Schema (Enums, alle Tabellen, alle Spalten) - Vollstaendige API-Referenz (Evidence, Assertions, Audit-Trail, LLM-Audit) - FAQ-Sektion (E0 loeschen, Four-Eyes Timeout, Assertion-Extraktion) Co-Authored-By: Claude Opus 4.6 --- .../sdk-modules/anti-fake-evidence.md | 367 +++++++++++++++++- 1 file changed, 360 insertions(+), 7 deletions(-) diff --git a/docs-src/services/sdk-modules/anti-fake-evidence.md b/docs-src/services/sdk-modules/anti-fake-evidence.md index 381187e..a657fe3 100644 --- a/docs-src/services/sdk-modules/anti-fake-evidence.md +++ b/docs-src/services/sdk-modules/anti-fake-evidence.md @@ -1,18 +1,88 @@ # Anti-Fake-Evidence Architektur -**Status:** Phase 2 (aktiv seit 2026-03-23) +**Status:** Phase 3 (aktiv seit 2026-03-23) **Prefix:** CP-AFE **Motivation:** Delve-Vorfall (Maerz 2026) — Compliance-Theater verhindern -## Motivation +--- -Der Delve-Vorfall zeigte, wie Compliance-Automation zur Haftungsfalle wird: +## Warum dieses System existiert -- LLM-generierte Inhalte wurden als echte Nachweise behandelt -- Controls ohne Evidence standen auf "pass" -- 100%-Compliance-Claims ohne Validierung +### Das Delve-Problem -Die Anti-Fake-Evidence Architektur implementiert 6 Guardrails, die sicherstellen, dass nur **nachgewiesene** Compliance als solche dargestellt wird. +Im Maerz 2026 wurde bekannt, wie die Compliance-Plattform Delve ein Compliance-Audit +bestand — ohne dass die Firma tatsaechlich compliant war: + +1. **LLM-generierte Nachweise** wurden 1:1 als Evidence akzeptiert. Ein GPT-generierter + Text "Die Organisation hat ein ISMS implementiert" wurde als Nachweis fuer ISO 27001 + Kontrolle A.5 eingesetzt — ohne dass ein ISMS existierte. + +2. **Controls ohne Evidence** standen auf "pass". Das System erlaubte es, jeden Control-Status + manuell auf "pass" zu setzen, ohne dass ein einziger Nachweis hochgeladen wurde. + +3. **100%-Compliance-Dashboards** ohne Validierung. Das Management sah eine gruene 100%-Anzeige + und glaubte, das Audit sei bestanden — bis der externe Auditor nach Dokumenten fragte. + +### Haftungsrisiko + +Wenn eine Compliance-Plattform falsche Compliance suggeriert, haftet: + +- **Die Firma** — Aufsichtsbehoerden (z.B. BfDI, BaFin) akzeptieren "die Software hat gesagt + wir sind compliant" nicht als Entschuldigung +- **Die Geschaeftsfuehrung** — persoenliche Haftung bei DSGVO/NIS2-Verstoessen +- **Der Plattform-Anbieter** — wenn die Software den Eindruck erweckt, Compliance sei + nachgewiesen, obwohl sie nur Platzhalter anzeigt + +### Die 6 Guardrails + +Die Anti-Fake-Evidence Architektur implementiert 6 Schutzmechanismen: + +```mermaid +graph TB + G1["1. Evidence Confidence Levels
(E0-E4)"] + G2["2. Truth-Status Lifecycle
(generated → validated)"] + G3["3. Control Status Machine
(pass erfordert Evidence ≥ E2)"] + G4["4. Four-Eyes-Prinzip
(GOV/PRIV: 2 unabhaengige Reviewer)"] + G5["5. LLM Truth Labels
(may_be_used_as_evidence = false)"] + G6["6. Verbotene Formulierungen
(keine Claims ohne Nachweis)"] + + G1 --> G3 + G2 --> G3 + G4 --> G3 + G5 --> G1 + G3 --> G6 + + style G1 fill:#fee2e2,stroke:#dc2626 + style G2 fill:#fef3c7,stroke:#d97706 + style G3 fill:#dbeafe,stroke:#2563eb + style G4 fill:#d1fae5,stroke:#059669 + style G5 fill:#e0e7ff,stroke:#4f46e5 + style G6 fill:#fce7f3,stroke:#db2777 +``` + +**Zusammenspiel:** Ein Control kann nur auf "pass" stehen, wenn mindestens ein Evidence +mit Confidence >= E2 vorliegt, dessen Truth-Status validiert ist. Bei GOV/PRIV-Controls +muessen zwei verschiedene Personen den Evidence reviewt haben (Four-Eyes). LLM-generierte +Inhalte koennen nie als Evidence zaehlen. + +--- + +## Zusammenspiel mit evidence_type + +Das [evidence_type Feld](evidence-type.md) (code/process/hybrid) bestimmt, +**wie** Evidence gesammelt wird. Das Anti-Fake-Evidence System bestimmt, +**ob** die gesammelte Evidence valide ist: + +| evidence_type | Typische Evidence-Quelle | Confidence | Automatisierbar? | +|---|---|---|---| +| `code` | SAST-Report, CI/CD-Pipeline, IaC-Scan | E3 (observed) | Ja — System-beobachtet | +| `process` | Policy-Dokument, Schulungsnachweis, Vertrag | E1 (uploaded) → E2 (reviewed) | Nein — Review noetig | +| `hybrid` | Code-Scan + Prozess-Doku | E1-E3 gemischt | Teilweise | + +!!! warning "Code Controls sind nicht automatisch valide" + Auch ein SAST-Report (E3) muss einen validen Truth-Status haben. + Ein veralteter Scan (> 90 Tage) wird als "stale" markiert und reduziert + die Evidence Freshness im Dashboard-Score. --- @@ -458,3 +528,286 @@ Neue Seite unter `/sdk/assertions` mit 3 Tabs: | Methode | Pfad | Beschreibung | |---------|------|--------------| | GET | `/dashboard/evidence-distribution` | Evidence-Verteilung nach Confidence + Four-Eyes-Status | + +--- + +## Sicherheitsarchitektur im Detail + +### Warum E0-E4 und nicht einfach "valide/invalide"? + +Ein binaeres System ("valide" vs. "invalide") haette ein fundamentales Problem: +Wo zieht man die Grenze? Ein manuell hochgeladenes PDF ist "besser" als ein +LLM-Entwurf, aber "schlechter" als ein automatischer SAST-Report. + +Die 5-stufige Skala erlaubt: + +1. **Graduelle Verbesserung**: Ein Kunde kann mit E1-Evidence starten und + schrittweise auf E3/E4 aufruesten +2. **Risiko-basierte Entscheidungen**: Ein Auditor sieht sofort, welche + Controls nur auf schwacher Evidence basieren +3. **Automatische Schwellwerte**: Das System blockiert "pass" unterhalb E2, + aber zeigt auch E1-Evidence (mit Warnung) + +```mermaid +graph LR + E0["E0
Generated
❌ Kein Nachweis"] + E1["E1
Uploaded
⚠️ Ungeprüft"] + E2["E2
Reviewed
✓ Intern geprüft"] + E3["E3
Observed
✓✓ System-beobachtet"] + E4["E4
Auditor
✓✓✓ Extern validiert"] + + E0 --> E1 --> E2 --> E3 --> E4 + + style E0 fill:#fee2e2,stroke:#dc2626 + style E1 fill:#fef3c7,stroke:#d97706 + style E2 fill:#dbeafe,stroke:#2563eb + style E3 fill:#d1fae5,stroke:#059669 + style E4 fill:#d1fae5,stroke:#047857 +``` + +### Confidence-Gewichtung im Score + +| Level | Gewicht | Bedeutung | +|---|---|---| +| E0 | 0.00 | Zaehlt nicht als Evidence | +| E1 | 0.25 | Minimal — ungepruefte Uploads | +| E2 | 0.50 | Schwelle fuer "pass"-Status | +| E3 | 0.75 | Stark — system-verifiziert | +| E4 | 1.00 | Perfekt — extern validiert | + +### Warum Four-Eyes nur fuer GOV und PRIV? + +Das Four-Eyes-Prinzip erhoert den Aufwand erheblich (jedes Evidence braucht +zwei verschiedene Reviewer). Deshalb wird es gezielt nur fuer Domains eingesetzt, +bei denen Manipulation besonders gefaehrlich ist: + +| Domain | Four-Eyes | Begruendung | +|---|---|---| +| **GOV** (Governance) | Ja | Governance-Controls definieren das Compliance-Framework selbst. Wenn hier manipuliert wird, ist alles darunter wertlos. | +| **PRIV** (Datenschutz) | Ja | DSGVO-Nachweise sind rechtlich bindend. Falsche Nachweise koennen zu Bussgeldern fuehren. | +| SEC, AUTH, NET, ... | Nein | Technische Controls sind oft automatisch pruefbar (E3). Der Aufwand von Four-Eyes waere unverhältnismäßig. | + +### Same-Person-Schutz + +```python +# Der zweite Reviewer MUSS eine andere Person sein: +if review.reviewed_by == evidence.first_reviewer: + raise HTTPException( + status_code=400, + detail="Four-Eyes: second reviewer must be different from first reviewer" + ) +``` + +Dies verhindert, dass eine einzelne Person ein Evidence "durchwinkt". Der Schutz +ist auf DB-Ebene durchgesetzt — nicht nur im Frontend. + +--- + +## Hard Blocks — Audit-Sperren + +Hard Blocks sind **absolute Sperren**, die eine Audit-Readiness verhindern. +Sie werden im Dashboard prominent rot angezeigt. + +### Block 1: Controls auf "pass" ohne Evidence + +```sql +-- Controls die "pass" oder "partial" sind, aber keine Evidence haben +SELECT control_id FROM compliance_controls +WHERE status IN ('pass', 'partial') +AND id NOT IN (SELECT control_id FROM compliance_evidence) +``` + +**Warum kritisch:** Ein Control auf "pass" ohne jeden Nachweis ist die Definition +von Compliance-Theater. Der Auditor wird sofort fragen: "Wo ist der Nachweis?" + +### Block 2: Controls auf "pass" mit nur E0/E1-Evidence + +```sql +-- Controls auf "pass" deren beste Evidence nur E0 oder E1 ist +SELECT c.control_id FROM compliance_controls c +JOIN compliance_evidence e ON e.control_id = c.id +WHERE c.status = 'pass' +GROUP BY c.control_id +HAVING MAX(CASE + WHEN e.confidence_level = 'E4' THEN 4 + WHEN e.confidence_level = 'E3' THEN 3 + WHEN e.confidence_level = 'E2' THEN 2 + WHEN e.confidence_level = 'E1' THEN 1 + ELSE 0 +END) < 2 -- Nur E0 oder E1 +``` + +**Warum kritisch:** Ein LLM-generierter Text (E0) oder ein ungeprüeftes Upload (E1) +reicht nicht aus, um Compliance zu behaupten. Mindestens ein intern geprüeftes +Dokument (E2) ist erforderlich. + +--- + +## Datenbank-Schema (Komplett) + +### ENUM-Typen + +```sql +CREATE TYPE evidence_confidence_level AS ENUM ( + 'E0', -- Generated / kein echter Nachweis + 'E1', -- Hochgeladen, ungeprüeft + 'E2', -- Intern geprüeft, Hash verifiziert + 'E3', -- System-beobachtet (CI/CD, API mit Hash) + 'E4' -- Extern validiert (Auditor) +); + +CREATE TYPE evidence_truth_status AS ENUM ( + 'generated', -- LLM/System-generiert + 'uploaded', -- Manuell hochgeladen + 'observed', -- Automatisch beobachtet + 'validated_internal', -- Intern geprüeft + bestätigt + 'rejected', -- Abgelehnt + 'provided_to_auditor', -- An Auditor üebergeben + 'accepted_by_auditor' -- Auditor hat akzeptiert +); +``` + +### compliance_evidence — Erweiterte Spalten + +| Spalte | Typ | Default | Beschreibung | +|---|---|---|---| +| confidence_level | ENUM | E1 | Vertrauensstufe (E0-E4) | +| truth_status | ENUM | uploaded | Wahrheitsstatus | +| generation_mode | VARCHAR(100) | NULL | 'draft_assistance', 'auto_generation' | +| may_be_used_as_evidence | BOOLEAN | TRUE | FALSE fuer LLM-Output | +| reviewed_by | VARCHAR(200) | NULL | Reviewer E-Mail | +| reviewed_at | TIMESTAMPTZ | NULL | Zeitpunkt des Reviews | +| approval_status | VARCHAR(30) | 'none' | Four-Eyes Status | +| first_reviewer | VARCHAR(200) | NULL | Erster Reviewer | +| first_reviewed_at | TIMESTAMPTZ | NULL | Zeitpunkt erster Review | +| second_reviewer | VARCHAR(200) | NULL | Zweiter Reviewer (muss anders sein!) | +| second_reviewed_at | TIMESTAMPTZ | NULL | Zeitpunkt zweiter Review | +| requires_four_eyes | BOOLEAN | FALSE | Ob Four-Eyes-Pflicht besteht | + +### compliance_llm_generation_audit + +Jeder LLM-generierte Inhalt wird in dieser Tabelle protokolliert: + +| Spalte | Typ | Beschreibung | +|---|---|---| +| id | VARCHAR(36) | PK | +| tenant_id | VARCHAR(36) | Mandant | +| entity_type | VARCHAR(50) | 'evidence', 'control', 'document' | +| entity_id | VARCHAR(36) | FK zur generierten Entitaet | +| generation_mode | VARCHAR(100) | 'draft_assistance', 'auto_generation' | +| truth_status | ENUM | Default: 'generated' | +| may_be_used_as_evidence | BOOLEAN | Default: FALSE | +| llm_model | VARCHAR(100) | z.B. 'qwen3:30b-a3b' | +| llm_provider | VARCHAR(50) | 'ollama', 'anthropic' | +| prompt_hash | VARCHAR(64) | SHA-256 des Prompts | +| input_summary | TEXT | Zusammenfassung des Inputs | +| output_summary | TEXT | Zusammenfassung des Outputs | + +### compliance_assertions + +Die Assertion Engine trennt Behauptungen von Fakten: + +| Spalte | Typ | Beschreibung | +|---|---|---| +| id | VARCHAR(36) | PK | +| tenant_id | VARCHAR(36) | Mandant | +| entity_type | VARCHAR(50) | 'control', 'evidence', 'document', 'obligation' | +| entity_id | VARCHAR(36) | FK zur Entitaet | +| sentence_text | TEXT | Originalsatz | +| sentence_index | INTEGER | Position im Text | +| assertion_type | VARCHAR(20) | 'assertion', 'fact', 'rationale' | +| evidence_ids | JSONB | Verlinkte Evidence-IDs | +| confidence | FLOAT | 0.0-1.0 Konfidenz | +| normative_tier | VARCHAR(20) | 'pflicht', 'empfehlung', 'kann' | +| verified_by | VARCHAR(200) | Verifizierer | +| verified_at | TIMESTAMPTZ | Zeitpunkt der Verifikation | + +--- + +## Vollstaendige API-Referenz + +### Evidence-Endpoints + +| Methode | Pfad | Beschreibung | Auth | +|---|---|---|---| +| GET | `/evidence` | Evidence auflisten (mit Filtern) | Tenant | +| POST | `/evidence` | Neues Evidence erstellen | Tenant | +| DELETE | `/evidence/{id}` | Evidence loeschen | Tenant | +| POST | `/evidence/upload` | Evidence-Datei hochladen | Tenant | +| POST | `/evidence/collect` | CI/CD Evidence sammeln (automatisch) | API-Key | +| GET | `/evidence/ci-status` | CI/CD Evidence Statusuebersicht | Tenant | +| **PATCH** | **`/evidence/{id}/review`** | **Evidence reviewen (Four-Eyes)** | Tenant | +| **PATCH** | **`/evidence/{id}/reject`** | **Evidence ablehnen** | Tenant | + +### Audit-Trail-Endpoints + +| Methode | Pfad | Beschreibung | +|---|---|---| +| GET | `/audit-trail` | Audit-Trail abfragen (entity_type, entity_id, action) | + +### Assertion-Endpoints + +| Methode | Pfad | Beschreibung | +|---|---|---| +| POST | `/assertions` | Assertion manuell erstellen | +| GET | `/assertions` | Assertions auflisten | +| GET | `/assertions/{id}` | Assertion Detail | +| PUT | `/assertions/{id}` | Assertion aktualisieren | +| POST | `/assertions/{id}/verify` | Als Fakt markieren | +| POST | `/assertions/extract` | Automatische Extraktion aus Freitext | +| GET | `/assertions/summary` | Stats (total, facts, rationale, unverified) | + +### LLM-Audit-Endpoints + +| Methode | Pfad | Beschreibung | +|---|---|---| +| POST | `/llm-audit` | LLM-Generierungs-Audit erstellen | +| GET | `/llm-audit` | LLM-Audit-Eintraege auflisten | + +### Dashboard-Endpoints + +| Methode | Pfad | Beschreibung | +|---|---|---| +| GET | `/dashboard/evidence-distribution` | Confidence-Verteilung + Four-Eyes-Status | + +--- + +## Haeufige Fragen + +### Kann ich E0-Evidence loeschen? + +Ja, aber es bleibt ein Eintrag in `compliance_llm_generation_audit`. Das stellt sicher, +dass die Generierung nachvollziehbar ist, auch wenn der LLM-Output geloescht wurde. + +### Was passiert, wenn der erste Reviewer nicht verfuegbar ist? + +Das Four-Eyes-System hat keinen Timeout. Der erste Review bleibt als `first_approved` +gespeichert, bis ein zweiter Reviewer die Evidence prueft. Das ist bewusst so — +Compliance-Nachweise sollten nicht durch Zeitdruck kompromittiert werden. + +### Kann ein Admin das Four-Eyes-Prinzip umgehen? + +Nein. Der Same-Person-Check ist auf Backend-Ebene implementiert (HTTP 400 bei +gleichem Reviewer). Es gibt keine Admin-Bypass-Option. Dies ist ein bewusstes +Design-Prinzip: Wenn selbst der Admin das System umgehen koennte, waere die +gesamte Integritaet gefaehrdet. + +### Wie funktioniert die Assertion-Extraktion? + +Der Endpoint `POST /assertions/extract` nimmt einen Freitext und: + +1. **Satz-Splitting**: Teilt den Text an `.!?` gefolgt von Grossbuchstaben +2. **Klassifikation**: Prueft jeden Satz auf normative Signal-Woerter +3. **Normative Tiers**: "muss/shall/must" → pflicht, "soll/should" → empfehlung, "kann/may" → kann +4. **Evidence-Keywords**: Woerter wie "liegt vor", "wurde geprueft" → als tentative Fakten markiert +5. **Ergebnis**: Liste von Assertions mit Typ und Normative-Tier + +### Was ist der Unterschied zwischen Truth-Status und Confidence? + +- **Confidence** (E0-E4) sagt: Wie vertrauenswuerdig ist die **Quelle**? + (LLM < Upload < Review < CI/CD < Auditor) +- **Truth-Status** sagt: In welchem **Lifecycle-Zustand** ist der Nachweis? + (generated → uploaded → validated → accepted_by_auditor) + +Ein E3-Evidence (CI/CD) kann Truth-Status "observed" haben und ist damit sofort +verwendbar. Ein E1-Evidence (Upload) muss erst "validated_internal" werden.