wiki/c-work/4-done/2026-06-po-cleanup-neutralization-docgen.md

30 KiB
Raw Blame History

PO-Cleanup: Chatbot-Entfernung + Neutralisierung (Quellen/Felder & Denormalisierung) + Dokumentengenerierung

Beschreibung und Kontext

Vier zusammenhaengende Aufraeum-/Verbesserungsarbeiten an der Plattform:

  • A0 (Cleanup, dringend): Das Feature chatbot wird nicht mehr benoetigt und soll vollstaendig aus dem Code entfernt werden (UI + Backend: Routen, Interfaces, Datamodels, Methoden, RBAC-/i18n-/Registry-Hooks, Tests). Zusaetzlich: LangChain/LangGraph komplett entfernen (Deps + Code) und die verbleibenden Nutzer (realEstate-BZO-Extraktion, ChatStreamingHelper) auf die regulaere AI-Service-Nutzung umstellen, wie alle anderen Nutzer im System. Wiki nachfuehren: Chatbot-Komponente in der aktuellen Doku entfernen bzw. ins Archiv verschieben. Scope: keine DB-Zeilen-Bereinigung (Feature-/Instanz-Rows, RBAC-Rollen, Drop poweron_chatbot separat).
  • A1 (Neutralisierung — Anreicherung/Denormalisierung): Pruefen, dass denormalisierte (rueckuebersetzte) Inhalte nie persistiert werden, und einen sicheren Agent-Pfad bereitstellen, der Platzhalter ausschliesslich lokal (Private-LLM-Mapping) rueckuebersetzt und zum Download ohne Speicherung zurueckgibt.
  • A2 (Neutralisierung — Quellen/Felder): Die Feld-Neutralisierung bei FeatureDataSource-Abfragen so korrigieren, dass Datensaetze nicht unbrauchbar werden: Strings immer (substring-basiert) neutralisieren, Binary droppen, andere Typen nur bei explizitem Feld-Flag — vererbungs- und typbewusst.
  • A3 (Dokumentengenerierung): Dokumente sehen heute alle gleich aus (ein Standard-Style). Typ-spezifisches Styling (z. B. Klageschrift vs. Marketing mit Bildern) ermoeglichen und die Eignung der Renderer fuer sehr grosse Dokumente (z. B. 1000-seitiges Word-Buch mit eingebetteten Bildern) klaeren/verbessern.

Business-Treiber: Reports/Dokumente sind das sichtbare Endprodukt beim Kunden; Neutralisierung ist Compliance-kritisch (kein Klartext-Leak in Storage). Chatbot-Reste erhoehen Wartungslast und RBAC-/i18n-Rauschen.

Risiko bei Nicht-Umsetzung: A0 — toter Code + verwirrende Admin-UI. A1 — Datenschutzrisiko (Klartext im Storage) und ein dokumentierter, aber nicht implementierter Pfad. A2 — neutralisierte DB-Datensaetze sind fuer den Sub-Agent unbrauchbar bzw. inkonsistent gegenueber der UI. A3 — Reports wirken unprofessionell und grosse Dokumente koennen OOM/Timeout verursachen.

Abhaengigkeiten: A1 und A2 nutzen dieselbe NeutralizationService-Engine; aenderungen an der dokumentierten Invariante in b-reference/platform/neutralization.md + e-compliance/neutralisierung-detail.md. A3 beruehrt den ADR aus 4-done/2026-04-ai-reports-theming-and-pipeline.md (bewusste Entscheidung GEGEN Theme-Presets).

Fokus und kritische Details

