Files
breakpilot-compliance/docs-src/services/sdk-modules/anti-fake-evidence.md
Benjamin Admin 81ce9dde07
All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 32s
CI/CD / test-python-backend-compliance (push) Successful in 29s
CI/CD / test-python-document-crawler (push) Successful in 21s
CI/CD / test-python-dsms-gateway (push) Successful in 16s
CI/CD / validate-canonical-controls (push) Successful in 10s
CI/CD / Deploy (push) Successful in 2s
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 <noreply@anthropic.com>
2026-03-25 22:22:01 +01:00

814 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Anti-Fake-Evidence Architektur
**Status:** Phase 3 (aktiv seit 2026-03-23)
**Prefix:** CP-AFE
**Motivation:** Delve-Vorfall (Maerz 2026) — Compliance-Theater verhindern
---
## Warum dieses System existiert
### Das Delve-Problem
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<br/>(E0-E4)"]
G2["2. Truth-Status Lifecycle<br/>(generated → validated)"]
G3["3. Control Status Machine<br/>(pass erfordert Evidence ≥ E2)"]
G4["4. Four-Eyes-Prinzip<br/>(GOV/PRIV: 2 unabhaengige Reviewer)"]
G5["5. LLM Truth Labels<br/>(may_be_used_as_evidence = false)"]
G6["6. Verbotene Formulierungen<br/>(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.
---
## Evidence Confidence Levels (E0E4)
| 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
```mermaid
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
```mermaid
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:
```json
{
"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:
```json
{
"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`:
```json
{
"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)
```json
{
"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_progress` Wert fuer `controlstatusenum`
- `status_justification` auf `compliance_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.
```mermaid
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
```mermaid
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)
```json
{
"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 `approvalStatus` nicht `approved` oder `rejected`
- **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-trail` abgerufen
### 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`
```json
{
"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 |
---
## 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<br/>Generated<br/>❌ Kein Nachweis"]
E1["E1<br/>Uploaded<br/>⚠️ Ungeprüft"]
E2["E2<br/>Reviewed<br/>✓ Intern geprüft"]
E3["E3<br/>Observed<br/>✓✓ System-beobachtet"]
E4["E4<br/>Auditor<br/>✓✓✓ 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.