Implement full evidence integrity pipeline to prevent compliance theater: - Confidence levels (E0-E4), truth status tracking, assertion engine - Four-Eyes approval workflow, audit trail, reject endpoint - Evidence distribution dashboard, LLM audit routes - Traceability matrix (backend endpoint + Compliance Hub UI tab) - Anti-fake badges, control status machine, normative patterns - 2 migrations, 4 test suites, MkDocs documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
14 KiB
Anti-Fake-Evidence Architektur
Status: Phase 2 (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:
- LLM-generierte Inhalte wurden als echte Nachweise behandelt
- Controls ohne Evidence standen auf "pass"
- 100%-Compliance-Claims ohne Validierung
Die Anti-Fake-Evidence Architektur implementiert 6 Guardrails, die sicherstellen, dass nur nachgewiesene Compliance als solche dargestellt wird.
Evidence Confidence Levels (E0–E4)
| Level | Bezeichnung | Beschreibung | Beispiel |
|---|---|---|---|
| E0 | Generated | LLM-Output, Platzhalter | KI-generierter Nachweis-Entwurf |
| E1 | Uploaded | Manuell hochgeladen, ungeprüft | PDF ohne Reviewer |
| E2 | Reviewed | Intern geprüft, Hash verifiziert | Dokument von Compliance-Beauftragtem bestätigt |
| E3 | Observed | System-beobachtet (CI/CD, API) | Automatischer SAST-Report mit SHA-256 |
| E4 | Auditor-validated | Extern validiert | Wirtschaftsprüfer hat akzeptiert |
Auto-Klassifikation
| Source | Confidence | Truth Status |
|---|---|---|
ci_pipeline |
E3 | observed |
api (mit Hash) |
E3 | observed |
manual / upload |
E1 | uploaded |
generated |
E0 | generated |
Evidence Truth-Status Lifecycle
stateDiagram-v2
[*] --> generated : LLM erzeugt
[*] --> uploaded : Manuell hochgeladen
[*] --> observed : CI/CD Pipeline
generated --> rejected : Review abgelehnt
uploaded --> validated_internal : Intern geprueft
uploaded --> rejected : Review abgelehnt
observed --> validated_internal : Intern bestaetigt
validated_internal --> provided_to_auditor : An Auditor uebergeben
provided_to_auditor --> accepted_by_auditor : Auditor akzeptiert
provided_to_auditor --> rejected : Auditor lehnt ab
Control Status-Transition State Machine
stateDiagram-v2
planned --> in_progress : immer erlaubt
in_progress --> pass : Evidence >= E2 + truth_status valid
in_progress --> partial : min 1 Evidence (beliebig)
in_progress --> fail : immer erlaubt
pass --> fail : Degradation (immer)
partial --> pass : Evidence >= E2 + truth_status valid
note right of pass
Voraussetzung: min 1 Evidence
mit confidence >= E2 UND
truth_status in (uploaded,
observed, validated_internal,
accepted_by_auditor)
end note
Transition-Regeln
| Von | Nach | Voraussetzung |
|---|---|---|
| planned | in_progress | keine |
| in_progress | pass | min 1 Evidence mit confidence >= E2, truth_status valide |
| in_progress | partial | min 1 Evidence (beliebig) |
| in_progress | fail | immer erlaubt |
| pass | fail | immer erlaubt (Degradation) |
| * | n/a | erfordert status_justification |
| * | planned | immer erlaubt (Reset) |
Bei Verstoß: HTTP 409 Conflict mit Liste der Violations.
LLM Truth-Labels
Jeder LLM-generierte Inhalt wird mit einem Truth-Label versehen:
{
"generation_mode": "draft_assistance",
"truth_status": "generated",
"may_be_used_as_evidence": false,
"generated_by": "system"
}
Audit-Trail
Tabelle compliance_llm_generation_audit:
| Feld | Typ | Beschreibung |
|---|---|---|
| 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 | generated, uploaded, ... |
| may_be_used_as_evidence | BOOLEAN | Default: FALSE |
| llm_model | VARCHAR(100) | z.B. 'qwen2.5vl:32b' |
| llm_provider | VARCHAR(50) | 'ollama', 'anthropic' |
| prompt_hash | VARCHAR(64) | SHA-256 des Prompts |
Multi-dimensionaler Compliance-Score
Statt einer einzelnen Prozentzahl zeigt der Score 6 Dimensionen:
| Dimension | Gewicht | Beschreibung |
|---|---|---|
| requirement_coverage | 20% | % Requirements mit verlinktem Control |
| evidence_strength | 25% | Gewichteter Durchschnitt der Evidence-Confidence |
| validation_quality | 20% | % Evidence mit truth_status >= validated_internal |
| evidence_freshness | 10% | % Evidence nicht expired + reviewed < 90 Tage |
| control_effectiveness | 25% | Bestehende Formel (pass + partial*0.5) |
| overall_readiness | — | Gewichteter Composite der 5 Dimensionen |
Hard Blocks
Zusaetzlich werden Sperrgründe angezeigt, die eine Audit-Readiness verhindern:
- Controls auf 'pass' ohne jegliche Evidence
- Controls auf 'pass' mit nur E0/E1-Evidence (keine Validierung)
Verbotene Formulierungen
Der Drafting-Engine Validator prueft auf Formulierungen, die ohne ausreichenden Nachweis nicht verwendet werden duerfen:
| Verboten | Sicher stattdessen |
|---|---|
| "ist compliant" | "soll compliant sein" |
| "erfuellt vollstaendig" | "soll vollstaendig erfuellt werden" |
| "wurde geprueft" | "soll geprueft werden" |
| "wurde umgesetzt" | "ist zur Umsetzung vorgesehen" |
| "ist auditiert" | "soll auditiert werden" |
| "vollstaendig implementiert" | "Implementierung ist vorgesehen" |
| "nachweislich konform" | "Konformitaet ist nachzuweisen" |
Erlaubt nur wenn: control_status = pass AND confidence >= E2 AND truth_status in (validated_internal, accepted_by_auditor).
API-Aenderungen
Neue Endpoints
| Methode | Pfad | Beschreibung |
|---|---|---|
| PATCH | /evidence/{id}/review |
Evidence reviewen (Confidence upgraden) |
| POST | /llm-audit |
LLM-Generierungs-Audit erstellen |
| GET | /llm-audit |
LLM-Audit-Eintraege auflisten |
Erweiterte Responses
EvidenceResponse — 6 neue Felder:
{
"confidence_level": "E3",
"truth_status": "observed",
"generation_mode": null,
"may_be_used_as_evidence": true,
"reviewed_by": null,
"reviewed_at": null
}
DashboardResponse — neues Feld multi_score:
{
"multi_score": {
"requirement_coverage": 85.0,
"evidence_strength": 60.0,
"validation_quality": 40.0,
"evidence_freshness": 90.0,
"control_effectiveness": 70.0,
"overall_readiness": 65.0,
"hard_blocks": ["3 Controls auf 'pass' haben nur E0/E1-Evidence"]
}
}
ControlResponse — neues Feld status_justification.
ControlUpdate — neues Feld status_justification (Pflicht fuer n/a-Transitions).
Status-Transition Fehler (409)
{
"detail": {
"error": "Status transition not allowed",
"current_status": "in_progress",
"requested_status": "pass",
"violations": [
"Transition to 'pass' requires at least 1 evidence with confidence >= E2..."
]
}
}
Migration
Phase 1
Datei: backend-compliance/migrations/076_anti_fake_evidence.sql
- Neue ENUM-Typen:
evidence_confidence_level,evidence_truth_status - 6 neue Spalten auf
compliance_evidence in_progressWert fuercontrolstatusenumstatus_justificationaufcompliance_controls- Neue Tabelle
compliance_llm_generation_audit - Backfill bestehender Evidence nach Source
- Indizes auf neue Spalten
Phase 2
Datei: backend-compliance/migrations/077_anti_fake_evidence_phase2.sql
- Neue Tabelle
compliance_assertions(Assertion Engine) - 6 neue Spalten auf
compliance_evidence(Four-Eyes: approval_status, first_reviewer, etc.) - Performance-Index auf
compliance_audit_trail (entity_type, action, performed_at)
Phase 2: UI-Badges
Badges werden auf Evidence-Cards angezeigt und zeigen den Vertrauensstatus auf einen Blick:
| Badge | Farben | Anzeige |
|---|---|---|
| ConfidenceLevelBadge | E0=rot, E1=gelb, E2=blau, E3=gruen, E4=emerald | Immer |
| TruthStatusBadge | generated=violet, uploaded=grau, observed=blau, validated=gruen, rejected=rot | Immer |
| GenerationModeBadge | violet + Sparkles-Icon | Wenn LLM-generiert |
| ApprovalStatusBadge | pending=gelb, first_approved=blau, approved=gruen, rejected=rot | Nur bei Four-Eyes |
Phase 2: Assertion Engine
Die Assertion Engine trennt Behauptungen von Fakten in Compliance-Texten.
flowchart LR
Text[Freitext] --> Split[Satz-Splitting]
Split --> Classify{Normativ?}
Classify -->|Pflicht| A[Assertion pflicht]
Classify -->|Empfehlung| B[Assertion empfehlung]
Classify -->|Kann| C[Assertion kann]
Classify -->|Begruendung| D[Rationale]
Classify -->|Evidence-Keywords| E[Fact tentativ]
E --> Verify[Manuell verifizieren]
Verify --> Fact[Verified Fact]
Assertion-Typen
| Typ | Bedeutung | Beispiel |
|---|---|---|
| assertion | Normative Aussage (unbewiesen) | "Die Organisation muss ein ISMS implementieren" |
| fact | Verifizierte Tatsache | "ISO-Zertifikat Nr. 12345 liegt vor" |
| rationale | Begruendung | "Dies ist notwendig, weil..." |
Normative Tiers
| Tier | Signal-Woerter |
|---|---|
| pflicht | muss, hat sicherzustellen, ist verpflichtet, shall, must, required |
| empfehlung | soll, sollte, gewaehrleisten, should, ensure |
| kann | kann, darf, may, optional |
Phase 2: Four-Eyes-Prinzip
stateDiagram-v2
[*] --> pending_first : Evidence erstellt (Gov/Priv Domain)
pending_first --> first_approved : 1. Reviewer OK
first_approved --> approved : 2. Reviewer OK (andere Person!)
first_approved --> rejected : 2. Reviewer lehnt ab
pending_first --> rejected : 1. Reviewer lehnt ab
note right of first_approved
Zweiter Reviewer MUSS
eine andere Person sein
als der erste Reviewer
end note
Domains mit Four-Eyes-Pflicht
| Domain | Four-Eyes? | Begruendung |
|---|---|---|
gov |
Ja | Governance-Controls sind audit-kritisch |
priv |
Ja | Datenschutz erfordert unabhaengige Pruefung |
ops, sdlc, ai, ... |
Nein | Operationale Controls mit Single-Review |
Phase 2: Audit-Trail-Erweiterung
Neue Audit-Trail-Eintraege:
| Entity | Action | Wann |
|---|---|---|
| evidence | create | Bei Evidence-Erstellung |
| evidence | review | Bei Confidence/Truth-Status-Aenderung |
| evidence | reject | Bei Evidence-Ablehnung |
| control | status_change | Bei Control-Status-Aenderung |
Jeder Eintrag enthaelt old_value, new_value und einen SHA-256 checksum.
Neuer Query-Endpoint: GET /audit-trail?entity_type=evidence&entity_id={id}
Phase 2: Neue API-Endpoints
| Methode | Pfad | Beschreibung |
|---|---|---|
| PATCH | /evidence/{id}/reject |
Evidence ablehnen |
| GET | /audit-trail |
Audit-Trail abfragen (Filter: entity_type, entity_id, action) |
| POST | /assertions |
Assertion manuell erstellen |
| GET | /assertions |
Assertions auflisten (Filter: entity_type, entity_id, assertion_type) |
| 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) |
Erweiterte EvidenceResponse (Phase 2)
{
"approval_status": "first_approved",
"first_reviewer": "reviewer1@example.com",
"first_reviewed_at": "2026-03-23T14:00:00Z",
"second_reviewer": null,
"second_reviewed_at": null,
"requires_four_eyes": true
}
Phase 3: Durchsetzung (UI + Dashboard)
Phase 3 macht das Anti-Fake-Evidence-System benutzbar und durchsetzbar im Frontend.
Evidence Review/Reject UI
Die Evidence-Seite bietet jetzt direkte Buttons fuer Review und Ablehnung:
- Reviewen-Button: Sichtbar wenn
approvalStatusnichtapprovedoderrejected - Ablehnen-Button: Sichtbar bei Four-Eyes-Evidence die noch nicht abgeschlossen ist
ReviewModal erlaubt:
- Confidence-Level aendern (E0-E4 Dropdown)
- Truth-Status aendern (Dropdown)
- Reviewer E-Mail angeben
- Four-Eyes-Warnung wenn noch ein weiterer Review noetig ist
RejectModal erlaubt:
- Ablehnungsgrund als Freitext
- Reviewer E-Mail angeben
Bei Four-Eyes Same-Person-Fehler (HTTP 400) wird eine Fehlermeldung angezeigt.
Control Status-Transition Fehlerbehandlung
Die Controls-Seite zeigt jetzt detaillierte Fehler bei blockierten Status-Transitionen:
- Optimistic Update mit Rollback: UI aktualisiert sofort, rollt bei Fehler zurueck
- TransitionErrorBanner: Zeigt Violations-Liste bei HTTP 409 Conflict
- z.B. "Transition to 'pass' requires at least 1 evidence with confidence >= E2"
- Link zur Evidence-Seite: "Evidence hinzufuegen" direkt im Fehler-Banner
Evidence Audit-Trail Anzeige
Neuer "Historie"-Button auf jeder Evidence-Card zeigt den vollstaendigen Audit-Trail:
- Timeline mit Zeitstempel, Aktion und Akteur
- Details zu Feldaenderungen (old_value → new_value)
- Lazy-Loading: Erst beim Aufklappen wird
GET /audit-trailabgerufen
Evidence Confidence-Filter
Neue Filter-Pills auf der Evidence-Seite:
[Alle] [Gueltig] [Abgelaufen] [Ausstehend] | [E0] [E1] [E2] [E3] [E4]
Farbcodierung: E0=rot, E1=gelb, E2=blau, E3=gruen, E4=emerald (passend zu den Badges)
Evidence Confidence-Verteilung (Dashboard)
Neuer Endpoint und Dashboard-Bereich:
Endpoint: GET /dashboard/evidence-distribution
{
"by_confidence": {"E0": 2, "E1": 5, "E2": 3, "E3": 8, "E4": 1},
"four_eyes_pending": 3,
"total": 19
}
Compliance Hub zeigt:
- Horizontal gestapelter Balken der Confidence-Verteilung (E0 rot → E4 emerald)
- Multi-Score Dimensionen als Fortschrittsbalken (5 Dimensionen + Audit-Readiness)
- Four-Eyes-Warteschlange (Anzahl pending)
- Hard-Blocks-Liste oder "Keine Hard Blocks" Status
Assertions-Seite
Neue Seite unter /sdk/assertions mit 3 Tabs:
| Tab | Inhalt |
|---|---|
| Uebersicht | Summary-Stats (Assertions, Facts, Rationale, Unverified) |
| Assertion-Liste | Filterbarer Tabelle (entity_type, assertion_type) mit AssertionCards |
| Extraktion | Textfeld + Button → POST /assertions/extract |
AssertionCard zeigt:
- Normative-Tier als farbiger Badge (Pflicht=rot, Empfehlung=gelb, Kann=blau)
- Typ-Badge (Assertion/Fact/Rationale)
- "Als Fakt pruefen"-Button →
POST /assertions/{id}/verify
Phase 3: Neue API-Endpoints
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /dashboard/evidence-distribution |
Evidence-Verteilung nach Confidence + Four-Eyes-Status |