199 KiB
Changelog (c-work)
Eine Zeile pro Change, NEUESTE EINTRAEGE ZUOBERST. Begruendungen gehoeren ins zugehoerige
c-work/<phase>/<feature>.md oder die PR-Beschreibung.
Format: - YYYY-MM-DD | <type> | <scope> | <Kurzbeschreibung> [(c-work: <relPfad>)] [(PR: #123)]
type: feat fix refactor docs test chore build · scope: platform-core ui-nyla service-llm-private service-preprocessing teams-bot wiki infra *
Skip: reine Refactors, Formatting, Lint, Dep-Bumps, Test-only, Wiki-Tippfehler.
2026-06-08
- 2026-06-08 | refactor | platform-core | ServiceHub eliminiert + ServicesBag als einziger Service-Bag:
serviceCenter/serviceHub.py(190 LOC,ServiceHub-Klasse mit 3 blanken Interface-Properties + 7 dynamischen Feature-Interfaces) komplett geloescht. 5 Consumer (neutralizePlayground,serviceBzo,serviceAiIntent,routeSharepoint,routeClickup) + 5 Test/Eval-Dateien aufgetService()+ServiceCenterContextmigriert._WorkflowAutomationServiceHubeliminiert,_ServicesAdapterzuServicesBagumbenannt — es gibt jetzt genau EINEN Service-Bag im gesamten System. Cursor Ruleservice-architecture.mdcerstellt zur Durchsetzung. Wikiarchitecture.mdaktualisiert. - 2026-06-08 | refactor | platform-core | Blanko Interface-Lecks gekappselt (B5): 14 neue ChatService-Methoden (File/Folder CRUD, Workflow-Listing) als Kapselungsschicht. ~60 Caller in coreTools, Workflows, AI/Generation/Neutralization von
interfaceDbComponent.*/interfaceDbChat.*aufchatService.*migriert.ServicesBag.interfaceDbComponentProperty entfernt. 3x totersaveGeneratedFile-Code (hasattr-Guard) entfernt. 3x Neutralization-DI aufgeloest (NeutralizationService nutzt jetzt_getService("chat")). - 2026-06-08 | refactor | platform-core | Services-Bag Workaround-Bereinigung (B4): Defensive
getattr-Fallbacks fuer garantierte Attribute (user,mandateId,chat,extraction) entfernt. Try/except Interface-Imports durchservices.*ersetzt.canAccessService()auf ServicesBag hinzugefuegt. Bidirektionaler ImportserviceCenter <-> workflowsaufgeloest viaself.services.getService("web"). - 2026-06-08 | refactor | platform-core | snake_case -> camelCase Public API (B6):
can_access_service->canAccessService,clear_cache->clearCache,get_resolution_cache->getResolutionCache,create_checkout_session->createCheckoutSession. Keine Legacy-Aliase. - 2026-06-08 | refactor | platform-core | Deprecated Items bereinigt (B3):
GRAPHICAL_EDITOR_DATABASE->WORKFLOW_AUTOMATION_DATABASE(8 Dateien).graphical_editor_runs->workflow_automation_runs+ camelCase (runFileLogger + 2 Caller). Demo-Configs: Dead Code (_ensurePilotWorkflow) geloescht,geDb->waDb, Descriptions aktualisiert.Automation2WorkflowView->AutoWorkflowView. - 2026-06-08 | refactor | ui-nyla | Automation2 UI-Naming eliminiert: 29 Dateien, 3 File-Renames (
Automation2FlowEditor->WorkflowFlowEditor,Automation2FlowEditor.module.css->WorkflowFlowEditor.module.css,Automation2DataFlowContext->WorkflowDataFlowContext). API-Typen umbenannt (Automation2Graph->WorkflowGraph,Automation2Run->WorkflowRun, etc.). 0 verbleibendeautomation2-Referenzen. - 2026-06-08 | refactor | ui-nyla | workflowApi.ts Shim aufgeloest: 23 Consumer auf
workflowAutomationApimigriert. ClickUp-Funktionen nachclickupApi.tsextrahiert. Shim geloescht. FlowEditorindex.tsRe-Export-Shim geloescht.connectionPath.test.ts(stale) geloescht.tsc-errors.txt/i18n_missing_report.mdgeloescht +.gitignore. - 2026-06-08 | refactor | ui-nyla | Keep-Alive Fix:
matchLocationmitlocation.searchParameter eingefuehrt. Workflow-Automation Keep-Alive matched jetzt nur beitab=editorstatt auf allen Sub-Pfaden. - 2026-06-08 | refactor | platform-core | Import-Violations komplett geloest (Phase 1-3):
nodeCatalog/(L2) extrahiert (Phase 1). External-Tool-Registry invertiert (Phase 2).systemComponentRegistryfuer Lifecycle-Hooks (Phase 3).workflowArtifactVisibility+entryPointsnach shared/nodeCatalog. Ergebnis:interfaces -> WA = 0,system -> WA = 0,serviceCenter -> WA = 0, bidirektional = 0. Alle 11 Aufwaerts-Violations und 2 bidirektionale Kopplungen geloest. - 2026-06-08 | docs | wiki | architecture.md aktualisiert: ServicesBag-Sektion mit Architektur-Regeln und verbotenen Patterns. Layer-Hierarchie mit L5b (workflowAutomation). Veraltete Pfade (
serviceHub/,automation2/,GRAPHICAL_EDITOR_DATABASE) korrigiert. Typed Action Architecture Pfade aufworkflowAutomation/engine/undnodeCatalog/aktualisiert.
2026-06-07
- 2026-06-07 | feat | platform-core, ui-nyla | Phasen 1–4 ausgeführt (WorkflowAutomation-Plan): Phase 1:
AutoWorkflow.runAsPrincipal(Optional), Nav-BlockworkflowAutomation(5 Items), mandatsweite APIrouteWorkflowAutomation.py(10 Endpunkte,_validateWorkflowAccessRBAC-Helper), Schedulerif-not-instanceId-Guard entfernt,_validateFeatureInstanceMandates()Guard inexecutionEngine.py. Phase 2:WorkflowAutomationPage.tsxHub-Seite mit Tabs (Workflows/Läufe/Tasks), Route inApp.tsx, Icons inpageRegistry.tsx,MandateNavigation.tsxrendert neue Nav-Sektionen als eigene Gruppen. Phase 3:featureInstanceId→Optional[str](softFk). Phase 4: Route-Imports auf kanonischedatamodels.datamodelWorkflowAutomationumgestellt (routeWorkflowDashboard,routeAutomationWorkspace,routeSystem); GE-Hardcode als DEPRECATED markiert. (c-work: c-work/1-plan/2026-06-automation-system-component.md) - 2026-06-07 | feat | platform-core | Phase 1 teilweise ausgeführt (WorkflowAutomation-Plan):
AutoWorkflow.runAsPrincipal(Optional, nullable, softFk→UserInDB) indatamodelWorkflowAutomation.py. Nav-BlockworkflowAutomation(order 25, 5 Items) indatamodelNavigation.py. Neue mandatsweite APIrouteWorkflowAutomation.pymit 10 Endpunkten unter/api/workflow-automation/+ Write-RBAC-Helper_validateWorkflowAccess(member=read, admin=write, isPlatformAdmin bypass). Schedulerif-not-instanceId-Guard inmainScheduler.pyentfernt. Runtime-Mandatsvalidierung_validateFeatureInstanceMandates()inexecutionEngine.py(defence-in-depth, A0.2). (c-work: c-work/1-plan/2026-06-automation-system-component.md) - 2026-06-07 | refactor | platform-core | Phase 0 + 0.5 ausgeführt (WorkflowAutomation-Plan): Delaminierung erledigt —
PauseForHumanTaskError/PauseForEmailWaitError→datamodels/serviceExceptions.py,coerceDocumentDataToBytes→shared/documentUtils.py, Re-Export-Shims inautomation2/executors/, Cross-Boundary-Caller umgebogen. Scheduler-Boot vonmainGraphicalEditor.onStartin System-Lifespan (app.py, nacheventManager.start()) verschoben;onStart/onStopausmainGraphicalEditor.pyentfernt; Scheduler- und Email-Poller-Stop inapp.pyShutdown (Schritt 3.5). Guard-Test bestätigt:methods/lädt keinautomation2mehr transitiv. (c-work: c-work/1-plan/2026-06-automation-system-component.md) - 2026-06-07 | docs | wiki | WorkflowAutomation-Plan an Import-Refactoring (2026-06-05/06) nachgeführt: Codebase-Abgleich gegen
local/notes/refernce-analysis/platform-core-import-analyse.md. Neue Layer-Hierarchie L0–L7; viele Plan-Vorarbeiten bereits erledigt: Contracts/Models nachdatamodels(L1,datamodelPortTypes/datamodelWorkflowAutomation, statt geplantemworkflowContracts/), Feature-Lifecycle-Hooks (mainGraphicalEditor.onInstanceCreate/onMandateDelete/onBootstrap, ex interfaceFeatures/interfaceDbApp/interfaceBootstrap),NAVIGATION_SECTIONS→datamodels/datamodelNavigation,EventManager/parseInlineRuns→shared,serviceHub→serviceCenter. GE↔Engine-Coupling wurde im Refactoring explizit auf diesen Plan vertagt (Deferred-Liste übernommen):features.graphicalEditor↔workflows(21/40),serviceCenter→GE(5× workflowTools),interfaceDbManagement:936, Re-Export-Shims. Boundary-Leck besteht weiter:PauseForHumanTaskError/coerceDocumentDataToBytesnoch inautomation2/executors, vonmethods/importiert → Delaminierung (→datamodels/serviceExceptions.pybzw.shared/documentUtils.py) bleibt erster Schritt. Neuer Abschnitt «Code-Stand», Phase 0.5/Betroffene Module/Entscheidungen/Links angepasst. (c-work: c-work/1-plan/2026-06-automation-system-component.md)
2026-06-05
- 2026-06-05 | docs | wiki | WorkflowAutomation-Plan nach 2 kritischen Code-Reviews überarbeitet (+ Trennung Automation ↔ Execution): Zentrale Korrektur — Automation (Graph-Editor/Engine
automation2/Scheduler/Solutions) und der geteilte Workflow-Execution-Layer (workflows/methods+processing, von reinen Chats/Agents genutzt) bleiben im Code getrennt; nur die Automation-Teile wandern in die Komponente. Frühere Aussage «automation2wird von Chats nicht importiert» als falsch korrigiert (sharedmethodsimportierenautomation2.executors) → neue Phase 0.5 Delaminierung (PauseForHumanTaskError/_coerce_document_data_to_bytes+portTypes/STATIC_NODE_TYPES→ neues geteiltesworkflows/workflowContracts/). Weitere Review-Fixes:featureInstanceIdist bereits DB-nullable (kein DDL, keine DB-FK), Scheduler ist hart auffeatureInstanceIdgekeyt (Entkopplung als eigener Schritt), Dashboard-RBAC deckt nur Lesen → eigener Write-Helper_validateWorkflowAccessfür 39 Sites, RBAC-Namespace Option B (kein Flip), Template-Instanziierungs-Trigger (_copyTemplateWorkflows) wandert inlauncher/, per-Node-Billing als bewusste Executor-Ausnahme,.cursor/rules/*aktualisieren. (c-work: c-work/1-plan/2026-06-automation-system-component.md) - 2026-06-05 | docs | wiki | Plan: System-Komponente
WorkflowAutomation(graphicalEditorraus aus dem Feature-Modell): Neuer Umsetzungsplan inc-work/1-plan/. Komponente heisstWorkflowAutomation(greppbares Token;graphicalEditor= ein Modul darin), modulares Layout (toolbox/editor/engine/scheduler/solutions/launcher/monitoring) gemappt auf L1–L4. Code-fundiert (Discovery/Registry,FeatureInstance-Lifecycle, DBpoweron_graphicaleditor, Scheduler-Boot via Feature-onStart, RBAC-PräzedenzrouteWorkflowDashboard/routeAutomationWorkspace, ~70 Backend-Touchpoints + UI-Navigation). Phasen 0–4: Scheduler-Boot in System-Lifespan → mandatsweite API/api/workflow-automation/…+ System-RBAC → Top-Level-Nav-Gruppe «Workflow-Automation» mit Tab-Seiten → DB (runAsPrincipal,featureInstanceIdals RBAC-Anker abbauen, Daten-Backfill) → Feature-Mantel entfernen. Vorgezogen aus A0.4, weil Voraussetzung für die Solution-Schicht. (c-work: c-work/1-plan/2026-06-automation-system-component.md) - 2026-06-05 | docs | wiki | CustomerCases A0.4 von Roadmap auf «jetzt» gezogen: step1-architecture + step3-features-plan verweisen für die
graphicalEditor→System-Komponente-Umstellung auf den neuen 1-plan; offene Frage #8 + Checkliste/Entscheidungstabelle entsprechend aktualisiert. (c-work: c-work/0-ideas/2026-06-CustomerCases-step3-features-plan.md) - 2026-06-05 | docs | wiki | A0 Code-verifiziert korrigiert: Workflow-Ownership = Mandant + Run-as-Principal (nicht Host-Feature): Code-Analyse (
executionEngine.py,mainScheduler.py,routeFeatureGraphicalEditor.py,datamodelFeatureGraphicalEditor.py, Trustee-Actions) zeigt, dass Workflows mandatsweit + identitätsgebunden über beliebige Feature-Instanzen laufen — kein Host-Feature-Owner. A0.1 neu: Owner-Achse =mandateId+runAsPrincipal, RBAC = Principal-RBAC; scheduled Runs sollen unter definierter Automations-Identität statt globalemevent-Sysadmin laufen. A0.2 neu: Multi-Feature/Multi-Instanz ist nativ (per-NodeFeatureInstanceRef), echte Schranke = Mandant; 3 Code-Lücken benannt (Runtime-Mandatscheck beim Ref-Auflösen, Read-RBAC analog Write, per-Node-Billing statt fixgraphicalEditor). A0.4 neu:graphicalEditorals Orchestrierungs-Substrat eingeordnet (kein DATA, eigene DB für alle Features, globaler Scheduler-Boot viaonStart) — Feature-Mantel bleibt als RBAC-/Store-Eintritt. step1-architecture + product-summary angeglichen. (c-work: c-work/0-ideas/2026-06-CustomerCases-step3-features-plan.md) - 2026-06-05 | docs | wiki | CustomerCases step3-Pläne überarbeitet + 3 Architektur-Leitentscheide (A0): Nach kritischem Review beide Pläne geschärft. Neuer Abschnitt A0 im features-plan löst die 3 kritischen Punkte: A0.1 Solution =
graphicalEditor-Execution mithostFeatureRefals alleinigem Owner für RBAC/Billing (Cross-Feature-Drift gelöst); A0.2 Multi-Instanz-Fan-out nur mandatsintern über explizitesinstanceSet, instanz-genaue Billing-Attribution; A0.3 Settings als Run-Envelope-Injektion (trigger.form/DataRef) statt Graph-Mutation (Published-Version-Invariante gewahrt). Zusätzlich: Node-IDs gegennodeDefinitions/verifiziert (neueremail.sendEmail-Versand-Node +data.writeToTableals Blocker erkannt;data.consolidatevorhanden), neuer i18n-Abschnitt (A5,t()+TextMultilingual), RBAC-Items/Deletion-Cascade/Adapter-Drift ergänzt, S5 als «vorhandene Templates exponieren» (statt migrieren) korrigiert. step1-architecture + product-summary + mockup auf neue Entscheide/Node-IDs angeglichen. (c-work: c-work/0-ideas/2026-06-CustomerCases-step3-features-plan.md, 2026-06-CustomerCases-step3-solutions-plan.md)
2026-06-04
- 2026-06-04 | docs | wiki | CustomerCases-Doks auf einheitliche Naming-Convention umbenannt:
2026-06-STEP*-Dateien →2026-06-CustomerCases-stepN-*(step1=architecture, step2=communication [product-summary md/pdf + mockup html], step3=solutions-plan/features-plan). Alle Cross-Referenzen in den Dokumenten + Changelog-Pfade angepasst. (c-work: c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md u. a.) - 2026-06-04 | docs | wiki | STEP2-Pläne neu strukturiert: Solutions vs. Features: Die drei bisherigen STEP2-Docs (lawyer-feature, pm-consolidated-customer-requirements, umsystem-integration) durch zwei architektur-konforme Pläne ersetzt.
step3-solutions-plan.md= alle konfigurierten Use Cases als Solutions (S1 SelectLine→RMA, S2 Pling-Reporting, S3 PWG-Mietzins, S4 Beleg-Import, S5 Finanz-Analysen, S6 Notification) mit Trigger/Bausteine/Settings/Output je Solution + Klassifikationstabelle.step3-features-plan.md= der Code dahinter (Teil A Plattform-Enabler: Solution-Schicht L3/L4, generische Nodes rbac.queryUsersByRole/testMode/integration.*, Connectors; Teil B vertikale Features: lawyer, commcoach, trustee-core). (c-work: c-work/0-ideas/2026-06-CustomerCases-step3-solutions-plan.md, 2026-06-CustomerCases-step3-features-plan.md) - 2026-06-04 | docs | wiki | Konzept: Solution-Schicht (Customer Workflows) + Pling-Use-Case: Architektur-Idee fuer generische L3/L4-Solution-Schicht ueber dem Workflow-Stack (Use Case → konfigurierter Workflow, kein Kunden-Code). Pling «Kaffee-Klatsch» Monatsreporting als staerkstes Validierungsbeispiel eingearbeitet (Multi-Instanz-Fan-out, rollenbasierte Verteilung). Plus generische Product-Summary und klickbares HTML-Mockup im ui-nyla-Look. (c-work: c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md, 2026-06-CustomerCases-step2-communication-product-summary.md, 2026-06-CustomerCases-step2-communication-mockup.html)
- 2026-06-04 | docs | wiki | Plan: Umsystem-Integration (Connectors + Workflows + Datenquellen-Seiten): Arbeitsdokument fuer generische Umsystem-Anbindung (SelectLine→RMA als Pilot). Trennung generische Bausteine (Connectors/kanonische Modelle/Workflow-Nodes) vs. kundenspezifische Logik (Workflow-Graph + Config). UI-Muster «Datenquelle = Seite» pro Kategorie (Buchhaltung existiert, Saläre als Idee). (c-work: c-work/1-plan/2026-06-umsystem-integration-connectors-und-datenquellen-seiten.md)
2026-06-03
- 2026-06-03 | fix | platform-core | Image MIME-Type Pre-Validation in Extraction Pipeline: Unsupported Bild-Formate (image/bmp, image/tiff, image/x-icon etc.) werden jetzt VOR dem Failover-Loop erkannt und uebersprungen. Magic-Bytes-Sniffing korrigiert falsche MIME-Types. Verhindert 6000+ Error-Storm bei EML-Verarbeitung (vorher: jedes unsupported Bild x 10+ Models = 30+ API-Errors). Safety-Net auch in aicorePluginAnthropic.
- 2026-06-03 | fix | platform-core | App Shutdown: ResilientHttp Sessions + EventManager Tasks:
closeAllResilientHttp()schliesst alle shared aiohttp-Sessions beim Shutdown.EventManager.shutdown()cancelt pending Cleanup-Tasks. Behebt 30s+ Shutdown-Hang. - 2026-06-03 | fix | ui-nyla | Data-Source Chip UUID-Fix: Race Condition in WorkspaceInput behoben --
refreshDataSources()gibt jetzt Promise zurueck,_handleDataSourceDropwartet darauf bevorpendingAttachDsIdgesetzt wird. Lokaler Label-Cache als Fallback. Verhindert UUID-Anzeige in Chips. - 2026-06-03 | fix | platform-core | Model Selector: totalTokens statt promptTokens: Filter in
aicoreModelSelector.pyprueft jetzttotalTokens(prompt+context) statt nurpromptTokensgegen 80%-Limit. Verhindert Auswahl von Modellen mit zu kleinem Context-Window bei grossen Dokumenten. - 2026-06-03 | fix | platform-core | simpleMode an Chunking-Pipeline angebunden:
process.pysimpleMode nutzt jetzt_resolve_file_refs_to_content_parts/_action_docs_to_content_partsstatt roher Bytes-Konkatenation. Dokumente fliessen durch die existierende Extraction+Chunking-Pipeline, oversized Prompts (4M+ Tokens) werden vermieden. - 2026-06-03 | fix | platform-core | Image-Element-Normalisierung:
_normalizeImageElementinsubStructureFilling.pystellt sicher, dass AI-generierte Image-Elemente immer dascontent-Dict-Format haben. Behebt Crash in rendererMarkdown wenn AI flache Keys liefert. - 2026-06-03 | fix | platform-core | Pre-Flight Guard in callWithTextContext: Defense-in-depth in
interfaceAiObjects.py-- lehnt Payloads ab die >95% des besten Modell-Context-Windows ueberschreiten, bevor die Failover-Schleife startet. - 2026-06-03 | fix | platform-core | PPTX Tabellen-Positionierung:
_renderSlideContentWithFramesin rendererPptx.py umgebaut auf sequenzielles Y-Tracking. Textboxen werden mit geschaetzter Hoehe statt full-height erstellt, Tabellen und Code-Blocks erhalten explizitetop-Positionen. Behebt Bug wo Tabellen unterhalb des sichtbaren Slide-Bereichs erschienen. - 2026-06-03 | feat | platform-core | HTTP Resilience Mixin fuer Connectors: Neues
_httpResilience.pymitResilientHttp-Klasse (Shared aiohttp.ClientSession, asyncio.Semaphore, Retry mit Backoff bei 429/502/503/504, Retry-After Header). Integriert in Google, MSFT und Infomaniak Connectors. Eliminiert 429-Storms durch Concurrency-Limit (Google 8, MSFT 10, Infomaniak 6). - 2026-06-03 | feat | platform-core | Sandbox readFileBytes + SafeZipFile:
sandboxExecutor.pyerweitert umreadFileBytes(fileId)Builtin (rohe Bytes, 50MB-Limit) undSafeZipFileWrapper (read-only, in-memory, kein extract/write). Ermoeglicht ZIP/XLSX/DOCX-Strukturanalyse im Agent-Sandbox ohne Dateisystem-Zugriff. - 2026-06-03 | refactor | platform-core | Style-System Overhaul: THEME_PRESETS + documentTheme entfernt, AI-Enhancement aktiviert:
THEME_PRESETS,resolveTheme()unddocumentTheme-Parameter end-to-end entfernt (styleDefaults, mainServiceGeneration, _mediaTools, methodAi, generateDocument, documentPath, mainServiceAi, mainTrustee). Statische Presets ersetzt durch AI-getriebene Style-Enhancement (_enhanceStyleWithAiin mainServiceGeneration); DEFAULT_STYLE auf Cursor/VS-Code-Aesthetik modernisiert (Calibri, GitHub-Farben, subtile Rahmen). Dead Code aus allen 5 Renderern entfernt (_getStyleSet, _enhanceStylesWithAI, _getDefaultStyleSet, _validateStylesContrast etc.). (c-work: c-work/4-done/2026-06-style-system-overhaul-smart-tables.md) - 2026-06-03 | fix | platform-core | Style-Chain-Luecken geschlossen: AI-Enhancement-Prompt bekommt jetzt das vollstaendige Style-Set (~920 Bytes) statt nur fonts/colors/table (3 von 12 Sektionen).
_convertUnifiedStyleToInternalerweitert um page, image, table font sizes, borderWidth, codeBlock.borderColor, coverPage, caption, table_banding, table_padding, fonts, colors. Fallback-Farben an DEFAULT_STYLE angeglichen (#1F3864->#24292e, lineSpacing 1.15->1.5). Heading-Key-Mismatch in XLSX/PPTX behoben (heading->heading{level}); DOCX h3/h4 Styles registriert. - 2026-06-03 | feat | platform-core | Smart Table Styling: Per-Table Style-Overrides via
content.tableStyleim JSON-Block (deep-merge mit globalem Table-Style). Neue Style-Keys:borderStyle(grid/horizontal/none),bandingEnabled(Toggle),cellPaddingPt. Automatische Spaltenausrichtung (_inferColumnAlignments: Zahlen rechts, Daten zentriert, Text links) oder explizit viacolumnAlignments. Neue Schema-SektionencoverPageundcaptionin DEFAULT_STYLE. Alle 5 Renderer (PDF/DOCX/PPTX/XLSX/HTML) implementieren borderStyle-Varianten, banding-Toggle und columnAlignments. - 2026-06-03 | refactor | platform-core | HTML-Renderer Legacy-Pfad entfernt:
_getStyleSet,_getDefaultStyleSetund zugehoerige Legacy-AI-Styling-Logik aus rendererHtml.py entfernt. Nur noch der Unified-Style-Pfad ueber_convertUnifiedStyleToInternal+_generateCssFromUnifiedStyleist aktiv. - 2026-06-03 | docs | wiki | Kanonische Referenzseite Dokumenten-Rendering: Neue
b-reference/platform-core/document-rendering.mddokumentiert die vollstaendige Style-Resolution-Pipeline (DEFAULT_STYLE -> Agent-Overrides -> AI-Enhancement -> Per-Element-Overrides), Table-Rendering-Modell, Renderer-Architektur, Font-Resolution, AI-Style-Enhancement-Prompt. TOPICS.md ergaenzt. ADR- und PO-Cleanup-Docs nachgefuehrt. - 2026-06-03 | refactor | * | Scope von DataSource entfernt (Datenschutz): Scope-Flag, -Icon und -Funktionalitaet komplett aus der UDB (Sources-Tab) entfernt — persoenliche Datenquellen duerfen nicht gescoped werden. DB-Spalte
DataSource.scopebleibt als deprecated, wird nicht mehr gelesen/geschrieben. UDB-Backend (udbNodes.py,_inheritFlags.py,routeUdb.py), Frontend (UdbSourcesProvider.tsx), Ingest (subConnectorIngestConsumer.py), Auth (routeDataSources.py) bereinigt. Scope existiert nur noch bei Files (folder-files). Wiki (unified-data-bar.md) aktualisiert. Tests angepasst.
2026-06-02
- 2026-06-02 | fix | service-llm-private | Private-LLM-Pricing byte-basiert statt Pauschale:
aicorePluginPrivateLlmrechnete Text/Vision/Reasoning pauschal pro Call ab (CHF 0.01/0.10/0.05,costPer1kTokens=0, Bytes ignoriert) -> faktisch fast gratis. Neu byte-/tokenbasiert via_calcPrivatePriceCHFmitPRICE_INPUT_PER_1K=0.0075/PRICE_OUTPUT_PER_1K=0.0375;costPer1kTokensder bepreisten Modelle entsprechend gesetzt. Embedding via_calcPrivateEmbedPriceCHF(PRICE_EMBED_PER_1K=0.0005, nur Input) statt gratis. Hintergrund: Depoformance-Angebot (privates CH-Modell muss teurer sein als oeffentliche Modelle). - 2026-06-02 | feat | platform-core | Grossdokument: Lazy File-Ref-Bilder (A3/AC15, Schritt 1): Block-Bilder koennen jetzt nur eine
fileIdtragen;renderReport(imageResolver=fileId->bytes)setzt einen Per-Render-Resolver am Renderer (BaseRenderer._lazyResolveImageBase64), den PDF/DOCX_renderJsonImageon-demand nutzen.renderDocument-Tool haelt fuer pdf/docx Bilder als Referenz (kein base64 mehr im JSON) und uebergibt den Resolver; HTML/Inline/uebrige Formate unveraendert (rueckwaertskompatibel). DOCX bekommt damit echten Ein-Bild-Speicher (python-docx kopiert Bytes sofort ins Package); PDF vermeidet base64-Overhead/JSON-Retention (voll-streamendes PDF via Temp-File-Bilder bleibt als Schritt 2). Tests: tests/serviceGeneration/test_large_document_render.py. (c-work: c-work/1-plan/2026-06-po-cleanup-neutralization-docgen.md) - 2026-06-02 | feat | platform-core | documentTheme end-to-end + Preset-Bibliothek (A3):
styleDefaults.pybekommtTHEME_PRESETS(general/finance/legal/technical/hr/marketing) +resolveTheme;resolveStyle(style, documentTheme)mergtDEFAULT_STYLE <- Preset <- explizites style(explizit gewinnt).documentThemeist jetzt durchverkabelt:ai.generateDocumentAction ->callAiContent->_handleDocumentGeneration->documentPath.generateDocument->renderResult->renderReport(documentTheme=...); ausserdem imrenderDocument-Tool (neuesdocumentTheme-Schema-Property) und inmethodAi.py(Param anai.generateDocument, Optionen ummarketingergaenzt). Reconciliation mit ADR 2026-04 (Presets als agent-ueberschreibbare Defaults, kein Hard-Mandate). Tests in tests/serviceGeneration/test_style_resolver.py. Offen: Grossdokument-Pfad (File-Ref-Bilder + Chunked-Render, AC15) — Entscheidung/Scope siehe Plan. (c-work: c-work/1-plan/2026-06-po-cleanup-neutralization-docgen.md) - 2026-06-02 | feat | platform-core | Typ-/vererbungsbewusste Feld-Neutralisierung (A2):
FeatureDataProviderneutralisiert Quelldaten jetzt regelbasiert viafinalizeRowsAsync/_neutralizeAndSerializeRows: Strings substring-neutralisiert wenn effektiv (explizit ODER geerbt, Feldname als Typ-Hint, async+dedupe ueber die lokale Engine), Binary gedroppt, andere Skalare nur bei explizitem Feld-Flag; IDs/System-Spalten ausgenommen, Engine-Ausfall = [REDACTED]. Policy aus_featureSubAgentToolsviaresolveEffectiveForFds; RAG-Bootstrap (subFeatureBootstrap) nutzt dieselbe Policy (Query-/Index-Paritaet). Unit-Tests in tests/unit/serviceAgent/test_field_neutralization.py (c-work: c-work/1-plan/2026-06-po-cleanup-neutralization-docgen.md) - 2026-06-02 | feat | * | Sichere De-Neutralisierung fuer Download (revealDocument): Neuer read-only Agent-Tool
revealDocumentloest Platzhalter [typ.uuid] ausschliesslich ueber das private lokale Mapping (resolveText, kein externes LLM) auf und liefert den Klartext als transienten Einmal-Download via SSE-SideEventrevealDownload; Klartext wird NICHT gespeichert, indexiert oder in der Chat-Historie abgelegt (persistiertes ToolResult enthaelt nur eine Bestaetigung). Toter_rehydrateResponse(nie aufgerufen) aus serviceAi entfernt und callAi/callAiStream-Docstrings korrigiert (keine Rueck-Hydration in Speicher). UI: sseClient + useWorkspace onRevealDownload (base64->Blob->Download->revoke) (c-work: c-work/1-plan/2026-06-po-cleanup-neutralization-docgen.md) - 2026-06-02 | refactor | * | Chatbot-Feature komplett entfernt: Backend (features/chatbot, methodChatbot, Routen, Interfaces, RBAC-Namespaces, datamodelChat WORKFLOW_CHATBOT, DB-/Script-Referenzen) und UI (chatbotApi, useChatbot, views/chatbot, ChatbotConfigSection, Routing, FeatureView, pageRegistry, Stores/Hooks/DEBUG-Logs) entfernt (c-work: c-work/1-plan/2026-06-po-cleanup-neutralization-docgen.md)
- 2026-06-02 | refactor | platform-core | LangChain/LangGraph entfernt: ChatStreamingHelper (langchain_core) geloescht; BZO-Extraktion (realEstate) von LangGraph-StateGraph auf direkte sequentielle Funktionsaufrufe migriert (bzoExtractionLangGraph.py -> bzoExtraction.py); langchain/langchain-core/langgraph/langchain-tavily/nest-asyncio aus requirements.txt entfernt (requirements.lock muss via pip-compile neu generiert werden)
- 2026-06-02 | docs | wiki | Chatbot/LangGraph aus aktiver Doku entfernt: README, product.md, b-reference (architecture/workflow/diagrams/database), e-compliance/security-overview, a-strategy/roadmap nachgefuehrt (z-archive unveraendert)
- 2026-06-02 | feat | platform-core | Agent data-source search-first guidance: Sharpened searchDataSource/browseDataSource tool descriptions (per-service query syntax, anti mass-download) and added a search-first rule to buildDataSourceContext so the agent queries server-side instead of downloading whole sources
- 2026-06-02 | fix | platform-core | SharePoint/OneDrive/Drive search scoping + pagination: SharePoint and OneDrive search now scope to the attached folder and follow @odata.nextLink; OneDrive browse paginates; Google Drive search uses fullText contains (name+content) with pageToken pagination and URL-encoded queries
- 2026-06-02 | feat | platform-core | Outlook mail metadata + date filter: browse/search expose sender+date inline in the agent tool, browse supports a date-range filter via Graph $filter, and search scopes to the attached folder
- 2026-06-02 | fix | platform-core | Gmail search metadata + label scoping: search returns real Subject/From/Date (was 'Message {id}'), scopes to the attached label, and resolves message metadata concurrently to cut the sequential N+1
- 2026-06-02 | feat | platform-core | Google Calendar date-range fetch: browse/search use timeMin/timeMax when a date range is given, avoiding full multi-year event listings
- 2026-06-02 | feat | platform-core | Contacts metadata inline (MSFT/Google/Infomaniak): agent tool shows email/phone/company per contact so vCards are only downloaded when the full record is needed
- 2026-06-02 | feat | platform-core | ClickUp task metadata inline: agent tool shows status/assignee/due-date per task instead of requiring a JSON download
- 2026-06-02 | feat | platform-core | Infomaniak Calendar date filter: events honour an agent-supplied date range (clamped to the vendor <3 month limit) instead of a fixed 90-day window
2026-05-31
- 2026-05-31 | fix | ui-nyla | UDB Sources panel compact: Reduced tree indent from 24px to 16px, shrunk compact row height to 28px, smaller chevrons/icons/action buttons in compact mode for better label visibility
- 2026-05-31 | fix | ui-nyla | Mobile FormGeneratorTable/Controls: Controls stay horizontal (row wrap) on mobile instead of going vertical, reduced padding/gap/font-size on mobile for table cells and pagination
- 2026-05-31 | fix | ui-nyla | Chat DataSource attach sends DataSource ID: SourcesTab now resolves DataSource UUID via ensureDataSourceId before attaching (was incorrectly sending connectionId)
- 2026-05-31 | fix | platform-core | TEXT to VECTOR schema migration: Added auto-migration for TEXT->VECTOR columns in PostgreSQL connector, fixing broken semantic search on databases created before pgvector was declared
- 2026-05-31 | fix | platform-core | ChatDocument DB fallback: getChatDocumentsFromDocumentList now queries ChatDocument table directly when in-memory workflow lookup fails, preventing orphaned document references
- 2026-05-31 | fix | platform-core | Table section string content normalization: subStructureFilling validates table elements after AI JSON parse; string content (CSV/markdown/pipe) is parsed into {headers, rows} instead of crashing rendererMarkdown
2026-05-30
- 2026-05-30 | docs | wiki | Depoformance Property Match — Backend ueber PORTA (Idee): 0-ideas-Dokument, das die Backend-Wuensche aus ihrer Techdoku (Kap. 11) in PORTA-Faehigkeiten uebersetzt statt Schlagworte woertlich zu nehmen. Mapping: 18 Provider-Interfaces -> generische RBAC-CRUD-Schicht; OpenRouter-Proxy -> unser AI-Gateway (serviceAi, kein OpenRouter); JWT-Felder -> PORTA Auth+RBAC (organizationId=mandateId); offene Punkte (Realtime/Upload/Mail/i18n/CI-CD) -> bereits PORTA-Plattformfunktionen; Security-Gate weitgehend abgedeckt. Keine Neutralisierung, CH-Residenz. Architektur: dedizierter Partner-Router (
/api/v1/depoformance/*), der ihre Endpunkte durchschleift. Pricing: einmalig CHF 24'000 + API-Grundgebuehr CHF 600/Mo (inkl. 100k Calls) + AI pay-as-you-go. (c-work: 0-ideas/2026-05-depoformance-api-integration.md)
2026-05-29
- 2026-05-29 | docs | wiki | Repo-Namen auf git.poweron.swiss/PowerOn migriert: Wiki-weit alte Repo-/Pfad-Namen ersetzt (
frontend_nyla/frontend-nyla→ui-nyla,gateway→platform-core,private-llm→service-llm-private). b-reference-Ordner umbenannt (gateway/ui-nyla/service-llm-private), README+product Komponenten-Tabellen aktualisiert,service-preprocessingergaenzt, Changelog-Scope-Legende angepasst. Konzeptionelle Prosa-Begriffe (Gateway, Private-LLM) und z-archive/Changelog-Historie bewusst belassen. - 2026-05-29 | feat | platform-core | Anthropic Claude Opus 4.8 hinzugefuegt:
aicorePluginAnthropic.pyum Opus 4.8 (claude-opus-4-8) erweitert -- Basic- + Vision-Variante, 1M Context, 128K max output, gleiche Preise wie 4.7 ($5/$25 pro M Tokens)._supportsCustomTemperatureerkennt 4.8 als Extended-Thinking-Modell (sendet keintemperature). - 2026-05-29 | feat | platform-core | Private-LLM Next-Gen Modelle vorbereitet:
aicorePluginPrivateLlm.pyum 3 neue Modell-Definitionen erweitert (deepseek-r1:70b Reasoning, llama4:scout Vision, nomic-embed-text Embedding). Werden automatisch aktiv wenn in Ollama verfuegbar -- kein Impact auf laufenden Betrieb. - 2026-05-29 | feat | private-llm | Config fuer GPU-Migration vorbereitet:
config.pyNext-Gen MODEL_MAPPING als kommentierter Block,_isVisionModelum llama4/scout erweitert. - 2026-05-29 | docs | wiki | Private-LLM Architektur-Seite aktualisiert: Migrations-Plan Infomaniak→FireStorm, geplante Modelle, Kostenvergleich dokumentiert.
- 2026-05-29 | feat | ui-nyla | SourcesTab sendToChat fuer Mobile: Chat-Icon (💬) im Sources-Tab reaktiviert --
onSendToChat_FeatureSourceundonAttachDataSourcean FormGeneratorTree durchgereicht. Mobile-User koennen nun Source-Objekte per Tap in den Chat senden. - 2026-05-29 | fix | infra | Gateway Workers auf 2 erhoeht (prod+int): Single-Worker-Bottleneck behoben -- RAG-Indexierung blockierte User-Requests nicht mehr.
2026-05-28
- 2026-05-28 | fix | platform-core | RAG ragLimits Vererbung:
ragLimits(z.B.maxBytes) auf der Connection-Root-DataSource (path/) wurden nicht an Kind-DataSources vererbt -- Walker fielen immer auf den 200 MB Default zurueck. Fix:_loadRagEnabledDataSourcespropagiertsettings.ragLimitsvom Connection-Root auf Kinder ohne eigene Werte._finalizeResultin allen 4 Walkern (SharePoint, GDrive, kDrive, ClickUp) zeigt nun effektive Limits statt hartkodierter Defaults. - 2026-05-28 | feat | platform-core+ui-nyla | DB Migration Streaming Import: Import grosser JSON-Dateien (>1 GB) lief bisher komplett im RAM (
json.load()), was OOM verursachte. Neuer Two-Pass-Ansatz mitijsonfuer speicher-effizientes Parsen: Pass 1 validiert + extrahiert Metadaten, Pass 2 splittet in per-Table JSONL-Dateien. NeuerGET /process-import-streamEndpoint mitStreamingResponse(ndjson) fuer Echtzeit-Fortschritt waehrend Validierung und Split. Frontend zeigt dynamischen Progress (Phase, DB, Tabelle, Datensatzzahl). - 2026-05-28 | feat | platform-core+ui-nyla | DB Migration Streaming Export: Export lief bisher client-seitig (
JSON.stringify) und schlug bei grossen DBs fehl (RangeError: Invalid string length). NeuerGET /export-streamEndpoint streamt die gesamte Export-JSON inkrementell viaStreamingResponse. Frontend nutztfetch()+ReadableStream+ File System Access API fuer direktes Streaming-to-Disk. Fortschrittslog zeigt aktuelle DB x/n mit MB-Angabe. - 2026-05-28 | fix | private-llm+infra | LLM-Server Recovery: Ollama-Modelle (
qwen2.5:7b,qwen2.5vl:7b,granite3.2-vision) auf Infomaniak GPU-Server neu installiert (waren nach Instanz-Neustart verloren). NVIDIA-Treiber-Mismatch per Reboot behoben. pgvector Extension auf prod+int DB-Servern installiert (OS-Package + CREATE EXTENSION). Doku aktualisiert:setupserver.md,README.md,infrastructure.md(DB-Setup-Anleitung fuer neue Installationen).
2026-05-27
- 2026-05-27 | fix | platform-core | UDB DS Auto-Create: Virtuelle DataSource-Nodes (Browse-Folder ohne DB-Record) auf eigener Connection koennen jetzt getoggelt werden.
canEditprueft Connection-Ownership viaUserConnection.userId;setFlagerstellt automatisch einen DataSource-Stub-Record analog zu_findOrCreateTableFds. Behebt 403-Errors beim Toggling von Browse-Foldern. 4 neue Tests (test_udbNodes.py). - 2026-05-27 | refactor | platform-core | UDB neutralizeFields-Handling von generischer Infrastruktur in polymorphe Node-Klassen verschoben:
_inheritFlags.cascadeResetDescendantsFdsist wieder rein generisch (keineneutralizeFields-Logik);_FdsFamilyNode.setFlagbietet generischen_onSetFlag-Hook;FdsTableNode._onSetFlagwipe-t eigeneneutralizeFieldsbei explizitem neutralize-Toggle;FdsWorkspaceNode._onSetFlagwipe-tneutralizeFieldsauf allen Descendant-Tables.FdsFieldNode.getEffectiveFlagerbt korrekt vom Table (Zwei-Quellen-Modell). 122/122 Tests gruen. Wikiunified-data-bar.md(Cascade-Reset-Abschnitt) aktualisiert.
2026-05-26
- 2026-05-26 | fix | gateway+frontend-nyla | UDB Toggle Spec Recovery: virtuelle Coordinates nutzen neu aggregate-Pfad (mixed moeglich ohne DB-Record); sechs redundante Aggregatoren + Parallel-Endpoint tree/attributes + Frontend refreshAttributes-Pfad entfernt; eine Pipeline, ein Resolver, immer refetch nach Toggle (Spec 2026-05-18 wiederhergestellt) (c-work: 3-validate/2026-05-udb-toggle-spec-recovery.md)
2026-05-24
- 2026-05-24 | docs | infra | Deployment-Infrastruktur Doku -- Neue kanonische Seite
b-reference/platform/infrastructure.md: Infomaniak-Projektstruktur (Porta, LLM, Teamsbot), Naming Convention ({bereich}-{env}-{komponente}), VM-Instanzenliste, Deploy-Patterns. TOPICS.md ergaenzt.
2026-05-23
- 2026-05-23 | refactor | platform-core+ui-nyla+wiki | UDB Polymorphic Refactor: neue
UdbNode-Klassenhierarchie (udbNodes.py), generischer RouterrouteUdb.pymitPOST /api/udb/tree/children+POST /api/udb/node/{key}/flag/{flag}, Hart-Cut der 4 PATCH-Routen + altem/api/workspace/{id}/tree/children. FDS-Schema entschlackt (keinuserId, keinworkspaceInstanceId, keinscopemehr — feature-owned, RBAC-gated viaroleLabel.endswith('-admin')). Neue kanonische Dokub-reference/platform/unified-data-bar.md; Updates aufneutralization.md,rbac.md,TOPICS.md. Tests: neutest_udbNodes.py, angepassttest_buildTree.py+test_inheritFlags.py+UdbSourcesProvider.test.ts(alle gruen) (c-work: 3-validate/2026-05-udb-polymorphic-refactor.md) - 2026-05-23 | feat | gateway+frontend | DB Migration Progress: Export und Import laufen per-DB sequentiell mit Echtzeit-Fortschrittslog (Timestamp, DB-Name, Tabellen-/Datensatzzahl, Fehler); neuer export-single Endpoint; Import via prepare-import + import-single (server-seitiger Payload-Cache mit Token); Export-Dateiname enthaelt Instanzlabel + full/partial (z.B. db_backup_main_full_2026-05-23T06-20-54.json)
- 2026-05-23 | feat | gateway+frontend-nyla | DB Migration Backup/Restore — Neuer Tab "Migration" auf der Datenbank-Gesundheit-Seite (SysAdmin). Backup: dynamische DB-Auswahl via Registry, Export als JSON. Restore: JSON-Upload, Validierung, Import mit Modus "Neu" (replace) oder "Zusammenfuehren" (merge). System-Objekte (Root-Mandant, Admin-User, Event-User) werden nie geloescht; ihre IDs werden beim Import automatisch auf die Live-IDs remapped. Neue Dateien:
databaseMigration.py, 4 API-Endpoints unter/api/admin/database-health/migration/, MigrationTab inAdminDatabaseHealthPage.tsx.
2026-05-22
- 2026-05-22 | fix | frontend-nyla | UDB FormGeneratorTree: RAG-Icon + Mixed-Symbol nach Merge-Konflikt-Verlust restauriert — In Commit
9488a7d("build errors") wurden bei einer Merge-Auflösung die RAG-Konstanten (_RAG_ON_EMOJI🧠,_RAG_OFF_EMOJI),_MIXED_SYMBOL(◩),_OFF_STATE_STYLEsowie der RAG-Button-JSX-Block und die Mixed-/Spinner-Branches in Scope/Neutralize entfernt. Surgical Restore: alle Stellen wieder eingebaut, Idas Neutralize-On/Off-Emoji-Distinction undhideRowActionButtons/dragDropEnabled-Refactor beibehalten. Auch verlorenes Auto-Expand-useEffectfürdefaultExpandedNodes wiederhergestellt (Test grün: 53/53). - 2026-05-22 | refactor | gateway+frontend-nyla | RAG Cost-Estimate Währung USD→CHF —
_costEstimate.estimateBootstrapCost()liefert nunestimatedChf(stattestimatedUsd); KonstanteEMBEDDING_CHF_PER_MTOKEN(Wert 0.02, Projekt-Konvention: Anbieter-Listenpreise werden direkt als CHF behandelt, identisch zucalculatepriceCHFinaicorePluginOpenai.py). Mit-aktualisiert:routeDataSources.pyDocstring,test_costEstimate.py(6/6 grün), FECostEstimate-Type,DataSourceSettingsModalAnzeige. Wiki:b-reference/gateway/ai-agent.mdEndpoint-Doku,TOPICS.md,c-work/2-build+4-done/2026-05-udb-datasource-settings.md.
2026-05-19
- 2026-05-19 | fix | gateway | RAG Inventory /mandate: ImportError UserMandate behoben (war in datamodelUam statt datamodelMembership); refactored zu getUserMandatesByMandate(); RBAC membership-Check hinzugefuegt (verhindert Zugriff auf fremde Mandate via X-Mandate-Id)
- 2026-05-19 | fix | gateway+frontend | RAG Inventory Mandate-Dropdown: neuer Endpunkt GET /api/rag/inventory/my-mandates liefert nur Mandate mit aktiver Mitgliedschaft; Frontend nutzt diesen statt /api/mandates/ (admin-only Route)
- 2026-05-19 | feat | gateway+frontend | RAG Inventory Feature-Daten: featureInstances-Array mit Datei-/Chunk-Zaehler, Status-Breakdown (indexed/pending/failed), FeatureDataSource-Details mit ragIndexEnabled-Flag, RAG-Aktiv-Indikator; Frontend zeigt Sync-Status-Banner, Datenquellen pro Instanz, RAG-Hinweis wenn inaktiv; leere Instanzen werden ausgefiltert
- 2026-05-19 | feat | gateway+frontend | Feature-Daten RAG-Sync: neuer Background-Job-Handler feature.bootstrap (subFeatureBootstrap.py) indexiert FeatureDataSource-Tabellendaten via FeatureDataProvider+requestIngestion; Handler-Registrierung in registerKnowledgeIngestionConsumer; neuer Endpoint POST /api/rag/inventory/reindex-feature/{workspaceInstanceId} mit FeatureAccess-Check; _buildFeatureInstanceInventory liefert runningJobs/lastSuccess/lastError; Frontend: Job-basierte Sync-Status-Banner + Reindex-Button fuer Feature-Instanzen (analog zu Connection-Sync)
- 2026-05-19 | fix | gateway | FeatureDataProvider: alle DB-Zugriffe (getActualColumns, browseTable, aggregateTable, queryTable, _resolveInstanceColumn) von deprecated db.connection.cursor() auf db.borrowCursor() migriert (Pool-API-Kompatibilitaet nach Pooling-Refactoring)
- 2026-05-19 | fix | gateway | Trustee Budget-Vergleich: _exportAccountingData liefert neu eine accountSummary (1 Zeile/Konto mit closingBalance + Q1-Q4) statt 5590 rohe Balance-Records (26/Konto); AI-Prompt praezisiert Datenquelle; reduziert Payload von 355KB auf 25KB und verhindert Faktor-100-Abweichungen durch versehentliches Summieren
- 2026-05-19 | fix | frontend-nyla+gateway | RAG-Inventar Mandate-Scope 403 + SQL-Fehler — Zwei Bugs: (1) Frontend sendete
mandateIdals Query-Parameter stattX-Mandate-Id-Header →context.mandateId=None→ 403. Fix: Header wird gesetzt. (2) BackendrouteRagInventory._getInventoryMandatefilterteUserConnectionmitrecordFilter={"mandateId": ...}, aberUserConnectionhat keinmandateId-Feld → SQL-Error. Fix: Mandate-Members viaUserMandate-Junction holen, dann derengetUserConnections(userId)aggregieren. - 2026-05-19 | refactor | gateway+frontend-nyla | UDB Toggle Refresh: Visible-IDs Pattern -- After a toggle, FE sends all visible node IDs in one POST request; backend returns correct attribute values (incl. mixed) for exactly those IDs. No full-tree reload, no optimistic updates. New endpoints:
POST /api/files/attributes(FilesTab) andPOST /api/workspace/{id}/tree/attributes(SourcesTab).TreeNodeProvider.refreshAttributes(ids)added to interface. Collapse now removes children from FE state (always fresh on re-expand). Removed_enrichFoldersWithMixedand_refetchAllExpanded.
2026-05-18
- 2026-05-18 | feat | gateway+frontend | UDB Resolve Endpoint: neuer POST /datasources/resolve-flags Bulk-Endpoint liefert effective-Werte (neutralize, scope, ragIndexEnabled) fuer beliebige Pfade auch ohne eigenen DB-Record; Frontend entfernt client-seitige Vererbungslogik (_findCoveringDs), nutzt ausschliesslich Backend-Daten via resolvedFlags Map
- 2026-05-18 | fix+feat | gateway+frontend-nyla | UDB Sources Recovery -- Zweite Smoke-Test-Runde (H1-H10) (
c-work/3-validate/2026-05-udb-sources-recovery.md). (H1) Logik-Audit aller drei Flags zusammengefasst:'mixed'ist Backend-Aggregate-Anzeige, niemals persistiert; FE-Handler mappen'mixed'immer auf konkreten Wert ('personal'/false); Cascade-PATCH setzt alle Nachkommen aufNULLund dann den Master, deshalb kann aggregate nach einem User-Toggle nicht'mixed'bleiben. (H2/H8) Initial-Render-Bug: sequentiellerfor ... awaitim Auto-Expand-Effekt loeste Cancellation-Race aus -- erstessetNodestriggerte cleanup, weitere defaultExpanded-Knoten blieben "expanded ohne Children". Fix:Promise.all(...)parallel + atomares Single-setNodes. ZusaetzlichautoExpandedRef.current.clear()in_loadRoot(StrictMode-Doppelmount + manuelle Refresh tauglich). (H3)PUT /api/files/{id}404: Route hatte keinenRequestContext,interfaceDbManagement.getInterface(currentUser)ohne mandate/featureInstance scope -> RBAC-Filter excludiert File. Fix: Context-Dep + scope-pass-through beiupdate_fileunddelete_file;move_folderakzeptiert sowohlparentIdals auchtargetParentIdaus dem Body. (H4) Neuer Folder erschien initial auf Legacy-Top-Level:FolderFileProvider.createChild(parentId=null, ...)setzt jetztparentId = _SYNTH_ROOT_ID('own')damit der neue Folder unter/rendert. (H5)+-Button pro Folder im FormGeneratorTree: neueonCreateChild?: (parentId: string) => void-Prop in TreeNodeRow + verdrahtetem_createFolderAt(parentId)Handler in der Hauptkomponente; sichtbar im Hover-Action-Slot fuer alle Folders mitprovider.createChild&&provider.canCreate(id). (H6) FilesTab neutralize partly broken: Diagnose plausibel mit H2-Fix erledigt (Optimistic-Update verfehlte Knoten, deren Children durch das Cancellation-Race nicht im FE-State waren). (H7) Hardcoded[Persoenliche Quellen]: Source-String hatteoe-Encoding,t()returned key fuer DE -> sichtbar mit fake-Umlaut. Fix:resolveTextSafe("Persoenliche Quellen")->resolveTextSafe("Persönliche Quellen")(echter Umlaut). (H9) FDS-Neutralize ging nicht:POST /api/workspace/{instanceId}/feature-datasources403te Cross-Mandate-Erstellung (Workspace mandate A, Feature mandate B beides user-zugaenglich),_ensureRecordschluckte den Fehler still. Fix: Cross-Mandate-Block entfernt, statt dessengetFeatureAccess(userId, body.featureInstanceId)-Validierung;mandateIdder neuen FDS =wsMandateId(= Workspace-Tenancy, konsistent mit Tree-Filter). (H10 = G5) Persistenter Expand-State umgesetzt:WorkspaceUserSettings.uiTreeExpansion: Dict[str, List[str]]Backend-Field; neue RoutenGET/PUT /api/workspace/{instanceId}/ui-tree-expansion/{scope}; FE-HookuseTreeExpansion(instanceId, scope)mit 600 ms Debounce-PUT;FormGeneratorTreePropsexpandedIds?: string[] | null+onExpandedIdsChange?: (ids) => void(controlled mode);SourcesTab(scope'sources'),FilesTab(scopes'filesOwn'+'filesShared') verdrahtet. Beinull(kein Record) Default-Verhalten + erster Toggle erstellt den Settings-Record; bei Array gewinnt persistierte Liste ueber Backend-defaultExpanded-Hints. Tests: Backendservices+routes107/107 gruen, Frontend UDB+FormGen 69/69 gruen. - 2026-05-18 | fix+feat | gateway+frontend-nyla | UDB Sources Recovery -- Smoke-Test-Followups (G1-G5) (
c-work/3-validate/2026-05-udb-sources-recovery.md). (G1)tsconfig.jsonreferenziert jetzt auchtsconfig.test.json; Testfile bekam explizitenimport React,afterEach,@testing-library/jest-dom/vitest. 139 -> 0 Lints; Tests 50/50 weiterhin gruen. (G2) Off-State derneutralize/ragIndexEnabled-Buttons:filter: grayscale(1); opacity: .45im OFF-Zustand -- offenes Schloss + greyed-Brain klar als "deaktiviert" lesbar. (G3a) Bug_browseChildren: Childs erbtenparentKey=ds|...|/statt des aufgerufenensvc|...; Children erschienen daher nie im FE-Tree. Fix:parentKeyals optionaler Parameter durchgereicht; Dispatcher uebergibt den asked-for-Key. (G3b) Per-Field-Neutralize fuer Feature-Tabellen:fdsTable.hasChildren=Truebei vorhandenermeta.fields-Liste; neuer Knoten-TypfdsField(Dispatcherfdstbl|fi|table->_featureTableFields). Effektiver Field-Neutralize =parent.neutralize OR field IN parent.neutralizeFields. Toggle:UdbSourcesProvider.patchNeutralizesplittet die Batch nach Kind und ruft fuer fdsFieldPATCH /api/datasources/{id}/neutralize-fieldsmit der mutierten Liste;neutralizeFieldsist im Tree-Payload mitgesendet -- kein Extra-GET. Scope/RAG auf Feldebene bewusst nicht editierbar. +3 neue Backend-Tests inTestFeatureTableFields. (G4) FilesTab synthetischer "/"-Root pro Ownership: Provider mapptparentId=nullauf[__filesRoot:<own|shared>](defaultExpanded=true); reale Top-Level-Items werden Children.moveNodesmit Synth-Root-Ziel re-mapt aufparentId/folderId=null(= Drop auf "/");patchScope/patchNeutralizemit Synth-Root-Id materialisieren ueber API alle Top-Level-Folders+Files und setzen pro FoldercascadeChildren=true-- globaler Toggle ohne Backend-Aenderung. Tests: Backend 19/19 gruen, Frontend UDB+FormGen 69/69 gruen. - 2026-05-18 | refactor | gateway+frontend-nyla | UDB Sources Recovery -- Folge-UX-Iteration (
c-work/3-validate/2026-05-udb-sources-recovery.md). Auf das User-Feedback nach Phase 1-3: (a) Visual cascade fuerneutralizeundragIndexEnabledwieder klar erkennbar -- vorher gleiches Symbol fuer on/off (nur Opacity), Cascade unsichtbar. Distinct emojis:_NEUTRALIZE_ON_EMOJI=closed lock/_NEUTRALIZE_OFF_EMOJI=open lock,_RAG_ON_EMOJI=brain/_RAG_OFF_EMOJI=thought-bubble. Backend-Cascade war korrekt (parametrisch incascadeResetDescendants(rec, flag)); rein UI-Issue. (b) Top-Level-Layout flach: synthetische WrappersrcRoot+mandateRootentfernt._topLevelemittiert direkt[personalRoot, mgrp|m1, mgrp|m2, ...]. Mandate-Groups haben nunparentKey=None. (c)TreeNode.defaultExpanded?: booleanals generisches Tree-Feature (one-shot pro Node-Id ueberautoExpandedRef); BE markiertpersonalRootund alle Mandate-Groups mitdefaultExpanded=True-- UI oeffnet bis zur Datenquellen-Ebene ohne User-Klick. (d) Icon-Reihenfolge inFormGeneratorTree(rechtsbuendig, von rechts nach links): neutralize, scope, sendToChat, rag, settings. Settings (extraActions) jetzt linksbuendig. (e) Settings-Icon nur auf Daten-Quellen-Root (kind in {connection, featureNode}), aber dort immer sichtbar, auch ohnedataSourceId; Klick triggert lazy_ensureRecord->onOpenSettings. (f)SourcesTabsetzttitle={t('Datenquellen')}als Section-Header. Tests: Backendtest_buildTree.py16/16 +test_inheritFlags.py72/72 -> 88/88 gruen. FrontendFormGeneratorTree.test.tsx50/50 (+defaultExpanded-Tests) +UdbSourcesProvider.test.ts16/16 (+settings-on-root + defaultExpanded-passthrough). TypeScript clean. - 2026-05-18 | refactor | gateway+frontend-nyla | UDB Sources Recovery: SourcesTab nutzt FormGeneratorTree (
c-work/3-validate/2026-05-udb-sources-recovery.md). Behebt das Folge-Problem aus dem Generic-Tree-Refactor vom selben Tag, dass der Sources-Tab nur "Lade Datenquellen..." zeigte, weil der ad-hoc_TreeNodeView-Renderer inSourcesTab.tsxan einem State-Race (StrictMode-Doppelmount ×mountedRef-Frueh-Abort × parallelerexpansionSignature-useEffect, vier sichtbare POSTs) erstickte. Diagnose via temporaerem_buildTree.getChildrenForParents-INFO-Log: Backend liefert saubercounts={'__root__': 6}-- Bug war ausschliesslich auf der ad-hoc-Renderer-Seite. Backend (_buildTree.py): synthetische ContainersrcRoot(Top-Level),personalRoot,mandateRootmit neuem_syntheticNodeHelper unddisplayOrder-Sort-Hint;_topLevelschrumpft auf[srcRoot],_srcRootChildrenemittiert[personalRoot, mandateRoot],_personalRootChildrenund_mandateRootChildrenenthalten die alte Connections-/Mandate-Logik mit korrigiertenparentKey. Dispatcher ingetChildrenForParentsmatchtparentKey == _KEY_*_ROOTvor dem Decode-Pfad. +7 neueTestSyntheticRootsTests, Service-Suite 89/89 gruen. FormGeneratorTree (generisch erweitert, kein UDB-Vokabular):TreeNode.ragIndexEnabled?: boolean | 'mixed',TreeNode.displayOrder?: number,TreeNodeProvider.patchRagIndex?+canPatchRagIndex?,FormGeneratorTreeProps.refreshAfterAction?: boolean. Sort-Comparator setztdisplayOrdervor folder-first. Dritter Flag-Button (_RAG_EMOJI,_ACTION_RAG) rendert nur wennragIndexEnabled !== undefined._runActionruft_refetchAllExpandedautomatisch auf wennrefreshAfterAction=true; optimistic-Update-Pfad fuer FilesTab unveraendert. +10 neue Tests, Tree-Suite 51/51 gruen. Frontend SourcesTab: ad-hoc-Renderer mit_TreeNodeView,_FlagButton, eigenempendingToggles-State, eigenem_fetchVisible-Pfad komplett geloescht. NeuerUdbSourcesProvider.tsxmappt Backend-UdbBackendNodeauf generischenTreeNode<T>(Synthese-Container ohne Flag-Felder); haelt internennodeCache: Map<key, UdbBackendNode>fuer Patch-Pfade;_ensureRecordPOSTet/datasourcesoder/feature-datasourcesje nachkind; danach PATCH/api/datasources/{id}/{scope|neutralize|rag-index}. NeueSourcesTab.tsxist 75 LOC duenner Wrapper:useMemoProvider +<FormGeneratorTree compact selectable={false} allowCreateFolder={false} refreshAfterAction />+ Settings-Modal-Anbindung ueberextraActions. +14 neue Provider-Tests, Tree+Provider-Suite 65/65 gruen. - 2026-05-18 | fix | gateway | PostgreSQL
recordCreate/_save_record: Zeichenketten-Parameter mit eingebetteten NUL-Bytes (\\x00) werden vor dem Bind gestriped — behebtingestion.failed/ContentChunk-Insert (psycopg2: „A string literal cannot contain NUL“), z. B. bei indexierten.sql/Dump-Dateien. - 2026-05-18 | refactor | gateway+frontend-nyla | UDB Generic Tree Refactor: Backend autoritativ, FE pure Renderer, RAG fuer FDS (
c-work/4-done/2026-05-udb-generic-tree-refactor.md). Schliesst die ueber mehrere Iterationen verschleppte UI-Inkonsistenz, dass Toggles unter bestimmten Bedingungen keinen UI-Effekt hatten. Root-Cause: parallele Logik im Frontend (_resolveFdsFlags, optimistic Updates,_findCoveringDs) widersprach den vom Backend gelieferten Werten. Architektur: Ein einziger EndpointPOST /api/workspace/{instanceId}/tree/childrenmit Body{parents: [null, ...expandedKeys]}liefertnodesByParentals flachen Map mit allen dreieffective*-Werten (neutralize,scope,ragIndexEnabledalsboolean|'mixed'bzw.string|'mixed') pre-computed auf dermode='aggregate'-Ebene. Neuer OrchestratorserviceKnowledge/_buildTree.pymit stabilem Key-Format (conn|<id>,svc|<connId>|<service>,ds|<connId>|<sourceType>|<path>,mgrp|<mid>,feat|<mid>|<code>|<fiId>,fdstbl|<fiId>|<table>) — preloadet DS+FDS einmal pro Request und dispatched pro Parent-Kind an Connector/Catalog/RBAC. Sourcetype-Mapping (sharepoint -> sharepointFolderetc.) ist nun Backend-autoritativ. FE-Refactor:SourcesTab.tsxvon ~2500 auf ~530 Zeilen reduziert. State nur nochchildrenByParent: Map,expandedKeys: Set,pendingToggles: Set. Toggle-Flow strikt PATCH -> Refetch -> Render mit Spinner ueber dem Flag-Button bis API-Response zurueck ist. Generischer_TreeNodeViewrekursiv fuer ALLE Kinds, generischer_FlagButtonmit einheitlichem Mixed-Symbol (U+25E9, "square with diagonal lines") fuer alle drei Flags. RAG fuer FDS:_INHERITABLE_FDS_FLAGSenthaelt nunragIndexEnabled;FeatureDataSource.ragIndexEnabled: Optional[bool]Field (Auto-Migration viaALTER TABLE ADD COLUMN);PATCH /api/datasources/{id}/rag-indexakzeptiert via_findSourceRecordsowohl DS als auch FDS (Bootstrap-Job + Chunk-Purge bleiben DS-only);GET /feature-datasourceslieferteffectiveRagIndexEnabled;resolveEffectiveForFdsum den dritten Wert ergaenzt. Geloescht (keine Konsumenten mehr):POST /datasources/resolve-flags+ 3 Models,GET /connections,GET /connections/{id}/services,GET /connections/{id}/browse,GET /feature-connections,GET /feature-connections/{fiId}/tables,GET /feature-connections/{fiId}/parent-objects/{tableName}, totesSourcesTab.module.css. Bewusste Reduzierung (User-Entscheidung): FDS-Records sind nicht mehr expandierbar (hasChildren: falsefuerfdsTable); Tabellen-Ebene reicht.FeatureDataSource.recordFilterbleibt fuer API-Kompat erhalten. Tests: neutest_buildTree.py(10 gruen — Key-Coding, Effective-Triplets, Record-Lookup, Orchestrator-Smoke), +5 neue intest_inheritFlags.py::TestResolveEffectiveForFds(RAG inherits, RAG aggregate-mixed,_INHERITABLE_FDS_FLAGSenthaelt RAG) +1 inTestCascadeResetFdsRag. Resultat: 82/82 gruen; Frontendnpx tsc --noEmitclean. - 2026-05-18 | feat | gateway+frontend-nyla | UDB Toggle-Semantik v2: 'mixed'-Aggregation + bottom-up cascade + Backend-autoritative effective values — Grundlegendes Redesign der Toggle-Semantik (neutralize, scope, ragIndexEnabled) für DataSource und FeatureDataSource. (1) Backend:
getEffectiveFlagundgetEffectiveFlagFdsmitmode='walk'|'aggregate'— walk gibt immer konkret, aggregate gibt 'mixed' wenn Subtree divergiert. (2)cascadeResetDescendants/Fdsjetzt bottom-up (deepest-first) für Crash-Sicherheit, RückgabeList[str]stattint. (3) GET /datasources und /feature-datasources liefern computedeffectiveNeutralize,effectiveScope,effectiveRagIndexEnabledpro Item. (4) PATCH-Response enthältresetDescendantIds+updatedAncestorsfür optimistic UI. (5) Bug-Fixes B1-B6: routeDataConnections consent-re-enable RAG, routeRagInventory reindex+inventory, routeDataSources settings-RBAC, _dataSourceTools download neutralize, _featureSubAgentTools FDS neutralize cascade — alle aufgetEffectiveFlag(mode='walk')umgestellt. (6) Frontend: Workarounds entfernt (_effectiveFlag,_findAncestorDs,_AUTHORITY_SOURCE_TYPES, prop-drillinginheritedScope/Neutralize), zentrale_readDsFlags/_readFdsFlagsaus Backend-Werten, Toggle-Handler mit optimistic cascade viaresetDescendantIds. (7) 'mixed'-Icon-Darstellung im UI. - 2026-05-18 | chore | gateway | RAG-Walker und
requestIngestion: per-item Lognois reduziert —subWalkerHelpers(walker.item.start,walker.download.start,walker.extract.start) undingestion.skipped.duplicatevon INFO auf DEBUG, damit Daily-Resync / wiederholtes Durchlaufen nicht das App-Log flutet; Stuck-Triage via DEBUG aufmodules.serviceCenter.services.serviceKnowledge.subWalkerHelpersbzw.mainServiceKnowledge. - 2026-05-18 | fix | gateway+frontend-nyla | UDB Cascade-Inherit Bugfix: Connection-Root Toggle hatte keinen UI-Effekt — User-Report: "no change in UI, whatever icon I press". Log-Analyse zeigte: jeder Toggle macht POST
/datasources(Backend gibt via Upsert die bereits existierende ID zurück) gefolgt von PATCH (Backend updated korrekt), aber UI bleibt unverändert. Root-Cause 1: Die ConnectionRoot-DataSource (sourceType='msft'/'google'/'clickup'/'infomaniak'/'local',path='/') wurde im Frontend von_findDsignoriert (if (node.type === 'connection') return undefined) — Workaround aus dem Vortag, der eine andere Race-Condition verhindern sollte. Folge:ds === undefinedfür Connection-Nodes →_addAsDataSource-POST → Backend Upsert findet bestehenden DS viaconnectionId+path-Match und returnt dieselbe ID → PATCH erfolgreich → UI rendert aber weiter mitds=undefined→ opacity bleibt 0.35. Fix 1:_findDsmatcht jetzt deterministisch viasourceType: für Connection-Nodesnode.authority('msft'/'google'/…), für Service-Nodes_SERVICE_TO_SOURCE_TYPE[node.service]('sharepointFolder'/…). Zwei DS mitconnectionId+path='/'aber unterschiedlichemsourceType(Connection-Root vs Service-Root) sind dadurch eindeutig unterscheidbar. Root-Cause 2: Cross-Authority-Vererbung fehlte komplett. User-Erwartung: Toggle auf Connection-Root muss alle Service-Children (SharePoint, OneDrive, Outlook unter derselben msft-Connection) visuell mitziehen. BackendgetEffectiveFlagundcascadeResetDescendantsfilterten aber strikt aufsourceType==parentSourceType, also keine Vererbung über die Authority-Grenze hinweg. Fix 2: Neue Konstante_AUTHORITY_SOURCE_TYPES = {'local','google','msft','clickup','infomaniak'}in_inheritFlags.pyund Mirror im Frontend._findAncestorChainergänzt um den ConnectionRoot als "äusseren" Ancestor (after all same-sourceType ancestors).cascadeResetDescendantscascadiert beiparentIsConnectionRoot=Trueüber die GANZE Connection (cross-sourceType). Frontend_findAncestorDsanalog. Tests: 23/23 grün (4 neue für Cross-Authority:test_connection_root_inherits_cross_sourcetype,test_same_sourcetype_ancestor_wins_over_connection_root,test_connection_root_does_not_self_inherit,test_connection_root_cascades_cross_sourcetype). Frontendnpm run build+tsc --noEmitgrün. - 2026-05-18 | feat | gateway+frontend-nyla | UDB Cascade-Inherit für DataSource-Flags (
neutralize,ragIndexEnabled,scope) — Plan:c-work/1-plan/2026-05-udb-cascade-inherit.md. Schliesst die Konsistenz-Lücke, dass Toggles an einem Parent nicht nach unten propagieren konnten, sobald ein Descendant einen eigenen DataSource-Record hatte. Beispiel-Bug: SharePoint=true → Folder1=false (explizit) → SharePoint=true (zweites Toggle) → Folder1 blieb auf false statt mit dem Parent zu folgen. Architektur: 3-wertige Felder mitNULL = inherit, expliziterTrue/False(oder'personal'/'mandate'/'platform'/'global'für scope). Backend: (1) DatenmodellDataSource.{neutralize,ragIndexEnabled,scope}undFeatureDataSource.{neutralize,scope}aufOptional[...]umgestellt; Migrationscript_db_migrate_datasource_inherit.pymacht Spalten nullable (idempotent, additiv — bestehende Werte bleiben explizit, NEW records starten mit NULL). (2) Neuer zentraler HelperserviceKnowledge/_inheritFlags.pymitgetEffectiveFlag(rec, flag, allDs)(path-traversal aufwärts, longest-prefix wins, defensivconnectionIdUNDsourceTypeals Filter),cascadeResetDescendants(rootIf, parentRec, flag)(setzt nur das EINE Flag der explizit-belegten Descendants auf NULL, andere Flags unangetastet) und_isAncestorPath(/ist Ancestor von allem;/fooNICHT von/foobar—/-Separator-Pflicht). (3) PATCH-EndpointsrouteDataSources.{_updateDataSourceScope,_updateDataSourceNeutralize,_updateDataSourceRagIndex}akzeptierenOptional[bool|str]als Body-Wert:null→ reset auf inherit (kein Cascade);true/false→ explizit + Cascade-Reset aller Descendants. RAG-Endpoint zusätzlich: nur beiTrueMini-Bootstrap-Job +_ensureConnectionKnowledgeFlag; nur beiFalsesynchrone Chunk-Purge —nullno-op. Audit-Lograg_index_toggledträgtcascadedDescendantsCount. (4) Walker-Integration:_loadRagEnabledDataSourcesfiltert auf effective ragIndexEnabled (viagetEffectiveFlag) und schreibt resolved Werte fürneutralize/scopedirekt in das returned dict — Walker (Sharepoint/Outlook/Gdrive/Gmail/Clickup/Kdrive) bleiben unverändert und lesen weiterds.get("neutralize", False). AltersubPolicyResolver.pyzu Backward-Compat-Shim aufgetEffectiveFlagdeprecated. Frontend:UdbDataSourceInterface mitboolean|nullundstring|null; neue Helper_findAncestorDs+_effectiveFlag(path-traversal analog zu Backend); Toggle-Handler senden!currentEffective(= aktuell sichtbarer Wert wird invertiert), Backend macht den Cascade. Local State: optimistisch +_fetchDataSources()nach PATCH damit cascade-resettete Descendants aus DB neu geladen werden. Alte unbenutzte_togglePersonalNeutralize/_togglePersonalRagIndex/_cyclePersonalScopeentfernt. Tests: neuertest_inheritFlags.pymit 19 grün — explicit-wins, ancestor-traversal, default-fallback, sourceType-Isolation, connectionId-Isolation,/foo≠ Ancestor von/foobar, root-is-ancestor-of-everything, scope-string-default, cascade-touches-only-target-flag, cascade-skips-other-sourcetypes. Bestehendetest_knowledge_ingest_consumer.py8/8 grün. Frontendnpm run buildgrün, TypeScript clean. Pre-existing Test-Failures (nicht durch diesen PR):test_p1d_consent_prefs.py(5) — Python-3.13 asyncio-Deprecation + Schema-DriftConnectionIngestionPrefs.neutralizeBeforeEmbed;test_bootstrap_sharepoint.py+test_bootstrap_gmail.py(5) — rufenbootstrapSharepoint/GmailohnedataSources=auf, was seit dem 2026-04 Unified-Indexing-PR den Early-Return triggert.
2026-05-17
- 2026-05-17 | fix | frontend-nyla | UDB Settings-Modal: RAG-Limits nur auf DataSource-Root — Settings-Icon (⚙️) bleibt auf allen Nodes sichtbar, aber RAG-Limits- und Kostenschätzungs-Sektionen werden nur noch auf DataSource-Root-Nodes (Level 2 =
service) angezeigt. Subelemente (Folder/File) können weiterhin die Connection-Settings sehen, erben aber die Walker-Limits vom Root. Neue Modal-PropshowRagSection. Neutralisierung/RAG-Toggle: Vererbungslogik ist korrekt (Parent aktiviert → Kinder werden mitgezogen, volle Opacity). Kein visueller Unterschied nötig — das ist gewolltes Verhalten. - 2026-05-17 | feat | gateway+frontend-nyla | i18n für BackgroundJob-Progress-Messages (Backend-translated) — User-Report: RAG-Page zeigte "145 Dateien verarbeitet, 106 indexiert" auch bei UI-Sprache=
en, weil walker das Plaintext-Deutsch direkt inBackgroundJob.progressMessageschrieben und das Frontend es 1:1 rendert. Root-Cause: BackgroundWorker hat keinen Request-Sprach-Kontext (_CURRENT_LANGUAGEist ContextVar pro Request), undprogressMessagewird persistiert — wäre selbst dann gefroren, wenn der User später die Sprache wechselt. Architektur (regelkonform zuwiki/b-reference/gateway/architecture.md#i18n): Backend speichert strukturiert + übersetzt server-side beim Route-Read; Frontend rendert 1:1 — keint()auf Backend-Werten. (1) Neue JSONB-SpalteBackgroundJob.progressMessageData = {key, params}(Migrationscript_db_migrate_backgroundjob_progress_data.py, additiv + idempotent). (2)JobProgressCallback.__call__akzeptiertmessageKey="LITERAL"+messageParams={…}und schreibt beides als JSON; zusätzlich rendert es einen DE-Fallback inprogressMessagefür Logs/Audit/Legacy-Clients. (3) Alle Walker (6 RAG +subConnectorIngestConsumer+ Trustee push/sync/import +accountingDataSync._progress) umgestellt —messageKey=ist immer ein String-Literal. (4) Key-Registrierung über string-literalet("…")Calls: neuesserviceKnowledge/_progressMessages.py(Side-Effect-Import inapp.pylifespan, 5 RAG-Keys), Trustee 14 Keys inmainTrustee.py— KEINE Variable-Aufrufe vont()(Wiki-Regel #1:t(variable)ist verboten). (5) Neuer Helperi18nRegistry.resolveJobMessage(messageData)analog zuresolveText(value)— der einzige zulässiget(variable)-Pfad, weil er in der i18n-Infrastruktur lebt; nutzt_CURRENT_LANGUAGEaus dem Request-Kontext und substituiert Params via.format(**params). (6)routeJobs._serialiseJobundrouteRagInventoryrufenresolveJobMessagebeim Read und schreiben das Ergebnis inprogressMessage— Frontend bekommt einen fertigen, übersetzten String. (7) Frontend zurückgebaut:utils/jobProgressUtils.tsHelper gelöscht, DTOs (useBackgroundJob,connectionApi,trusteeApi) ohneprogressMessageData-Feld, Render-Stellen (RagInventoryPage,RagRunningBadge,TrusteeAccountingSettingsView) lesen direktjob.progressMessage. Tests: 22/26 grün; die 4 Failures intest_knowledge_ingest_consumer.pysind pre-existing (verifiziert viagit stashDiff). Frontendnpm run buildgrün. Smoke:resolveJobMessage({'key': '{n} Dateien verarbeitet, {indexed} indexiert', 'params': {'n': 145, 'indexed': 106}})→'145 Dateien verarbeitet, 106 indexiert'. Wiki: neuer Abschnitt "BackgroundJob-Progress-Messages" inb-reference/gateway/architecture.mdmit den 4 Schritten (Walker → Registrierung → Route-Resolve → Frontend-Render). - 2026-05-17 | feat | gateway+frontend-nyla | UDB DataSource Settings (⚙️) + konfigurierbare RAG-Limits (Plan & Build:
c-work/2-build/2026-05-udb-datasource-settings.md). Schliesst zwei Lücken: (1) RAG-Walker-Limits (maxBytes=200 MBetc.) waren hartkodiert — User mit 500-MB-Folder konnte nur Code-Änderung machen; (2) FeatureDataSource hatte gar keinen Settings-Ort. Backend: JSONB-SpaltesettingsaufDataSource+FeatureDataSource(Migrationscript_db_migrate_datasource_settings.py, additiv + idempotent). Neues ModulserviceKnowledge/_ragLimits.pymitFILES_LIMITS_DEFAULT/CLICKUP_LIMITS_DEFAULTals zentrale Source-of-Truth — die altenMAX_*_DEFAULT-Konstanten in den 4 Walkern (subConnectorSyncSharepoint/Kdrive/Gdrive/Clickup.py) sind nur noch Aliase. Kritische Semantik:getStoredOverrides(ds, kind)liefert NUR explizit gesetzte Overrides → Walker mergen sie auf den caller-suppliedlimits=-Parameter, damit Test-/Caller-Overrides weiter gewinnen (test_bootstrap_maxTasks_caps_ingestion=3bleibt grün);getRagLimits(ds, kind)mergt auf Defaults → API/Cost-Estimate-Pfad. Keine Override-Schicht, keine Resolver-Logik — was im Modal steht, ist exakt was der Walker liest. Zwei neue Endpunkte inrouteDataSources.py:PATCH /api/datasources/{id}/settings(akzeptiert nur Top-Level-KeyragLimits, unknown → 400, positive Ints only, Owner-only/Mandate-Admin, Audit-Logdatasource_settings_changed) undGET /api/datasources/{id}/cost-estimate(indikative USD-Schätzung via_costEstimate.py-Heuristik:text-embedding-3-small @ $0.02/1M Token,BYTES_PER_TOKEN=4,EXTRACTABLE_FRACTION=0.4; Antwort trägt vollständigesbasis-Objekt mit Annahmen/Formel/Notes). Frontend: Neues ⚙️-Icon pro Node imUnifiedDataBar/SourcesTab.tsx(vor dem 🧠) öffnet den neuenDataSourceSettingsModal.tsxmit drei klar abgegrenzten Sektionen: (1) Connection —knowledgeIngestionEnabled-Toggle viapatchKnowledgeConsent(mit Confirm-Dialog beim Deaktivieren); (2) RAG-Limits — Felder editierbar, Bytes in MB im UI; (3) Kostenschätzung — refresh nach Save. Dasselbe Modal wird auf derRagInventoryPage.tsxvom amber Partial-Banner (stoppedAtLimit) via neuen "Limit anpassen"-Button geöffnet → User hat direkten Pfad vom Symptom zur Behebung. Workspace-RouteGET /api/workspace/{instanceId}/connectionsliefert jetztknowledgeIngestionEnabledmit, damit der Modal-Initial-Toggle korrekt vorbelegt. Tests: 12 neue Unit-Tests intests/unit/services/test_ragLimits.py+ 6 intest_costEstimate.py(Defaults-Isolation, partial-override, non-int dropped, doubling-formula, basis-shape) — alle grün; bestehende Bootstrap-Tests für Sharepoint/Kdrive/Gdrive/ClickUp weiter grün (caller-limits-Override respektiert). Frontendnpm run buildgrün, keine neuen Lint-Errors. Doku:b-reference/gateway/ai-agent.md(Abschnitt "Konfigurierbare RAG-Limits"),TOPICS.md(neuer Eintrag). Verbleibende Hard-Limits insubConnectorSyncOutlook/Gmail.pyhaben aktuell kein UI-Override, bleiben aber als next-step (gleicher Helper anwendbar). - 2026-05-17 | feat | frontend-nyla+gateway | Knowledge-Consent Toggle auf ConnectionsPage + Forward-Sync DataSource→Connection. Zwei Lücken in der RAG-Consent-UX geschlossen, die zu der Beobachtung "valueon hat Index aktiviert, aber Checkbox fehlt" geführt haben: (1) Die ConnectionsPage zeigte
knowledgeIngestionEnablednur als generische "Ja/Nein"-Spalte der FormGeneratorTable — kein Toggle-Element. Neu: zwei CustomActions (FaToggleOn/FaToggleOff, je nach State sichtbar viavisible-Filter), Klick ruftpatchKnowledgeConsent→/api/connections/{id}/knowledge-consentund refetcht die Liste. Damit ist die UI 1:1 konsistent mit dem Master-Switch auf der RagInventoryPage (gleiches Backend-Endpoint, gleiches Icon, gleicher Confirm-Dialog beim Deaktivieren). (2) Backend:routeDataSources._updateDataSourceRagIndexpropagierte bisher nicht auf die Parent-Connection. Neuer Helper_ensureConnectionKnowledgeFlag(rootIf, connectionId)setzt forward-onlyUserConnection.knowledgeIngestionEnabled=True, sobald min. eine DataSource aufragIndexEnabled=truetoggelt — kein Auto-Disable, weil der Master-Switch dem User gehört (verhindert versehentliches Zurücksetzen eines explizit gegebenen Consents, z.B. einer Connection ohne aktive DataSource, aber mitknowledgePreferences). Plan-Doc für die UDB-Settings-Erweiterung (Issue 2):c-work/1-plan/2026-05-udb-datasource-settings.md. Der Fix für Limit-Transparenz wirkte UI-seitig nicht, weil_bootstrapJobHandlerinsubConnectorIngestConsumer.pydie Sub-Service-Results in ein wrappendes Dict packt ({"authority", "connectionId", "sharepoint": {...}, "outlook": {...}}für msft; analog fürdrive/gmail/clickup/kdrive).routeRagInventory._buildConnectionInventorygriff aber auf Top-Levelresult.stoppedAtLimit/indexed/etc. zu — alleNone. Folge: amber Banner blieb aus UND die Statistik-Zeile zeigte gar keine Zahlen ("Sync erfolgreich" ohne "— 25 unverändert"). Neuer_flattenJobResult()-Helper aggregiert über alle bekannten Sub-Keys (sum für counters, max für durationMs, erstes Limit-Hit fürstoppedAtLimit/limits). Verifiziert anhand Job2374aecd-3e17-460a-a13e-530f9f1115e6:bytesProcessed=209894527≥maxBytes=209715200, jetzt korrekt alsstoppedAtLimit="maxBytes"an die UI durchgereicht. Diagnose-Skriptgateway/scripts/debug_rag_job_result.pyzeigt vor/nach-Flatten und bleibt für künftige Bootstrap-Result-Debugging im Repo. - 2026-05-17 | feat | gateway+frontend-nyla | RAG-Inventar: echte Chunks + Limit-Transparenz. Drei Probleme behoben: (1)
routeRagInventory._buildConnectionInventoryzählte bisherlen(FileContentIndex)(= indizierte Dateien) und labelte das im UI als "Chunks" — bei einer 99-Seiten-PDF erscheint dort statt der echten ~99 Chunks die Zahl 1. NeueinterfaceDbKnowledge.countChunksByFileIds()macht eine einzige Aggregat-SQLSELECT "fileId", COUNT(*) FROM "ContentChunk" WHERE "fileId" = ANY(%s) GROUP BY "fileId"(kein Vector-Body geladen), die Response trägt jetztfileCountUNDchunkCountpro DataSource +totalFiles/totalChunkspro Connection. (2)RagInventoryPage.tsx/connectionApi.tszeigen beide Werte getrennt ("25 Dateien · 1240 Chunks") mit Tooltip-Definition für Chunks (~400 Tokens). (3) Limit-Transparenz: SharePoint/kDrive/gDrive-Bootstrap stoppen bei den ersten Limits (MAX_BYTES_DEFAULT=200 MB,MAX_ITEMS_DEFAULT=500,MAX_DEPTH_DEFAULT=4,MAX_FILE_SIZE_DEFAULT=25 MB); ClickUp analog (MAX_TASKS_DEFAULT=500,MAX_WORKSPACES_DEFAULT=3,MAX_LISTS_PER_WORKSPACE_DEFAULT=20). Bisher:returnohne Log + ohne Marker im Bootstrap-Result → User sah "Sync erfolgreich" obwohl 706 Dateien fehlten. Fix: neuer_recordLimitStop()-Helper in allen 4 Connectoren setztBootstrapResult.stoppedAtLimit(1. exhausted Budget), schreibt 1 WARNING in den Log und liefert das Feld + die effektivenlimitsim_finalizeResultDict anBackgroundJob.result.routeRagInventoryreichtlastSuccess.stoppedAtLimit/limits/bytesProcessedans Frontend durch. Neuer amberpartialBannerauf der RagInventoryPage warnt mit "Limit maxBytes=200 MB (200 MB verarbeitet) erreicht — Weitere Dateien wurden NICHT indexiert" und bietet "Erneut indexieren". Verifiziert anhandlocal/logs/log_app_20260517.log: SharePoint-Sync hat genau beibytesProcessed=209_894_527 ≥ MAX_BYTES_DEFAULT (209_715_200)gestoppt (Kumulative Summe der 25 indizierten Dateigrößen = 200.17 MB). ClickUp hat beiskippedDup=500 >= maxTasks=500gestoppt. Outlook/Gmail brauchen das gleiche Pattern noch (haben aktuell keine harten Limits im Code, daher kein Bug, aber wenn welche kommen → gleicher Helper). - 2026-05-17 | fix | gateway | Secrets Decryption TTL-Cache (
gateway/modules/shared/configuration.py):decryptValue()cached jetzt erfolgreich entschlüsselte Plaintexts process-wide für 60 s (Key = Ciphertext, thread-safe,clearDecryptionCache()für Rotation/Tests). Root-Cause aus S7-Smoke-Test (local/logs/log_app_20260517.log:609): RAG-Inventory-Polling + paralleler Walker-Burst triggerte fürsystem/DB_PASSWORD_SECRET>10 Decrypts/s, das Brute-Force-Schutz-Rate-Limit warfValueError: Decryption rate limit exceeded→routeRagInventory._getInventoryPlatformHTTP 500. Hot-Path warmainBackgroundJobService._getDb(), das pro CallAPP_CONFIG.get("DB_PASSWORD_SECRET")evaluiert (eager arg eval), bevorgetCachedConnectorüberhaupt seinen Wrapper-Cache prüfen kann. Cache-Hit umgeht das Rate-Limit (kein neuer Krypto-Op, nur Re-Read eines bereits autorisierten Plaintexts); Cache-Miss konsumiert weiter Rate-Budget — die Schutzfunktion gegen wiederholt falsche Decrypts bleibt damit erhalten. Wirkt global für alle_SECRET-Reader (auditLogger,routeI18n, alle Feature-Interfaces), nicht nur für den BackgroundJobService. - 2026-05-17 | refactor | gateway | PostgreSQL Connection Pool — Steps S3–S6 abgeschlossen (
c-work/2-build/2026-05-postgres-connection-pool.md). S3:getCachedConnectorDocstring präzisiert (Cache = Wrapper-Recycling + DB-Init-Spam-Schutz, Pool = echte Connection-Verwaltung). S4: Shutdown-HookcloseAllPools()ingateway/app.pylifespan als letzter Schritt nach Feature-onStop-Hooks. S5: Neuer Test-Filegateway/tests/unit/connectors/test_connectorDbPostgre_pool.pymit 6 Concurrency-Tests gegen live-Postgres (auto-skip wenn keine DB erreichbar): 50 Threads × 20 Reads (0 Errors), 20 Threads × 50 Reads (p99 < 5 s), interleaved load/save,statement_timeout=500mstriggertQueryCanceledund gibt Connection sauber zurück, Pool-Identity pro (host, db, port),closeAllPoolsleert Registry. Beim ersten Lauf entdeckt: psycopg2-Pool wirftPoolErrorsofort bei Exhaustion statt zu blockieren →borrowConn()um bounded Wait-Retry erweitert (_BORROW_WAIT_TIMEOUT_S=30s,_BORROW_WAIT_BACKOFF_S=50ms). Altertest_connectorDbPostgre_failLoud.pyauf das neueborrowConn-Mocking umgestellt (alle 6 weiter grün). S6: Regression-Run: 639/656 unit grün (vorher 638) — der eine durch den Refactor verursachte Fail (test_folder_crud._FakeDbbrauchteborrowCursor-Stub) gefixt, die übrigen 17 Failures sind pre-existing RAG/Adapter/Workflow-Drift ohne Pool-Bezug. 76/79 integration grün (3 pre-existing Trustee-Workflow-Fails). Backward-Compat-StubborrowCursorauch intest_folderRbac._FakeDbergänzt. Offen: S7 (manueller 1 h Smoke-Test, Anleitung in der Plan-Doc) und S8 (b-reference/platform/database-architecture.md). - 2026-05-17 | refactor | gateway | CORE: PostgreSQL Connection Pooling implementiert (S1+S2 von
c-work/2-build/2026-05-postgres-connection-pool.md). Root-Cause:DatabaseConnectorhielt eine psycopg2-Connection pro Instanz und teilte sie viagetCachedConnector(...)über den gesamten FastAPI-Thread-Pool und über asyncio-Tasks. psycopg2-Connections sind NICHT thread-safe — paralleler Zugriff aus z.B. RAG-Polling,routeI18n,mainBackgroundJobServiceund Hintergrund-Jobs führte zuanother command in progressund — viel schlimmer — unendlichem Block inrecv()(keinstatement_timeoutgesetzt). Dasself._lockinDatabaseConnectorwar zwar deklariert, aber nirgends verwendet. Folge: Backend hat sich komplett aufgehängt, sogar die i18n-API für die Login-Seite lieferte nichts mehr. Lösung: Neuer_PoolRegistry(gateway/modules/connectors/connectorDbPostgre.py) mitpsycopg2.pool.ThreadedConnectionPoolpro(host, db, port), lazy-init, thread-safe (min=2,max=20perDB_POOL_MAX_CONN,statement_timeout=30s,connect_timeout=10s). Jede DB-Operation borrowed eine Connection via neuemdb.borrowConn()-Context-Manager (auto-commit/rollback/return);db.borrowCursor()als 1:1-Ersatz für das altewith db.connection.cursor() as cursor:Pattern.getCachedConnectorbleibt API-kompatibel, Connector-Wrapper sind nun leichtgewichtig (kein per-instance Socket). Backward-Compat-Shimdb.connection(no-opcommit()/rollback()/closed, RuntimeError aufcursor()damit kein Stillschweigend-Bruch). 18 interne Cursor-Stellen + ~30 externe (interfaceRbac, interfaceDbManagement, interfaceDbBilling, interfaceFeatureRealEstate, routeWorkflowDashboard, routeHelpers, gdprDeletion, dbMultiTenantOptimizations, _featureSubAgentTools, scripts/stage0) auf das neue Pattern umgestellt._ensure_connectionals No-Op gehalten (Pool re-connectet selbständig). Public Shutdown-HookcloseAllPools()wartet auf S4 (FastAPI-Lifespan-Integration). Working-Doc:c-work/2-build/2026-05-postgres-connection-pool.md(Step S1+S2).
2026-05-16
- 2026-05-16 | fix | frontend-nyla |
AddConnectionWizardAdmin-Consent-Button war NoOp:ConnectionsPagehat dasonMsftAdminConsent-Prop nie übergeben, der?.()-Aufruf im Wizard wurde schweigend übersprungen und der Wizard sprang einfach zum nächsten Schritt. Im Backend kam kein einziger Request an/api/msft/adminconsentan — User aus Multi-Tenants, in denen die App-Registration noch nie admin-consented wurde, hingen unauflöslich im "Anforderung gesendet"-Screen fest. Fix:ConnectionsPage._handleMsftAdminConsentöffnet jetzt ein Popup auf/api/msft/adminconsent, und das Prop wird an den Wizard durchgereicht. Doc-Sync:d-guides/microsoft-entra-registration-checklist.md(Redirect-URI-Tabelle um/api/msft/adminconsent/callbackergänzt — Fehlen führte zuAADSTS50011; Multi-Tenant-Hinweis: Admin Consent gilt pro Tenant).
2026-05-15
- 2026-05-15 | fix | gateway |
subAiCallLooping.py: fehlender Top-Level-ImportextractJsonString(undrepairBrokenJson) im Modul-Header ergänzt. BeigetContexts()-Success (jsonParsingSuccess=True, overlapContext='') flog einNameError, wurde vom zu breitenexcept Exceptionals "completePart not serializable" geschluckt, hatmergeFailCounthochgezählt und nach 3 Iterationen leeren String zurückgegeben — Folge:subStructureFillingbekam""und meldetetryParseJson failed: Expecting value/No elements produced. Zusätzlichexcept-Hygiene:(json.JSONDecodeError, KeyError, TypeError)→ WARNING + retry (erwartete Daten-Probleme), generischerexcept Exception→ ERROR mitexc_info=Trueund Re-Raise (Code-Bugs werden nicht mehr 3× silently verfressen). Logging enthält jetzt den Exception-Typ als Prefix. - 2026-05-15 | feat | gateway | Feature Data Sub-Agent Phase 1.5 + Phase 2 abgeschlossen. Eval-Harness (
gateway/tests/eval/runTrusteeBenchmark.py, standalone Runner) fährt 19 Goldstandard-Fragen × 3 Modi (baseline / phase1 / phase2) mit echten AI-Calls gegen einenFakeFeatureDataProvider(in-memoryBenchmarkFixture, kein DB-Setup) und schreibt Markdown + JSON-Report nachlocal/notes/. Trustee-Ontologie (gateway/modules/features/trustee/trusteeOntology.py): 6 Entities (Account + BankAccount/CashAccount-Spezialisierungen, AccountBalance, JournalEntry/Line), 3 Relations, 6 Constraints (NEVER_AGGREGATE auf alle 4 Balance/Total-Felder, REQUIRES_FILTER_ON für AccountBalance, PREFERRED_TABLE_FOR_INTENT), 8 CanonicalQueryPatterns. OntologyToPromptCompiler (ontologyToPromptCompiler.py) rendert die Descriptor deterministisch als kompakten Prompt-Block.mainTrustee.getAgentOntology()Hook +_AGENT_DOMAIN_HINTS_LEGACYgeparkt.featureDataAgent._buildSchemaContextnutzt_loadFeatureOntologyBlock()bevorzugt (Fallback auf_loadFeatureDomainHints);_buildValidatorForFeature()verkabelt Validator+Ontologie automatisch (Single Source of Truth). Eval-only OverridePOWERON_DISABLE_FEATURE_ONTOLOGY=1. Side-Fix:aggregateTableexponiert jetztfiltersim Tool-Schema (war Code-Bug, blockierte SUM-pro-Konto-Anfragen); Validator validiert filters analog zu queryTable. Resultate (local/notes/trustee-benchmark-20260515-161126.md): Accuracy Baseline 89.5 % → Phase 1 94.7 % (Validator triggert in q13 2× und steuert Agent eigenständig auf queryTable um) → Phase 2 100 % (Ontologie verhindert q09-Halluzination "creditTotal statt closingBalance" präemptiv). +18 neue Unit-Tests intest_trusteeOntology.py(Descriptor, Compiler, Validator-Integration, mainTrustee-Hook, _buildValidatorForFeature);test_featureDataAgent_schema.pyum Ontology-Pfad + Eval-Override erweitert. Working-Doc verschoben nachc-work/3-validate/2026-05-feature-data-agent-ontology-and-repair.md. Doc-Sync:b-reference/gateway/ai-agent.md(neuer Abschnitt "FeatureDataAgent: Query-Repair-Loop + Ontologie"),b-reference/gateway/features/trustee.md(neuer Abschnitt "Agent-Ontologie"),d-guides/coding-conventions.md(Migrations-MustergetAgentDomainHints→getAgentOntology). - 2026-05-15 | feat | gateway | Feature Data Sub-Agent Phase 1 (Query-Repair-Loop) implementiert. Neuer
QueryValidator(gateway/modules/serviceCenter/services/serviceAgent/queryValidator.py) prüftbrowseTable/queryTable/aggregateTable-Calls vor dem Provider gegen das Pydantic-Modell und liefert strukturierte Repair-Hints statt SQL-Exceptions. Vier Constraint-Klassen:FIELD_NOT_FOUND(mit Fuzzy-Suggestion via difflib),OPERATOR_INCOMPATIBLE(LIKE/ILIKE nur auf String,>=/<=nur auf Numerisch),INVALID_AGGREGATE_TARGET(SUM/AVG auf*Balance/*Total-- fängt die flagship Trustee-HalluzinationSUM(closingBalance) × 7 Jahre × 13 Perioden ≈ 90× Saldodeterministisch ab),ORDER_BY_INVALID. Neues DatenmodelldatamodelOntology.pymitQueryValidationError,Constraint,OntologyDescriptor(Phase-2-Ready); Phase-2-Override via Ontologie-Constraints schon eingebaut, aber inaktiv solange keine Ontologie pro Feature definiert ist.ToolResult.errorDetails: Optional[Dict]undToolCallLog.validationFailureCode: Optional[str]zudatamodelAgent.pyergänzt (LLM bekommt machine-readable Repair-Hint, Audit-Log behält Kurz-String).agentLoop._computeRepairCountersaggregiert pro Sub-Agent-RunvalidationFailures,repairAttempts,successAfterRepairaus denToolCallLog-Einträgen und legt sie aufAgentTrace+ insAGENT_SUMMARY-Event (Eval-Harness-Ready). Tool-Descriptions der drei Sub-Agent-Tools erklären daserrorDetails-Format explizit. 35 neue Unit-Tests (24 für QueryValidator, 3 für Tool-Integration, 8 für Trace-Aggregation), alle 62 bestehenden serviceAgent-Tests bleiben grün. Working-Doc:c-work/2-build/2026-05-feature-data-agent-ontology-and-repair.md. - 2026-05-15 | chore | wiki | Plan-Finalisierung: (1) RAG C&C Unification+Implementation → status
done, alle Testplan-Einträge manuell verifiziert,b-reference/platform/neutralization.md(DataSource=SSoT, kein neutralizeBeforeEmbed, Tree-Vererbung) undb-reference/frontend-nyla/architecture.md(RagInventoryPage, UDB 4. Button, RagRunningBadge, AddConnectionWizard) aktualisiert, beide Pläne nach4-done/verschoben. (2) Enterprise Subscription →4-done/. (3) FormGenerator Grouping →4-done/. (4) STT Benchmark Page implementiert (Backend + Frontend, SysAdmin-only). - 2026-05-15 | docs | wiki | Feature Data Sub-Agent Plan (
c-work/1-plan/2026-05-feature-data-agent-ontology-and-repair.md) gegen Codebase verifiziert und um 5 Klärungen geschärft: (A)ToolResult.errorDetails: Optional[Dict]neu indatamodelAgent.pystatt JSON-in-error-String; (B) Repair-Telemetrie wandert vonaiAuditLoggerinAgentTrace/ToolCallLog(per-Run-Aggregation passt nicht in per-Call-Audit-Log); (C) Eval-Fixture als Python-Loader + Pydantic/recordCreatestattfixture.sql(konsistent mit Trustee-Tests); (D) AC#3 alsrepairConversionRate ≥ 0.8über Repair-Triggered-Subset präzisiert, nicht als End-Accuracy; (E) Doc-Sync-Liste umb-reference/gateway/features/trustee.mdundd-guides/coding-conventions.mderweitert. Plan ist damit umsetzungsreif für Phase 1.
2026-05-16
- 2026-05-16 | fix | gateway, frontend-nyla | RAG-Reindex hängt nach manuellem Trigger im Status RUNNING/PENDING, ohne dass ein Walker startet — UI zeigt endlosen Spinner bis Zombie-Killer nach 30 min eingreift. Root Cause: drei Job-Submit-Routen waren sync (
def, nichtasync def) und enthielten ein "loop = asyncio.get_event_loop(); ... except RuntimeError: asyncio.run(_enqueue())"-Konstrukt. FastAPI führt sync-Routes im Worker-Threadpool aus → kein laufender Event-Loop →asyncio.runöffnet einen temporären Loop, in demstartJob_runJobviacreate_taskregistriert →asyncio.runschliesst den Loop sofort nach Return → Task wird gecancelled, bevor er ein einziges Statement ausführt. Daily-Resync funktionierte, weil er aus APScheduler im Main-Loop läuft. Fix: alle drei Routen aufasync defumgestellt undawait startJob(...)direkt verwendet — keine Loop-Hack-Logik mehr. Betroffene Routes:routeRagInventory._reindexConnection,routeDataSources._updateDataSourceRagIndex(UDB-Toggle 🧠),routeDataConnections._updateKnowledgeConsent(globaler Consent-Toggle). Zusätzlich: Inventar-Response liefert jetztlastSuccessmit{jobId, finishedAt, indexed, skippedDuplicate, skippedPolicy, failed, durationMs}pluslastError.finishedAt— Frontend zeigt grünes Erfolgs-Banner mit Stats + relativem Zeitstempel ("Sync erfolgreich vor 3 Min — 4 neu indexiert · 183 unverändert (198.3s)") statt nur leerem Spinner; Error wird nur angezeigt wenn er neuer ist als der letzte Erfolg, sonst gewinnt das Success-Banner.RagInventoryPageundRagRunningBadgepollen jetzt schnell (5s) während Jobs laufen und langsam (60s) im Idle. Badge zeigt einen 4s-"Sync abgeschlossen ✓"-Toast wenn der letzte aktive Job verschwindet. Hängender Job 7ee09ca7 wurde via Onetime-Skript gekillt.
2026-05-15
- 2026-05-15 | fix | gateway | RAG-Sync Log-Spam + DB-Reinit-Storm. Root Cause:
mainBackgroundJobService._getDb()rief bei jeder Job-CRUD-OperationDatabaseConnector(...)direkt auf — pro Reindex-Klick mehrfach (submitJob,_updateJob,getJob,listJobs,cancelJob). Jeder Konstruktor-Call lief komplett durch_create_database_if_not_exists→_create_tables→ neue psycopg2-Connection →_initializeSystemTableund loggte "PostgreSQL database system initialized successfully" auf INFO. Folgen: Log-Lärm bei jedem Reindex (~5-10 INFO-Zeilen) + echter DB-Overhead pro Job-Operation. Fix: (1)_getDb()nutzt jetztgetCachedConnector()(Cache-Key = host/db/port, FIFO-Eviction nach 32, Thread-safe), pro Worker-Lifetime nur noch 1× Init für die jobs-DB. Smoke-Test bestätigt: 3×_getDb()→ identische Instanz. (2) Init-Log inconnectorDbPostgre.initDbSystemvon INFO auf DEBUG gesenkt + umdb/host/port-Felder ergänzt — wenn doch mal ein Connector neu erzeugt wird, ist das im Steady-State nicht mehr wert auf INFO-Level zu schreien. Andere Hot-Path-Komponenten (interfaceDbApp,interfaceDbKnowledge,aiAuditLogger) nutzten den Cache bereits korrekt;auditLoggerist Singleton, also unkritisch.
2026-05-14
- 2026-05-14 | fix | gateway | RAG-Sync: Zombie-Job-Handling + Walker-Timeouts. (1) Neuer 5-Minuten-Cron
background_jobs.zombie_killerinmainBackgroundJobService.killZombieJobs()markiert RUNNING-Jobs ohne Progress-Update >30 min als ERROR und beendet so auf Dauer hängende Bootstraps. (2) Neuer HelpersubWalkerHelpers.py(downloadWithTimeout60s,extractWithTimeout90s viaasyncio.to_thread+wait_for,ingestWithTimeout60s,logItemStart) — alle Walker (sharepoint, kdrive, gdrive, gmail, outlook, clickup) loggen jetzt vor jedem Itemwalker.item.start service=… path=…, sodass das letzte solche Log bei einem Hang das verursachende Item exakt benennt. Sync-Extraktion läuft auf Worker-Thread, blockiert das Event-Loop nicht mehr. (3) Aktive Zombies (msft 81min, infomaniak 81min, clickup 81min) wurden via Onetime-Skript gekillt. - 2026-05-14 | docs | wiki | WW Stephan-Lieferablage:
c-work/2-build/walderwyss-stephan-output/(Stephan legt nichts in pamocreate ab). Auftrags-PDFs Homepage + Infomaniak für Stephan. - 2026-05-14 | docs | wiki | Lawyer-Feature geplant (Mandatsvorbereitung + Dashboards für Anwaltskanzleien), ausgelöst durch WW-Pitch-Bedarf (David Vasella). Working-Doc in
c-work/1-plan/2026-05-lawyer-feature.md.
2026-05-12
- 2026-05-12 | fix | service-teams-browser-bot | Auth bot PiP loop fix: in full Teams web app, chat toggle navigates to Chat section -> PiP -> periodic scan reopens -> PiP again (endless loop). Fix: added isAuthMode flag to ChatProcedure; in auth mode: skip chat panel toggle entirely, skip periodic reopen, skip panel-open preflight for sendChatMessage. Chat send uses direct input lookup in the meeting view. Replaced _returnToMeetingIfPip() approach (reactive) with prevention (don't toggle)
- 2026-05-12 | fix | service-teams-browser-bot | Auth bot meeting minimized (PiP): chat button click hit Teams sidebar "Chats" navigation instead of in-meeting toggle -> meeting minimized, all PeerConnections closed, video/audio broke. Fix: isDangerousNavButton filter excludes sidebar nav, tab-items, submenu triggers; aria-pressed fallback for panel detection in full Teams web app; _openMoreMenu scoped to calling toolbar
- 2026-05-12 | feat | gateway, frontend-nyla, teams-bot | Avatar-Bild/Video für TeamsBot: Neues Feld
avatarFileIdinTeamsbotConfig/TeamsbotUserSettingsunddefaultAvatarFileIdinTeamsbotMeetingModule. Benutzer können in den Bot-Einstellungen und pro Modul ein Bild oder Video aus den Systemdateien auswählen, das anstelle der statischen Farbfläche als Bot-Video im Meeting gerendert wird. Modul-Einstellung überschreibt Instanz-Default. Gateway löst die Datei beim Session-Start auf, konvertiert zu Base64, und sendet sie im Join-Payload an den Browser-Bot. Bot-seitig:mediaGetUserMediaPatch.tsrendert Bilder perdrawImage()auf den Canvas, Videos per<video>-Element mit Loop. Für Videos wird FPS auf 15 erhöht undcontentHint='motion'gesetzt. Fallback bleibt die statische Farbfläche mit Bot-Name. - 2026-05-12 | fix | gateway, frontend-nyla | TeamsBot Module-Status
[null]:createModule-Route schrieb keinenstatusin die DB, weilCreateMeetingModuleRequestkeinstatus-Feld hat undrecordCreatebei Dict-Input keine Pydantic-Defaults anwendet. Frontendt(null)ergab[null]. Fix: (1) Route setztdata.setdefault("status", "active"), (2)getModulessetzt fehlenden Status defensiv auf"active"für existierende Records, (3) Frontend-Fallbackmod.status || 'Aktiv'als letzte Absicherung. - 2026-05-12 | fix | frontend-nyla | TeamsBot Director-Panel Sichtbarkeit: gleiches Whitelist-Problem wie zuvor beim Stop-Button.
TeamsbotSessionView.tsxZ.903 prüfte['active','joining','pending'].includes(session.status)— wenn der Status direkt nach Mount kurz leer / unbekannt war (SSE-Race vor_loadSession-Resolve, oder Backend schickt einen Übergangsstatus den die Liste nicht kennt), verschwand das ganze "Regieanweisungen"-Panel und kam erst nach Page-Reload wieder. Auf Blacklist umgestellt:!['ended','error','leaving'].includes(session.status). Andere Whitelist-Stellen in derselben Datei (Session-Auswahl Z.136, SSE-Reconnect Z.186/373/439, Listen-Label Z.792) sind defensive Filter mitstatus &&-Guard und bleiben korrekt; Dashboard-Stop-Button war bereits auf Blacklist (Vorgänger-Fix). - 2026-05-12 | fix | teams-bot, gateway | STT-Sprache: hardcodierten
alternativeLanguages=["en-US"]-Fallback inservice._processAudioChunkentfernt. Symptom: nach längerem Bot-TTS-Playback (z.B. 30s Web-Recherche-Antwort) sprang Google STT bei verrauschter Audio auf en-US (language_code: "en-us"im Response, Confidence 0.3–0.5) und lieferte englisches Kauderwelsch ("The transition trade constitute the Range Line."), während saubere Sprache derselben Session korrekt als de-DE mit 0.97 transkribiert wurde. Root Cause: der hardcodierte Englisch-Alternative gab Google die Erlaubnis, bei niedriger DE-Konfidenz nach EN umzuschalten. Fix: nur noch die Sessionsprache (self.config.language, Defaultde-DE) wird übergeben —TeamsbotUserSettings.languageüberschreibtTeamsbotConfig.languagewie gehabt. Settings-Audit bestätigt: alle 12 UI-Felder (botName,aiSystemPrompt,responseMode,responseChannel,transferMode,language,voiceId,triggerIntervalSeconds,triggerCooldownSeconds,contextWindowSegments,debugMode,browserBotUrl) sind im Code aktiv genutzt — keine Karteileichen. (b-ref: teams-bot/architecture.md → "STT auf dem Gateway") - 2026-05-12 | refactor | teams-bot | Chat-Panel-Detection: tote Fallback-Schichten entfernt.
_isChatPanelOpen()reduziert auf den nachweislich funktionierenden Pfad:[data-tid="calling-right-side-panel"]Existenz+Visibility + chat-spezifischer Child-data-tiddarin. Schicht 2 (aria-pressed-Toggle für "ältere Auth-Layouts") und Schicht 3 (Compose-Box-Sichtbarkeit als Last-Resort) waren toter Code — anon und auth nutzen beide denselbencalling-right-side-panel-Container, deraria-pressed-Pfad war zwei Iterationen vorher selbst als unzuverlässig verworfen worden. Konform mit "Do not add fallback code, if not necessary". (b-ref: teams-bot/architecture.md → "Chat-Panel-Detection") - 2026-05-12 | feat | teams-bot | Statisches Avatar-Video für anonymen Bot ersetzt Teams' grünen "no video"-Spinner. Neuer Toggle
BOT_USE_CANVAS_VIDEO=true(Default true im.env) plusBOT_AVATAR_BG_COLOR=#a8d4f0/BOT_AVATAR_TEXT_COLOR=#1a3552insrc/config.ts, durchgereicht viaaudioProcedure.tsan den Init-Script-PayloadmediaGetUserMediaPatch.ts._startBotAvatarStream()zeichnet jetzt eine ruhige einfarbige Fläche + zentrierter Anzeigename (kein Pulse, kein Gradient, keine "PORTA"-Marke), Tick-Rate von 15 fps auf 2 fps gesenkt (genug umcaptureStream()in headless Chromium aktiv zu halten, ohne dass der Encoder Frame-Diffs sieht),contentHint='motion'→'detail'damit WebRTC für statisches Bild Bitrate spart und Text scharf bleibt. Auth-Bot ist nur betroffen wenn der Toggle aktiv ist. (b-ref: teams-bot/architecture.md → "Statisches Avatar-Video (ersetzt grünen Lade-Spinner)") - 2026-05-12 | fix | frontend-nyla | TeamsBot Stop-Button Sichtbarkeit: Logik von Whitelist (
['active','joining','pending']) auf Blacklist (!['ended','error','leaving']) umgestellt inTeamsbotSessionView.tsxZ.841 +TeamsbotDashboardView.tsxZ.264. Verhindert Verschwinden des Buttons bei kurzfristig leerem/unbekanntem Status (z.B. SSE-Race kurz nach Mount, neuer Backend-Status). Button verschwindet nur noch nach explizit terminalen States. Hinweis zur i18n: Source-Keyst('Sitzung beenden')/t('Stoppen')waren bereits korrekt verpackt — die User-sichtbare englische Anzeige "End Session" stammt aus der Übersetzungs-DB und ist die intendierte i18n-Auflösung des deutschen Source-Keys. - 2026-05-12 | fix | teams-bot | Chat-Panel-Toggle-Auswahl im Auth-Layout:
chatProcedure._openChatPanel()neu implementiert. Auth-Full-Teams hat zwei "Chat"-Buttons — einen echten Toggle (UUID-id,aria="Chat (Ctrl+Shift+2)",aria-pressed="false") und einen Schein-Button#chat-buttonohnearia-pressed, der nicht togglt. Vorher: Selector-Liste nahm#chat-buttonals ersten Treffer und klickte 12× denselben falschen Button. Neu: alle visibility-gefilterten Chat-Hint-Kandidaten in Page-Evaluate gesammelt, Toggle-Buttons (mitaria-pressed) bevorzugt, geklickte Keys getrackt — derselbe Button wird nie zweimal geklickt, Loop wechselt zum nächsten Kandidaten. Sprachunabhängig (DE/EN-Hintschat/unterhalt/besprechung/conversation). (b-ref: teams-bot/architecture.md → "Chat-Panel-Toggle-Auswahl im Auth-Layout") - 2026-05-12 | fix | teams-bot | Chat-Panel Detection —
vdi-occlusion-Trapdoor entschärft + Side-Pane-Container als primäre Quelle. Befund am DOM (User-Inspect): die Klassevdi-occlusionist im neuen Calling-Layout Permanent-Marker aufcalling-right-side-panelundmessage-pane-layout— auch bei sichtbar offenem Panel. Mein vorheriger Check "vdi-occlusion → zu" war daher immer false-negative → Toggle-Loop. Der<button id="chat-button">selbst ist byte-identisch in beiden States (keinaria-pressed, keindata-state, blaue Linie kommt aus CSS-:has()auf dem Side-Panel). Detection neu: Schicht 1 prüft[data-tid="calling-right-side-panel"]Existenz + offsetWidth/Height + offsetParent (echtes Visibility-Signal), und Mode-Disambiguation per chat-spezifischen Tids drinnen (message-pane-layout,chat-pane-compose-message-footer,#chat-pane-list,[data-app-name="chats"]u.a.) — sprachunabhängig, trennt Chat von People/Info ohne Text-Lookup. Schicht 2 (aria-pressed Toggle) bleibt für legacy-Auth-Layouts. (b-ref: teams-bot/architecture.md → "Chat-Panel-Detection — Schicht-Strategie") - 2026-05-12 | fix | teams-bot | Chat-Panel Detection (zwischenzeitlich) — Schicht-Strategie via aria-pressed:
chatProcedure._isChatPanelOpen()umgestellt auf "echter Toggle-Button" (chat-Hint im aria-label UNDaria-pressed∈ {true,false}, sprachunabhängig) und liest dessenaria-pressedals Quelle der Wahrheit — fixt den Auth-Toggle-Loop. Im Auth-Layout existieren mehrere "chat"-aria Buttons (Side-Nav-Einträge "Chats", "Meeting chats", Tab-Itemstab-item-com.microsoft.chattabs.*), aber nur der echte Meeting-Chat-Toggle hataria-pressed. Vorher prüften wir hartcodiert#chat-button(= Side-Nav-App in Auth, NICHT der Toggle), bekamen False-Negative "Panel zu" obwohl offen → periodischer Scan klickte den echten Toggle → schloss Panel → klickte weitere Buttons → Endlos-Toggle-Loop mitUPR-Page-Errors. Light-meetings-Pfad (message-pane-layoutmitvdi-occlusion-Klasse oderoffsetHeight=0) bleibt als Schicht 2 für Anon (keinaria-pressed-Toggle vorhanden). (b-ref: teams-bot/architecture.md → "Chat-Panel-Detection — Schicht-Strategie") - 2026-05-12 | build | teams-bot | Container-Image installiert echtes Chrome:
Dockerfileergänzt umRUN npx playwright install --with-deps chrome(lädt Google Chrome stable + alle apt-Deps an Playwright-bekannten Pfad) undENV BOT_BROWSER_CHANNEL=chrome.docker-compose.ymlsetztBOT_BROWSER_CHANNEL=${BOT_BROWSER_CHANNEL:-chrome}als Default. Macht den anon-Bot-Fix container-deploy-fähig. (b-ref: teams-bot/architecture.md → "Container-Deployment") - 2026-05-12 | fix | teams-bot | Anonymer Bot: Browser-Channel auf echtes Chrome umgestellt (
BOT_BROWSER_CHANNEL=chrome). Playwrights gebündeltes Chromium wird von Teams'light-meetings-Pfad als Automation gefingerprintet → erzwungene Lobby + Preheating-Crash (rejectMediaDescriptionsUpdateAsync) → "Sorry, we couldn't connect you". Mit lokal installiertem echten Chrome geht der Bot direkt ohne Lobby ins Meeting, kein Crash. Neu:botBrowserChannelinconfig.ts, anchromium.launch({ channel })inorchestrator._launchBrowser()durchgereicht. Bisect bestätigt: weder Media-Wrapper (BOT_DISABLE_MEDIA_WRAPPERS) noch Anon-spezifische Chromium-Args / Stealth-Init (BOT_ANON_USE_AUTH_BROWSER_SETUP) waren die Ursache; beide Debug-Schalter bleiben als Bisect-Tools im Code. Auth-Joins funktionieren auch mit Bundled-Chromium (echte MS-Session überspringt den Check). (b-ref: teams-bot/architecture.md → "Browser-Channel: echtes Chrome für anonyme Joins") - 2026-05-12 | fix | teams-bot | TeamsBot Chat-Scraper: Container-Fallback für light-meetings DOM-Branche.
chatProcedure.tsperiodischer Scan promovierttargetzudocumentwenn der Chat-Container (message-pane-layout)offsetHeight=0hat ODER Selectoren 0 Treffer liefern, aber global[class*="fui-ChatMessage"]existiert (light-meetings rendert Chat-Bubbles in paralleler DOM-Branche). Zusätzlich Root-Cause-Guardif (!text && author !== 'Unknown')in beiden Pfaden (MutationObserver Strategy 1 + periodischer Scan) restauriert — verhindert dass strukturelle Fragmente ohne Author alsUnknown: 22:04Transcripts durchsickern. (c-work: 4-done/2026-04-teamsbot-greenfield-ia-and-live-update.md) - 2026-05-12 | fix | teams-bot | Anonymer Bot: Audio-Capture WebRTC-Wrapper greift nicht mehr in Teams' Pre-Join/Lobby-SDP-Zyklen ein (Ursache des
rejectMediaDescriptionsUpdateAsync-Crashes und der Lobby-Hänger).audioCaptureProcedure.ts: neues__audioCaptureEnabled-Flag (default false),track-Handler im Wrapper macht nur noch DIAG-Log solange Flag false ist;__audioCaptureAttachTrackals window-exponierter Builder;startCapture()setzt Flag erst nach_setState('in_meeting')und iteriertgetReceivers()allerconnectedPCs für bereits existierende Audio-Spuren. Label-FiltermainAudio-*entfernt (war falsch generalisiert — manche Sessions haben nur eine PC mit UUID-Label). (c-work: 4-done/2026-04-teamsbot-greenfield-ia-and-live-update.md) - 2026-05-12 | feat | frontend-nyla, gateway | FormGeneratorTable Grouping Refactor: Default auf Inline-Modus umgestellt; Toggle-Icon (Inline/Sections) in TableViewsBar; Sections-Mode Multi-Level (alle Permutationen als flache Sections); pageSizeOptions um 1000/2000/10000 erweitert; Collapse-All/Expand-All Buttons fuer Inline-Grouping; 4 Pages (Connections, Prompts, Files, BillingData) auf Inline-Default umgestellt.
- 2026-05-12 | feat | frontend-nyla | RAG Consent & Control Phase D Ergänzungen: UDB
SourcesTab4. Toggle-Button (🧠 ragIndexEnabled) mit Vererbung;RagRunningBadgeFloating-Komponente (Polling, Job-Dropdown);WorkspaceRagInsightsPagephysisch gelöscht;ConnectionsPageAdminConsent+Infomaniak Standalone-Buttons entfernt (nur noch via Wizard). - 2026-05-12 | docs | wiki |
b-reference/gateway/ai-agent.mdAbschnitt "RAG Consent & Control" ergänzt (Prinzipien, Datenmodell, Walker-Architektur, API, Frontend-Komponenten, Vererbung);TOPICS.mdRAG-C&C-Eintrag. - 2026-05-12 | feat | gateway, frontend-nyla | RAG Consent & Control: Phase A–D implementiert. Backend:
DataSource.autoSync→ragIndexEnabled(rename + Migration-Script);cancelJob()+cancelJobsByConnection()in BackgroundJobService;JobProgressCallback.isCancelled()(3s-cached); Walker-Refactor (alle 5 Connectoren iterieren nur über ragIndexEnabled DataSources + Cancel-Check alle 50 Items +provenance.dataSourceId); neuersubPolicyResolver.py(Tree-Vererbung); neue Routes/knowledge-consent,/knowledge-preferences,/knowledge-stop,/datasources/{id}/rag-index; neuerrouteRagInventory(4 Endpoints);GET /connections/liefert Knowledge-Felder;WorkspaceRagInsightsRoute+Permission gelöscht. Frontend:AddConnectionWizardvereinfacht (connector-aware Steps, MSFT AdminConsent + Infomaniak PAT integriert, keine Kostenschätzung/Prefs);connectionApi.tsneue Methoden + bereinigte Types; neueRagInventoryPage+ CSS;pageRegistry+App.tsxRoute + Navigation-Eintrag;FeatureViewrag-insightsMapping entfernt. - 2026-05-12 | docs | wiki | Implementierungsplan:
1-plan/2026-05-rag-consent-and-control-implementation.md— code-grounded Phasenplan (A→F) mit Audit-Befunden (autoSyncungenutzt → safe rename;cancelJob-API fehlt;routeDataConnectionsGET liefert Knowledge-Felder nicht; PATCH-Pattern ausrouteDataSourcesals Vorlage), Datei-genaue Änderungen, Acceptance-Gates pro Phase, Risiko-/Decision-Liste, ~17 Tage T-Shirt-Schätzung. - 2026-05-12 | docs | wiki | Plan:
1-plan/2026-05-rag-consent-and-control-unification.md— datenzentrierte RAG-Architektur: Per-Element-Index-Toggle in UDB analog Scope/Neutralize (kaskadierende Tree-Vererbung; per-Feld bei Tabellen vianeutralizeFields[]); Walker iteriert nur überragIndexEnabled=trueDataSources; Stop-Mechanismus an drei Sichtbarkeits-Orten (Header-Badge, ConnectionsPage-Row, RagInventoryPage); Wizard ist einziger Eintrittspunkt für alle Connector-Typen (integrierter MSFT Admin-Consent-Step + Infomaniak-PAT-Step); globaleStart > Nutzung > RAG-InventarSeite; Wizard ohne Kostenschätzung/Preferences; Löschung der workspace-scopedWorkspaceRagInsightsPage.
2026-05-11
- 2026-05-11 | feat | gateway | ToolDefinition.displayLabel: neues Feld fuer menschenlesbare Aktivitaetsbeschreibungen; Agent-Loop propagiert Label in TOOL_CALL Events; TeamsBot nutzt es fuer kontextuelle Fortschrittsmeldungen statt "Schritt N von M"
- 2026-05-11 | fix | gateway | TeamsBot Speaker-Attribution: retroaktive Zuordnung von "Unknown"-Eintraegen erfolgt jetzt bei jedem neuen Caption-Speaker, nicht nur beim ersten
- 2026-05-11 | fix | service-teams-browser-bot | Chat-Scraper Root Cause: Timestamp-Separatoren ("22:01") wurden als Chat-Nachrichten erkannt weil der innerText-Fallback auch bei unbekanntem Autor griff; Fallback jetzt nur wenn Autor identifiziert wurde
- 2026-05-11 | fix | gateway | mainServiceWeb progressLogUpdate: fehlende
if operationId:Guards bei Zeilen 101/125 verursachten "Operation None not found" Warnung wenn Agent-Tool webSearch ohne operationId aufrief - 2026-05-11 | fix | gateway | SPEECH_TEAMS Prompt: spezifische Beispiele entfernt, Eskalationsregeln generisch gehalten
- 2026-05-11 | fix | service-teams-browser-bot | Anonymous bot stuck after lobby admission: _waitForMeetingAdmission now tracks lobby-to-meeting transition, waits patiently when lobby vanishes (= admitted), and reloads page as recovery; isInMeeting expanded with light-meetings + German selectors
- 2026-05-11 | docs | wiki | d-guides:
google-registration-checklist.md,microsoft-entra-registration-checklist.md(Vendor-Registrierung + Gateway-Env/Code-Referenzen); TOPICS ergänzt. - 2026-05-11 | feat | gateway, frontend-nyla, wiki | TeamsBot:
GET /api/teamsbot/{instanceId}/dashboard/stream(SSE dashboardState 3s/20s); dashboard consumes EventSource + reconnect; module tiles navigate tomodules?moduleId=with expand + scroll highlight; canonicalb-reference/teams-bot/architecture.md, TOPICS,b-reference/frontend-nyla/architecture.md(Teams Bot UI row). (c-work: 2-build/2026-04-teamsbot-greenfield-ia-and-live-update.md)
2026-05-10
- 2026-05-10 | feat | gateway | CommCoach Fast Conversational Mode:
AgentConfig.excludeAllToolsflag fuer tool-freie Turns; generischer RAG-Session-Cache inagentLoop(TTL 120s / 5 Msgs); CommCoach nutzt beides fuer fluessige Coaching-Gespraeche - 2026-05-10 | fix | gateway | RAG-Cache-Bug: doppelter
workflowId-Parameter in_getOrRefreshRagbehoben (Keyword-Kollision) - 2026-05-10 | fix | gateway | CommCoach TTS:
_TTS_WORD_LIMITvon 200 auf 80 Woerter reduziert; Sprachausgabe fasst laengere Antworten jetzt zusammen statt alles vorzulesen - 2026-05-10 | feat | gateway |
AgentConfig.priority(speed/quality/cost/balanced) anagentLoopdurchgereicht; CommCoach conversational turns nutzenPriorityEnum.SPEEDfuer schnellere Modellauswahl - 2026-05-10 | fix | gateway |
interfaceDbManagement.getInterfaceSingleton Race-Condition behoben: shared mutable instance ueberschrieb featureInstanceId zwischen async Requests; Agent konnte Files nicht finden - 2026-05-10 | feat | frontend-nyla | TeamsBot UI aligned to greenfield IA: dashboard as KPI + module-activity + quick actions (no duplicate start form); MFA on live session SSE; assistant step adds join mode, MS account block, session context; modules header
Modul anlegendialog +Meeting starten; nav icons for assistant/modules;FEATURE_REGISTRYtab label Dashboard. (c-work: 2-build/2026-04-teamsbot-greenfield-ia-and-live-update.md) - 2026-05-10 | feat, fix | gateway, frontend-nyla, teams-bot | TeamsBot:
startSessionbindsmoduleIdwith validation; DB migration M2TeamsbotMeetingModule.defaultMeetingLink/defaultBotName; assistant prefill + searchable multi-row module list; modules edit saves defaults; session view polls while pending/joining even with SSE and syncs switcher row; browser bot chat compose marker + safeAudioContext.close. (c-work: 2-build/2026-04-teamsbot-greenfield-ia-and-live-update.md) - 2026-05-10 | docs | wiki | Kanon:
b-reference/gateway/voice-google.md; TOPICS + README Ordnerbaum; Querverweise in gateway/architecture, teams-bot/architecture, frontend-nyla/architecture, ai-agent. - 2026-05-10 | feat | gateway, frontend-nyla | STT: configurable model/lightweight/audioFormat on batch
speechToText; streaming supports model/lightweight/singleUtterance; duration fromresult_end_time; WSopen+end_of_single_utterancereplumbing. CommCoach useslatest_short+ lightweight + single-utterance; Teamsbot passesaudioFormat=linear16. Chirp/v2 evaluation tracked inwiki/c-work/1-plan/stt-chirp-v2-evaluation.md. - 2026-05-10 | fix | gateway | CommCoach: conversational turns use
operationType=DATA_QUERY+priority=SPEEDfor faster model selection (gpt-5.4-mini instead of gpt-5.5); model selector speed priority weight scaled from/10to*100to be meaningful. - 2026-05-10 | fix | gateway | CommCoach: persona sessions now distinguish first vs follow-up; opening prompt references prior sessions instead of re-introducing persona every time.
- 2026-05-10 | feat | gateway | Document generation: unified
documentTitlestyle separate fromheadings.h1; BASE/renderer converts independently; HTML/CSS, PDF title block, Markdown/Text heading offsets updated; DEFAULT_STYLE h1 lowered vs title.
2026-05-09
- 2026-05-09 | feat | actan | SanctionsCheck: Login rememberMe + session cookies; public
/signup+POST /api/public/signup; e-mail templates +templateRenderer; SMS retries + NOTIFICATION activities; profile tabs; activity API enrichments (akteurTyp,sichtbarkeit,includeInternal) and Activities UI badges/panel. - 2026-05-09 | feat | gateway | Enterprise Subscription: sysadmin-managed flat-price subscriptions with custom limits (users, features, storage, AI budget), invoice email, hard-block on overage, auto-renewal cron job. New endpoints: POST enterprise/create, enterprise/renew, PUT enterprise/update. (c-work: 1-plan/2026-05-enterprise-subscription.md)
- 2026-05-09 | refactor | frontend-nyla, gateway | CommCoach: remove Dossier view (route, FeatureView registry, RBAC UI object, Dashboard link, pageRegistry icon, barrel export). Session details (summary, score, duration, export) moved into Modules expand view.
2026-05-08
- 2026-05-08 | fix | frontend-nyla | CommCoach: add missing
Route path="dossier"under feature-instance routes (was catch-all not-found). - 2026-05-08 | fix | gateway | JWT cookies: resolve SameSite/Secure per request via _cookiePolicy() (not import-time); optional APP_COOKIE_SECURE override; env-gateway int/prod: APP_COOKIE_SECURE=true + CORS nyla*.poweron-center.net.
- 2026-05-08 | fix | gateway | JWT cookies: SameSite=None+Secure when APP_API_URL is HTTPS (cross-origin SPA+API); SameSite=Lax on HTTP localhost. Fixes credentialed API calls when UI and gateway differ by site. CSRF middleware unchanged.
- 2026-05-08 | chore | frontend-nyla | config/.env.{dev,int,prod}: keep only VITE_API_BASE_URL and VITE_APP_NAME; removed unused flags and duplicated Entra/secret keys (backend owns secrets). env.d.ts aligned.
- 2026-05-08 | refactor | frontend-nyla | Remove MSAL from UI: deleted authConfig.ts + AuthProvider.tsx, rewrote ProtectedRoute (sessionStorage-only), removed useMsalRegister, simplified logout, uninstalled @azure/msal-browser + @azure/msal-react. All auth logic lives in gateway.
- 2026-05-08 | chore | frontend-nyla | Rename env files:
.env.{dev,int,prod}→env-poweron-nyla-{dev,int,prod}.env(naming matches workflow). Updated workflows, .gitignore, README. - 2026-05-08 | chore | gateway | Rename env files:
env_{dev,int,prod,prod_forgejo}.env→env-gateway-{dev,int,prod,prod-forgejo}.env. Updated GitHub/Forgejo workflows, deploy-gcp, .gitignore, .dockerignore, .gcloudignore, Dockerfile, scripts. - 2026-05-08 | chore | gateway | Domain migration poweron-center.net → poweron.swiss: APP_API_URL, CORS origins, OAuth redirect URIs (MSFT, Google, ClickUp) in env-gateway-{int,prod,dev}. Updated billing email and doc URLs in stripeCheckout.py, datamodelTeamsbot.py.
2026-05-07
- 2026-05-07 | fix | gateway | sandboxExecutor:
opendurch In-Memory-VirtualFS ersetzt (statt geblockt); AI-generierter Code kann jetzt Dateien lesen/schreiben ohne echten Dateisystem-Zugriff - 2026-05-07 | feat | gateway | RedmineTicketMirror + RedmineTicketDto: Feld
doneRatio(% erledigt) ergaenzt; Sync-Mapping und DTO-Konvertierung aktualisiert - 2026-05-07 | feat | gateway | Neues Agent-Tool
redmine.listRelationsfuer direkte Abfrage der Beziehungstabelle (Filter: issueId, relationType, pagination) - 2026-05-07 | feat | gateway |
redmine.listTickets:offset-Parameter ergaenzt fuer echte Pagination; Response liefertoffset+hasMorestatttruncated
2026-05-06
- 2026-05-06 | fix | frontend | UDB tab "Chatverläufe" renamed to "Dossiers" (UnifiedDataBar.tsx + i18n seed for xx/de/en/fr)
- 2026-05-06 | fix | gateway | PDF rendering: (1) _convertUnifiedStyleToInternal now maps spaceBeforePt/spaceAfterPt for headings, lineSpacing for paragraphs, bulletChar for lists — previously dropped silently; (2) DEFAULT_STYLE heading spacing increased (h1: 24pt before, h2: 20pt) for professional visual hierarchy; (3) _renderJsonBulletList uses dedicated BulletItem ParagraphStyle with leftIndent/firstLineIndent from bullet_list config — was identical to paragraph normalStyle
2026-05-05
- 2026-05-05 | fix | frontend-nyla | FormGeneratorTree:
window.confirm()durchuseConfirm-Modal ersetzt; Hover-Icons ueberlappen jetzt die Dateigroesse statt daneben zu stehen (spart Breite im File-Tree) - 2026-05-05 | fix | gateway | 4 warning fixes: (1) mainServiceAgent skips getWorkflow for synthetic workflowIds with ":" prefix (commcoach billing keys); (2) ActionNodeExecutor + actionToolAdapter inject parentOperationId so ai.process progress nests correctly; (3) ChatService.interfaceDbComponent now receives featureInstanceId — root cause was missing scope causing getFile to miss featureInstance-scoped files during graph execution; (4) IMAGE_GENERATE sections use concise _buildImagePrompt instead of full 700KB userPrompt — eliminates DALL-E truncation
- 2026-05-05 | fix | gateway | _getOrCreateTempFolder rewritten to use ComponentObjects.getOwnFolderTree/createFolder instead of raw db.getRecordset bypass; added explicit logging for all code paths; _persistLargeDocument now logs updateFields before updateFile call
- 2026-05-05 | fix | frontend+gateway | AI-generated files not visible: (1) useCommcoach.ts sendMessage documentCreated handler used undefined
sessionIdinstead ofsession.idcausing ReferenceError silently swallowed by SSE parser catch-all — system note never shown; (2) SSE parser catch blocks narrowed to JSON.parse only so handler errors propagate; (3) _getOrCreateTempFolder re-implemented to find/create user Temp folder; (4) all file-update call sites consolidated into single updateFile call to avoid RBAC scope conflict - 2026-05-05 | fix | gateway | CommCoach completeSession: session.get("contextId") → session.get("moduleId") — stale field name caused sessionCount to never update (always 0); getModules now computes live sessionCount from sessions table
- 2026-05-05 | fix | gateway | actionToolAdapter: _persistLargeDocument now handles bytes documentData (PDF/DOCX/PPTX were silently discarded); _formatActionResult returns sideEvents for fileCreated; scope set to featureInstance when featureInstanceId available; CommCoach+TeamsBot _runAgent forward FILE_CREATED as documentCreated SSE; silent warnings elevated to errors for data-loss scenarios
2026-05-04
- 2026-05-04 | feat | * | CommCoach Persona-Management: Gespraechspartner konfigurierbar. Backend: 5 neue Builtin-Personas (Paartherapeutin, Psychologe, Rechtsanwalt, Mediatorin, HR-Managerin), ModulePersonaMapping M:N-Tabelle mit DB-Migration M8, GET/PUT Module-Persona-Zuordnung. Frontend: Settings-Tab 'Gespraechspartner' mit FormGeneratorTable CRUD (Create/Edit/Delete custom Personas, Inline-Toggle isActive), Modul-Edit-Dialog mit Persona-Multi-Select, Session-Persona-Picker filtert nach Modul-Zuordnung. (c-work:
2-build/2026-04-comcoach-greenfield-ia.md)
2026-05-03
- 2026-05-03 | feat | * | ComCoach + TeamsBot Greenfield-IA: Implementierung abgeschlossen. Backend: CoachingContext -> TrainingModule (Rename, moduleType Enum, kpiTargets, category entfernt), neue Module-CRUD-Routes. TeamsBot: TeamsbotMeetingModule Entity (additiv), Module-CRUD, agentRun SSE-Events sichtbar, Stats-Karten, adaptives Dashboard-Polling (3s/30s). Frontend: Beide Features 5-Tab-IA (Dashboard, Assistent, Module, Session, Settings), neue View-Komponenten (AssistantView Wizard, ModulesView CRUD), KeepAlive nur noch fuer Session-Tab, Settings Statistik entfernt, Dashboard navigiert zu Modules statt Dossier. (c-work:
2-build/2026-04-comcoach-greenfield-ia.md,2-build/2026-04-teamsbot-greenfield-ia-and-live-update.md) - 2026-05-03 | docs | wiki | ComCoach + TeamsBot Greenfield-IA: Plaene verifiziert und in
2-build/verschoben. Alle Zeilennummern und Code-Referenzen gegen aktuelle Codebase geprueft (alle korrekt). ComCoach-Plan ergaenzt:goals-Feld existiert bereits (JSON->Freitext-Migration),category-Enum wird durchmoduleTypeersetzt,description-Feld bleibt. TeamsBot-Plan ergaenzt: NamenskonventionstartedByUserIddokumentiert. Beide Plaene:<!-- status: build -->,<!-- verified: 2026-05-03 -->. (c-work:2-build/2026-04-comcoach-greenfield-ia.md,2-build/2026-04-teamsbot-greenfield-ia-and-live-update.md) - 2026-05-03 | fix | gateway | AI Step Output:
contextFeld zeigte Prompt statt Input-Context.actionNodeExecutor.pybauteout["context"]falsch auspromptText + extractedContextzusammen. Wenn AI ein Binary-Dokument erzeugte (z.B. Excel), warextractedContextleer undcontextwurde identisch mitprompt. Jetzt wird der tatsaechliche aufgeloestecontext-Input-Parameter gespeichert. - 2026-05-03 | fix | frontend-nyla | FormGeneratorTree: Auto-Scroll bei Expand am unteren Bildschirmrand. Wenn ein Gruppenobjekt in der unteren Haelfte des sichtbaren Bereichs expanded wird, scrollt der Container den Parent-Node zur Mitte, damit Kinder ohne manuelles Scrollen sichtbar sind.
- 2026-05-03 | fix | frontend-nyla | Automation > Workspace Tab: Polling fuer laufende Runs.
_WorkspaceTabpolltfetchWorkspaceRunDetailalle 3s solange Run-Status nicht terminal. Stoppt automatisch bei completed/failed/cancelled. - 2026-05-03 | fix | gateway | executeCode Sandbox:
typeentblockt,iorestricted, Modul-Liste dynamisch.type()aus_PYTHON_BLOCKED_BUILTINSentfernt.import ioliefert eingeschraenktes Modul (nur StringIO/BytesIO, kein io.open). Tool-Beschreibung dynamisch ausSANDBOX_ALLOWED_MODULESgeneriert.type()war faelschlich in_PYTHON_BLOCKED_BUILTINS(harmlos ohne exec/eval).StringIO/BytesIOals sichere Builtins (io.open wird nicht exponiert). Tool-Beschreibung aktualisiert. - 2026-05-03 | fix | gateway | AI Agent: docItem-Resolution Root Cause + executeCode readFile. (1)
coerceDocumentReferenceList: Dict-Pfad strippt jetztdocItem:/docList:Prefix korrekt viafrom_string_list(war: Prefix blieb indocumentId, erzeugte Doppel-Prefix beito_string()). (2)process.py:DocumentItemReferencewird nur im Automation2-Kontext (kein Chat-Workflow) an_resolve_file_refs_to_content_partsgeroutet; im Agent-Kontext fliessen sie korrekt durchgetChatDocumentsFromDocumentList(war: alle Refs wurden abgefangen und fehlerhaft als File-Store-IDs behandelt). Gebrochenen_resolveChatDocIdToFileId-Fallback entfernt. (3) executeCode Sandbox:readFile(fileId)Built-in fuer Workspace-Dateizugriff (kein open(), nur managed Files via interfaceDbComponent). - 2026-05-03 | fix | gateway | AI Agent + Rendering: 9 Issues geloest. (1) Sandbox
time-Modul erlaubt. (2) ActionToolAdapter: grosse Docs als Workspace-Files persistiert. (3) downloadFromDataSource: Debug-Logging fuer Filename-Swap. (4) clickup_listTasks: Datums-/Custom-Field-Filter. (5) Renderer style-Bug:styleKeyword auf allen 8 Renderern akzeptiert (CSV, Text, JSON, Markdown, Image, CodeXml, CodeJson, CodeCsv). (6) _ServicesAdapter: workflow-Setter fuer Agent-Kontext (getChatDocumentsFromDocumentList braucht workflow). (7) _ServicesAdapter: interfaceDbComponent Property (ai_process file-ref Resolution). (8) Auto-index nach Neutralize: mandateId/featureInstanceId an _autoIndexFile durchgereicht. (9) Kombination: Agent sollte AI-Workspace-Aufgaben effizient loesen. - 2026-05-03 | chore | frontend-nyla | Stage 4: FolderTree Dead-Code geloescht + Tree-Assessment. Gesamter
components/FolderTree/-Ordner entfernt (FolderTree.tsx 1170 LOC, SharepointBrowseTree.tsx 319 LOC, actions/, CSS -- alles Dead Code). ESLint-Deprecation-Regel entfernt. Assessment aller verbleibenden Tree-Kandidaten: DataPicker, InstanceHierarchyView, AccessRulesEditor, TreeNavigation, redmineTreeLogic -- alle SKIP (kein Entity-Tree-Paradigma). (c-work:4-done/2026-05-formgenerator-tree-and-folder-recovery.md) - 2026-05-03 | docs | wiki | Stage 5: FormGeneratorTree Wiki-Dokumentation.
formgenerator.md: neuer Abschnitt FormGeneratorTree (Provider-Interface, Features, Props, Verwendung, Tree-vs-Table-Vergleich).architecture.md: FolderTree-Referenzen durch FormGeneratorTree ersetzt.TOPICS.md: FormGenerator-Eintrag ergaenzt. Plan nach4-done/verschoben. (c-work:4-done/2026-05-formgenerator-tree-and-folder-recovery.md) - 2026-05-03 | docs | wiki | FormGeneratorTree Plan: Stage 3 deferred, Stage 0-2 abgeschlossen. Stage 3.A/3.B (SourcesTab/ChatsTab-Refactor auf FormGeneratorTree) deferred -- domaen-spezifische Tree-Logik passt nicht sinnvoll auf generische TreeNodeProvider-Abstraktion. Plan-Status auf
donegesetzt. Stage 2.C Checkliste aktualisiert mit allen 2.C-Fixes (405-Fix, typeMap, Refresh-Icon, confirm-Dialoge, FilesPage-Sync). (c-work:4-done/2026-05-formgenerator-tree-and-folder-recovery.md)
2026-05-02
- 2026-05-02 | fix | frontend-nyla | Tree batch-delete: separate Ordner/Dateien-Aktionen.
TreeBatchAction.typeFilterintypes.ts;FormGeneratorTree.tsxfiltertselectedIdsnach Typ und zeigt Counts pro Button.FolderFileProvider.tsxliefert zwei getrennte Batch-Aktionen (Ordner-Cascade-Delete vs. File-Delete/Batch-Delete). FilesPage tree-table Sync wiederhergestellt:selectedFolderIdfiltert Tabelle nach Ordner; File-Klick im Tree scrollt+highlighted die Tabellenzeile (2.5s auto-clear). (c-work:1-plan/2026-05-formgenerator-tree-and-folder-recovery.md)
2026-05-01
- 2026-05-01 | feat | gateway | Stage 1.B FormGenerator Folder RBAC: FileFolder in TABLE_NAMESPACE, 11 folder methods in interfaceDbManagement (CRUD, move, cascade-delete, scope, neutralize), 6 routes in routeDataFiles replacing 501 stubs
- 2026-05-01 | feat | frontend-nyla | Stage 2.A + 2.B: FilesTab + FilesPage tree integration.
FilesTab.tsxrewritten fromFormGeneratorTableto twoFormGeneratorTreesections (Eigene/Geteilt mit mir) with drag-drop upload, refresh-by-key, and workflow-import on node click.FilesPage.tsxupdated with split-view layout: 300px tree panel (left, own+shared trees) andFormGeneratorTable(right) with view-mode toggle (Tree-Sicht / Liste mit Gruppen); groupingConfig applied only in grouped mode; upload and refresh sync both tree and table. (c-work:1-plan/2026-05-formgenerator-tree-and-folder-recovery.md) - 2026-05-01 | feat | gateway | FormGeneratorTree Plan Stage 0 + 1.A: Schema-Check-Skript
scripts/stage0_filefolder_schema_check.py;FileFolderPydantic +FileItem.folderIdindatamodelFiles.py; StubgetOwnFolderTree/getSharedFolderTree; RoutenGET /api/files/folders/tree(leere Liste) + Folder-Mutationen 501 bis Stage 1.B;migrate_folders_to_groups.pynachmodules/migrations/_archive/mit README. (c-work:1-plan/2026-05-formgenerator-tree-and-folder-recovery.md) - 2026-05-01 | docs | wiki | Plan FormGeneratorTree: Stages packetisiert nach LLM. Stages 1-3 in Sub-Packets aufgeteilt (1.A BE-Boilerplate / 1.B BE RBAC-Kern / 1.C FE Greenfield / 2.A FE-Boilerplate / 2.B FE-Komposition / 2.C manuelle Verifikation / 3.A Provider-Refactors / 3.B Tab-Umbau). Pro Packet: Modell-Hinweis (Opus 4.6 fuer Architektur/RBAC/Greenfield, Composer 2 Fast fuer Boilerplate/Recovery/Doku), Eingang/Lieferumfang/Abnahme. Eskalations-Regel ergaenzt. (c-work:
1-plan/2026-05-formgenerator-tree-and-folder-recovery.md) - 2026-05-01 | docs | wiki | Plan FormGeneratorTree + Folder-Recovery konsolidiert. Neuer FormGenerator-Familienteil
FormGeneratorTree(Provider-Pattern, Cascade-Multiselect, DnDapplication/x-poweron-tree-items, Backend-Attribut-Resolution) zur Konsolidierung der ~8 parallelen Tree-Implementierungen. Recovery der Folder/File-Funktionen ueber Modell A (FileFolder+FileItem.folderIdreaktivieren; DB-Schema unveraendert). RBAC-/Sichtbarkeitsmodell verbindlich: Default-Scopepersonal; Sharing nur ueber Owner-Scope-Patch; geteilte Objekte read-only fuer Nicht-Owner (analogupdateFile/deleteFile); UI rendert inFilesTab/FilesPagezwei getrennte Trees (Eigene/CRUD + Geteilt mit mir/read-only); Files ohne sichtbaren Folder-Kontext fallen in den Root mitcontextOrphan-Hint; Folder-Scope-Cascade auf Files = opt-in; Folder-Neutralize-Vererbung beim Drop = nein; Drag aus Geteilt in Eigenes = gesperrt. 22 konsolidierte Entscheidungen (D1-D22), keine offenen Backlog-Punkte mehr. UDB hat fix drei Tabs (Files, Sources, Chats) aufFormGeneratorTree.FormGeneratorTable.groupingConfigbleibt unveraendert. KeinFormGeneratorChart-- Berichte =FormGeneratorReport(Komponenten-Zeile inb-reference/frontend-nyla/formgenerator.md). 6 Stages (0 Schema-Sanity-Check optional, 1 Backend+Skeleton, 2 FilesTab/FilesPage Recovery, 3 SourcesTab/ChatsTab Konsolidierung, 4 optional weitere Trees, 5 Doku). (c-work:1-plan/2026-05-formgenerator-tree-and-folder-recovery.md)
2026-05-01
- 2026-05-01 | docs | wiki | Plan D (AI Reports Pipeline) abgeschlossen ->
4-done/. Alle Checklisten-Items auf[x], Testplan-Status aufdone, Headerstatus: done,completed: 2026-05-01. Wiki-Referenz-Updates (ai-agent.md,workflow.md,neutralization.md) als TODO fuer naechste Review-Runde markiert. (c-work:4-done/2026-04-ai-reports-theming-and-pipeline.md)
2026-04-30
- 2026-04-30 | refactor | gateway | GraphEditor: Hidden DataRefs sichtbar gemacht fuer alle
ai.*Nodes.frontendType: "hidden"->"dataRef"fuerdocumentListinai.prompt,ai.summarizeDocument,ai.translateDocument,ai.convertDocument(gateway/modules/features/graphicalEditor/nodeDefinitions/ai.py). Zwei neue sichtbare Parameter aufai.prompt:context(dataRef, beliebiger Upstream-Output, wird vom Action zu JSON serialisiert) +documentTheme(select, finance/legal/...). Action-Definitionai.process(gateway/modules/workflows/methods/methodAi/methodAi.py) deklariertcontextunddocumentThemejetzt explizit, statt sie als undeklarierte Pass-Through-Keys mitlaufen zu lassen. Effekt: Trustee-Templates (Budget-Vergleich, KPI, Cashflow, Forecast, Year-end) zeigen ihre bisher unsichtbaren DataRef-Bindings (trigger.payload.documentList,refresh.data.accountingData) jetzt im Properties-Panel als gruene Bindungs-Boxen, der User kann sie via DataPicker veraendern. Kein Frontend-Code-Change noetig: bestehenderDataRefRenderer+DataPickerrendern die JSON-DataRef-Werte direkt. Runtime unveraendert --resolveParameterReferencesverarbeitet{"type":"ref",...}wie bisher.
2026-04-29
-
2026-04-29 | test | gateway | Phase 7 AI-Reports: 19 unit tests for MD-to-JSON parser (inlineRuns), styleDefaults resolver, AiCallOptions allowedModels whitelist, inline-image paragraphs
-
2026-04-29 | feat | gateway, frontend-nyla | D: AI Reports Pipeline komplett umgebaut. Phase 1: MD->JSON konsolidiert (Inline-Run-Modell,
_parseInlineRuns). Phase 2: Generisches Style-System (styleDefaults.py,resolveStyle,renderDocumentstyle-Param). Phase 3: Alle 5 Renderer auf Style-Lookups + Inline-Runs umgestellt. Phase 4: Inline-Bilder in Paragraph/Tabelle/Liste. Phase 5:allowedModelsinAiCallOptions+_calculateEffectiveModelsim AI-Gate. Phase 5a:WorkspaceUserSettingsPersistenz (GET/PUT Endpoint). Phase 5b:modelMultiSelectim FlowEditor + Workspace-Settings UI. Phase 6: Trustee-Templates mitrequireNeutralization+ Finance-Style-Hint. Phase 7: 19 Unit-Tests. (c-work:1-plan/2026-04-ai-reports-theming-and-pipeline.md) -
2026-04-29 | feat | gateway, frontend-nyla | B: Trustee Budget-Vergleich auf Excel umgestellt.
mainTrustee.pyTemplate:resultType: "xlsx"+documentTheme: "finance"hart gesetzt. Prompt komplett refaktoriert: 1 Tabelle alle Konten, 1 Uebersichts-Chart (kein pro-Konto-Chart), Management-Summary. Frontend: Hinweistext "Excel-Bericht" im Budget-Tab ergaenzt. XLSX-Renderer (PNG-unter-Tabelle) verifiziert. (c-work:3-validate/2026-04-trustee-budget-comparison-refactor.md) -
2026-04-29 | feat | gateway, frontend-nyla | A2 Workflow-Run-Workspace + targetFeatureInstanceId implementiert. Phase 1:
AutoWorkflow.targetFeatureInstanceId(Pydantic + DB), createWorkflow-Fallback, Save-Validation (400 fuer non-template ohne targetId), Execute-RBAC-Check,executeGraphPlaceholder-Substitution ({{featureInstanceId}}), Scheduler-Durchreichung,_copyTemplateWorkflowsexplizites Setzen, idempotente Boot-Backfill-Migration. Phase 2: FlowEditor CanvasHeader "Ziel-Instanz" Dropdown mit FeatureStore-Integration, Save/Load mittargetFeatureInstanceId. Phase 3: Neuer Backend-EndpointGET /api/automations/runs+GET /api/automations/runs/{runId}/detail(RBAC via FeatureAccess), neuer "Workspace" Tab in AutomationsDashboardPage mit Run-Liste + Detail-View (Steps, Files, Download). Phase 4: TrusteeAnalyseView inline-Results durch "Im Workspace ansehen"-Link ersetzt, TrusteeAbschlussView Workspace-Link nach Completion ergaenzt. (c-work:1-plan/2026-04-trustee-workflow-audit-and-run-workspace.md) -
2026-04-29 | docs | wiki | Plan A2 finalisiert: Trustee Workflow-Audit + Generischer Workflow-Run-Workspace. Cross-Check gegen Codebase (12 Punkte verifiziert, 4 Korrekturen eingearbeitet):
executeGraphhat keine Placeholder-Substitution (muss neu gebaut werden),_copyTemplateWorkflowssetztfeatureInstanceIdnicht im Payload (implizit via GE-Interface),TrusteeAbschlussViewhat keinresultText/resultDocuments(nur status/summary), 7 Trustee-Templates statt 5 im Audit. Risiko-Sektion ergaenzt. (c-work:1-plan/2026-04-trustee-workflow-audit-and-run-workspace.md) -
2026-04-29 | chore | gateway |
gateway/scripts/aufgeraeumt: 5 obsolete one-shot-Scripts archiviert + 1 Ad-hoc-Snippet geloescht. Im Anschluss an den Bootstrap-Cleanup. Neuer Unter-Ordnergateway/scripts/_archive/mit eigenem README beschreibt Inhalt + Begruendung pro Datei. Verschoben (mit User-Bestaetigung pro File):check_orphan_featureinstance.py(hardcoded Vor-Ort-UUIDs),script_db_cleanup_duplicate_roles.py(IS NULL-Bug-Cleanup, Bug laengst gefixt),migrate_async_to_sync.py(one-shotasync def->defCodemod, Refactor durch),i18n_rekey_plaintext_keys.py(Frontend Klartext-Keys, Migration durch siehe4-done/2026-04-ui-i18n-dynamic-language-sets.md),script_db_migrate_accessrules_objectkeys.py(Navigation-API-Migration MIGRATION_MAP nur fuer trustee+realestate hardcoded, durch). Geloescht:_listMandates.py(26-Zeilen Ad-hoc-Debug-Snippet, jederzeit aus Git rekonstruierbar). Status danach: 21 aktive Scripts ingateway/scripts/(inkl. neuesscript_db_audit_legacy_state.py) + 5 archivierte Scripts. Dev-Boot 20:24:09 bestaetigt das aufgeraeumte interfaceBootstrap.py + Telemetrie-Hook laufen sauber durch (kein WARN, kein Restbestand, neue Code-Pfad-Line-Refs). (c-work:4-done/2026-04-bootstrap-migrations-cleanup.md) -
2026-04-29 | refactor | gateway | Bootstrap-Cleanup ausgefuehrt: 4 idempotente Migrations-Routinen + 1 Aggregations-Fallback aus dem Boot-Pfad entfernt. Vor Removal Audit-Skript
gateway/scripts/script_db_audit_legacy_state.py(NEU, lese-only, exit-code-gated) gegen Dev-DB gelaufen -> 4/5 GREEN sofort, Check 5 (RAG-Orphans) RED mit 20 verwaistenFileContentIndex-Rows ohnemandateId/featureInstanceId-> via--purge-rag-orphansbereinigt -> Re-Audit 5/5 GREEN. Dann entfernt ausgateway/modules/interfaces/interfaceBootstrap.py:_migrateMandateDescriptionToLabel(Funktion + Aufruf),_migrateMandateNameLabelSlugRules(Funktion + Aufruf, ~64 Zeilen),initRootMandate-Legacy-Block (name="Root"-Migration, 7 Zeilen; Funktion selbst bleibt),_migrateAndDropSysAdminRole(Funktion + Aufruf, ~95 Zeilen). IninterfaceDbKnowledge.py:aggregateMandateRagTotalBytes-Fallback-Block (try/exceptmit FileItem-ID-Korrelation aus Management-DB, ~27 Zeilen) entfernt -- die Funktion bleibt aktiv, da sie 4 externe Caller hat. Ersatz: neuer Helpergateway/modules/interfaces/_legacyMigrationTelemetry.pymit 4 lese-only WARN-Checks (gleiche Logik wie Audit-Skript, prozessweit gecached) wird am Ende voninitBootstrapeinmalig aufgerufen -- falls je doch Restbestand auftauchen sollte (alter DB-Restore o.ae.), gibt's klare WARN-Logs mit Routine-Name + IDs. Teststests/unit/bootstrap/test_mandateNameMigration.py(8 Tests) undtests/unit/rbac/test_sysadmin_migration.py(5 Tests) geloescht (referenzierten entfernte Funktionen, wuerden ImportError werfen). Smoke-Test: 17/17 verbliebene rbac+bootstrap-Tests GREEN, Imports aller drei Module GREEN. User-Statement zur Risk-Lage: "die codebase lief bereits auf int und main/prod" -- d.h. die idempotenten Migrations sind dort schon mehrfach durchgelaufen, das Removal-Risiko = 0; das Audit-Skript bleibt fuer pre-deploy-Gating. Plan urspruenglich in1-plan/, jetzt direkt in4-done/2026-04-bootstrap-migrations-cleanup.md. (c-work:4-done/2026-04-bootstrap-migrations-cleanup.md) -
2026-04-29 | feat | frontend-nyla, gateway | Generischer
frontendType: templateTextareafuer Freitext mit{{nodeId.path}}-Variablen (DataPicker-Insert);email.draftEmail.contextundai.prompt.aiPromptnutzen ihn statt reiner Textarea -- Aufloesung ausschliesslich via bestehendesresolveParameterReferences(kein Loop-Spezialcode im Executor). Loop-Preview-Enrichment + IfElse/AI-responseData-Picker bleiben. Unit-Testtest_legacy_string_template_loop_current_item_nestedintest_automation2_graphUtils.py. -
2026-04-29 | docs | wiki | 6 neue UX-/Architektur-Plaene angelegt in
wiki/c-work/1-plan/aus Topics-TODO A-F: (A1+A2) Trustee-Workflow-Audit (alle 5 Reporting-Workflows GREEN auf Pick-not-Push) + generischerWorkflowRunWorkspace-Tab unter/automationsals Single-Source-of-Truth fuer Workflow-Resultate, plus Pflicht-BindingWorkflow.featureInstanceId(2026-04-trustee-workflow-audit-and-run-workspace.md); (B) Budget-Vergleich auf Excel-only mit eindeutigem 1-Tabelle-1-Chart-Prompt, Word-Pfad raus (2026-04-trustee-budget-comparison-refactor.md); (C) Inventar idempotenter Boot-Routinen, Removal-Plan fuer 5 b-Kandidaten via Audit-Skript + 30-Tage-Telemetrie (2026-04-bootstrap-migrations-cleanup.md-- noch am gleichen Tag umgesetzt, siehe Eintrag oben, jetzt unter4-done/); (D) Theme-System fuer AI-Reports pro Workflow (4 Themes standard/finance/marketing/presentation + Mandate-CI-Overlay), MD->JSON-Konsolidierung, Renderer-Refactor, Bilder-in-Tabellenzellen (2026-04-ai-reports-theming-and-pipeline.md); (E) ComCoach Greenfield-IA mitTrainingModule-Datenmodell (RenameCoachingContext) + 5-Tab-Struktur Dashboard/Assistent/Module/Session/Einstellungen, dossier=coaching-Doppelung weg,?context=-Bug fix (2026-04-comcoach-greenfield-ia.md); (F) TeamsBot Greenfield-IA analog mit neuerMeetingModule-Entity + 5-Tab-Struktur und 4 Live-Update-Fixes (SSE-Reconnect-Hook, agentRun-Status-Bubble, stats-Karten, adaptives Dashboard-Polling) (2026-04-teamsbot-greenfield-ia-and-live-update.md). Empfohlene Reihenfolge der Bauphase: C -> A2-Phase-1 (FeatureInstance-Pflicht) -> A2-Phase-2/3 (Workspace) -> B -> D -> E/F parallel. (c-work: 6 neue Dateien in1-plan/) -
2026-04-29 | fix | gateway |
checkForDuplicateFilemacht jetzt einen RBAC-Cross-Check und liefert keine "Geister-Duplicate" mehr aus. Ursache desFile with ID ... not found-Fehlers indownloadFromDataSourcedirekt nachDuplicate detected for user ...:interfaceDbComponentwird ueberserviceHubohnefeatureInstanceIdinitialisiert,checkForDuplicateFilefaellt deshalb auf denmandateId-Filter zurueck und benutztedb.getRecordset(kein RBAC) -- damit konnte er ein File aus einer FREMDEN featureInstance returnen. Der nachfolgendeupdateFile-Aufruf prallte dann am RBAC-gefiltertengetFileab und crashte den ganzen Tool-Call. Sauberer Fix an der Wurzel: nach dem Recordset-Treffer zwingendself.getFile(fileId)als RBAC-Cross-Check; wennNone, gilt als kein Duplicate fuer den aktuellen Scope und der Caller (saveUploadedFile/createFile) erstellt eine frische per-Scope-Kopie. Damit entfaellt jeglicher Workaround inupdateFile(die in der Vorgaenger-Session gebaute Try/Except-Schleife wurde gestern bereits ausgebaut, weil sie in einer Sackgasse stand). Folge: identische Files koennen pro Mandate mehrfach existieren -- eines pro featureInstance -- was gewollt ist, da sie pro Scope eigene Folder-/Tag-/Neutralize-Metadaten brauchen. Symptom-Doku inwiki/b-reference/gateway/agent-file-bridge.md(Section "Ghost-Duplicate-Fix"). (c-work: Begleitfix zum Agent-File-Bridge-Build vom selben Tag) -
2026-04-29 | fix | gateway | Agent-Tools binden jetzt jede produzierte Datei als ChatDocument an den aktiven Workflow -- damit funktioniert der
documentList-Resolver fuer Agent-Outputs. Bisher erzeugtendownloadFromDataSource,writeFile mode=create,renderDocument,generateImageundcreateChartzwar eineFileItem(viasaveUploadedFile/saveGeneratedFile), liessen den Workflow-Document-Graph aber unberuehrt -- statt einesChatDocumentfloss nur einsideEvent fileCreatedan die UI. Folge:getChatDocumentsFromDocumentList(und damitai_summarizeDocument/ai_process/context_extractContent/context_neutralizeData) konnte die FileItem-IDs nicht aufloesen, weil der Resolver ausschliesslichworkflow.messages[*].documents[*].idmatcht. Symptom war "Building structure prompt with 0 valid ContentParts" und entsprechend leere Summaries direkt nach einem Agent-Download. Loesung: zentraler Helper_attachFileAsChatDocument(services, fileItem, label, userMessage)incoreTools/_helpers.py, der intern eine ChatMessage (Rolleassistant, Statusstep, generierterdocumentsLabel) inklusive einem ChatDocument (mitroundNumber/taskNumber/actionNumberaus dem aktiven Workflow) viachatService.storeMessageWithDocumentspersistiert -- exakt das Pattern, dasworkflowProcessor.persistTaskResultundmethodTrustee.extractFromFilesschon laenger benutzen. Helper wird jetzt aus allen fuenf File-erzeugenden Agent-Tools aufgerufen; der ToolResult-Text traegt einheitlich beide IDs (documentList ref: docItem:<chatDocId>fuer AI-Tools,file id: <fileId>fuerreadFile/Embeds). Tool-Descriptions +conversationManager.buildSystemPromptergaenzt um die explizite Anweisung "use docItem: in documentList, NOT the file id, NOT a{"documents":[...]}wrapper". Zusatzlich:mainServiceAgent.runAgentpropagiert das Workflow-Object jetzt in alle Service-Contexts (chat._context.workflowetc.) -- bisher tat das nurworkflowManager._propagateWorkflowToContext, weshalb der Agent ueber die Workspace-Route ohne aktiven Workflow-Context lief undchatService._workflowNonewar. Folge: der Helper konnte ohne diesen Propagations-Fix nie greifen. Die in der vorhergehenden Session eingebaute RBAC-toleranteupdateFile-Try/Except-Schleife in_downloadFromDataSourceist jetzt obsolet und wieder ausgebaut -- mit korrektem ChatDocument-Bind kommt derfeatureInstanceIdueber den Workflow-Pfad und die Duplicate-File-RBAC-Probleme verschwinden an der Wurzel. Pattern-Doc neu unterwiki/b-reference/gateway/agent-file-bridge.md. (c-work: kein dedizierter Eintrag, kritischer Fix on top der documentList-Coercer-Aenderung) -
2026-04-29 | fix | gateway |
ai_process/context_extractContent/context_neutralizeDataakzeptieren jetzt LLM-typische Dict-Wrapper-Formate fuerdocumentList. Der Agent serialisiertdocumentListregelmaessig als{"documents":[{"id":"<uuid>","name":"<file>"}]}(Folge dertype=DocumentList-Schema-Definition, das LLMs als generic Object lesen). Bisher fielen alle drei Actions in denelse: Invalid documentList type: <class 'dict'>-Branch und liefen mit leerer Document-Liste weiter -- der Folder-Summarize-Workflow produzierte dann eine Zusammenfassung "ueber 0 Dokumente". Loesung: zentraler HelpercoerceDocumentReferenceList(value)indatamodelDocref.pyder ALLE praktisch vorkommenden Shapes parst --None,str,DocumentReferenceList,list[str],list[dict mit id/documentId/label],dict mit "documents"/"references"/"items"/"files"-Wrapper, unddict mit id/documentId(single item). Alle vier Aufrufstellen (process.py + extractContent.py + neutralizeData.py x2) auf den Helper umgezogen; die Inline-ActionDocument-Sonderbehandlung inprocess.pybleibt davor. Helper wirft NIE -- gibt im worst case eine leere Liste mit WARN-Log zurueck, der Caller entscheidet ob das fatal ist. (c-work: kein dedizierter Eintrag, Begleitfix zum Infomaniak-Test) -
2026-04-29 | fix | gateway |
listFiles-Tool: dict-vs-attribute-Mismatch inmainServiceChat.listFilesbehoben.interfaceDbComponent.getAllFiles()returnt seit dem Pydantic-RefactorList[dict](jeder Eintrag ist einFileItem.model_dump()mit Label-Spalten), abermainServiceChat.listFiles()griff weiter mitfileItem.fileName/fileItem.idzu (Pydantic-Style) -- daher'dict' object has no attribute 'fileName'und'dict' object has no attribute 'id'aus demlistFiles-Agent-Tool. Komplette Methode auf.get(...)umgestellt; Type-Annotation ingetAllFiles(Union[List[FileItem], PaginatedResult]) ist immer noch irrefuehrend -- das ist ein orthogonaler Tech-Debt-Punkt, kein Blocker. (c-work: kein dedizierter Eintrag) -
2026-04-29 | fix | gateway | kDrive: Single-File-DataSources funktionieren jetzt sauber (Browse + Download). Wenn der User eine einzelne Datei als DataSource anhaengt (z.B.
path=/2980592/12, wo12die kDrive-File-ID einer.html-Datei ist), brachten browseDataSource und downloadFromDataSource bisher Folgefehler: (1) Browse rief blind/2/drive/{driveId}/files/{fileId}/filesauf -> kDrive antwortet400 destination_not_a_directory-> Adapter loggte das als Empty-Folder -> Agent dachte "leerer Ordner" und konstruierte einen Pseudo-Pfad/2980592/12/platform-overview.html. (2)download(/2980592/12/platform-overview.html)nahm dannsegments[-1] = "platform-overview.html"als File-ID ->/2/drive/2980592/files/platform-overview.html->404 method_not_found. Saubere Loesung: (a) Neuer Helper_lastNumericSegment(segments)zieht aus einem Pfad immer die letzte rein-numerische ID -- kDrive-IDs sind grundsaetzlich Integer; haengt der Agent einen Filename dran, wird dieser ignoriert. (b)KdriveAdapter.browseholt vor dem Children-Listing die Item-Metadata (/files/{id}); beitype=filewird ein Single-Entry mit Name/Size/MimeType/Modified zurueckgegeben statt children aufzurufen. (c)KdriveAdapter.downloadbenutzt denselben Helper + denselben Metadata-Fetch (jetzt extrahiert in_fetchItemMeta). Folge: Single-File-Quellen sind jetzt browse-/downloadbar; Folder-Quellen verhalten sich unveraendert. (c-work:c-work/2-build/2026-04-infomaniak-connector.md) -
2026-04-29 | fix | gateway | downloadFromDataSource: Metadata-Updates auf Duplicate-Files werfen den Tool-Call nicht mehr aus dem Tritt.
saveUploadedFilereturnt bei Hash+Name-Match das EXISTIERENDE FileItem -- das kann aber in einem anderenfeatureInstanceId/Folder-Scope leben als die aktuelle Anfrage. Die nachfolgendenupdateFile-Aufrufe (featureInstanceId/neutralize/folderId) prallten dann am RBAC-gefiltertengetFileab und warfenFile with ID ... not found-- obwohl der Download korrekt war (File ist in der DB, addressierbar viafileItem.id). Fix: die drei Metadata-Updates laufen jetzt in einer Schleife mit individuellem Try/Except und WARN-Log; der Tool-Call meldet weiter Success mit der File-ID. (c-work: kein dedizierter Eintrag, Folge des kDrive-Fixes oben) -
2026-04-29 | fix | gateway | Agent-Tools:
kdriveFolder/calendarFolder/contactFolderwerden jetzt korrekt auf die Connector-Serviceskdrive/calendar/contactgemappt. DerSourcesTab.tsxschreibt diese FE-seitigen Source-Type-Literals beim Anhaengen einer Datenquelle ansDataSource-Record;_dataSourceTools._resolveDataSource(und parallelrouteFeatureWorkspace._SOURCE_TYPE_TO_SERVICE) hatten aber nur Eintraege fuer SharePoint/OneDrive/Drive/Outlook/Gmail/FTP/ClickUp -- daher kamenService 'kdriveFolder' not available. Options: ['kdrive', 'calendar', 'contact']ausbrowseDataSource/searchDataSource/downloadFromDataSourcesobald der Agent eine Infomaniak/Calendar/Contact-Quelle anfasste. Beide Maps um die drei Eintraege erweitert;DataSource.sourceType-Field-Description ergaenzt; Inline-Kommentar im_dataSourceTools.pywarnt vor Drift gegenueber FE und_SERVICE_MAP. BestehendeDataSource-Records funktionieren ohne Migration (dassourceType-Literal bleibt gleich). (c-work:c-work/2-build/2026-04-infomaniak-connector.md) -
2026-04-29 | fix | gateway | kDrive-Download folgt jetzt dem 302-Redirect. Der Endpoint
/2/drive/{driveId}/files/{fileId}/downloadantwortet bandwidth-bedingt mit302 Found -> presigned CDN URL(Standard fuer File-Bytes); unser_infomaniakDownload-Helper hatte aberallow_redirects=False(kopiert vom_infomaniakGet-Helper, wo das wichtig ist um nicht versehentlich auf OAuth-Login-Pages zu landen). Folge: jeder kDrive-Download lieferteNone->Tool result: downloadFromDataSource FAILED -> Download returned emptyim Agent-Log. Fix: nur fuer Downloadsallow_redirects=True, mit Doc-String der erklaert warum (gleiches Pattern bei Calendar/Contacts-Export-Endpoints, gleicher Host = Authorization-Header bleibt erhalten). Listing/Metadata-Calls bleiben weiterallow_redirects=False, damit nicht-PAT-faehige Routes als302sichtbar bleiben statt eine HTML-Login-Page zu liefern. (c-work:c-work/2-build/2026-04-infomaniak-connector.md) -
2026-04-29 | fix | gateway | Anthropic-Plugin:
temperaturewird fuer Extended-Thinking-Modelle (Claude 4.7 Opus, spaeter 4.7 Sonnet/Haiku, alle 5.x) nicht mehr gesendet. Anthropic antwortet seit dem 4.7-Release mit400 invalid_request_error: 'temperature' is deprecated for this model.-- nur der modellinterne Default ist akzeptiert. Analog zum gestrigen_supportsCustomTemperature-Helper im OpenAI-Plugin (gpt-5/o-Serie) jetzt auch hier: Praefix-Match aufclaude-opus-4-7/-sonnet-4-7/-haiku-4-7undclaude-*-5*->temperatureweglassen. Wirkt in allen drei Anthropic-Pfaden (callAiBasic,callAiBasicStream,callAiImage). Aeltere Modelle (Claude 4.5/4.6) bekommentemperatureweiter wie gehabt. (c-work: kein dedizierter c-work-Eintrag -- analog OpenAI gpt-5-Fix vom 2026-04-28) -
2026-04-29 | fix | gateway, frontend-nyla, wiki | Infomaniak-Connector: kDrive findet jetzt auch Drives, in denen der User nur
role: userist (stattaccount_admin). Live-Beweis vom User mit Files inhttps://ksuite.infomaniak.com/1696919/kdrive/app/drive/2980592/files/11: das Drive haengt korrekt an account_id 1696919, aber/2/drive?account_id=1696919antwortet trotzdem200 [] -- empty, weil dieser Endpoint zur Drive-Manager-Admin-Sicht gehoert (filtered aufaccount_admin: true) und nicht zur Endbenutzer-Sicht. Direkt-Aufrufe wie/2/drive/2980592/filesfunktionieren fuer denselben User mitrole: usereinwandfrei (PDF "Start_with_kDrive.pdf", Ordner "Nyla-Analysen" und "Onboarding" alle sichtbar). Root-Endpoint gefunden:GET /2/drive/init?with=drives-- enumeriert ALLE Drives die der User sehen kann, unabhaengig von der Admin-Rolle, braucht NUR dendrive-Scope (verifiziert mit PAT deraccounts-Scope explizit nicht hat). Implementierung: (a) Neuer HelperlistAccessibleDrives(token) -> List[dict]imconnectorInfomaniak.py-- ein einzelner/2/drive/init?with=drives-Call, raisedInfomaniakIdentityErrormit Scope-Message wenndrive-Scope fehlt. (b)KdriveAdapterhaelt jetzt_drives: Optional[List[Dict]](statt_accountId/_accountIds);_listDrives()mappt direkt aus dem gecachten Init-Response. (c)submit_infomaniak_tokenvalidiert in zwei Schritten:listAccessibleDrives(drive-Scope) undresolveOwnerIdentity(workspace:calendar/workspace:contact-Scope). (d) Der zwischenzeitlicheresolveAccessibleAccountIds()+accounts-Scope-Workaround wieder ENTFERNT (war eine Sackgasse:/1/accountslistet Manager-Organizations, nicht Drive-Accounts). (e)_probeDriveScope()-httpx-Helper im Submit-Route entfernt;httpx-Import +INFOMANIAK_API_BASE-Konstante raus. Frontend: PAT-Setup-Modal wieder auf 4 Pflicht-Scopes zurueck (accountsraus). Doku: Status-Tabelle, Validation-Section und "How the kDrive adapter discovers your drives" komplett auf deninit-Endpoint umgeschrieben. Bestehende Connections sollten ohne User-Aktion sofort funktionieren -- es ist kein neuer Scope und keine Token-Rotation noetig, der Adapter wechselt nur den Discovery-Endpoint. (c-work:c-work/2-build/2026-04-infomaniak-connector.md) -
2026-04-29 | fix | gateway | Infomaniak-Connector: Calendar-Events und Contacts-Download auf die echten PAT-faehigen Pfade gezogen. Live-Tests gegen die Vendor-API zeigten zwei Pfad-Mismatches im gestrigen Build: (1) Calendar-Events: der nested Route
/api/pim/calendar/{id}/event302t zur OAuth-Login-Seite (also nicht PAT-faehig); korrekter Endpoint ist/api/pim/event?calendar_id={id}&from=YYYY-MM-DD HH:MM:SS&to=...mit Pflicht-Range max 3 Monate (Vendor-Constraintrange_must_be_lower_than_3_months) -- Adapter waehlt jetzt fix 90-Tage-Window (heute -30 / +60), URL-Encoding viaurllib.parse.quote. Event-Detail und.ics-Export laufen ueber/api/pim/event/{eventId}und.../export(also ohne calendar-Praefix). (2) Contacts-Download:/addressbook/{book}/contact/{id}antwortet mit500 unexpected_errorund.../export302t zu OAuth -- beide Detail-Endpoints sind also nicht PAT-faehig. Listing dagegen funktioniert, liefert aber per Default nur Stammdaten -- ohnewith=emails,phones,addresses,detailskommen Email/Phone/Adresse leer. Loesung: ContactAdapter holt das Listing mit demwith-Param und rendert die.vcfselbst via_renderInfomaniakVcard()(vCard 3.0, escaped, mit N/FN/ORG/EMAIL/TEL/ADR/URL/NOTE) -- konsistent mit MSFT/Google-Adapter, die ihre.vcfs ebenfalls selbst synthetisieren. Plus: Helper_safeFileNameaus dem Calendar-Adapter zu modullokal hochgezogen, von beiden Adaptern genutzt; ungenutzteimport re/import json-Inline-Imports raus. kDrive-Adapter ist im Live-Test korrekt:/2/drive?account_id=1696919antwortet 200 mit leerem Array fuer den Test-Account (kein kDrive-Produkt aktiviert). (c-work:c-work/2-build/2026-04-infomaniak-connector.md)
2026-04-28
-
2026-04-28 | refactor | gateway | Infomaniak-Connector:
account_idist Adapter-State, nicht Connection-State. Symptom im Log:Infomaniak GET https://api.infomaniak.com/2/drive?account_id=pat-XXXXXXXX -> 422 validation_rule_integer "The account id must be an integer.". Root cause: derKdriveAdapterlasconnection.externalIdalsaccount_id-Quelle, und bei kaputten Submits konnte dort der Token-Fingerprint ("pat-59ee48d9") statt deraccount_idstehen. Saubere Loesung statt Fingerprint-Migration: (a) Neuer modullokaler HelperresolveOwnerIdentity(token) -> InfomaniakOwnerIdentityimconnectorInfomaniak.py-- versucht PIM Calendar (workspace:calendar-Scope), faellt auf PIM Contacts (workspace:contact-Scope) zurueck, raisedInfomaniakIdentityErrorwenn keine Owner-Records gefunden. (b)KdriveAdapterhat keinenaccountId-Konstruktor-Parameter mehr, sondern resolvt zur Laufzeit ueber_ensureAccountId()(gecached auf der Adapter-Instanz). Damit ist der Adapter self-contained und liest nichts mehr aus der Connection --externalIdist reiner UI-State. (c)submit_infomaniak_tokenruft denselbenresolveOwnerIdentity()als Pre-Flight-Check, dann/2/drive?account_id={resolved}als sauberer 200-Probe. Der frueher noetige_probeScope-422-Tolerance-Hack ist entfallen. (d)getServiceAdapterhat keine kDrive-Sonderbehandlung mehr; alle drei Adapter werden uniform mitaccessTokenkonstruiert. (e)_PIM_PREFIXist auf Modul-Ebene definiert; CalendarAdapter und ContactAdapter haben keine Klassen-Konstanten mehr. Konsequenz: jede existierende Infomaniak-Connection arbeitet ohne User-Aktion sofort wieder, auch wennexternalIdhistorisch einen Fingerprint enthaelt -- der Adapter zieht dieaccount_iddeterministisch aus der API. Setup-Guide um Architektur-Abschnitt erweitert. (c-work:c-work/2-build/2026-04-infomaniak-connector.md) -
2026-04-28 | feat | gateway, frontend-nyla | MSFT- und Google-Connector: CalendarAdapter + ContactsAdapter neu, plus Reconnect-Button. Nachdem Infomaniak heute Calendar/Contacts kann, ziehen MSFT und Google nach. Backend: (a)
oauthProviderConfig.googleDataScopesumcalendar.readonly+contacts.readonlyerweitert,msftDataScopesumCalendars.Read+Contacts.Read. (b)connectorMsft.CalendarAdapter(Graph:me/calendars,me/calendars/{id}/events?$top&$orderby=start/dateTime desc, Pagination via@odata.nextLink,.ics-Download als selbstgebautes RFC-5545 VCALENDAR/VEVENT da Graph keinen$value-Endpoint fuer Events kennt;$searchfuer query). (c)connectorMsft.ContactsAdapter(Graph:me/contactFolders+ virtuellerdefault-Ordner fuerme/contacts,me/contactFolders/{id}/contacts?$orderby=displayName,.vcfals vCard-3.0 selbstgebaut mit N/FN/ORG/TITLE/EMAIL/TEL/ADR/NOTE). Helper_eventToIcs,_contactToVcard,_safeFileName,_personLabelplus_icsEscape/_icsDateTime. (d)connectorGoogle.CalendarAdapter(Calendar v3:users/me/calendarList,calendars/{id}/events?singleEvents=true&orderBy=startTime,.icsaus Event-Detail). (e)connectorGoogle.ContactsAdapter(People API:contactGroups+ virtuellerall-Folder ueberpeople/me/connections, fuer Gruppenpeople:batchGet?resourceNames=..., Search viapeople:searchContacts,.vcfauspersonFields=names,emailAddresses,phoneNumbers,organizations,addresses,biographies). (f)_SERVICE_MAPvon beiden Connectoren um"calendar"/"contact"ergaenzt;routeFeatureWorkspaceundrouteFeatureGraphicalEditorService-Label-/Icon-Maps umkdrive,calendar,contactergaenzt, damit die UDB sinnvolle Anzeigen macht. (g) Reconnect-Flow:POST /api/connections/{id}/connectakzeptiert optionalen Body{"reauth": true}und haengt&reauth=1an die Auth-URL.routeSecurityMsft.auth_connectsetzt beireauth=1prompt=consent(sonst select_account/login),routeSecurityGoogle.auth_connectdroppt beireauth=1include_granted_scopes=truedamit Google strikt fuer die aktuelle Scope-Liste neu signiert (sonst werden neue Scopes still uebersprungen). Frontend:connectionApi.connectService(id, reauth?)-> POST mit Body,useConnections.connectWithPopup(id, reauth?)reicht durch,ConnectionsPagezeigt fuer aktive MSFT/Google/ClickUp-Connections einenFaSyncAlt-Button "Erneut verbinden (neue Scopes erteilen)" mit eigenem Loading-Set. Bestehende Connections muessen einmal reconnected werden, damit Calendar/Contacts in der UDB auftauchen. (c-work:c-work/2-build/2026-04-msft-google-calendar-contacts.md) -
2026-04-28 | fix | gateway | OpenAI-Connector:
temperaturefuer GPT-5.x / o-Serie aus dem Payload nehmen. Symptom im Log: jede AI-Anfrage failt mit HTTP 400Unsupported value: 'temperature' does not support 0.2 with this model. Only the default (1) value is supported., der Failover spricht 14 Modelle durch und schreibtRecorded failure for gpt-5.5, cooldown 60.0s. Root cause: die GPT-5-Familie (gpt-5, gpt-5.4*, gpt-5.5*) und die o-Serie (o1/o3/o4) sind Reasoning-Modelle; OpenAI akzeptiert dort -- analog zurmax_tokens->max_completion_tokens-Restriction -- nur den Default (1). Wir senden aber unverhandelttemperature=0.2aus jedemAiModel-Eintrag. Fix: Helper_supportsCustomTemperature(modelName)und incallAiBasic/callAiBasicStream/callAiImageden Key nur conditional ins Payload aufnehmen (Modellnamen mit Praefixgpt-5,o1,o3,o4lassen ihn weg). Der vom User im UI gesetzte Override ueberAiCallOptions.temperaturewird auf den nicht unterstuetzten Modellen still verworfen statt einen 400 zu erzwingen. Tests:tests/unit/aicore/test_aicorePluginOpenai_temperature.py(18 Tests, parametrisiert ueber Legacy-Modelle vs. Reasoning-Familie). Suite gesamt: 530 passed. -
2026-04-28 | docs | wiki | Infomaniak-Connector: Mail-Adapter formal als "blocked by vendor" markiert. Erschoepfende Pfad-Tests am 2026-04-28 zeigen: alle 7 plausiblen Mail-Endpoints sind heute nicht PAT-faehig.
api.infomaniak.com/{1,2}/mail-> 404 nginx (existiert nicht);mail.infomaniak.com/api/mail[?account_id=...],/api/pim/mail,/api/pim/mailbox,/api/pim/folder-> 302 zulogin.infomaniak.com/authorize(nur OAuth-Web-Session, Bearer-PAT wird abgelehnt);mail.infomaniak.com/api/mail/?account_id=...-> 301 zuhttp://mail.infomaniak.com:5000(interner Cyrus-IMAP-Port, von aussen nicht erreichbar). Derworkspace:mail-Scope bleibt im PAT-Standard-Setup, damit der MailAdapter spaeter ohne Token-Rotation freigeschaltet werden kann; Setup-Guide und c-work-Doku zementieren den Befund. Kein Code-Change. (c-work:c-work/2-build/2026-04-infomaniak-connector.md) -
2026-04-28 | feat | gateway, frontend-nyla | Infomaniak-Connector: ContactAdapter neu. Nachfolge-Tests gegen die Contacts-PIM-API zeigten, dass
https://contacts.infomaniak.com/api/pim/addressbook(Singular!) mit dem PAT-Scopeworkspace:contactund Bearer-Auth200+ JSON liefert -- gleiche Antwort-Struktur wie Calendar (addressbooks[].id/name/account_id/...). Die Plural- und/contact*-Pfade (/api/pim/contacts,/api/pim/contact/addressbook) sind weiterhin OAuth-only bzw. 404. NeuerContactAdapter1:1 analogCalendarAdapter:browse("/")-> Adressbuecher,browse("/{bookId}")-> Kontakte (Display-Name, Email, Phone, Organization in Metadata),download("/{bookId}/{contactId}")->.vcfvia/contact/{id}/exportmit JSON-Fallback,search()als kostenguenstiger Client-Filter. Geteilte Organisations-Adressbuecher (name="",is_dynamic_organisation_member_directory=true) bekommen "Organisation" als Anzeigename, sonst waere der Tree-Knoten leer. Neue Konstante_CONTACTS_BASE,ContactAdapterin_SERVICE_MAPregistriert. Frontend:SourcesTabkenntcontact-Icon (👤), -Color und Mapping; PAT-Modal nennt Contacts als heute aktiv (Mail bleibt "in Vorbereitung"). Setup-Guide: Status-Tabelle, UDB-Verifikations-Liste und Validation-Beschreibung aktualisiert. (c-work:c-work/2-build/2026-04-infomaniak-connector.md) -
2026-04-28 | feat | gateway, frontend-nyla | Infomaniak-Connector: kDrive PAT-Fix + Calendar-Adapter neu. Nach den ersten echten PAT-Test-Calls aufgeraeumt: (a)
/2/drivebraucht einaccount_id-Query-Arg, sonst422 account_id required. Fix:account_ideinmalig beim Token-Submit aus dem Calendar-PIM-Endpoint (https://calendar.infomaniak.com/api/pim/calendar-- liefertaccount_id,user_id, Anzeigename) ziehen, inUserConnection.externalIdpersistieren und ueberInfomaniakConnector.getServiceAdapterals Konstruktor-Parameter in denKdriveAdapterinjizieren./1/profile(haetteuser_info-Scope verlangt) und/1/mail(existiert nicht: 404 nginx) raus aus den Probes. (b)_probeScopetoleriert jetzt 4xx ausser 401/403 (z.B. 422validation_failed) als "Scope ist da, Endpoint braucht nur weitere Args". (c) NeuerCalendarAdapter(browse-> Calendars/Events uebercalendar.infomaniak.com/api/pim/calendar,download->.icsvia/event/{id}/export, JSON-Fallback)._infomaniakGetund_infomaniakDownloadakzeptieren ein optionalesbaseUrl, sodass Calendar gegencalendar.infomaniak.comund kDrive gegenapi.infomaniak.comlaufen koennen. (d)MailAdapteraus_SERVICE_MAPentfernt:mail.infomaniak.com/api/mailredirected mit 302 zulogin.infomaniak.com/authorize, akzeptiert also keine PATs; gleiches gilt fuercontacts.infomaniak.com/api/pim/contact. Beide Scopes werden weiterhin ingrantedScopesgespeichert, damit kuenftige Adapter ohne Token-Rotation aufgeschaltet werden koennen. (e) Frontend:SourcesTabkenntcalendar-Icon, -Color und_SERVICE_TO_SOURCE_TYPE-Mapping; PAT-Modal inConnectionsPagezeigt Calendar als zweiten aktiven Service, Mail/Contact als "in Vorbereitung, Scope schon mitnehmen". (f) Setup-Guide aktualisiert (Status-Tabelle + Validation-Beschreibung). (c-work:c-work/2-build/2026-04-infomaniak-connector.md) -
2026-04-28 | refactor | gateway, frontend-nyla | Infomaniak-Connector: OAuth -> Personal Access Token. Infomaniaks
login.infomaniak.com/authorizeakzeptiert nur Identity-Scopes (openid,profile,email,phone); Versuche mitkdrive/mail-Scopes quittieren miterror=invalid_scope. Datenzugriff geht ausschliesslich ueber manuell im Manager erstellte PATs. Umbau: (a) BackendrouteSecurityInfomaniakkomplett neu -- ein EndpointPOST /api/infomaniak/connections/{id}/token, validiert PAT viaGET https://api.infomaniak.com/1/profile, persistiert Bearer mit 10-Jahres-Horizont (analog ClickUp), entfernt OAuth-Connect/Callback-Pfade. (b)tokenManager.refreshInfomaniakToken+tokenRefreshService._refresh_infomaniak_tokenentfernt, AuthAuthority.INFOMANIAK aus den Background-Refresh-Filtern raus -- PATs sind langlebig. (c)oauthProviderConfig.infomaniakDataScopes+infomaniakDataScopesForRefreshentfernt. (d)routeDataConnections.connect_serviceantwortet bei Infomaniak jetzt mit 400 + Hinweis auf den PAT-Endpoint. (e) Env-Cleanup:Service_INFOMANIAK_DATA_CLIENT_ID/SECRETundService_INFOMANIAK_OAUTH_REDIRECT_URIaus.env+env_dev/int/prod[_forgejo].envraus. (f) Frontend:useConnections.createInfomaniakConnectionAndAuth(OAuth-Popup) ersetzt durchcreateInfomaniakConnection+submitInfomaniakToken;ConnectionsPagezeigt PAT-Modal mit Schritt-Anleitung + Deeplink zumanager.infomaniak.com/v3/ng/accounts/token/list; Cancel rollt PENDING-Connection per DELETE zurueck. (g) Doku:wiki/d-guides/infomaniak-oauth-setup.mdgeloescht,wiki/d-guides/infomaniak-token-setup.mdneu. (c-work:c-work/2-build/2026-04-infomaniak-connector.md) -
2026-04-28 | refactor | gateway | Cleanup der zwei tieferliegenden Defensive-Programming-Schichten, die den Trustee-Bug (vorheriger Eintrag) ueberhaupt erst durchgelassen haben.
- (1) DB-Connector: fail-loud statt swallow.
connectorDbPostgre.getRecord/getRecordset/getRecordsetPaginated/getDistinctColumnValues/_loadTable/semanticSearchhaben bisher jede Exception perexcept Exception → log → return [](bzw.None/leeres Pagination-Resultat) verschluckt. Folge: jeder echte DB-Fehler (Postgres-Adapt, UndefinedTable, UndefinedColumn, OperationalError, etc.) wurde fuer den Caller ununterscheidbar von "0 Rows" -- darauf basierten misleading downstream Errors wie "No active accounting configuration found". Neu: typisierte ExceptionDatabaseQueryError(table, message, original)plus zentrales_rollbackQuietly(connection)(Postgres setzt die Connection in Error-State nach jedem fehlgeschlagenen Statement). Empty Result Sets liefern weiterhin[]/None/{items: [], totalItems: 0, totalPages: 0}(= Normalpfad uebercursor.fetchall()/fetchone()), aber jede Exception innerhalb des Query-Pfads wird hochgereicht. Tests:tests/unit/connectors/test_connectorDbPostgre_failLoud.py(9 Tests). - (2) Action-Parameter: zentrale Validierung statt impliziter Kontrakt. Workflow-Actions haben
parameters: Dict[str, Any]ohne Schema-Enforcement bekommen; die Aktionsimplementationen mussten ad-hocisinstance-Branches haben oder mit Postgres-Errors abstuerzen (siehe Trustee-Bug). Neues Modulgateway/modules/workflows/processing/shared/parameterValidation.pymitInvalidActionParameterError(ValueError)+validateAndCoerceParameters(actionDef, parameters). Zentral aufgerufen inActionExecutor.executeAction-- gilt fuer alle Aufrufpfade (Agent, Workflow-Graph, REST). Logik:- Required-Parameter erzwungen (typisierter Fehler statt opaque downstream).
- Ref-Schemas (
FeatureInstanceRef/ConnectionRef/...) -- Dict mitidwird auf String-UUID kollabiert; Pass-Through fuer bereits-Strings; Dict ohneidraisst kontrolliert. - Primitive-Coercion (
bool/int/float) aus haeufigen String-Formen ("true"/"12"/"3.14"). Unbekannte Extra-Keys (parentOperationId,expectedDocumentFormats, ...) bleiben unangetastet. Die in der vorherigen Iteration inactionToolAdaptereingebaute Ref-Normalisierung wurde komplett entfernt (Single Source of Truth inparameterValidation). Tests:tests/unit/workflows/test_parameterValidation.py(19 Tests).
- Gesamttest-Suite: 512 passed (vorher 503, plus 9 neue DB-Tests; +19 neue Validation-Tests; -7 obsolete Adapter-Tests, da Logik umgezogen).
- (1) DB-Connector: fail-loud statt swallow.
-
2026-04-28 | fix | gateway | Agent-Tool-Calls auf Workflow-Actions mit
*Ref-Parametern (z.B.trustee_refreshAccountingData(featureInstanceId=...)) brachen mit irrefuehrendem "No active accounting configuration found" ab. Root cause: das Tool-Schema (Phase-3 Typed Action Architecture) exponiertFeatureInstanceRef/ConnectionRefabsichtlich als typisiertes Objekt mitid+Diskriminator (featureCode/authority), damit der LLM bei mehreren Instanzen die richtige picken kann -- aber die Action-Implementierungen verwenden den Wert direkt als String-UUID inrecordFilter={"featureInstanceId": <value>, ...}. Der LLM uebergibt korrekt das Dict{id, featureCode, label, mandateId}, Postgres-Adapter scheitert mitcan't adapt type 'dict', der DB-Connector swallowed den Fehler (soft-fail mit[]), und die Action interpretiert das leere Resultset als "Konfiguration fehlt". Initial-Fix inactionToolAdapter(Ref-Dict -> id-String). Diese Adapter-Normalisierung wurde im Folgeschritt zur zentralenparameterValidationmigriert (siehe naechster Eintrag).
2026-04-27
- 2026-04-27 | fix | gateway | Trustee-Subagent gab fuer "Banksaldo per 31.12.2025" CHF 11'861'162.50 zurueck statt der echten 48'507.41 (Konto 1020) und identifizierte 5400 (Materialaufwand) + 3434 (Erloeskorrekturen) als "Bankkonten". Root cause war doppelt: (1)
closingBalanceist bereits ein Saldo pro Periode -- der Agent riefaggregateTable(SUM, closingBalance, GROUP BY accountNumber)ohne periodYear/periodMonth-Filter und summierte 7 Jahre x 13 Perioden auf (~90x echter Saldo); (2) er hatte kein Wissen darueber, dass Schweizer KMU-Bankkonten dem Praefix102xfolgen undperiodMonth=0das Jahres-Total bedeutet. Fix in zwei Teilen: (a) generische Regel infeatureDataAgent._buildSchemaContextSystem-Prompt -- "NEVER apply SUM/AVG to columns that already represent a balance, closing/opening total or aggregate" mit konkreten BeispielenclosingBalance/openingBalance/debitTotal/creditTotal; (b) Pro-Feature-HookgetAgentDomainHints() -> strinmainXxx.py: wenn die Funktion existiert, wird ihr Rueckgabetext ans Ende des Subagent-Prompts angehaengt. Trustee liefert jetzt einen kompakten Domain-Guide mit KMU-Kontoplan-Praefixen (1xxx/2xxx/3xxx/4xxx, 100x/102x), Periodenkonvention (periodMonth=0= Jahr, 1-12 = Monat), drei kanonischen Query-Patterns (Banksaldo, Konto-Saldo, Buchungen-im-Monat) und einer Anti-Pattern-Liste (kein SUM auf closingBalance, debitTotal/creditTotal sind keine Salden). Loader in_loadFeatureDomainHintsnutztloadFeatureMainModules()und ist tolerant gegen fehlende Hooks/Module. Unit-Tests intests/unit/services/test_featureDataAgent_schema.py(4 neue: Generische Regel, Trustee-Hints angehaengt, kein Hints-Block fuer Features ohne Hook, Anti-Pattern-Erwaehnungen)
2026-04-26
- 2026-04-26 | fix | gateway+frontend | Automation Workflow-Tab:
Automation2WorkflowViewerstellt damit sysCreatedAt (timestamp) und lastStartedAt korrekt als PeriodPicker-Spalten erkannt werden; lastStartedAt nutzt jetzt AutoRun.startedAt statt sysCreatedAt; computed-field Filter/Sort via applyFiltersAndSort in-memory; Runs-Tab auf startedAt/completedAt umgestellt statt System-Audit-Felder - 2026-04-26 | perf | gateway | routeWorkflowDashboard get_system_workflows: N+1 AutoRun-Abfragen ersetzt durch LEFT JOIN + Subquery-Aggregation (eine Daten- + eine Count-Query); FK-Sort-Pfad nutzt eine gebündelte Run-Stats-Query; lastStartedAt/runCount/isRunning-Filter im Join-Pfad in SQL
- 2026-04-26 | fix | gateway | Feature-Data-Subagent (
queryFeatureInstance) Schema-Prompt war zu duenn: Agent erhielt nur Tabellennamen + flache Spalten-Liste, ohne Typen / Beschreibungen / FK-Beziehungen. Folge: bei Trustee-Saldo-Queries summierte erTrusteeDataJournalLine.debitAmount/creditAmountohne Datumsfilter (JournalLine hat gar keinbookingDate!) statt die Periode-bezogenenTrusteeDataAccountBalance.closingBalancezu nutzen; ISO-Date-Strings wurden gegen Float-Unix-Timestamps gefiltert (bookingDate <= '2025-12-31'). Fix infeatureDataAgent._buildSchemaContext: pro Tabelle wird jetzt der zugehoerige Pydantic-Klasse viaMODEL_REGISTRYresolved und pro selektiertem Feld eine angereicherte Zeile gerendert -- Python-Typ ausfield.annotation, deutsches Label ausjson_schema_extra.label, Description ausField(description=...), FK-Target ausfk_target. Dazu drei neue Regeln im System-Prompt: (a) Float-Felder mit "unix timestamp" in der Description sind Sekunden-seit-Epoch (Beispiel'2025-12-31' -> 1735603200.0), (b) Tools koennen nicht JOINen -- FK-Tabellen separat abfragen, (c) Periode-aggregierte Tabellen (Opening/Closing-Balances) bevorzugt vor SUM ueber Rohdaten. Fallback auf flache Feldliste wenn die Tabelle nicht im Pydantic-Registry ist. Unit-Tests intests/unit/services/test_featureDataAgent_schema.py - 2026-04-26 | feat | gateway+frontend-nyla | Infomaniak-Connector (kDrive + Mail) als neuer ProviderConnector analog Google/MSFT/ClickUp. Backend:
AuthAuthority.INFOMANIAK,providerInfomaniak/connectorInfomaniak.pymitKdriveAdapter+MailAdapter(httpx, OAuth-Bearer, Path-Konvention/{driveId}/{fileId}bzw./{mailboxId}/{folderId}/{uid}),routeSecurityInfomaniak.pymit_FLOW_CONNECT-only (kein Login -- pure DATA_CONNECTION), Token-Refresh viatokenManager.refreshInfomaniakToken+tokenRefreshService._refresh_infomaniak_token,connectorResolver-Registry-Eintrag, Authority-Map/Labels/Dispatch inrouteDataConnections, Router-Mount inapp.py. Refresh-Token-Persistierung holt bei fehlendemrefresh_token-Response aus dem letzten gespeicherten Token (analog Google). Frontend:connectionApi.tsAuthority-Typ erweitert,useConnections.createInfomaniakConnectionAndAuth+infomaniak_connection_success/error-Event-Listener,ConnectionsPagemit Infomaniak-Button (FaCloud),SourcesTabIcons/Colors/Service-Mapping fuerinfomaniak/kdrive/mail-- inkl. Fix der bisher fehlenden ClickUp-Eintraege in_SERVICE_ICONS+_SERVICE_TO_SOURCE_TYPE. Setup-Guide unterwiki/d-guides/infomaniak-oauth-setup.md(c-work: c-work/2-build/2026-04-infomaniak-connector.md) - 2026-04-26 | fix | gateway | Feature-Data-Subagent (
queryFeatureInstance) hat seine Loop hardcoded auf 8 Runden begrenzt, unabhaengig vom WorkspacemaxAgentRounds. Im int-System brachen Trustee-Saldo-Queries deshalb mitMaximum rounds reached. Progress after 8 roundsab, obwohl der Parent-Agent z.B. mit 25 Runden konfiguriert war. Fix:agentLoop._executeToolCallspropagiert jetztparentMaxRounds+parentMaxCostCHFueber den Tool-Context;_featureSubAgentTools._queryFeatureInstanceliest sie aus und reicht sie anrunFeatureDataAgent(maxRounds=, maxCostCHF=)weiter. Default fuer Direktaufrufer/Tests bleibt 8. Cost-Cap skaliert linear (_MAX_COST_CHF_PER_ROUND = 0.02 * maxRounds), damit nicht der 0.15-CHF-Guard die Loop vor Erreichen der konfigurierten Runden abschiesst (25 Runden -> 0.50 CHF). Subagent-Start loggt jetzt effektivemaxRounds/maxCostCHFzur Diagnose - 2026-04-26 | feat | gateway+frontend-nyla | Database-Health Orphan-Cleanup: neue Checkbox
Ohne FK-Referenzen zu UserInDB.id(default ON). Deleted-User-Reste in Audit/Billing/Membership-Tabellen sammeln sich natuerlich an wenn ein User geloescht wird und gehoeren in den separaten User-Purge-Workflow, nicht in die generische FK-Bereinigung. Backend:_isUserIdFk(targetTable, targetColumn)-Helper (case-insensitive auf Tabellenname);_cleanAllOrphans(force, excludeUserFks)ueberspringt entsprechende Relationen;/orphans?excludeUserFks=truefiltert Scan-Resultate;OrphanCleanAllRequest.excludeUserFksfiltert clean-all. Frontend: Checkbox nebenNur Probleme, default checked, mit Tooltip; URL-Param + clean-all Body-Field synchron;Alle bereinigen-Counter zeigt jetzt nur Non-User-FK-Orphans - 2026-04-26 | fix | gateway | aicorePluginOpenai:
max_tokensdurchmax_completion_tokensersetzt incallAiBasicundcallAiBasicStream. Hintergrund: OpenAI lehntmax_tokensfuer gpt-5.x / o-series Modelle mit HTTP 400unsupported_parameterab (Use 'max_completion_tokens' instead). Im Loglog_app_20260426.log(L741-764) sichtbar:gpt-5.4-nanofailover scheiterte sofort, ModelSelector wechselte aufclaude-opus-4-6. Per OpenAI API-Reference akzeptieren ALLE aktuellen Chat-Completions-Modelle (legacy gpt-4o/gpt-4.1, gpt-5.x, o1/o3/o4)max_completion_tokens, daher universeller Wechsel statt Modell-spezifischer Verzweigung - 2026-04-26 | feat | gateway | PDF-Renderer Emoji-Support: Noto Emoji (monochrome, OFL) als Fallback-Font registriert. Bisher rendern WinAnsi-Core-Fonts (Helvetica/Courier) Emoji-Codepoints (U+2600+, U+1F300+) als fehlende Glyphen-Quadrate. Neu unter
gateway/assets/fonts/NotoEmoji-Regular.ttf(~419 KB, 887 Codepoints) +_pdfFontFallback.pyHelper: registriert die TTF einmalig bei reportlab, scannt deren cmap, undwrapEmojiSpansInXmlumschliesst zusammenhaengende Emoji-Runs (codepoint >= U+2000 ∧ in cmap) mit<font name="NotoEmoji">…</font>— nestet sauber in<b>/<i>/<font name="Courier">.rendererPdf._markdownInlineToReportlabXmlwendet das am Ende an, also greift es ueberall wo Paragraph-Markup gebaut wird (Headings, Paragraphs, Bullet-Lists, Table-Cells, extracted_text).Preformatted(Code-Blocks) ist Single-Font-only und bleibt unveraendert — Emojis in Code-Bloecken sind selten, Box-Drawing wird wie bisher zu ASCII normalisiert. Smoke-Test intest_renderer_pdf_smoke.py - 2026-04-26 | fix | gateway | FK Orphan-Scanner loeschte korrekte Trustee-Workflows:
AutoWorkflow.templateSourceIdenthaelt teils Sentinel-IDs (z.B."trustee-receipt-import"ausfeatureModule.getTemplateWorkflows()), die absichtlich keine DB-Zeile haben — wurden faelschlich als Orphans markiert und mitforce=true(oder unter 50%-Schwelle) geloescht. NeuersoftFk: TrueFlag infk_target:fkRegistry.FkRelationshiptraegt das Flag,databaseHealth._scanOrphans/_cleanOrphans/_listOrphansueberspringen soft FKs komplett (kein Display, kein Cleanup). Label-Resolution unveraendert.templateSourceIdalssoftFk: Truemarkiert. Wikib-reference/platform/database-architecture.mdaktualisiert - 2026-04-26 | refactor | gateway+frontend-nyla | Letzte 4 hardcoded Cell-Label-Stellen entfernt: (1)
RoleView.scopeType(select mitfrontend_optionsSystem-Template/Template/Mandant) +RoleView.userCount->AdminMandateRolesPagezieht Attribute jetzt vonRoleView, kein lokalerscopeType-Formatter mehr; (2)Invitation.expiredFlagals Pydantic@computed_field(live ausexpiresAt+time.time()) mitfrontend_format_labels=["Ja","-","Nein"]; (3)Invitation.emailSent->emailSentFlagumbenannt + neuesemailSentAt-Feld (Persistenz im DB-Record),routeInvitations.create_invitationsetzt beide nach erfolgreichem Mailversand; (4)TrusteePositionViewmitsyncStatus(select Ausstehend/Synchronisiert/Fehler/Abgebrochen) +syncErrorMessage->routeFeatureTrustee.get_positionsenriched Rows ausTrusteeAccountingSync,useTrusteelookt Attribute via neuemattributesEntityName-Override,TrusteePositionsViewhat eigenen Sync-State + Custom-Renderer geloescht.attributeUtils.getModelAttributeDefinitionsundi18nRegistry.@i18nModelverarbeiten jetzt auchmodel_computed_fields(Labels +frontend_format_labelswerden registriert) - 2026-04-26 | refactor | gateway+frontend-nyla | Hardcoded Cell-Labels aus FormGeneratorTable-Pages entfernt: Boolean-Formatter ("Ja"/"Nein", "OK"/"Fehler") und Enum-Maps (
_STATUS_LABELS,scopeLabels) ausGraphicalEditorWorkflowsPage,GraphicalEditorTemplatesPage,AutomationsDashboardPage,ComplianceAuditPageersatzlos geloescht. Stattdessen Pydantic-Modelle (AutoWorkflow.active|sharedReadOnly|isTemplate|notifyOnFailure|templateScope,AutoRun.status,AutoStep.status,AutoTask.status,AutoVersion.status,Automation2WorkflowView.isRunning,AuditLogEntry.success) mitfrontend_format_labels/frontend_optionsausgestattet.resolveColumnTypesmerged jetzt auchlabelundoptionsaus dem Backend;FormGeneratorTablerendert Cells UND Filter-Dropdowns uebercolumn.optionsautomatisch — Pages duerfen Labels nicht mehr im Frontend hardcoden - 2026-04-26 | feat | frontend-nyla | FormGeneratorTable + columnTypeResolver:
ColumnConfig.options(ausfrontend_optionsder Pydantic-Felder) ist jetzt erste Klasse; Cell-Renderer und Filter-Liste resolven Value -> Label automatisch;column.labelist optional und wird vom Backend-Attribut gefuellt - 2026-04-26 | fix | gateway+frontend-nyla | GraphicalEditor Workflows-Tabelle:
createdAt-Alias ausrouteFeatureGraphicalEditor.get_workflowsentfernt — Frontend nutzt nun das kanonischesysCreatedAt.GraphicalEditorWorkflowsPage+GraphicalEditorTemplatesPageholen Attribute jetzt vonAutomation2WorkflowView(mitfrontend_type=timestampfuersysCreatedAt/lastStartedAtundfrontend_type=numberfuerrunCount); Spalten haben explizitsortable/filterablegesetzt — fehlende Sort-Icons und Zahl-statt-PeriodPicker behoben.Automation2Workflow-TS-Interface aufsysCreatedAtumgestellt - 2026-04-26 | refactor | frontend-nyla | RealEstate Parcels+Projects + GraphicalEditor Workflows+Templates:
apiEndpointauf den jeweiligen Listenroute gesetzt — Backend-Routen unterstuetzenmode=filterValues&column=Xundmode=idsueberhandleFilterValuesInMemory/handleIdsInMemory; FormGeneratorTable holt Filter-Werte jetzt sauber vom Backend (kein Local-Mode mehr noetig) - 2026-04-26 | feat | gateway | routeFeatureGraphicalEditor:
/workflowsund/templatesEndpunkte unterstuetzen jetztmode=filterValues&column=Xundmode=ids(FormGeneratorTable Backend-Pattern) ueberhandleFilterValuesInMemory/handleIdsInMemoryaus routeHelpers - 2026-04-26 | fix | frontend-nyla | AdminLanguagesPage:
hookData.fetchFilterValuesimplementiert (offizielles Pattern fuer In-Memory-Tabellen ohne Backend-Endpunkt) — distinct Filter-Werte ausdisplayRowsmit Cross-Filter-Support; ersetzt das zuvor versuchte FormGeneratorTable-Local-Mode - 2026-04-26 | revert | frontend-nyla | FormGeneratorTable: Local-Mode-Fallback in
getUniqueValuesForColumnund das Entfernen der console.warn rueckgaengig gemacht — silent Fallbacks verstossen gegen das Prinzip "klare Datenstrukturen + Modelle im Backend"; Tabellen muessen stattdessenapiEndpoint(Backend) oderhookData.fetchFilterValues(explizit) setzen - 2026-04-26 | fix | frontend-nyla | AutomationsDashboardPage Workflows-Tab: Spalten
isRunningundrunCountalssortable+filterablemarkiert (Backend unterstuetzt JOIN-basierte Sortierung/Filterung dieser computed fields) - 2026-04-26 | fix | gateway | Automation2 ExecutionEngine:
AutoRun.startedAtwird jetzt increateRungesetzt;AutoRun.completedAtwird inupdateRunautomatisch gesetzt sobald Status terminal wird (completed/failed/stopped/cancelled); routeWorkflowDashboard.stopRun setztcompletedAtebenfalls. Bisher wurden diese Felder nie befuellt — daher warenstarted/completedSpalten in der Runs-Tabelle leer - 2026-04-26 | fix | frontend-nyla | PeriodPicker in FormGeneratorTable: Preset-Kind (
thisMonth,thisQuarteretc.) wird im Filter-Wert mitgespeichert, damit es beim Round-Trip erhalten bleibt undisValueAllowednicht faelschlicherweise aufytdzurueckfaellt - 2026-04-26 | fix | gateway | routeAudit: 500-Fehler bei Datumsfilter behoben —
PaginationParams(pageSize=999999)verletztele=1000-Constraint; nutzt jetztmodel_construct+SortField-Konvertierung - 2026-04-26 | refactor | gateway | 5 Pattern-Inkonsistenzen aus FormGeneratorTable-Audit behoben: routeDataUsers stiller Fallback entfernt; routeFeatureRealEstate Projekte+Parzellen nutzen jetzt
applyFiltersAndSortstatt nur Sorting; routeAdminRbacRules custom filter/sort durch shared Helper ersetzt +enrichRowsWithFkLabelsergaenzt - 2026-04-26 | fix | frontend-nyla | ComplianceAuditPage: Fallback-Formatter fuer
instanceLabelundusernamezeigen jetztNA(uuid)statt abgeschnittener UUID ohne Kontext - 2026-04-26 | fix | gateway | aicoreModelRegistry: Race-Condition in
refreshModelsbehoben — Lock verhindert konkurrierende Refreshes; harmlose Duplikate (gleicher Name+Connector) werden toleriert statt als Fehler geworfen - 2026-04-26 | fix | gateway | routeDataFiles:
mode=filterValuesnutzt jetztenrichRowsWithFkLabels+handleFilterValuesInMemorystatt direktemgetDistinctColumnValues— FK-Spalten (mandateId, featureInstanceId) zeigen wieder Labels statt UUIDs - 2026-04-26 | fix | gateway | routeFeatureTrustee: 3x
mode=filterValues(Documents, Positions, generisch) vongetDistinctColumnValuesWithRBACaufenrichRowsWithFkLabels+handleFilterValuesInMemoryumgestellt — FK-Spalten (organisationId, roleId, userId, contractId etc.) zeigen Labels statt UUIDs; generischer Endpunkt nutzt zusaetzlich_buildFeatureInternalResolversfuer Feature-interne FKs - 2026-04-26 | fix | gateway | routeAudit:
_enrichUserAndInstanceLabelssetzt jetztNA(uuid)als Fallback stattNonefuer nicht aufloesbare FeatureInstance/User-IDs — Filter-Dropdown fuer Feature-Instanz war leer weil alle LabelsNonewaren - 2026-04-26 | fix | gateway | Zwei Filter-Bugs: (1)
applyFiltersAndSortin routeHelpers:value is Nonefiltert jetzt auf leere Felder statt den Filter zu ueberspringen ("Leer"-Option funktioniert); (2)routeAudit._applySortFilterSearchdurch Delegation an sharedapplyFiltersAndSortersetzt — Datumsbereich-Filter (between-Operator) und Null-Filter funktionieren jetzt konsistent - 2026-04-26 | fix | gateway | Stille
except Exception-Fallbacks inmode=filterValuesentfernt:routeFeatureTrustee(_handleDocumentMode, _handlePositionMode, _paginatedReadEndpoint),routeDataFiles,routeDataMandates— Fehler bubblen jetzt hoch statt stillschweigend auf teuren In-Memory-Pfad auszuweichen - 2026-04-26 | fix | gateway | Filter-Dropdown-UUID-Bug:
enrichRowsWithFkLabelsfehlte immode=filterValues-Pfad bei 8 Routen (routeDataConnections, routeInvitations, routeAdminFeatures, routeSubscription, routeFeatureRealEstate x2); Wikifk-label-resolution.mdmit Filter-Enrichment-Regel fuer AI-Agent ergaenzt - 2026-04-26 | refactor | gateway | FK-Metadaten konsolidiert: alle Datamodels nutzen
fk_targetmit Pflicht-Keysdb/table/labelField;fk_model/fk_label_fieldentfernt;_BUILTIN_FK_RESOLVERS["UserInDB"];_buildLabelResolversFromModelskip ohnelabelField;attributeUtilssetztdisplayFieldnur bei gesetztemlabelField;validateFkTargets()Startup-Validierung infkRegistry.py+app.py lifespan; Wikifk-label-resolution.md+database-architecture.mdaktualisiert - 2026-04-26 | fix | gateway |
connectorDbPostgre._ensureTableExists: TEXT->DOUBLE PRECISION Spalten-Migration schlug fehl fuer ISO-Datetime-Strings — Regex\\d{{4}}korrigiert zu\\d{4}(doppelte Klammern waren kein f-string-Escaping sondern literal),::timestampauf::timestamptz(Timezone-Offset korrekt parsen), SAVEPOINT pro ALTER (eine fehlgeschlagene Migration killt nicht mehr die gesamte Transaktion) — betraf MandateSubscription (6 Spalten) und BackgroundJob (3 Spalten) - 2026-04-26 | refactor | frontend-nyla | FlowEditor Form-Field-Type-Zentralisierung:
FORM_FIELD_TYPES+FORM_FIELD_TYPE_LABELSinattributeTypeMapper.ts;FormStartNodeConfig,FormNodeConfig,FieldBuilderEditorbeziehen Feldtypen aus zentraler Library statt hardcoded Listen; ClickUp-spezifische Typen (clickup_status,clickup_tasks) und zugehoerige UI (Connection-Picker, Status-Hinweis) entfernt; sharedFormField-Typ aufAttributeType+ generischesoptionsumgestellt;TriggerFormFieldRoweliminiert;clickupFormSync.tsgeloescht (dead code, nirgends importiert) - 2026-04-26 | refactor | gateway+frontend-nyla | Column-Type-Refactoring Schritte 1-10 abgeschlossen: 6 Pydantic View-Modelle (
UserMandateView,FeatureAccessView,BillingTransactionView,MandateSubscriptionView,UiLanguageSetView,DataNeutralizerAttributesView) indatamodelViews.py;createdAt/createdByAliase in Invitation- und Billing-DTOs aufsysCreatedAt/sysCreatedBystandardisiert;_COL_MAP-Remapping ininterfaceDbBillingentfernt; 7 Admin/Billing/Compliance-Seiten beziehen Spaltentypen viaresolveColumnTypes+fetchAttributes('<ViewModelName>')statt hardcodedtype:— tsc + Grep-Completeness-Check bestanden - 2026-04-26 | refactor | frontend-nyla | Schritt 8: Vollstaendigkeits-Grep — verbleibende hardcoded
type:in ComplianceAuditPage entfernt (username/instanceLabel/ipAddress im Modell); alle anderen type:-Werte berechtigt dokumentiert (enriched View-Spalten, synthetische Zaehler, Alias-Keys) - 2026-04-26 | refactor | frontend-nyla | Schritt 7: weitere FormGenerator-Tabellen (AdminUsers, Connections, Files/Prompts, Mandate-Hook, RealEstate*, Trustee*) bauen Spaltentypen nur noch via
resolveColumnTypesstatttype: attr.typeim Column-Map - 2026-04-26 | feat | gateway |
attributeUtils.getModelClasses: Feature-datamodel*.pyuntermodules/features/**rekursiv importieren (Trustee, Teamsbot, GraphicalEditor, …) fuer/api/attributes/{entityType} - 2026-04-26 | refactor | frontend-nyla | Workflow-Seiten (GraphicalEditorWorkflowsPage, AutomationsDashboardPage) beziehen Spaltentypen via
resolveColumnTypes+fetchAttributesvom Backend statt hardcodedtype:im Frontend; neuer Shared-UtilitycolumnTypeResolver.ts - 2026-04-26 | feat | frontend-nyla |
attributesApi.AttributeDefinition.typenutztAttributeTypeausattributeTypeMapper; Mapper um Backend-Typobject(JSON/Dict) ergaenzt - 2026-04-26 | feat | gateway | Pydantic CHECK-Cleanup: fehlendes
frontend_type: "timestamp"bei float-Zeitfeldern (UAM resetTokenExpires, DataSource, Security Token, Chat ChatLog/publishedAt/ActionItem/TaskItem/TaskHandover, Knowledge extractedAt); Redmine*OnTsvonnumberauftimestamp; Redmine DTOs (RedmineSyncResultDto,RedmineSyncStatusDto,RedmineConfigDto);UsageStatistics.periodStartmitfrontend_type: "date"; allefrontend_type: "datetime"auf"timestamp"(Audit, AuthEvent, GraphicalEditor Auto*, Messaging sentAt) — konsistent mitattributeTypeMapper.isDateTimeType - 2026-04-26 | refactor | gateway | Boot-Optimierung: Chatbot-Duplikat-Prewarm entfernt (
routeFeatureChatbot), Stripe-Bootstrap parallelisiert via ThreadPoolExecutor (stripeBootstrap) — erwartete Bootzeit-Reduktion ~8s - 2026-04-26 | fix | gateway |
interfaceRbac: Pagination-Dict-Filter (getRecordsetPaginatedWithRBAC/getDistinctColumnValuesWithRBAC) nutzen_rbacAppendPaginationDictFilter— numerischegt/gte/lt/lte/betweenmit::double precision, ISO-Datum + numerische Spalte als Unix-Bounds wie Connector - 2026-04-26 | feat | frontend-nyla |
FormGeneratorTable: Datum-Filter nutzt PeriodPicker (Presets + Kalender) statt primitiver<input type="date">; PeriodPicker rendert ausserhalbfilterDropdownOptions(Popover nicht durchoverflow-y: autogeclippt) - 2026-04-26 | fix | gateway |
TrusteeDataJournalEntry.bookingDate:Optional[str]->Optional[float](unix timestamp); Konvertierung in_persistJournalvia_isoDateToTimestamp(ValueError bei ungueltigem Datum, kein Fallback);_aggregateLocalMovementsliest float; FK-Label-Resolver formatiert float als ISO; Demo-Daten konvertiert; DB-Migration TEXT->DOUBLE PRECISION in_ensureTableExists - 2026-04-26 | fix | gateway |
datamodelFeatureTrustee:lastSyncAt/chartCachedAt/syncedAtbekommtfrontend_type: "timestamp",lastSyncDateFrom/lastSyncDateTofrontend_type: "date"— damit Frontend Date-Filter statt Text anzeigt - 2026-04-26 | fix | frontend-nyla |
FormGeneratorTable: Filter-Dropdown peruseLayoutEffectalsposition: fixedin den Viewport geklemmt; Audit-Timestamp-Spalten (sysCreatedAtetc.) bei numerischemtypeals Datums-UI + kein distinct-Fetch - 2026-04-26 | feat | frontend-nyla |
FormGeneratorTable: typbezogene Spaltenfilter — Zahlen (integer/int/number/float) mit Operator (=, >, >=, <, <=, Zwischen) undAnwenden; Datum-Filter mit CSS-Panel; keinfilterValues-Fetch mehr fuer bool/date/number-Spalten - 2026-04-26 | fix | gateway |
routeHelpers._matchesBetween: numerischefrom/tonach fehlgeschlagenem Datums-Parse (korrekte BETWEEN-Logik fuer Zahlenspalten);connectorDbPostgre:gt/gte/lt/lteundbetweenauf INTEGER/DOUBLE PRECISION mit::double precisionstatt lexikographischem TEXT-Vergleich
2026-04-25
- 2026-04-25 | feat | * | Phase 4 FK:
frontend_fk_*und FormGenerator-fkSource/Client-Cache entfernt;fk_label_field+displayFieldonly;_resolveRoleLabels;getRecordsetPaginated+getRecordsetPaginatedWithRBAC+ FK-Sort-Pfad mit_enrichRowsWithFkLabels;attributeUtils+ betroffene Datamodels + Pages auf reines Backend-Enrichment - 2026-04-25 | fix | gateway | Trustee Account Balances: echte Schlusssalden aus Buchhaltungssystem importieren (RMA via
/gl/saldo; Bexio via Journal-Aggregation; Abacus via OData-Aggregation); korrigierte kumulative Fallback-Berechnung in_persistBalances; neuesAccountingPeriodBalance-Modell +getAccountBalances-Methode inBaseAccountingConnector; Bug "Banksaldo per Stichtag falsch" (BuHa SoHa Konto 1020) geloest (c-work: c-work/4-done/2026-04-trustee-account-balances-import.md) - 2026-04-25 | test | gateway | Unit-Tests fuer Trustee-Balance-Import: RMA-Connector (BuHa-SoHa-Szenario + ER-Reset), Bexio-Connector (kumulative Aggregation + Carry-Over), Abacus-Connector (OData-Aggregation), AccountingDataSync (Connector-Path + Local-Fallback)
- 2026-04-25 | feat | gateway | FK-Resolution Phase 2 (A1+A2): Neue zentrale
_enrichRowsWithFkLabels()inrouteHelpers.py— bulk-resolved FK-Labels als{field}Label-Spalten pro Row;_resolveMandateLabels/_resolveInstanceLabels/_resolveUserLabelsliefernNonestatt ID bei fehlender Aufloesung;routeWorkflowDashboard,routeAudit,routeBilling(Transactions + Billing-Aggregation),routeSubscriptionauf zentrale Funktion migriert (or mid[:8]/or uid[:8]/or iid-Fallbacks entfernt) - 2026-04-25 | feat | gateway | FK-Resolution Phase 2 (B2):
_enrichedFilterValuesinrouteWorkflowDashboardliefert{value, label}Objekte fuer FK-Spalten (mandateId, featureInstanceId) — Frontend zeigt Labels im Filter-Dropdown ohne separatefkSource-Aufloesung; Leerwerte (null) fuer "(Leer)"-Filter inkludiert - 2026-04-25 | fix | gateway+frontend | FK-Resolution Korrektur:
routeWorkflowDashboardruns/workflows-Enrichment benenntmandateIdLabel→mandateLabelum (Frontend-Interface-Kompatibilitaet);AutomationsDashboardPageSpalten mandateId/featureInstanceId nutzendisplayField: 'mandateLabel'/'instanceLabel' - 2026-04-25 | feat | gateway | FK-Resolution Phase 2 (B1):
getDistinctColumnValues+getDistinctColumnValuesWithRBAC+_extractDistinctValues+_distinctColumnValuesliefernnullals letzten Eintrag wenn NULL/Leer-Zeilen existieren — Frontend kann "(Leer)"-Filter anbieten - 2026-04-25 | feat | frontend-nyla | FK-Resolution Phase 3 (C1+C2):
FormGeneratorTable.ColumnConfig.displayField— neues Pattern: Cell rendertrow[displayField]stattrow[key], CSV nutztdisplayField;fkSource/fkDisplayFieldals@deprecatedmarkiert (Legacy-Pfad funktioniert weiterhin) - 2026-04-25 | feat | frontend-nyla | FK-Resolution Phase 3 (B3):
FilterValuesListakzeptiertstring | null | {value, label}Eintraege;FilterValue-Typ eingefuehrt;_normalizeFilterValuenormalisiert alle 3 Formate; Backend-null-Eintraege werden als "(Leer)"-Option gerendert - 2026-04-25 | fix | gateway | Fallback-Cleanup Phase 1 (D1+D2): Pagination-Parsing in
routeWorkflowDashboard(runs/workflows) undrouteDataMandateswirft 400 bei kaputtem JSON statt silent default;runsByStatus/Run-Enrichment in/metrics+/workflowspropagieren DB-Fehler stattlogger.warning+200;delete_system_workflowCallback-Trigger meldet Listener-Bugs (500 stattexcept: pass);routeBilling._isAdminOfMandate/_isMemberOfMandateundrouteSubscription._assertMandateAdminfail-loud (kein "DB-Down → 403"-Mask mehr); StripeSubscription.retrieveim Checkout-Webhook re-raised statt silent skip - 2026-04-25 | fix | gateway | Fallback-Cleanup Phase 1 (D2):
routeInvitationsRollen-Zuweisung —addRoleToFeatureAccess/addRoleToUserMandatesind bereits idempotent, dahertry/except: pass # Role might already be assignedentfernt → echte FK-/DB-Fehler beim Einladungs-Akzept werden jetzt sichtbar - 2026-04-25 | fix | frontend-nyla | Fallback-Cleanup Phase 1 (D3+D4):
AutomationsDashboardPage._handleExecutezeigt "Workflow gestartet" nur noch, wenn die 1s-Beobachtungs-Phase weder Erfolg noch Fehler beobachtet hat (kein Doppel-Toast "gestartet" + "fehlgeschlagen" mehr);_loadMetricstoast-t Backend-Fehler statt nurconsole.error;Automation2FlowEditor.handleWorkflowRenamezeigt Fehler-Toast statt unsichtbaremconsole.error - 2026-04-25 | feat | frontend-nyla |
FormGeneratorTable: Leerwert-Filter(Leer)in allen Filter-Dropdowns — filtert aufIS NULL OR = ''(Backend unterstützt bereitsnullin Pagination-Filtern); Filter-Icon/Clear-Button erkennennull-Filter korrekt viakey in filters - 2026-04-25 | fix | frontend-nyla | NodeConfigPanel/RequiredAttributePicker/FeatureInstancePicker: Texte (Type-Badges, Bound-Refs, Vorschlag-Labels, Beschreibungen) verlassen den 280px-Panel-Frame nicht mehr — Header-Layout
label flex:1 1 100 %lässt Badge umbrechen;box-sizing: border-box,overflow-x: hidden,overflow-wrap: anywhereals Safety-Net auf.nodeConfigPanel; Bound-Chip/Vorschlag-Button mitwhitespace: normal+word-break - 2026-04-25 | fix | frontend-nyla | KeepAlive-Wrapper (
GraphicalEditor,Workspace,Commcoach): Persistenz strikt pro(mandateId, instanceId)—key={mandate:instance}an die gehaltene Page; Wechsel der Mandanten-/Instanz-Tupel unmountet den alten Editor (kein Cross-Tenant-Save mehr, "not found"-Bug behoben); Unit-TestGraphicalEditorKeepAlive.test.tsx - 2026-04-25 | fix | frontend-nyla |
DataPicker: percreatePortalnachdocument.body(entkoppelt von.nodeConfigPanel button-Primary-Override); neues List-Row-Layout/Theme (dataPickerNodeHeaderneutral), Header-Badge/Filter/Close-Styles, höheres z-index - 2026-04-25 | fix | frontend-nyla | Flow-Editor
CanvasHeader: Zwei-Spalten-Layout (Kontext: fester Workflow-Dropdown + Titel mit Ellipsis | Aktionspanel); Run-Buttonmin-width; Version-Zeile getrennt;retryButton-Margin im Toolbar-Panel neutralisiert - 2026-04-25 | fix | gateway | Trustee-Template
trustee-receipt-import:documentListals DataRefextract→process→sync(Pick-not-Push), nicht leere Listen; Unit-Testtest_trustee_template_workflows.py - 2026-04-25 | feat | gateway | Trustee + Redmine Nodes auf typisierten
FeatureInstanceRef[<code>]-Param +frontendType: featureInstancemigriert (c-work: c-work/4-done/2026-04-feature-instance-ref-adapter-migration.md) - 2026-04-25 | feat | gateway | Neuer Endpoint
GET /api/workflows/{instanceId}/options/feature.instance?featureCode=…fuer Mandanten-gefilterte FeatureInstance-Auswahl (c-work: c-work/4-done/2026-04-feature-instance-ref-adapter-migration.md) - 2026-04-25 | feat | frontend-nyla |
FeatureInstancePicker(0/1/N) als Renderer fuerfrontendType: featureInstance; Sysadmin-Toggle "Schema-Details" im CanvasHeader (c-work: c-work/4-done/2026-04-feature-instance-ref-adapter-migration.md) - 2026-04-25 | fix | frontend-nyla | NodeConfigPanel-Banner zeigt
param.namestatt der ausschweifenden Description (Tooltip enthaelt vollen Text); hidden-Pflicht-Params werden zentral infindRequiredErrorsgefiltert (kein Phantom-Pflichtfeld mehr) (c-work: c-work/4-done/2026-04-feature-instance-ref-adapter-migration.md) - 2026-04-25 | fix | frontend-nyla | DataPicker-Modal auf CSS-Variablen umgestellt; Hover-Safety-Net
dataPickerLeaf:hover *haelt Type-Hints auf blauem Hintergrund lesbar (c-work: c-work/4-done/2026-04-feature-instance-ref-adapter-migration.md) - 2026-04-25 | docs | wiki | Audit
2026-04-node-typization-audit.mdarchiviert; Folge-Track-Doc2026-04-feature-instance-ref-adapter-migration.mddirekt in4-done/als erledigt - 2026-04-25 | docs | wiki | Changelog-Konvention im
_CHANGELOG.mdeingefuehrt; inREADME.md+doc-sync.mdcreferenziert