Saga-Lehren — Methodische Konstitution¶
Die Defense-in-Depth-Saga (Phase 1 + Phase 2 + Phase 3 #1-3 + Quick-Win- CI-Integration + Pre-Existing-Drift-Cleanup, ~50h Wall-Clock, 13 Karten) hat 13 methodische Lehren etabliert. Sie gelten produkt-weit und werden bei künftigen Sicherheits-Initiativen als Konstitution referenziert.
Diese Page dokumentiert sie mit Herleitungs-Kontext und Cross-References zu den Karten in denen sie etabliert wurden. Das ist die kanonische Langfassung — die kompakte Liste in der Defense-in-Depth-Architektur-Doku verweist hierher.
Saga-Lehre 1 — Phase-0-Discovery zahlt sich aus¶
Etabliert in: K-Layer-2 (Phase 1, ~10h) + K-Layer-5 (Phase 1, ~5h)
Kern-Aussage: Read-only Discovery vor Implementierung deckt Sub-Bugs auf, die ohne Discovery erst während des Refactors als teure Korrektur-Schleifen sichtbar würden.
Begründung: L2 wäre ohne den Phase-0-Sub-Bug-Fund („Sources-im-
Prompt fehlt") trotz Refactor LLM-blind geblieben — die DB-Prompts
hatten kein {{ sources }}-Platzhalter, das LLM sah Sources gar nicht
(Trainings-Wissen-Drift). L5 wäre ohne den Phase-0-Frontend-Befund
(„read-only msg.content") in eine teure α-„drop-turn"-Variante
gelaufen statt der UX-neutralen β-Marker-Replace.
Praxis-Anwendung: Vor jeder größeren Saga-Karte: 30-60min Phase 0, auch wenn die Karte simpel scheint. Discovery-Outputs werden als in-Karten-Dokumentation persistiert.
Saga-Lehre 2 — Cluster-X-False-Positive-Lehre¶
Etabliert in: Phase 2 Cluster-X (Diagnose 1h)
Kern-Aussage: Pattern-Detection NIEMALS auf isolierten
Single-Keywords (role, vergiss, ab jetzt). IMMER primary +
min_co_matches-Co-Indicators.
Begründung: Single-Keyword-Pattern produzieren tautologische False-Positives: jede legitime Anfrage die zufällig das Keyword enthält wird geblockt. Cluster-X dokumentierte 22+ FP-Tests die nur durch Co-Indicator-Anforderung sauber differenzieren.
Praxis-Anwendung: L3, L5, α-Layer halten dieses Muster konsequent durch. 3/3 (L3) bzw. 22/22 (L5) FP-Tests bestanden.
Saga-Lehre 3 — Audit-Tabellen statt Drop-Behavior¶
Etabliert in: K-Layer-3 (Phase 1, ~7h) + K-Layer-5 (Phase 1, ~5h)
Kern-Aussage: Bei Filter-Match das Original IMMER persisten (Audit-Trail), niemals drop'en. Pattern-Tuning braucht den Original-Text.
Begründung: Drop-Behavior eliminiert die Empirie für künftige
Pattern-Verfeinerung. Sowohl L3 (output_filter_audit) als auch L5
(history_persist_filter_audit) folgen diesem Muster, beide mit RLS und
3 Indizes (chatbot+created, pattern, tenant+created).
Praxis-Anwendung: Drei Audit-Tabellen Saga-weit:
output_filter_audit (L3, Migration 0013), history_persist_filter_
audit (L5, Migration 0017), input_filter_audit (α, Migration 0019).
Identisches Schema-Pattern — neue Filter folgen der Vorlage.
Saga-Lehre 4 — Layer-Reihenfolge L4 → L3 → L2 → L5 ist saga-korrekt¶
Etabliert in: Phase 1 (Reihenfolge-Validierung post-merge, 24h Total)
Kern-Aussage: Schnellster Win zuerst (L4 ~1.5h), defensives Netz (L3 ~7h), dann großer Refactor (L2 ~10h), zum Schluss Multi-Tenancy-Foundation (L5 ~5h, RLS-aware).
Begründung: Der Refactor (L2) konnte auf dem L3-Audit-Pattern aufbauen, das L5 wiederum 1:1 kopiert. Hätte die Reihenfolge umgedreht (L5 zuerst), wäre die Audit-Trail-Konvention erst zur L3-Stufe etabliert und L5 hätte sie nachträglich nachziehen müssen.
Praxis-Anwendung: Sign-off-Decision D3 in der Saga; die Reihenfolge wird nicht ohne explizite Begründung geändert.
Saga-Lehre 5 — Defense-in-Depth wirkt nur wenn alle Layer aktiv sind¶
Etabliert in: Phase 1 (Cross-Layer-Verifikation post-merge)
Kern-Aussage: Mehrere Schichten müssen aktiv sein — niemals nur einen Layer.
Begründung: L3 hat F-01 (Prompt-Leak-Debug-Block) defensiv geschlossen, BEVOR L2 strukturell schloss. Hätte L2 versagt, wäre L3 noch da. Hätte L5 versagt, würde der LLM den Poison vielleicht ignorieren — aber das Audit-Log fehlte.
Praxis-Anwendung: Entwurf neuer Filter prüft explizit: welche Schichten greifen orthogonal? Was passiert wenn Schicht X versagt? Die Failure-Mode-Spalte in der Defense-in-Depth-Layer-Tabelle dokumentiert das pro Schicht.
Saga-Lehre 6 — Saga-Convention zahlt sich aus¶
Etabliert in: Phase 1 (4 Karten mit identischer Struktur)
Kern-Aussage: Identische Karten-Struktur (Phase 0 → Commits → Smoke → Code-Review → Merge → Plan-Update) reduziert Cognitive Load und macht Bilanzen einfach.
Begründung: Vorhersehbarer Ablauf bedeutet weniger Workflow-Entscheidungen pro Karte; der Karten-Operator kann sich auf den Inhalt konzentrieren statt auf den Prozess.
Praxis-Anwendung: Alle 13 Saga-Karten folgen dieser Struktur. Die Karten-Templates in den User-Prompts spiegeln das wider.
Saga-Lehre 7 — Output-Filter-Co-Indicators MÜSSEN Output-Format-Marker sein¶
Etabliert in: Phase 2 Cluster 2 (K-L3-Output-Marker-Patterns, ~2.5h)
Kern-Aussage: Pattern-Co-Indicators MÜSSEN aus empirischen LLM-Output-Beobachtungen abgeleitet werden, niemals aus den User-Input-Phrasen die das Pattern abwehren soll.
Begründung: Wenn die Tenant-Persona genau die User-Input-Begriffe enthält, die das Pattern als Co-Indicator nutzt, „funktioniert" das Pattern zufällig: das LLM reproduziert die Persona-Phrasen bei Leak-Angriffen, und die Co-Indicators matchen. Sobald die Persona bereinigt wird (Phase 2 Cluster 1), reproduziert das LLM die Phrasen nicht mehr — es paraphrasiert generisch. Das Pattern stoppt still mit dem Triggern, ohne dass irgendwo eine Fehlermeldung kommt.
Praxis-Anwendung: L3-Pattern verwenden ausschließlich
Output-Format-Marker als Co-Indicators (**Chunk N**, ## Inhalts-
verzeichnis, code-fence-open, etc.). Phase-0-Empirie-Sweep auf realen
Leak-Outputs ist nicht-verhandelbar.
Saga-Lehre 8 — Pre-LLM-Filter-Co-Indicators MÜSSEN User-Input-Vokabular sein¶
Etabliert in: Phase 2 Cluster 3 (α-Layer JSON-Pressure, ~3.5h)
Kern-Aussage: Lehre 8 ist die deliberate Inversion von Lehre 7. Zur Filter-Zeit eines Pre-LLM-Layers (L5, α) existiert noch keine LLM-Emission, deren Marker man matchen könnte — der einzige Beobachter ist die User-Anfrage selbst.
Begründung: Wer Lehre 7 unreflektiert auf einen Pre-LLM-Layer überträgt, baut ein Pattern, das niemals matcht (Co-Indicators sind im Input nicht da). Wer Lehre 8 unreflektiert auf einen Post-LLM-Layer überträgt, baut ein Pattern, das vom LLM trivial umgangen werden kann (Persona-Cleanup eliminiert die User-Input-Echo-Co-Indicators).
Praxis-Anwendung: Die Saga-Topologie hält das durch Trennung in
zwei Module konsequent durch: output_filter.py (Lehre 7) vs.
input_filter.py (Lehre 8). Beweis: Cluster-3-Smoke 15/15 PASS, in dem
_JSON_PRESSURE (L3, Lehre 7) und _JSON_FORMAT_PRESSURE (α, Lehre 8)
für dieselbe Pen-Test-Vulnerability zwei semantisch unterschiedliche
Pattern brauchen.
Saga-Lehre 9 — Detection-Event allein ist unvollständige Verifikation¶
Etabliert in: Phase 3 #1 (α-Layer Pentest-FU-Patterns, ~4h)
Kern-Aussage: Korrekte Smoke-Methodik prüft drei Eigenschaften gleichzeitig: (a) Detection-Event triggert; (b) Token-Stream enthält Leak-Inhalt nicht; (c) Detection-Event-Position relativ zu letztem Token.
Begründung: Saga-Cluster 1-3 haben (a) verifiziert, (b) und (c)
implizit als gegeben angenommen. Pentest 2026-05-08 hat diese Annahme
widerlegt: für drei Pentest-Findings emittierte L3 zwar correction
(a ✅), aber 311-1024 Token-Events waren bereits gestreamt (b ❌), und
correction kam +3 Lines nach letztem Token (c ❌). End-User-UX bleibt
durch Widget-DOM-Replace OK, aber API-Konsumenten und der Roh-Stream
sind exponiert.
Praxis-Anwendung: Smoke-Klasse C „Stream-Position-Verifikation"
permanent in scripts/security-smoke.sh und in der Extended-Pentest-
Suite-Harness (tests/security_pentest/redteam-harness-extended.mjs).
Saga-Lehre 10 — Stream-Architektur ist eigene Verteidigungs-Schicht¶
Etabliert in: Phase 3 #2 (Stream-Architektur-Hardening Option C, ~6h)
Kern-Aussage: Pattern-Detection korrekt zu implementieren ist notwendig aber nicht hinreichend. Der Detection-Zeitpunkt relativ zum Token-Stream entscheidet ob Defense funktioniert.
Begründung: Post-Hoc-Detection auf accumulated buffer nach Stream-Ende fängt Pattern-Match, aber Tokens mit Leak-Inhalt sind dem Client zu diesem Zeitpunkt bereits geliefert. Inkrementelle Stream-Prüfung mit Look-Ahead-Buffer + Hard-Stop-Event verschiebt L3-Output-Filter von Post-Hoc-Symptom-Erkennung zu Inline-Stream- Hardening.
Praxis-Anwendung: LookAheadBuffer (K=16 Token Vorlauf) zwischen
vLLM-Stream und SSE-Token-Yield; check_output(buffer.accumulated_text)
vor jedem Token-Yield; bei Match discard_buffered() + Hard-Stop-
Correction (hard_stop: true + clear_previous: true). Topologie post
Phase 3 #2: L5 → α → Cache → L2 → LLM-Stream-with-Inline-L3 → L4.
Latenz-Trade-off: K × ~25ms ≈ 400ms zusätzliche TTFT — akzeptabel für Sicherheits-Hardening.
Saga-Lehre 11 — Pattern-Detection hat eine harte Untergrenze¶
Etabliert in: Phase 3 #3 (L3-Pattern-Coverage gegen 20-Leak-Korpus, ~3h)
Kern-Aussage: Schritt-basierte Bot-Antworten ohne Schema- oder Debug-Marker sind strukturell vom RAG-Erwartungs-Output ununterscheidbar.
Begründung: Der 20-Leak-Korpus enthält 4 pl_para_*-Fixtures, deren
Bot-Output rein aus „Schritt 1: …, Schritt 2: …"-Anleitungen besteht —
kein Schema-Marker, kein Debug-Block, kein Originaltexte-Header.
Post-Phase-3-#3 ist die Coverage 2/4 (über Spillover via Filename-
Source-Line-Primary), aber die übrigen 2 Fixtures (code_fence_hide,
emotional_pressure) bleiben strukturell unfangbar: ein Pattern, das
diese fängt, würde gleichzeitig legitime Step-by-Step-Antworten triggern.
Praxis-Anwendung: L3-Coverage hat eine harte Untergrenze. Antworten
ohne distinguishable Output-Format-Marker können Defense-in-Depth nur
durch upstream Layer (L2, α, L5) gefangen werden, nicht durch
L3-Output-Filter. Empirie-Korpus + Real-Eval-FP-Sweep (gegen
tests/evaluation/results/*.json) ist die korrekte Methodik —
Coverage maximieren ohne legitime-Antwort-Regression.
Saga-Konvention: für jede zukünftige L3-Pattern-Erweiterung MUSS
der Real-Eval-FP-Sweep ausgeführt werden, bevor commit gemerged wird.
Korpus-Coverage allein ist nicht ausreichend (Beweis: Code-Review
C1-Fix in Phase 3 #3 zeigte deterministisch dass die initial großzügig
formulierte [—–_]+-Alternative 2/30 FP gegen Real-Eval-Antworten
produzierte).
Saga-Lehre 12 — Pentest-Suite-Hardening als dritter Pfeiler¶
Etabliert in: Quick-Win CI-Integration (~2.5h, post Phase 3 #3)
Kern-Aussage: Defense-in-Depth-Methodik ist dreidimensional: Detection (Pattern-Coverage) + Architektur (Stream-Position-Timing) + Empirie-Druck (CI mit Threshold-Gates).
Begründung: Ohne kontinuierlichen Empirie-Druck via CI-Regression entsteht Drift: Pattern werden hinzugefügt, Architektur ändert sich, aber niemand prüft systematisch ob die Coverage hält. Eine produktionsreife Defense-in-Depth-Architektur muss aktiv gegen frische Adversarial-Inputs validiert werden, sonst regrediert sie.
Praxis-Anwendung: Versionierte Extended-Pentest-Suite unter
tests/security_pentest/, drei sequenzielle CI-Jobs (pattern-coverage
→ real-eval-fp → live-suite, nightly 03:00 UTC + on-push path-
filtered), Threshold-Konfiguration in thresholds.json. Real-Eval-FP-
Sweep wird permanent zweite Threshold-Achse (Saga-Lehre 11 von
Empfehlung zu Konvention upgraded). Pattern-Coverage ohne FP-Garantie
wäre tautologische Sicherheit.
Beweis-Methodik: Pre-Merge-Smoke gegen die Pre-Phase-3-#3-Reference
(reference-2026-05-08-pre-phase3-3/) reproduziert die 16 Real Leaks
deterministisch (analyzer exit 1) — der Threshold-Mechanismus
funktioniert auch retrospektiv gegen den Drift-Stand vor Phase 3 #3.
Saga-Lehre 13 — Cleanup-Disziplin: Drifts vertagt sammeln, vor Architektur-Phasen geschlossen¶
Etabliert in: Pre-Existing-Drift-Cleanup (~1.5h, post Quick-Win-CI)
Kern-Aussage: Pre-existing Drifts werden während Feature-Karten dokumentiert, nicht gefixt — aber müssen vor strategischen Architektur-Phasen systematisch geschlossen werden.
Begründung: Während der Defense-in-Depth-Saga wurden mehrfach
pre-existing Drifts erkannt (mypy-Schulden in query_service.py,
tenant/module test failures, mkdocs broken-link), aber bewusst NICHT
im Scope der jeweiligen Saga-Karte gefixt — Disziplin um Karten klein
und fokussiert zu halten. Die akkumulierten Schulden würden vor
v1.0.0 SaaS-Multi-Tenancy aber False-Negatives in der Tenant-
Isolation-Validierung produzieren: ein 87-error pytest-Lauf maskiert
echte Multi-Tenancy-Regressions hinter Test-Infrastructure-Noise.
Praxis-Anwendung: Cleanup-Karte mit strikten Aufwands-Caps pro Sub-Phase (A mypy 1.5h / B Tests 1h / C mkdocs 30min / D weitere 1h) und Total-Cap 4h. Bei Cap-Überschreitung: Sub-Phase abschließen mit Teil-Fix, Rest in separate Karte vertagen — niemals Cleanup-Scope erweitern. Quick-Win-CI als systematisches Drift-Detection-Tool: erste echte Nutzung der Phase-3-#3-CI-Infrastructure für Drift-Inventur.
Saga-Konvention: Cleanup-Karten sind disziplinarisch gegen Schulden-Wirbel — sie erweitern nicht den Scope der schmerzhaftesten Drift, sondern bekennen offen welche Drifts vertagt sind (separate Folge-Karten mit Schätzungen). Honesty-over-Coverage.
Bilanz Pre-Existing-Drift-Cleanup: -89 pytest-Probleme (107 → 18,
87 errors → clean skips via DSN-gating), -6 mypy-Errors in
query_service.py (0 verbleibend in der Datei, 58 → 52 total), -1
mkdocs warning, -9 ruff auto-fixable. Out-of-Scope vertagt: Mypy-
Cleanup ~6-8h, Test-Hygiene ~3-4h, Ruff-Stylistik+Format ~2h.
Cross-Reference-Index¶
| Lehre | Karte / Phase | Kategorie |
|---|---|---|
| 1 | Phase 1 (K-Layer-2 + K-Layer-5) | Methodik / Discovery |
| 2 | Phase 2 Cluster-X Diagnose | Pattern-Methodik |
| 3 | Phase 1 (K-Layer-3 + K-Layer-5) | Audit-Trail-Konvention |
| 4 | Phase 1 (Reihenfolge-Validierung) | Karten-Reihenfolge |
| 5 | Phase 1 (Cross-Layer) | Defense-in-Depth-Argument |
| 6 | Phase 1 (Saga-Convention) | Prozess-Methodik |
| 7 | Phase 2 Cluster 2 (L3-Output-Marker) | Output-Marker-Empirie |
| 8 | Phase 2 Cluster 3 (α-Layer) | Pre-LLM-Filter-Methodik |
| 9 | Phase 3 #1 (α-Layer Erweiterung) | Stream-Position-Verifikation |
| 10 | Phase 3 #2 (Stream-Architektur) | Stream-Architektur-Pillar |
| 11 | Phase 3 #3 (L3-Pattern-Coverage) | Real-Eval-FP-Methodik |
| 12 | Quick-Win CI-Integration | Pentest-Suite-Hardening |
| 13 | Pre-Existing-Drift-Cleanup | Drift-Disziplin |
Verhältnis zur Saga-Bilanz¶
Diese Saga-Lehren sind methodische Konstitution, nicht projekt-spezifische Erinnerungen. Sie gelten:
- Produkt-weit — alle künftigen Customer-Tenants, alle künftigen Bot-Domänen, alle künftigen Sicherheits-Initiativen
- Saga-übergreifend — auch wenn die nächste große Initiative (v1.0.0 SaaS-Multi-Tenancy) thematisch ganz anders ist, gelten Lehre 1 (Phase-0-Discovery), Lehre 4 (Reihenfolge-Validierung), Lehre 6 (Saga-Convention), Lehre 13 (Cleanup-Disziplin) genauso
- Bei Konflikt mit Pragma-Versuchen wins die Lehre — z.B. wenn jemand vorschlägt „lass uns nur die schritt-basierten Fixtures eng matchen" (gegen Lehre 11), die Lehre setzt sich durch
Saga-Bilanz und Audit-Trail aller 13 Karten:
docs/security-hardening/action-plan.md
(im AVS-Repo als Living Document).