Stufe 3: reversible Pseudonymisierung im Router — Eigenbau nach Cordon-Vorbild, Korpus zuerst #1
Open
opened 2026-09-12 06:49:00 +02:00 by elton
·
0 comments
Labels
Clear labels
EPIC
Fokus
Quick Win
Service
Show
Sprint
Ein Epic / Übergeordnetes Thema
Das Ticket ist aktuell im Fokus der Aufmerksamkeit
Klein und risikoarm — schnell zwischendurch machbar. Gut zum Auffüllen von Leerlauf.
Service-/Support-Vorgang aus externer Anfrage oder Anwenderkontext
Für die Show relevant / dafür vorgezogen. Anlass-Marker, unabhängig von Zielversion und Priorität.
Im aktuellen Arbeitsvorrat — wird bearbeitet oder steht kurz davor. Unabhängig von der Zielversion.
prio
erforderlich
Must-Have, zwingend benötigt
prio
wichtig
Hohe Priorität
prio
wünschenswert
Nice-To-Have, wäre schön
status
Abgelehnt
Bewusst entschieden, das nicht umzusetzen (wontfix). Unabhängig vom Typ — das Ticket kann inhaltlich ein Bug oder eine Anforderung sein.
status
Bleibt
Bewusste Entscheidung: bleibt so, wie es ist
status
Blockiert
Kann derzeit nicht weiter — hängt an einer externen Abhängigkeit oder einem anderen Ticket/Vorgang. Unabhängig vom Typ.
status
Duplikat
Das gibt es schon woanders — als Dublette geschlossen. Unabhängig vom Typ.
status
In Arbeit
Wird gerade aktiv bearbeitet — jemand ist dran. Unabhängig vom Typ.
status
Nachtest
Fix/Umsetzung steht, muss noch nachgetestet/verifiziert werden. Meist Bugs, gilt aber auch für zu verifizierende Anforderungen.
status
No Repro
Nicht reproduzierbar — mangels Reproduktion nicht bearbeitet. Unabhängig vom Typ.
status
Review
Liegt zur Entscheidung oder Rückmeldung vor (GF, Kunde/Partner oder intern) und wartet darauf, bevor es weitergeht. Kein Code-Review — fertige Umsetzungen gehen nach status/Nachtest. Unabhängig vom Typ.
type
Anforderung
Erweiterung / Change Request / Feature Request
type
Aufgabe
Konkrete Aufgabe / Chore (kein Bug, kein Feature)
type
Bug
Fehler
type
Business
Geschäftliches
type
Doku
Dokumentation und Web Auftritt
type
Frage
Fragen & Antworten, FAQ, Informationen, ...
type
Idee
Eine Idee / Verbesserungsvorschlag
type
Refactoring
Aufräumarbeiten
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Assignees
andreas (Andreas Ahmann)
aria (Aria)
elton
festus (Festus)
klara (Klara)
spark (Spark)
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: spine/llmrouter#1
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Bezug: Vorgang und Dreistufen-Zuschnitt in live/live#1751, Plattform-Sicht in spine/core#21. Dort ist Stufe 3 („reversible Pseudonymisierung nach Cordon-Vorbild") als eigenes Ticket vorgesehen, sobald Stufe 1 und 2 stehen. Dieses Ticket ist jener Vorschlag — konkretisiert durch die Feldsicht vom 12.09.2026 und durch das Lesen des aktuellen Codes. Stufe 1 (Secret-Scan fail-closed) und Stufe 2 (harte Lokal-nur-ACL) bleiben in #1751 und sind nicht Teil davon.
Vorbild: Cordon — Node/TS-Drop-in-Proxy, deterministische Erkennung per Regex plus Prüfsummen, Modi
reversible/strip/off, fail-closed.Entscheidung: Eigenbau, kein Fremd-Dienst in der Kette
Der Router ist der einzige LLM-Endpunkt der ganzen Flotte. Dass er am 09.09.2026 für alle vier Agenten und den Mac ausfiel, ist genau das Argument gegen einen weiteren synchronen Hop: jede zusätzliche Komponente erbt diese Kritikalität, ohne sie zu verdienen.
Die Feldsicht vom 12.09.2026 (Lizenzen und Pflegezustand am 12.09. gegen GitHub gemessen) ergibt nichts, was wir als Fremd-Dienst einsetzen wollten:
Cloud-DLP scheidet aus, weil es die Rohdaten erst recht nach außen schickt. Was offen und gereift ist, ist die Erkennungsengine (Presidio, MIT, rund 11k★) — die kann als Sidecar hinter einer eigenen Schnittstelle laufen, die Architektur bleibt Eigenbau.
Der Bauplan, den #1751 noch nicht hat: dritte Schiene
#1751 Befund 1 hält richtig fest, dass Regex Schuldner-Namen und Anschriften im Freitext nicht zuverlässig fängt, und beantwortet das mit NER. Für unsere Daten ist NER aber der unbequemere Weg: probabilistisch, in Deutsch mittelmäßig, mit einem Modell, das jemand pflegen muss. Der nähere Weg ergibt sich daraus, dass das Risiko bei uns schon strukturiert vorliegt.
encrypt-Operator), falls Schiene 2 nach dem Korpus-Test Lücken lässt. Nicht vor dem Korpus entscheiden.Einbauorte (am Stand vom 12.09. gelesen)
Alle nötigen Punkte existieren bereits, das Ticket ist additiv:
src/server.ts:196jsonBody()— die eine Stelle, an der der Upstream-Body entsteht. Hier sitzt der Rewrite.src/server.ts:444— der SSE-TransformStream, der heute denusage-Chunk zeilenweise mitliest. Hier sitzt die Rückführung im Strom; die Zeilenpuffer-Logik ist vorhanden, neu ist der Grenz-Puffer gegen zerfallende Platzhalter ([PERSON_/7]).key-acls.json— die Identität des Aufrufers ist je Anfrage schon bekannt.Zwingend: rekursiv durch das ganze JSON, nicht nur
messages[].content. Die Tool-Call-Argumente sind die Lücke, über die alles andere wertlos wird. Der PrivAiTe-Benchmark (deren eigener, mit Vorsicht zu lesen) misst für das LiteLLM-Presidio-Guardrail und für LLM Guard 100 % unveränderte PII intool_calls[].function.arguments— erkannt wird sie in denselben Systemen im Klartext. Und umgekehrt: ein maskierter Wert, der über einen Tool-Aufruf zurück in unsere Datenhaltung läuft, muss am richtigen Übergang aufgelöst werden, sonst landetPERSON_7in einem Vorgang (#1751 Befund 3).Aktivierung pro Key, nie pauschal
Falsch wäre, den Router als Ganzen zu scrubben: Über
llm.lanlaufen auch opencode und Claude Code. Hostnamen, IP-Adressen, Pfadnamen und Bezeichner pseudonymisiert sind für Code-Agenten keine Sicherheit, sondern Zerstörung. Für diese Keys ist die ehrliche Regel „keine Fachdaten im Prompt", nicht Maskierung.An ist es bei den Pfaden mit echtem Kundenbezug: Klara (Mailtexte) und Inka (Telefontranskripte). Modus je Key:
off/strip/reversible.Erster Schritt: das Akzeptanzkorpus
Vor jeder Zeile Erkennungslogik ein Fixture mit erwarteten Funden: reale Mailtexte und Transkript-Ausschnitte, mit fiktiven, aber realistischen Werten — keine produktiven Personen- oder Auftragsdaten ins Repo, Klassifikation beachten. Ebenso Negativproben: Quelltext, Konfigurationsdateien, Hostnamen und Logs, die nicht getroffen werden dürfen. Fehlalarme sind bei Code-Keys der Ausfallgrund.
Der Grund, warum das zuerst kommt: ohne Korpus ist „Test grün" nicht von „es ist immer noch alles durchgerutscht" zu unterscheiden. Die Fehlerverteilung ist asymmetrisch — zu viel maskiert ist lästig, ein durchgelassener Name ist der Vorfall, für den das hier gebaut wird.
Mapping-Behandlung
Sitzungsbezogene Tabelle, TTL, verschlüsselt abgelegt (AES-GCM, wie Cordon und whitestag pii-proxy es vormachen). Sie darf niemals in
requests.jsonloder in die SQLite-Kostenzeile landen — der Log hält heute nur Metadaten (ts, key, ticket, alias, Modell, Upstream, Tokens, Kosten), und das muss so bleiben. Ergänzt wird höchstensscrubbed: trueplus Zähler je Kategorie, nie ein Entitätswert.Zu entscheiden (Andreas, ggf. mit Festus)
Umfang
src/redact.tsmit Erkennung, Map je Vorgang und Rückführung: einige hundert Zeilen, ohne Änderung an einem einzigen Client (#1751). Der Löwenanteil liegt nicht in der Erkennung, sondern im Korpus und im SSE-Grenzpuffer.Hinweis zur Beschriftung
Die Org
spineführt keine Labels —type/Anforderungundprio/wichtigwaren beim Anlegen gesetzt, sind aber still verloren (dieselbe Erscheinung, weswegen #1122/#1123 damals ohne Label ankamen). Nachzuholen ist das nur über ein Label-Set in der Org, nicht am Ticket.