A0

  • Feature-Discovery ist glob-basiert (loadFeatureRouters / loadFeatureMainModules in modules/system/registry.py) — Loeschen des Ordners ist boot-sicher; der Loader ueberspringt fehlende Module.
  • chatbot-Feature (featureCode=chatbot, LangGraph, DB poweron_chatbot, ChatbotConversation/Message/Document/Log) ist klar getrennt vom generischen Agent-Chat (datamodelChat.py: ChatWorkflow/ChatMessage, Workspace). Letzteres bleibt.
  • methodChatbot ist chatbot-spezifisch und wird entfernt; methodAi ist unabhaengig und bleibt.
  • WorkflowModeEnum.WORKFLOW_CHATBOT in datamodelChat.py wird ausserhalb der Datei nicht referenziert — Datei bleibt, nur das Enum-Element + frontend_options-Eintrag entfernen.
  • LangChain/LangGraph wird komplett entfernt. Die einzigen Nicht-Chatbot-Nutzer sind:
    • realEstate/bzoExtractionLangGraph.py: nutzt langgraph.graph.StateGraph nur als triviale Orchestrierung. create_bzo_extraction_graph() ist eine lineare 4-Knoten-Pipeline aus reinen Python-/Regex-Funktionen (classify_and_assemble -> extract_zones_and_tables -> extract_rules) ohne LLM -> ersetzbar durch sequenzielle Funktionsaufrufe. create_bzo_params_extraction_graph() ist ein Ein-Knoten-Graph um llm_extract_bauzone_params_node, der den LLM-Call bereits ueber ai_service.callAiPlanning(...) macht (also schon regulaerer AI-Service) -> Knoten direkt awaiten. Es ist keine LangChain-Model-Bridge noetig.
    • serviceCenter/core/serviceStreaming/helpers.py (ChatStreamingHelper): nutzt langchain_core.messages; einzige Konsumenten sind die Chatbot-Module (mainChatbot/service/chatbot, in A0 entfernt) -> nach A0 unbenutzt, kann mit helpers.py + den serviceStreaming-Exports entfernt werden.
  • requirements.txt: langchain, langchain-core, langgraph, langchain-tavily, nest-asyncio (nur fuer LangGraph) entfernen; requirements.lock neu erzeugen.
  • AdminFeatureAccessPage.tsx traegt die meisten UI-Referenzen (~82) — chirurgisch, nicht Datei loeschen.

A1

  • Reverse-Resolution ist ein DB-Mapping-Lookup (NeutralizationService.resolveText: [typ.uuid] -> DataNeutralizerAttributes.originalText), kein LLM-Call. Der Private-LLM macht nur die Vorwaerts-Erkennung. Das ist der datenschutzsichere Pfad (lokal, deterministisch, kein externes Modell sieht Klartext).
  • _rehydrateResponse() in mainServiceAi.py ist toter Code (keine Call-Sites), die Docstrings behaupten aber automatische Rehydration — Chat persistiert die Modell-Antwort wie geliefert (kein Re-Save mit Klartext). Doc/Impl-Mismatch.
  • Tatsaechliche Klartext-Risiken liegen NICHT bei der Denormalisierung, sondern bei: downloadFromDataSource (Roh-Bytes at rest), writeFile/renderDocument (agent-komponierter Inhalt), RoundMemory.fullData.

A2

  • Aktuell: _neutralizeRowFields ersetzt den ganzen Feldwert durch [NEUT.<field>.<hash>], nur fuer explizit gelistete neutralizeFields; die Maskenliste in _featureSubAgentTools.py ignoriert vererbte neutralize-Flags zur Query-Zeit; keine Typ-Verzweigung; Binary wird zu "<binary N bytes>" stringifiziert und ggf. gehasht (nicht gedroppt).
  • Das ist die heute dokumentierte Invariante (neutralization.md Failsafe 5/6) — A2 aendert sie bewusst.
  • Substring-Neutralisierung pro String-Zelle via Private-LLM erzeugt Latenz/Kosten bei grossen Result-Sets — Batching + bestehender 5-Min-Result-Cache als Mitigation.

A3

  • JSON-Dokumentmodell + Unified-Style-Schema sind ein Asset, nicht das Problem.
  • Ursache "alle Dokumente gleich": resolveStyle(None) injiziert immer DEFAULT_STYLE und reicht es truthy an die Renderer (mainServiceGeneration.py ~L410/L475); der Agent setzt style selten; documentTheme ist deklariert, aber nicht verkabelt (methodAi.py). Renderer sind in Ordnung — Orchestrierung ist die Luecke.
  • ADR-Spannung: 2026-04-ai-reports-theming-and-pipeline.md entschied bewusst GEGEN Theme-Presets/Mandate-CI und FUER "Agent fuellt generischen Style-Block". Der Wunsch nach typ-spezifischem Styling (Klageschrift/Marketing) wird damit nur erreicht, wenn der Agent den Style wirklich treibt. Vorschlag (ADR-konform): Presets als smarte Defaults, die der Agent waehlt und ueberschreiben kann — nicht als harte Vorgabe.
  • Grosse Dokumente: voll in-memory, Bilder als base64 im JSON, kein Streaming (reportlab doc.build, python-docx Document()). Das ist der echte Blocker fuer 1000 Seiten + Bilder.

A3 Grossdokument-Analyse & Empfehlung (2026-06-02, AC15 — Schritt 1+2 UMGESETZT)

