# Neutralisierungs-System ## Überblick Neutralisierung ersetzt mandantensensible Inhalte durch stabile Platzhalter, bevor Text an externe KI-Modelle geht oder dauerhaft im RAG landet. Rohdaten aus Tools werden nicht separat „nachgefiltert“: der Schutz liegt am **Content-Einstieg** (Indexierung, Extraktion, zentrales AI-Gate) und an vererbten Flags auf `FileItem` / Session / Feature-Konfiguration. ## Architektur: Einzige zentrale Stelle **Für jeden AI-Modell-Call** gilt: Prompt, RAG-Kontext und Chat-Nachrichten werden **ausschließlich** in `mainServiceAi.py` geprüft und neutralisiert (`_shouldNeutralize`, `_neutralizeRequest`). Kein anderes Modul entscheidet parallel „stattdessen“ für dieselbe Modell-Schnittstelle. Orthogonal dazu (kein Ersatz des Gates, sondern Data-at-rest bzw. Workflow): - **RAG:** `mainServiceKnowledge.indexFile()` neutralisiert Chunks bei `FileItem.neutralize=True`. - **Agent:** DataSource- und FeatureDataSource-Flags setzen bzw. vererben Neutralisierungspflicht; Sub-Agent-Calls können `requireNeutralization=True` tragen. - **Workflows:** Aktion `neutralizeData` neutralisiert explizit extrahierte ContentParts (prüft u. a. `NeutralizationConfig.enabled`, nicht das Session-Flag). ## Neutralisierungs-Trigger (Prioritätsreihenfolge) **Am AI-Gate (`_shouldNeutralize`)** (Auswertung in der dokumentierten Reihenfolge): 1. **Feature-Konfiguration:** `NeutralizationConfig.enabled` (DataNeutraliser / Feature-Instanz). 2. **Chat-/Session-Level:** `ServiceCenterContext.requireNeutralization` (z. B. Workspace, Automation). 3. **Pro Request:** `AiCallRequest.requireNeutralization` — expliziter Override auf dem Call. **Quellen gesamt (OR-Logik):** Ist irgendwo Neutralisierung erforderlich (Feature-Instanz, Workflow/Session, konkretes Objekt mit `FileItem.neutralize` / `DataSource.neutralize` / `FeatureDataSource.neutralize`), wird entsprechend verarbeitet. Dokumentierte Produktregel: **Kein `False` von einer Quelle hebt ein `True` einer anderen auf.** ## Was neutralisiert wird Im zentralen AI-Gate (`_neutralizeRequest`): - `request.prompt` - `request.context` (RAG-Kontext) - `request.messages` (OpenAI-artige Nachrichten) **Engine** (`NeutralizationService`): `processText`, `processFile`, `processBinaryBytes` (synchron/asynchron); Rückübersetzung über `resolveText` / Mappings. Modell-Familien u. a. `NEUTRALIZATION_TEXT` / `NEUTRALIZATION_IMAGE` (Private-LLM-Plugin; externe Provider ohne diese Ratings werden für Neutralisierung nicht gewählt). **Nicht erneut neutralisieren:** Bereits neutral indexierte RAG-Chunks; Web-Suchergebnisse ohne Mandantendaten (laut Spezifikation). **Bekannter Ist-Stand Medien:** Bild-Binary wird in der Engine derzeit weitgehend durchgereicht bzw. übersprungen — dedizierter Bild-Neutralisierungspfad ist in der Fachdoku als Lücke / Soll beschrieben, nicht als abgeschlossene Implementierung ausgewiesen. ## Failsafe-Kette 1. **Toggle `FileItem.neutralize`:** Index und Chunks werden synchron gelöscht; Re-Index im Hintergrund verhindert Leaks bei Fehlern in der Nachindexierung. 2. **Indexierung:** `indexFile()` neutralisiert Text-Chunks bei `FileItem.neutralize=True` → Data-at-rest abgesichert. 3. **DataSource-Download:** `neutralize`-Flag wird auf erzeugte `FileItem`s vererbt. 4. **FeatureDataSource:** `_queryFeatureInstance()` setzt bei `neutralize=True` u. a. `requireNeutralization=True` für Sub-Agent-AI-Calls. 5. **AI-Call:** Bei erzwungener Neutralisierung (`requireNeutralization=True`) schlägt fehlgeschlagene Neutralisierung hart fehl (`RuntimeError` / Blockierung bzw. Entfernen betroffener Message-Teile — kein Durchleiten im Rohzustand). 6. **`_rehydrateResponse()`:** Als Hilfsmethode vorhanden; automatische Rückübersetzung der Modellantwort ist nicht mehr der Standardpfad. **Engine-Failsafe (Spezifikation):** Neutralisierung verlangt, Engine nicht verfügbar → nicht weiterverarbeiten; Teilfehler → Teil entfernen, nicht roh weitergeben; fehlendes internes Medienmodell → Medien-Part entfernen. ## NeutralizationPanel (Frontend) `frontend_nyla/src/pages/views/workspace/NeutralizationPanel.tsx` — Übersicht zu Dateien mit `neutralize`-Flag, Status und Platzhalter-Mappings. Datenbasis u. a. `GET /api/workspace/{instanceId}/files` → `{ files: [...] }`. ## Schlüssel-Dateien | Bereich | Pfad | |--------|------| | **Zentrales AI-Gate** | `serviceCenter/services/serviceAi/mainServiceAi.py` | | **Neutralisierungs-Engine** | `features/neutralization/serviceNeutralization/mainServiceNeutralization.py` (+ `subProcess*.py`) | | **Feature-Config / DB** | `features/neutralization/datamodelFeatureNeutralizer.py`, `interfaceFeatureNeutralizer.py` | | **RAG-Index** | `serviceCenter/services/serviceKnowledge/mainServiceKnowledge.py` | | **Agent / Quellen** | `serviceCenter/services/serviceAgent/mainServiceAgent.py` (`_resolveDataSource`, `_downloadFromDataSource`, `_queryFeatureInstance`) | | **Datei-Toggle / Index** | `routes/routeDataFiles.py` — `PATCH /{fileId}/neutralize` | | **Workflow-Aktion** | `workflows/methods/methodContext/actions/neutralizeData.py` | | **Kontext** | `serviceCenter/context.py` — `requireNeutralization` | | **Flags (Modelle)** | `datamodels/datamodelFiles.py` (`FileItem.neutralize`), `datamodelDataSource.py`, `datamodelFeatureDataSource.py` | | **AI-Operationen / Enums** | `datamodels/datamodelAi.py`, `aicore/aicorePluginPrivateLlm.py` | ## Regeln / Invarianten - **Ein Gate pro Modell-Call:** Sämtlicher Text in Richtung externes LLM für diesen Call läuft über `mainServiceAi` — keine parallele „zweite“ Neutralisierungstelle für dieselbe Schnittstelle. - **Hard-Mode:** `requireNeutralization=True` und Neutralisierung scheitert → Call blockieren bzw. Inhalt nicht im Klartext an das Modell geben. - **Kein stilles Weiterreichen** sensibler Inhalte bei Pflicht zur Neutralisierung. - **Platzhalter:** Mapping `[typ.uuid]` in der DB; `resolveText` für kontrollierte Rückübersetzung. - Detaillierte Compliance- und Prozessbeschreibung: `wiki/e-compliance/neutralisierung-detail.md`.