Zum Inhalt

Defense-in-Depth Architektur

Diese Seite dokumentiert die Sicherheits-Topologie der kora-platform, wie sie nach Abschluss der K-Security-Hardening Saga (Phase 1 + Phase 2 + Phase 3 #1, #2 und #3, ~47h Wall-Clock, Saga-Lehren 1–11) live ist.

Die Architektur besteht aus sieben orthogonalen Schichten, die nacheinander einen User-Request verarbeiten. Jede Schicht hat ein eigenes Versagensprofil; bei Versagen einer Schicht greift die nächste — Defense-in-Depth im klassischen Sinn.

Die Topologie ist produkt-weit, nicht customer-spezifisch. Konkrete Customer-spezifische Pattern-Listen, Filename-Marker und Pentest-Befunde aus der jeweiligen Customer-Demo-Umgebung sind in der Customer-Doku referenziert (siehe Abschnitt Customer-spezifische Erweiterungen).

Topologie

User-Request
┌───────────────────────────────────────────────────┐
│  L5 — Multi-turn Persona-Defense (history_filter) │  Pre-LLM
│  α  — Input-Filter (input_filter)                 │  Pre-LLM
│  Cache — Semantischer Response-Cache (Redis)      │  Pre-LLM
│  L2 — Operator-Template Persona-Cleanup           │  Prompt-Bau
│  LLM — vLLM-Inference mit LookAheadBuffer K=16    │  In-Stream
│  Inline-L3 — Pattern-Match auf accumulated text   │  In-Stream
│  L4 — SourceWireForm + Post-Stream-Fallback       │  Post-LLM
└───────────────────────────────────────────────────┘
Token-Stream an Client

Layer-Details

L5 — Multi-turn Persona-Defense

Aspekt Wert
Position Pre-LLM, vor α-Layer
Code src/kora_platform/services/history_filter.py
Patterns persistent_time_marker, ok_only_conditioning, role_override, forget_previous (4 Patterns)
Trigger primary regex + min_co_matches Co-Indicators (Lehre 8: User-Input-Vokabular)
Wirkung β-Marker-Replace: persistierter User-Turn wird in chat_messages durch [FILTERED]-Marker ersetzt; Cache-Skip; LLM erhält die bereinigte History
Audit-Log history_persist_filter_audit (Migration 0017, RLS-isoliert)
Failure-Mode Bei Versagen wird die toxische User-Turn-Persistenz von α nicht mehr gesehen (α arbeitet auf der aktuellen Turn, nicht der History) — Schutz für zukünftige Turns entfällt; aktueller Turn ist trotzdem durch α + Inline-L3 gefangen
Saga-Karte K-Layer-5-History-Persist-Filter (Phase 1, ~5h)

α — Input-Filter

Aspekt Wert
Position Pre-LLM, nach L5, vor Cache
Code src/kora_platform/services/input_filter.py
Patterns json_format_pressure, prompt_leak_input, raw_context_input (3 Patterns)
Trigger primary regex + min_co_matches Co-Indicators (Lehre 8: User-Input-Vokabular, niemals Output-Format-Marker)
Wirkung Pre-LLM-Block; Refusal-Replacement direkt an Client; kein vLLM-Call (NO_TOKENS)
SSE-Reasons input_format_pressure_filter, input_prompt_leak_filter, input_raw_context_filter
Audit-Log input_filter_audit (Migration 0019, RLS-isoliert)
Failure-Mode Bei Versagen läuft der Request voll durch — Schutz fällt auf L2 (Operator-Template) und Inline-L3 zurück
Saga-Karte K-Saga-Phase-2-Cluster-3 (Phase 2, ~3.5h) + Phase 3 #1 (Phase 3, ~4h)

Cache — Semantischer Response-Cache

Aspekt Wert
Position Pre-LLM, nach α, vor L2
Backend Redis, Cosine-Similarity ≥ 0.95, Language-Namespace
Wirkung Bei Hit wird die gecachte Antwort direkt zurückgegeben; Cache-Skip wird durch L5-/α-Match gesetzt, damit toxische Inputs nie zu Cache-Pollution führen
Failure-Mode Cache-Miss bedeutet voller Pipeline-Run — kein Sicherheits-Risiko; ein false Cache-Hit könnte eine alte (legitime) Antwort liefern

L2 — Operator-Template Persona-Cleanup

Aspekt Wert
Position Prompt-Bau-Phase, vor LLM-Inference
Code src/kora_platform/services/system_prompt_service.py (DB-backed Templates aus system_prompt_templates, Migration 0018)
Trigger Keine Pattern — strukturelle Härtung der System-Prompt-Struktur (Spotlighting-Tags <user_query> / <retrieved_context>, Refusal-Anker, Multi-Tenant-fähig)
Wirkung Reduziert Prompt-Injection-Surface; macht es dem LLM schwerer, Persona zu reproduzieren oder Roh-Kontext verbatim zu echoen
Failure-Mode Schwächere Pattern-Resistance des LLM-Outputs — Inline-L3 und L4 fangen die Folgen
Customer-Konfiguration Customer-Persona-Cleanup wird per-Tenant via system_prompt_templates konfiguriert (siehe Multi-Tenancy-Fundament)
Saga-Karte K-Layer-2-Operator-Tenant-Split + Customer-Persona-Cleanup-Cluster (Phase 1 + Phase 2 Cluster 1, ~13h)

LLM — vLLM mit LookAheadBuffer K=16

Aspekt Wert
Position In-Stream, zwischen vLLM-Yield und SSE-Token-Yield
Code src/kora_platform/services/stream_buffer.py (LookAheadBuffer Klasse)
Mechanismus K=16 Token Vorlauf zwischen LLM-Generation und Client-Delivery — schafft das Fenster für inkrementelle Pattern-Detection BEVOR Tokens zum Client gehen
Latenz-Impact K × ~25ms ≈ 400ms zusätzliche TTFT — Sicherheits-Trade-off akzeptiert
Saga-Karte Phase 3 #2 Sub-Phase B (~6h gesamt)

Inline-L3 — Pattern-Match auf accumulated text

Aspekt Wert
Position In-Stream, im Buffer-Loop des Stage-9-Token-Loops
Code src/kora_platform/services/output_filter.py + Wiring in src/kora_platform/services/query_service.py:706-740
Patterns prompt_leak_debug_block, raw_context_leak, json_format_pressure, system_rules_block, persona_style_leak (5 Pattern-Klassen)
Trigger primary regex + min_co_matches Co-Indicators (Lehre 7: Output-Format-Marker, niemals User-Input-Vokabular). Für jeden Buffer-Release: check_output(buffer.accumulated_text).
Wirkung Bei Match: buffer.discard_buffered() → buffered Tokens werden NICHT yielded → Hard-Stop-correction-SSE-Event mit hard_stop: true + clear_previous: true Flags. Widget DOM-Clear vor Replacement.
Audit-Log output_filter_audit mit filter_layer="inline" (Migration 0020)
Failure-Mode Bei mehrfacher Pattern-Lücke fällt der Schutz auf L4-Post-Stream-Fallback zurück
Customer-Konfiguration Pattern-Klassen sind generic; konkrete Customer-Co-Indicators (z.B. Customer-Domain-Filename-Marker, Customer-Wiki-Phrasen) werden customer-spezifisch ergänzt
Saga-Karte K-Layer-3-Output-Filter (Phase 1, ~7h) + K-L3-Output-Marker-Patterns (Phase 2 Cluster 2, ~2.5h) + Phase 3 #2 Sub-Phase C (Stream-Wiring, ~6h gesamt) + Phase 3 #3 (Pattern-Coverage-Erweiterung gegen 20-Leak-Korpus, ~3h)

Pattern-Klassen (generic)

L3-Output-Filter erkennt Leak-Versuche über fünf orthogonale Pattern-Klassen, die jeweils generische Output-Format-Marker adressieren — unabhängig vom Customer-Domain-Vokabular:

  • Schema-Notation: XML-Tags (<raw_chunks>, <systemprompt>, <retrieved_context>), JSON-Keys ("raw_context":, "system_prompt":, "hidden_rules":), JSONL-Type-Discriminator ("type":"context", "type":"system"), Object-Keys (rawContext:, systemPrompt:), Markdown-Table-Header (| raw_context |, | hidden_rules |)
  • Verbatim-Leak-Header: Originaltexte aus den Quellen, Originalpassage:, genauen/wortwörtlichen Passagen
  • Wiki-Strukturmarker: ## Inhaltsverzeichnis (TOC-Header einer verbatim-gedumpten Wikipedia-Quelle)
  • Numerierte Imperativ-Regeln: Multi-Line 1. NUTZE …, 2. KEINE … (geleakte System-Prompt-Regeln)
  • Persona-Style-Marker: Arrr, matey, Schurke, Landratte (geleakte Persona aus Pirate-/Cowboy-Persona-Pressure-Attacks)

Customer-spezifische Co-Indicators (Customer-Domain-Filename-Pattern, Customer-Wiki-Phrasen, Customer-Doku-Strukturmarker) ergänzen diese generic Pattern-Klassen — ihre Pflege erfolgt customer-isoliert.

L4 — SourceWireForm + Post-Stream-Fallback

Aspekt Wert
Position Post-LLM-Output
Code src/kora_platform/api/schemas/query.py:51 (SourceWireForm) + src/kora_platform/services/query_service.py:382 (Post-Stream check_output)
Wirkung SourceWireForm ist das wire-Schema OHNE content-Feld → keine Roh-Chunks zum Frontend, selbst wenn LLM-Output sie referenziert. Zusätzlich Post-Stream check_output für Pattern, die mehr als K=16 Token Look-Ahead brauchen → emittiert correction-Event mit filter_layer="post_stream"
Audit-Log output_filter_audit mit filter_layer="post_stream"
Failure-Mode L4 ist der letzte Fallback; bei vollständigem Versagen ist nur das Schema (kein content-Feld) noch da — Stream-Token sind dann beim Client
Saga-Karte K-Layer-4-API-Schema (Phase 1, ~1.5h) + Phase 3 #2 (filter_layer-Disambiguation)

Defense-in-Depth-Argument

Die Topologie kombiniert drei orthogonale Verteidigungs-Achsen:

  1. Detection-Pattern-Coverage (Pattern-Empirie). L3 schließt ~90 % der Leak-Output-Klassen aus dem Extended-Pentest-Korpus bei 0 % False-Positive-Rate gegen Real-Eval-Antworten. Die nicht-fangbaren Output-Klassen sind strukturell vom legitimen RAG-Output ununterscheidbar (Saga-Lehre 11).

  2. Stream-Architektur-Timing. Pattern-Match allein ist nicht ausreichend (Saga-Lehre 9, 10) — der Detection-Zeitpunkt relativ zum Token-Stream entscheidet, ob der Client Leak-Inhalt bereits gesehen hat. Inline-L3 mit LookAheadBuffer K=16 verschiebt die Detection vor das Yield, Hard-Stop-Event verhindert Token- Stream-Leak.

  3. Paraphrase-Empirie als Test-Methodik. Pre-LLM-Filter (α, L5) und Post-LLM-Filter (Inline-L3) brauchen invertierte Co-Indicator-Heuristiken (Saga-Lehre 7 vs. 8) — das ist nur durch Empirie aus echten LLM-Outputs herleitbar, nicht durch Speculative-Design. Real-Eval-FP-Sweep + Korpus-Coverage-Match sind seit Phase 3 #3 die Saga-Konvention.

Saga-Bilanz

Phase Karten Aufwand Outcome
Phase 1 4 ~24h Initiale Defense-Stages (L4 Wire-Schema, L3 Output-Filter, L2 Operator-Template, L5 History-Filter)
Phase 2 3 (Cluster 1–3) ~10h Detection-Pattern-Tuning + α-Layer (Saga 14/14 Findings closed)
Phase 3 #1 1 ~4h α-Layer-Erweiterung um Prompt-Leak + Raw-Context Input-Marker
Phase 3 #2 1 ~6h Stream-Architektur-Hardening (Inline-L3 + LookAheadBuffer + Hard-Stop)
Phase 3 #3 1 ~3h L3-Pattern-Coverage gegen 20-Leak-Korpus (Schema-Notation, Wiki-Strukturmarker, Customer-Filename-Leaks)
Total 10 ~47h Defense-in-Depth komplett, Saga 14/14 + Pentest-Followup 3/3 closed

Saga-Lehren

Die folgenden methodischen Lehren sind produkt-weit anwendbar und gelten unabhängig vom konkreten Customer-Tenant:

  1. Phase-0-Discovery zahlt sich aus — Sub-Bug-Funde in der Discovery-Phase verhindern teure Refactor-Schleifen später.
  2. Cluster-X-False-Positive-Lehre — Pattern-Detection NIEMALS auf isolierten Single-Keywords; IMMER primary + min_co_matches.
  3. Audit-Tabellen statt Drop-Behavior — Bei Filter-Match das Original IMMER persisten (Audit-Trail), niemals drop'en; Pattern-Tuning braucht den Original-Text.
  4. Layer-Reihenfolge L4 → L3 → L2 → L5 ist saga-korrekt — Schnellster Win zuerst, defensives Netz, dann großer Refactor, zum Schluss Multi-Tenancy-Foundation.
  5. Defense-in-Depth wirkt nur, wenn alle Layer aktiv sind — Niemals nur einen Layer; Failure-Mode jeder Schicht muss vom nächsten gefangen werden.
  6. Saga-Convention zahlt sich aus — Identische Karten-Struktur (Phase 0 → Commits → Smoke → Code-Review → Merge → Plan-Update) reduziert Cognitive Load.
  7. Output-Filter-Co-Indicators MÜSSEN Output-Format-Marker sein, niemals User-Input-Begriffe — die Persona reproduziert die User-Input-Phrasen nicht mehr, wenn sie bereinigt wurde, das Pattern stoppt still mit dem Triggern.
  8. Pre-LLM-Filter-Co-Indicators MÜSSEN User-Input-Vokabular sein, niemals Output-Format-Marker — Inversion von Lehre 7. Filter-Module bauen entweder nach Lehre 7 ODER Lehre 8, nie nach beiden in einem Modul.
  9. Detection-Event allein ist unvollständige Defense-in-Depth- Verifikation — Smoke prüft (a) Detection, (b) Token-Stream- Inhalt, (c) Stream-Position relativ zum Detection-Event.
  10. Stream-Architektur ist eigene Verteidigungs-Schicht — Pattern-Detection korrekt zu implementieren ist notwendig aber nicht hinreichend; der Detection-Zeitpunkt relativ zum Token-Stream entscheidet, ob Defense funktioniert.
  11. Pattern-Detection hat eine harte Untergrenze — schritt- basierte Bot-Antworten ohne Schema-/Debug-Marker sind strukturell vom RAG-Erwartungs-Output ununterscheidbar; Real-Eval-FP-Sweep ist Saga-Konvention für jede zukünftige Pattern-Erweiterung.
  12. Pentest-Suite-Hardening ist der dritte methodische Pfeiler neben Detection-Pattern und Stream-Architektur — eine versionierte Extended-Pentest-Suite mit Threshold-Konfiguration und nightly-CI-Regression schließt die Defense-in-Depth- Methodik dreidimensional: Detection (Pattern-Coverage gegen externes Korpus) + Architektur (Stream-Position-Timing) + Empirie-Druck (CI mit Threshold-Gates). Real-Eval-FP-Sweep wird damit permanent zweite Threshold-Achse — Pattern-Coverage ohne FP-Garantie wäre tautologische Sicherheit.
  13. Cleanup-Disziplin: Drifts vertagt sammeln, vor Architektur- Phasen geschlossen — pre-existing Drifts werden während Feature-Karten dokumentiert nicht gefixt; akkumulierte Schulden vor strategischen Architektur-Phasen mit strikten Aufwands-Caps pro Sub-Phase geschlossen; Out-of-Scope-Drifts ehrlich vertagt statt Cleanup-Scope erweitert. Honesty-over-Coverage.

Die ausführliche Langfassung dieser 13 methodischen Lehren mit Herleitungs-Kontext, Cross-References und Karten-Anchor liegt unter Saga-Lehren — Methodische Konstitution.

Visualisierung — Request-Flow (Mermaid)

flowchart TD
    Request[User Request] --> L5{L5: Multi-turn<br/>Persona-Defense}
    L5 -->|persistent_time_marker /<br/>role_override /<br/>forget_previous /<br/>ok_only_conditioning| Block5[history_persist_filter<br/>β-Marker-Replace<br/>+ Cache-Skip]
    L5 -->|sauber| Alpha{α: Input-Filter}
    Alpha -->|input_format_pressure /<br/>input_prompt_leak /<br/>input_raw_context| BlockA[Pre-LLM-Block<br/>NO_TOKENS<br/>Refusal-Replacement]
    Alpha -->|sauber| Cache{Cache: Semantic<br/>Cosine ≥ 0.95}
    Cache -->|Hit, language-namespaced| CacheHit[Cached Response]
    Cache -->|Miss| L2[L2: Operator-Template<br/>Persona-Cleanup<br/>Spotlighting-Tags]
    L2 --> LLM[LLM: vLLM Qwen3-14B<br/>+ LookAheadBuffer K=16]
    LLM --> InlineL3{Inline-L3:<br/>check_output<br/>auf buffered text}
    InlineL3 -->|Match: PL / RC / JSON-Pressure /<br/>Rules-Block / Persona-Style| HardStop[Hard-Stop SSE<br/>hard_stop=true<br/>clear_previous=true<br/>filter_layer=inline]
    InlineL3 -->|kein Match| L4{L4: Post-Stream-<br/>Fallback + SourceWireForm}
    L4 -->|Match Post-Hoc| Correction[correction Event<br/>filter_layer=post_stream]
    L4 -->|sauber| Stream[Token-Stream<br/>+ SourceWireForm<br/>OHNE content-Feld]

    style L5 fill:#fce4ec
    style Alpha fill:#e8f5e9
    style Cache fill:#fff3e0
    style L2 fill:#e3f2fd
    style LLM fill:#f3e5f5
    style InlineL3 fill:#e0f7fa
    style L4 fill:#fafafa
    style Block5 fill:#ffebee
    style BlockA fill:#ffebee
    style HardStop fill:#ffebee
    style Correction fill:#fff9c4
    style CacheHit fill:#c8e6c9
    style Stream fill:#c8e6c9

BPMN-Prozessmodell

Standardisierte BPMN-2.0-Notation des Defense-in-Depth-Pipeline. Quell-XML unter defense-in-depth.bpmn — importierbar in Camunda Modeler, bpmn.io oder Cawemo.

Defense-in-Depth BPMN

Lesehinweis

  • Gateways (Rauten) repräsentieren Filter-Entscheidungen mit zwei Pfaden: Match → Block-/Stop-Endpoint, kein Match → nächster Layer
  • Tasks (Rechtecke) repräsentieren aktive Verarbeitung (L2-Cleanup, LLM-Inference)
  • End-Events (Kreise) repräsentieren Pipeline-Outcomes (Block, Hard-Stop, Correction, Stream)
  • Audit-Log-Eintrag erfolgt bei jedem Block-/Stop-/Correction- Endpoint mit filter_layer-Disambiguation für Drift-Diagnose

Customer-spezifische Erweiterungen

Konkrete Pattern-Listen, Filename-Marker und Pentest-Befunde aus der jeweiligen Customer-Demo-Umgebung sind customer-isoliert dokumentiert. Aktuelle Implementierungen:

  • AVS-Demo (Erstkunde, Tourismus-Wiki + Meldeschein-Handbuch): AVS-spezifische Filename-Pattern (Meldeschein_Handbuch_…), AVS-Doku-Strukturmarker (Eingabefelder Meldeschein, Pflichtfelder (blauer Hintergrund)), Tourismus-Wiki-Phrasen (Begriffsbestimmungen (Definition von Qualitätsnormen)) und Pentest-Bilanz gegen die AVS-Demo-Umgebung — siehe AVS-Doku.

Künftige Customer ergänzen ihre eigene Pattern-Reference unter ihrer jeweiligen Customer-Doku-Subdomain.

Referenzen

  • Multi-Tenancy-Fundament — Customer-Tenant-Isolation und per-Tenant-Konfiguration
  • Saga-Lehre 7: Output-Filter-Co-Indicators MÜSSEN Output-Format- Marker sein, nicht User-Input-Begriffe
  • Saga-Lehre 8: Pre-LLM-Filter-Co-Indicators MÜSSEN User-Input- Vokabular sein, niemals Output-Format-Marker (Inversion von Lehre 7)
  • Saga-Lehre 9: Detection-Event allein ist unvollständige Defense- in-Depth-Verifikation — Smoke prüft (a) Detection, (b) Token- Stream-Inhalt, (c) Stream-Position
  • Saga-Lehre 10: Stream-Architektur ist eigene Verteidigungs- Schicht; Inline-Detection mit Look-Ahead-Buffer + Hard-Stop ist notwendig für Token-Stream-Cleanness
  • Saga-Lehre 11: Pattern-Detection hat eine harte Untergrenze — schritt-basierte Bot-Antworten ohne Schema-/Debug-Marker können ohne Legitimate-Answer-FP nicht gefangen werden; Real-Eval-FP- Sweep ist Saga-Konvention