Status: Schritt 1+2 umgesetzt+getestet; Schritt 3 (HTML-Backend) bewusst geschlossen (nein). Theming (AC13) ist umgesetzt+getestet.

Konkrete Engpaesse (mit Fundstellen):

  • Ein grosses JSON haelt ALLE Bild-Bytes gleichzeitig. _mediaTools._renderDocument (L110185) loest file:fileId-Bilder VOR renderReport zu base64Data im JSON auf; PDF/DOCX-Renderer (_renderJsonImage) lesen ausschliesslich base64Data/Data-URI. → Peak-Memory ~ Summe aller Bilder (base64 ≈ +33%).
  • Voll-in-memory Build: rendererPdf baut komplette story-Liste + doc.build (L198245); rendererDocx baut Document() und doc.save (L122180). Keine Section-/Seiten-Chunking, kein Flush.

Umsetzungsplan (jeweils einzeln testbar):

  1. Lazy File-Ref-Bilder — UMGESETZT 2026-06-02: Block-Bilder behalten fileId statt vorab-base64Data. renderReport(imageResolver=fileId->bytes) setzt einen Per-Render-Resolver am Renderer (BaseRenderer._lazyResolveImageBase64); PDF/DOCX _renderJsonImage loesen on-demand auf. renderDocument haelt fuer pdf/docx Bilder als Referenz und speist den Resolver aus Knowledge-Chunks/chat.getFileData. DOCX: echter Ein-Bild-Speicher (python-docx kopiert Bytes sofort ins Package). PDF: vermeidet base64-Overhead + JSON-Retention; voll-streamendes PDF (reportlab haelt Image-Flowables bis doc.build) erst mit Temp-File-Bildern in Schritt 2. Tests: tests/serviceGeneration/test_large_document_render.py (7 Tests, gruen) — Resolver-Aufrufe == N, Bilder eingebettet, JSON bleibt base64-frei.
  2. Temp-File-Bilder fuer PDF — UMGESETZT 2026-06-02: PDF nutzt datei-basierte Image(tmpPath)-Flowables (rendererPdf._renderJsonImage schreibt Bytes in tempfile.NamedTemporaryFile, reportlab liest erst beim doc.build von Disk; Cleanup in finally via _cleanupTempImageFiles). Damit sind nicht mehr alle Bild-Bytes gleichzeitig resident — echtes Streaming auch fuer PDF. python-docx bleibt single-save (Lib-Grenze), kopiert Bytes aber bereits beim add_picture (Ein-Bild-Speicher). Section-Chunking ueber mehrere doc.build-Passes wurde NICHT umgesetzt: reportlab braucht die Story fuer eine SimpleDocTemplate.build ohnehin komplett, und Text-Flowables sind gegenueber den (jetzt datei-basierten) Bildern vernachlaessigbar — der eigentliche OOM-Treiber ist beseitigt. Tests: test_pdf_images_are_file_backed_and_cleaned.
  3. Optionales HTML-first-Backend — ENTSCHIEDEN: nein (2026-06-02): WeasyPrint/Chrome wird NICHT als Zusatz-Backend eingefuehrt. Begruendung: Lazy- + Temp-File-Bilder beseitigen den Memory-Engpass fuer die unterstuetzten Formate; ADR 2026-04 sprach explizit gegen einen WeasyPrint-Ersatz. Bleibt als optionaler Future-Pfad ohne aktuellen Bedarf.

Bis dahin gilt als Mitigation der bestehende writeFile+renderDocument(sourceFileId=…)-Pfad (vermeidet riesige Tool-JSONs), und der PDF-Overflow-Guard (_buildPdfWithOverflowGuard) verhindert Layout-Abbrueche durch uebergrosse Bilder.

Ziel und Nicht-Ziele

Ziel

  • A0: Keine lebenden chatbot-Symbole/Referenzen mehr im Code (Backend + UI); kein LangChain/LangGraph-Import oder -Dep mehr; realEstate-BZO-Extraktion + ChatStreamingHelper-Pfad auf regulaeren AI-Service/Std-Python umgestellt; aktuelle Wiki-Doku ohne Chatbot-Komponente; Boot, Tests, Build gruen.
  • A1: Korrekte/ehrliche Doku + neues Agent-Tool, das Platzhalter via lokalem Mapping rueckuebersetzt und transient (Download, kein Save/Index/RoundMemory) zurueckgibt; toter Rehydrate-Code entfernt.
  • A2: Feld-Neutralisierung gemaess Regeln 14 (siehe unten), vererbungs- und typbewusst, konsistent zwischen Query-Pfad und RAG-Bootstrap.
  • A3: documentTheme end-to-end verkabelt + kleine Preset-Bibliothek (agent-ueberschreibbar); Layout-Primitive fuer echte Dokumenttypen; Grossdokument-Pfad (File-Referenz-Bilder + Chunked/Streamed-Render).

Explizit NICHT

  • A0: keine DB-Zeilen loeschen, kein Drop von poweron_chatbot. z-archive-Inhalte NICHT inhaltlich anpassen — nur Dokumente ins Archiv verschieben, wo noetig. Keine funktionale Aenderung an der realEstate-BZO-Logik (nur Orchestrierung/Imports), keine Aenderung am Extraktions-Ergebnis.
  • A1: keine automatische Rehydration der Modell-Antwort wieder einfuehren; kein externer LLM fuer Reverse-Resolution.
  • A2: keine Aenderung an der Engine selbst (NeutralizationService), nur an Aufruf/Policy in featureDataProvider/Sub-Agent-Tool; externe Connector-Quellen (Folder-Level) bleiben unveraendert.
  • A3: kein vollstaendiger Renderer-Austausch als Pflicht; HTML-first-Backend nur als zusaetzliches, format-waehlbares Backend (Entscheidung offen).

Betroffene Module

A0 — Gateway (loeschen)

  • modules/features/chatbot/ (gesamt: mainChatbot, routeFeatureChatbot, interfaceFeatureChatbot, service, chatbot, config, chatbotConstants, bridges/*, __init__)
  • modules/workflows/methods/methodChatbot/ (methodChatbot, actions/queryDatabase, __init__)
  • scripts/script_db_init_chatbot.py
  • tests/demo/test_demo_uc3_chatbot.py
  • docs/althaus-bot-v2-aufwandsschaetzung.md, -fragenkatalog.md, -preprocessor-assessment.md

A0 — Gateway (chirurgisch)

  • modules/routes/routeSystem.py (_getUiObjectsForFeature("chatbot")-Branch)
  • modules/routes/routeAdminFeatures.py (Config-Cache-Invalidierung ~L781 + Docstrings)
  • modules/shared/gdprDeletion.py (Chatbot-Interface-Branch ~L578)
  • modules/interfaces/interfaceRbac.py (DATA_OBJECT_NAMESPACE_MAP Chatbot*-Eintraege + USER_OWNED_NAMESPACES "chatbot")
  • modules/shared/i18nRegistry.py (mainChatbot in beiden _featureModulePaths-Tupeln)
  • modules/datamodels/datamodelChat.py (WORKFLOW_CHATBOT-Enum + frontend_options-Eintrag)
  • tests/unit/methods/test_action_signature_validator.py (L267), tests/demo/test_demo_bootstrap.py (test_*NoChatbot), tests/demo/README.md
  • scripts/script_migrate_user_uid.py, scripts/script_db_export_migration.py (poweron_chatbot/DB_CHATBOT)
  • Nur Kommentare (kein Verhalten): modules/aicore/aicoreModelRegistry.py, app.py, modules/workflows/methods/methodAi/methodAi.py, requirements.txt

A0 — Frontend (loeschen)

  • src/api/chatbotApi.ts, src/hooks/useChatbot.ts
  • src/pages/views/chatbot/ (ChatbotConversationsView, ChatbotViews.module.css, index)
  • src/pages/admin/ChatbotConfigSection.tsx
  • work-around/chatbot.ts

A0 — Frontend (chirurgisch)

  • src/App.tsx (Legacy-Redirect chatbot)
  • src/pages/FeatureView.tsx (Import, ChatbotSettings, FEATURE_VIEWS.chatbot, DEBUG)
  • src/config/pageRegistry.tsx (Icon-Keys)
  • src/types/mandate.ts (FEATURE_VIEW_REGISTRY.chatbot)
  • src/pages/admin/AdminFeatureAccessPage.tsx (Import + State/Config-Builder + JSX-Bloecke)
  • src/pages/admin/Admin.module.css (.chatbotConfigSection), src/styles/pages.module.css (.chatbot*)
  • src/stores/featureStore.tsx, src/api/featuresApi.ts (inkl. Mock-Fallback), src/hooks/useInstancePermissions.tsx (DEBUG + Keys)

A0 — LangChain/LangGraph-Entfernung + Migration (Gateway)

  • modules/features/realEstate/bzoExtractionLangGraph.py -> umbenennen zu bzoExtraction.py: from langgraph.graph import StateGraph, START, END entfernen; create_bzo_extraction_graph()/graph.invoke(state) durch sequenziellen Aufruf (classify_and_assemble -> extract_zones_and_tables -> extract_rules) ersetzen; create_bzo_params_extraction_graph()/graph.ainvoke(state) durch direktes await llm_extract_bauzone_params_node(state) ersetzen (LLM-Call bleibt ai_service.callAiPlanning)
  • modules/features/realEstate/mainRealEstate.py (L281 Import anpassen; Kommentare L2334/L2492/L2546 "LangGraph" entfernen)
  • modules/features/realEstate/routeFeatureRealEstate.py (Docstrings L709/L790 "LangGraph"), modules/routes/routeRealEstate.py (Docstrings L2237/L2243)
  • modules/serviceCenter/core/serviceStreaming/helpers.py (loeschen — ChatStreamingHelper/langchain_core), serviceStreaming/__init__.py (Export entfernen), serviceStreaming/mainServiceStreaming.py (getChatStreamingHelper() entfernen)
  • requirements.txt (langchain/langchain-core/langgraph/langchain-tavily/nest-asyncio entfernen) + requirements.lock neu erzeugen

A0 — Wiki nachfuehren (aktive Doku; z-archive-Inhalte unveraendert)

  • Chatbot-Referenzen aus aktiven Docs entfernen: b-reference/product.md (Feature-Zeile + Repo-/Tech-Stack), b-reference/platform/database-architecture.md (poweron_chatbot), b-reference/platform-core/workflow.md, b-reference/platform-core/architecture.md, b-reference/platform/platform-diagrams.md, b-reference/ui-nyla/architecture.md, e-compliance/security-overview.md, README.md (Verweis auf nicht-existentes features/chatbot.md)
  • LangChain/LangGraph aus Tech-Stack-/Architektur-Doku entfernen, wo erwaehnt (b-reference/product.md, b-reference/platform-core/architecture.md)
  • a-strategy/roadmap.md: Chatbot-Erwaehnungen pruefen/streichen (Strategie-Doc — nur wenn als aktive Komponente gefuehrt)
  • Falls ein aktives Doc rein Chatbot-spezifisch ist: nach z-archive/ verschieben (keine inhaltliche Aenderung). Aktuell existiert kein dediziertes aktives Chatbot-Reference-Doc -> ueberwiegend chirurgische Entfernung
  • c-work/_CHANGELOG.md: Eintraege fuer Chatbot-Removal + LangChain-Removal

A1 — Gateway

  • modules/serviceCenter/services/serviceAgent/coreTools/_mediaTools.py (neues Tool, z. B. revealDocument)
  • modules/serviceCenter/services/serviceAgent/toolboxRegistry.py (restriktive Toolbox)
  • modules/serviceCenter/services/serviceAi/mainServiceAi.py (_rehydrateResponse entfernen, Docstrings korrigieren)
  • modules/features/neutralization/serviceNeutralization/mainServiceNeutralization.py (resolveText wiederverwenden)

A2 — Gateway

  • modules/serviceCenter/services/serviceAgent/featureDataProvider.py (_neutralizeRowFields, _applyFieldNeutralization, _serializeRow)
  • modules/serviceCenter/services/serviceAgent/coreTools/_featureSubAgentTools.py (Maskenliste-Aufbau)
  • modules/serviceCenter/services/serviceKnowledge/udbNodes.py (FdsFieldNode.getEffectiveFlag), _inheritFlags.py (Resolver)
  • modules/serviceCenter/services/serviceKnowledge/subFeatureBootstrap.py (_serializeRowToText angleichen)

A3 — Gateway

  • modules/serviceCenter/services/serviceGeneration/styleDefaults.py (THEME_PRESETS, resolveTheme)
  • modules/serviceCenter/services/serviceGeneration/mainServiceGeneration.py (Theme-Aufloesung)
  • modules/serviceCenter/services/serviceGeneration/renderers/* (Layout-Primitive, File-Ref-Bilder, Chunking)
  • modules/serviceCenter/services/serviceAgent/coreTools/_mediaTools.py (renderDocument: Theme/Style aus Intent, aiService durchreichen)
  • modules/workflows/methods/methodAi/methodAi.py + actions/generateDocument.py (documentTheme durchreichen)
  • modules/datamodels/datamodelJson.py (Layout-Section-Typen)

DB-Migration

  • A0: nein (Code-only; DB-Cleanup separat). A1: nein. A2: nein (Verhalten, keine Schema-Aenderung). A3: ggf. additive Schema-Erweiterung im JSON-Modell (kein DB-Pflichtfeld).

Andere Komponenten

  • service-llm-private, service-preprocessing, service-teams-browser-bot: keine chatbot-spezifischen Anpassungen noetig (A0). A1/A2 nutzen Private-LLM-Ratings (bereits vorhanden).
  • Deployment: nach LangChain-Removal Build/Image ohne diese Deps verifizieren (kleinere Image-Size, keine nest-asyncio-Patches).

Entscheidungen

Datum Entscheidung Begruendung
2026-06-02 A0 nur Code (keine DB/Wiki/Archive) User-Scope-Entscheid; DB-Cleanup separat
2026-06-02 datamodelChat.py bleibt; nur WORKFLOW_CHATBOT-Enum entfernen Agent-Chat ist unabhaengig vom Chatbot-Feature
2026-06-02 LangChain/LangGraph komplett entfernen, verbleibende Nutzer migrieren User-Entscheid; Nutzung ist trivial ersetzbar (realEstate-LLM laeuft schon ueber callAiPlanning, ChatStreamingHelper nur vom Chatbot genutzt)
2026-06-02 bzoExtractionLangGraph.py -> bzoExtraction.py: StateGraph durch sequenzielle Aufrufe ersetzen Graphen sind lineare/Ein-Knoten-Pipelines; kein Funktionsverlust
2026-06-02 Aktive Wiki-Doku ohne Chatbot/LangChain; z-archive nur verschieben, nicht anpassen User-Entscheid (Wiki nachfuehren)
2026-06-02 A1: Reverse-Resolution bleibt DB-Mapping-Lookup (kein externer LLM) Datenschutzsicher, deterministisch; "Private LLM" = lokal/intern
2026-06-02 A1: Neues Tool gibt transient zum Download zurueck, niemals Save/Index/RoundMemory Klartext darf nicht at-rest landen
2026-06-02 A1: _rehydrateResponse entfernen statt verkabeln Toter Code + Doc/Impl-Mismatch; Auto-Rehydration ist Datenschutzrisiko
2026-06-02 A2: String-Zellen substring-neutralisieren (Feldname als Typ-Hint) statt Whole-Value-Hash Datensaetze bleiben brauchbar; Platzhalter-Typ passend zum Feld
2026-06-02 A2: Binary droppen statt maskieren Spez-Regel 2; Binary nie neutralisieren
2026-06-02 A2: number/date/bool nur bei EXPLIZITEM Feld-Flag (nicht vererbt) Spez-Regel 3
2026-06-02 A2: Query-Maske aus effektivem Flag (Vererbung) statt nur neutralizeFields-Liste UI-Effektivwert = Laufzeitverhalten
2026-06-02 A3: Presets als agent-ueberschreibbare Defaults (kein Hard-Mandate) Reconciliation mit 2026-04-ADR
2026-06-02 A3: Theme-Wahl agent-getrieben via documentTheme-Tool-Param (Enum + Beschreibung), kein serverseitiges Auto-Select ADR-konform (Agent treibt Style); kein zusaetzlicher LLM-Call noetig
2026-06-02 A3: Layout-Primitive = cover_page + image_grid (Markdown-Fenced-Bloecke); letterhead/multi-column zurueckgestellt Hoechster Nutzen (Klageschrift-Titelseite, Marketing-Bildraster); multi-column ist Page-Template-Thema, nicht Block-Primitive
2026-06-02 A3: HTML-first-Backend (WeasyPrint/Chrome) — ENTSCHIEDEN: nein Lazy+Temp-File-Bilder loesen Memory-Engpass; ADR sagte "kein WeasyPrint-Ersatz"

Umsetzungs-Checkliste

A0 — Chatbot entfernen (Code)

  • Backend-Verzeichnisse/Dateien loeschen (siehe Betroffene Module)
  • Backend chirurgische Edits (routeSystem, routeAdminFeatures, gdprDeletion, interfaceRbac, i18nRegistry, datamodelChat, Tests, Scripts)
  • Frontend-Dateien loeschen
  • Frontend chirurgische Edits (App, FeatureView, pageRegistry, mandate, AdminFeatureAccessPage, CSS, Stores/Hooks/Api DEBUG+Keys)
  • LangChain/LangGraph entfernen + migrieren: bzoExtractionLangGraph.py -> bzoExtraction.py (StateGraph raus), mainRealEstate.py-Import, ChatStreamingHelper/helpers.py + serviceStreaming-Exports entfernen, requirements.txt
  • Wiki nachfuehren: Chatbot + LangChain aus aktiven b-reference/e-compliance-Docs entfernen; ggf. Doc nach z-archive verschieben; _CHANGELOG.md
  • Verifikation: Boot ok, pytest gruen, tsc/vite build gruen, keine lebenden chatbot/langchain/langgraph-Referenzen im Code; BZO-Extraktion liefert identisches Ergebnis wie vorher
  • [~] requirements.lock NICHT noetig (Projekt nutzt nur requirements.txt) — Punkt gestrichen (User-Entscheid 2026-06-02)

A1 — Denormalisierung sicher

  • Agent-Tool revealDocument (resolveText, mandate/instance-scoped, transient/no-save, readOnly=True)
  • In restriktiver Toolbox registrieren (neutralization-Toolbox, isDefault=False -> explizit via requestToolbox); RBAC ueber bestehende Neutralisierungs-Feature-Access
  • _rehydrateResponse entfernen + Docstrings in callAi/callAiStream korrigieren
  • Doku: neutralization.md (Failsafe 8 + Tool), neutralisierung-detail.md
  • Leak-Pfade dokumentieren (downloadFromDataSource/RoundMemory) + Folge-Ticket-Hinweis (neutralization.md "Bekannte Klartext-at-rest-Pfade")

A2 — Feld-Neutralisierung

  • _resolveFieldsToMaskForTable/neutralizePolicy (spiegelt FdsFieldNode.getEffectiveFlag)
  • Regel 1: String-Zellen substring-neutralisieren via NeutralizationService mit Feldname-Typ-Hint
  • Regel 2: Binary-Spalten vor Serialisierung droppen
  • Regel 3: number/float/int/date/bool nur bei explizitem Feld-Flag
  • RAG-Bootstrap _serializeRowToText an denselben Resolver/dieselbe Platzhalter-Policy angleichen (finalizeRowsAsync/_neutralizeAndSerializeRows)
  • Doku: neutralization.md Failsafe 5/6 + neutralisierung-detail.md Abschnitt 3

A3 — Dokumentengenerierung

  • THEME_PRESETS + resolveTheme(name) in styleDefaults.py (deep-merge auf DEFAULT_STYLE, agent-ueberschreibbar)
  • documentTheme end-to-end verkabeln (Node/Action -> renderReport(documentTheme=...))
  • renderDocument: Theme agent-getrieben via Tool-Param (Enum+Beschreibung); kein serverseitiges Auto-Select (ADR-konform)
  • JSON-Layout-Primitive cover_page + image_grid (Markdown-Fenced-Bloecke) + PDF/DOCX-Handler; letterhead/multi-column zurueckgestellt
  • Grossdokumente: File-Referenz-Bilder statt base64 (Schritt 1) + Temp-File-PDF-Bilder (Schritt 2)
  • HTML-first-Backend evaluiert -> ENTSCHIEDEN: nein (nicht benoetigt)

Querschnitt

  • RBAC / Permissions: A0 entfernt Chatbot-RBAC-Objekte/Template-Rollen aus Code; A1 Tool-Zugriff ueber bestehende Neutralisierungs-Rechte
  • Neutralisierung betroffen? A1 + A2 = ja (Doku-Update Pflicht — erledigt)
  • Navigation / Routing: A0 entfernt Chatbot-Feature-Views/Routen
  • Billing-Impact? Nein (A2 nutzt bestehende AI-Call-Billing)

Akzeptanzkriterien

# Kriterium (Given-When-Then) Prio
1 Given Codebase nach A0, When rg -i chatbot (ohne wiki/z-archive), Then keine lebenden Symbole/Routen/Interfaces must
2 Given Backend-Boot nach A0, When Worker startet, Then keine ImportError, Feature-Registry laedt ohne Chatbot must
3 Given UI-Build nach A0, When vite build/tsc, Then keine dangling Imports/Typfehler must
1b Given Codebase nach A0, When `rg -i "langchain langgraph"im Code, Then keine Treffer;requirements.txt` ohne diese Deps
1c Given dieselbe BZO-PDF vor/nach Migration, When run_extraction/run_bzo_params_extraction, Then identisches fakten/zones/rules-Ergebnis must
1d Given aktive Wiki-Doku nach A0, When durchsucht, Then keine Chatbot-Komponente/LangChain im Tech-Stack; z-archive-Inhalte unveraendert should
4 Given Datei mit neutralisiertem Inhalt, When Agent revealDocument(fileId) aufruft, Then Klartext wird transient zurueckgegeben und NICHTS gespeichert/indexiert must
5 Given revealDocument, When ausgefuehrt, Then keine externe LLM-API beteiligt (nur DB-Mapping) must
6 Given mainServiceAi.py, When Code-Review, Then _rehydrateResponse ist entfernt und Docstrings korrekt should
7 Given FDS-Tabelle mit neutralize=True (vererbt, leere neutralizeFields), When queryTable, Then String-Felder sind substring-neutralisiert (Platzhalter im Text) must
8 Given String-Feld "Name"/"Adresse", When neutralisiert, Then Platzhalter-Typ entspricht dem Feldnamen-Hint should
9 Given Binary-Spalte bei aktiver Neutralisierung, When queryTable, Then Spalte wird gedroppt (nicht maskiert) must
10 Given numerisches Feld nur via Vererbung (nicht explizit), When queryTable, Then Wert bleibt unveraendert must
11 Given numerisches Feld mit explizitem Feld-Flag, When queryTable, Then Wert wird neutralisiert must
12 Given RAG-Bootstrap einer FDS-Tabelle, When indexiert, Then dieselbe Policy/Platzhalter wie Query-Pfad should
13 Given renderDocument mit documentTheme="legal", When gerendert, Then typ-spezifischer Style (nicht DEFAULT_STYLE) must
14 Given renderDocument ohne Theme/Style, When gerendert, Then neutrale Defaults (kein Crash) must
15 Given ~1000-seitiges Dokument mit Bildern, When gerendert, Then kein OOM/Timeout (Chunked + File-Ref-Bilder) must

Testplan

ID AC Art Automatisiert Repo-Pfad Status
T1 1,2,1b smoke ja platform-core (boot + pytest tests/demo) pending
T2 3 build ja ui-nyla (tsc, vite build) pending
T1b 1c regression ja platform-core/tests/features/realEstate/test_bzo_extraction_parity.py pending
T3 4,5 integration offen revealDocument no-persist: durch Tool-Design (transient SSE, kein Save/Index) + Code-Review abgedeckt; dedizierter Integrationstest braucht volle services-Plumbing -> als Folge-Ticket deferred
T4-T6 7-11 unit ja platform-core/tests/unit/serviceAgent/test_field_neutralization.py (8 Tests: string/hint/binary-drop/inherited-skip/explicit/failsafe/dedup) done
T7 12 unit ja platform-core/tests/unit/serviceAgent/test_field_neutralization.py::test_rag_bootstrap_parity_with_query_path (gemeinsame _neutralizeAndSerializeRows-Policy; _serializeRowToText leakt nicht) done
T8 13,14 unit ja platform-core/tests/serviceGeneration/test_style_resolver.py (Theme-Presets + Praezedenz) done
T9 15 unit ja platform-core/tests/serviceGeneration/test_large_document_render.py (8 Tests: PDF/DOCX lazy file-ref, Resolver-Count, JSON base64-frei, Temp-File-Bilder Schritt 2 + Cleanup) done (Schritt 1+2)
T10 13 unit ja platform-core/tests/serviceGeneration/test_layout_primitives.py (8 Tests: cover_page/image_grid Markdown-Parse + PDF/DOCX-Handler) done

Abschluss

  • b-reference/platform/neutralization.md aktualisiert (A1 Failsafe 8 + reveal-Tool + Leak-Pfade; A2 Failsafe 5/6)
  • b-reference/platform-core/ai-agent.md aktualisiert (revealDocument-Tool + neutralization-Toolbox + Doc-Theming/Layout-Primitive)
  • e-compliance/neutralisierung-detail.md aktualisiert (A1/A2)
  • b-reference/product.md + Architektur-/DB-/Diagramm-Docs: Chatbot-Komponente + LangChain/LangGraph aus aktiver Doku entfernt (Teil A0)
  • c-work/_CHANGELOG.md je Change 1 Zeile
  • TOPICS.md geprueft
  • [~] Dokument-Move nach 2-build//z-archive/: Verschiebung dem User ueberlassen (Arbeit fachlich abgeschlossen)