wiki/c-work/_CHANGELOG.md
2026-06-08 23:40:35 +02:00

199 KiB
Raw Blame History

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 auf getService() + ServiceCenterContext migriert. _WorkflowAutomationServiceHub eliminiert, _ServicesAdapter zu ServicesBag umbenannt — es gibt jetzt genau EINEN Service-Bag im gesamten System. Cursor Rule service-architecture.mdc erstellt zur Durchsetzung. Wiki architecture.md aktualisiert.
  • 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.* auf chatService.* migriert. ServicesBag.interfaceDbComponent Property entfernt. 3x toter saveGeneratedFile-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 durch services.* ersetzt. canAccessService() auf ServicesBag hinzugefuegt. Bidirektionaler Import serviceCenter <-> workflows aufgeloest via self.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 verbleibende automation2-Referenzen.
  • 2026-06-08 | refactor | ui-nyla | workflowApi.ts Shim aufgeloest: 23 Consumer auf workflowAutomationApi migriert. ClickUp-Funktionen nach clickupApi.ts extrahiert. Shim geloescht. FlowEditor index.ts Re-Export-Shim geloescht. connectionPath.test.ts (stale) geloescht. tsc-errors.txt/i18n_missing_report.md geloescht + .gitignore.
  • 2026-06-08 | refactor | ui-nyla | Keep-Alive Fix: matchLocation mit location.search Parameter eingefuehrt. Workflow-Automation Keep-Alive matched jetzt nur bei tab=editor statt 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). systemComponentRegistry fuer Lifecycle-Hooks (Phase 3). workflowArtifactVisibility + entryPoints nach 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 auf workflowAutomation/engine/ und nodeCatalog/ aktualisiert.

2026-06-07

  • 2026-06-07 | feat | platform-core, ui-nyla | Phasen 14 ausgeführt (WorkflowAutomation-Plan): Phase 1: AutoWorkflow.runAsPrincipal (Optional), Nav-Block workflowAutomation (5 Items), mandatsweite API routeWorkflowAutomation.py (10 Endpunkte, _validateWorkflowAccess RBAC-Helper), Scheduler if-not-instanceId-Guard entfernt, _validateFeatureInstanceMandates() Guard in executionEngine.py. Phase 2: WorkflowAutomationPage.tsx Hub-Seite mit Tabs (Workflows/Läufe/Tasks), Route in App.tsx, Icons in pageRegistry.tsx, MandateNavigation.tsx rendert neue Nav-Sektionen als eigene Gruppen. Phase 3: featureInstanceIdOptional[str] (softFk). Phase 4: Route-Imports auf kanonische datamodels.datamodelWorkflowAutomation umgestellt (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) in datamodelWorkflowAutomation.py. Nav-Block workflowAutomation (order 25, 5 Items) in datamodelNavigation.py. Neue mandatsweite API routeWorkflowAutomation.py mit 10 Endpunkten unter /api/workflow-automation/ + Write-RBAC-Helper _validateWorkflowAccess (member=read, admin=write, isPlatformAdmin bypass). Scheduler if-not-instanceId-Guard in mainScheduler.py entfernt. Runtime-Mandatsvalidierung _validateFeatureInstanceMandates() in executionEngine.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/PauseForEmailWaitErrordatamodels/serviceExceptions.py, coerceDocumentDataToBytesshared/documentUtils.py, Re-Export-Shims in automation2/executors/, Cross-Boundary-Caller umgebogen. Scheduler-Boot von mainGraphicalEditor.onStart in System-Lifespan (app.py, nach eventManager.start()) verschoben; onStart/onStop aus mainGraphicalEditor.py entfernt; Scheduler- und Email-Poller-Stop in app.py Shutdown (Schritt 3.5). Guard-Test bestätigt: methods/ lädt kein automation2 mehr 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 L0L7; viele Plan-Vorarbeiten bereits erledigt: Contracts/Models nach datamodels (L1, datamodelPortTypes/datamodelWorkflowAutomation, statt geplantem workflowContracts/), Feature-Lifecycle-Hooks (mainGraphicalEditor.onInstanceCreate/onMandateDelete/onBootstrap, ex interfaceFeatures/interfaceDbApp/interfaceBootstrap), NAVIGATION_SECTIONSdatamodels/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/coerceDocumentDataToBytes noch in automation2/executors, von methods/ importiert → Delaminierung (→ datamodels/serviceExceptions.py bzw. 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 «automation2 wird von Chats nicht importiert» als falsch korrigiert (shared methods importieren automation2.executors) → neue Phase 0.5 Delaminierung (PauseForHumanTaskError/_coerce_document_data_to_bytes + portTypes/STATIC_NODE_TYPES → neues geteiltes workflows/workflowContracts/). Weitere Review-Fixes: featureInstanceId ist bereits DB-nullable (kein DDL, keine DB-FK), Scheduler ist hart auf featureInstanceId gekeyt (Entkopplung als eigener Schritt), Dashboard-RBAC deckt nur Lesen → eigener Write-Helper _validateWorkflowAccess für 39 Sites, RBAC-Namespace Option B (kein Flip), Template-Instanziierungs-Trigger (_copyTemplateWorkflows) wandert in launcher/, 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 (graphicalEditor raus aus dem Feature-Modell): Neuer Umsetzungsplan in c-work/1-plan/. Komponente heisst WorkflowAutomation (greppbares Token; graphicalEditor = ein Modul darin), modulares Layout (toolbox/editor/engine/scheduler/solutions/launcher/monitoring) gemappt auf L1L4. Code-fundiert (Discovery/Registry, FeatureInstance-Lifecycle, DB poweron_graphicaleditor, Scheduler-Boot via Feature-onStart, RBAC-Präzedenz routeWorkflowDashboard/routeAutomationWorkspace, ~70 Backend-Touchpoints + UI-Navigation). Phasen 04: Scheduler-Boot in System-Lifespan → mandatsweite API /api/workflow-automation/… + System-RBAC → Top-Level-Nav-Gruppe «Workflow-Automation» mit Tab-Seiten → DB (runAsPrincipal, featureInstanceId als 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 globalem event-Sysadmin laufen. A0.2 neu: Multi-Feature/Multi-Instanz ist nativ (per-Node FeatureInstanceRef), echte Schranke = Mandant; 3 Code-Lücken benannt (Runtime-Mandatscheck beim Ref-Auflösen, Read-RBAC analog Write, per-Node-Billing statt fix graphicalEditor). A0.4 neu: graphicalEditor als Orchestrierungs-Substrat eingeordnet (kein DATA, eigene DB für alle Features, globaler Scheduler-Boot via onStart) — 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 mit hostFeatureRef als alleinigem Owner für RBAC/Billing (Cross-Feature-Drift gelöst); A0.2 Multi-Instanz-Fan-out nur mandatsintern über explizites instanceSet, 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 gegen nodeDefinitions/ verifiziert (neuer email.sendEmail-Versand-Node + data.writeToTable als Blocker erkannt; data.consolidate vorhanden), 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, _handleDataSourceDrop wartet darauf bevor pendingAttachDsId gesetzt 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.py prueft jetzt totalTokens (prompt+context) statt nur promptTokens gegen 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.py simpleMode nutzt jetzt _resolve_file_refs_to_content_parts / _action_docs_to_content_parts statt 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: _normalizeImageElement in subStructureFilling.py stellt sicher, dass AI-generierte Image-Elemente immer das content-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: _renderSlideContentWithFrames in rendererPptx.py umgebaut auf sequenzielles Y-Tracking. Textboxen werden mit geschaetzter Hoehe statt full-height erstellt, Tabellen und Code-Blocks erhalten explizite top-Positionen. Behebt Bug wo Tabellen unterhalb des sichtbaren Slide-Bereichs erschienen.
  • 2026-06-03 | feat | platform-core | HTTP Resilience Mixin fuer Connectors: Neues _httpResilience.py mit ResilientHttp-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.py erweitert um readFileBytes(fileId) Builtin (rohe Bytes, 50MB-Limit) und SafeZipFile Wrapper (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() und documentTheme-Parameter end-to-end entfernt (styleDefaults, mainServiceGeneration, _mediaTools, methodAi, generateDocument, documentPath, mainServiceAi, mainTrustee). Statische Presets ersetzt durch AI-getriebene Style-Enhancement (_enhanceStyleWithAi in 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). _convertUnifiedStyleToInternal erweitert 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.tableStyle im 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 via columnAlignments. Neue Schema-Sektionen coverPage und caption in 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, _getDefaultStyleSet und zugehoerige Legacy-AI-Styling-Logik aus rendererHtml.py entfernt. Nur noch der Unified-Style-Pfad ueber _convertUnifiedStyleToInternal + _generateCssFromUnifiedStyle ist aktiv.
  • 2026-06-03 | docs | wiki | Kanonische Referenzseite Dokumenten-Rendering: Neue b-reference/platform-core/document-rendering.md dokumentiert 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.scope bleibt 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: aicorePluginPrivateLlm rechnete 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 _calcPrivatePriceCHF mit PRICE_INPUT_PER_1K=0.0075 / PRICE_OUTPUT_PER_1K=0.0375; costPer1kTokens der 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 fileId tragen; renderReport(imageResolver=fileId->bytes) setzt einen Per-Render-Resolver am Renderer (BaseRenderer._lazyResolveImageBase64), den PDF/DOCX _renderJsonImage on-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.py bekommt THEME_PRESETS (general/finance/legal/technical/hr/marketing) + resolveTheme; resolveStyle(style, documentTheme) mergt DEFAULT_STYLE <- Preset <- explizites style (explizit gewinnt). documentTheme ist jetzt durchverkabelt: ai.generateDocument Action -> callAiContent -> _handleDocumentGeneration -> documentPath.generateDocument -> renderResult -> renderReport(documentTheme=...); ausserdem im renderDocument-Tool (neues documentTheme-Schema-Property) und in methodAi.py (Param an ai.generateDocument, Optionen um marketing ergaenzt). 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): FeatureDataProvider neutralisiert Quelldaten jetzt regelbasiert via finalizeRowsAsync/_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 _featureSubAgentTools via resolveEffectiveForFds; 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 revealDocument loest Platzhalter [typ.uuid] ausschliesslich ueber das private lokale Mapping (resolveText, kein externes LLM) auf und liefert den Klartext als transienten Einmal-Download via SSE-SideEvent revealDownload; 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-nylaui-nyla, gatewayplatform-core, private-llmservice-llm-private). b-reference-Ordner umbenannt (gateway/ui-nyla/service-llm-private), README+product Komponenten-Tabellen aktualisiert, service-preprocessing ergaenzt, 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.py um 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). _supportsCustomTemperature erkennt 4.8 als Extended-Thinking-Modell (sendet kein temperature).
  • 2026-05-29 | feat | platform-core | Private-LLM Next-Gen Modelle vorbereitet: aicorePluginPrivateLlm.py um 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.py Next-Gen MODEL_MAPPING als kommentierter Block, _isVisionModel um 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_FeatureSource und onAttachDataSource an 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: _loadRagEnabledDataSources propagiert settings.ragLimits vom Connection-Root auf Kinder ohne eigene Werte. _finalizeResult in 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 mit ijson fuer speicher-effizientes Parsen: Pass 1 validiert + extrahiert Metadaten, Pass 2 splittet in per-Table JSONL-Dateien. Neuer GET /process-import-stream Endpoint mit StreamingResponse (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). Neuer GET /export-stream Endpoint streamt die gesamte Export-JSON inkrementell via StreamingResponse. Frontend nutzt fetch() + 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. canEdit prueft Connection-Ownership via UserConnection.userId; setFlag erstellt 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.cascadeResetDescendantsFds ist wieder rein generisch (keine neutralizeFields-Logik); _FdsFamilyNode.setFlag bietet generischen _onSetFlag-Hook; FdsTableNode._onSetFlag wipe-t eigene neutralizeFields bei explizitem neutralize-Toggle; FdsWorkspaceNode._onSetFlag wipe-t neutralizeFields auf allen Descendant-Tables. FdsFieldNode.getEffectiveFlag erbt korrekt vom Table (Zwei-Quellen-Modell). 122/122 Tests gruen. Wiki unified-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 Router routeUdb.py mit POST /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 (kein userId, kein workspaceInstanceId, kein scope mehr — feature-owned, RBAC-gated via roleLabel.endswith('-admin')). Neue kanonische Doku b-reference/platform/unified-data-bar.md; Updates auf neutralization.md, rbac.md, TOPICS.md. Tests: neu test_udbNodes.py, angepasst test_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 in AdminDatabaseHealthPage.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_STYLE sowie 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 und hideRowActionButtons/dragDropEnabled-Refactor beibehalten. Auch verlorenes Auto-Expand-useEffect für defaultExpanded Nodes wiederhergestellt (Test grün: 53/53).
  • 2026-05-22 | refactor | gateway+frontend-nyla | RAG Cost-Estimate Währung USD→CHF_costEstimate.estimateBootstrapCost() liefert nun estimatedChf (statt estimatedUsd); Konstante EMBEDDING_CHF_PER_MTOKEN (Wert 0.02, Projekt-Konvention: Anbieter-Listenpreise werden direkt als CHF behandelt, identisch zu calculatepriceCHF in aicorePluginOpenai.py). Mit-aktualisiert: routeDataSources.py Docstring, test_costEstimate.py (6/6 grün), FE CostEstimate-Type, DataSourceSettingsModal Anzeige. Wiki: b-reference/gateway/ai-agent.md Endpoint-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 mandateId als Query-Parameter statt X-Mandate-Id-Header → context.mandateId=None → 403. Fix: Header wird gesetzt. (2) Backend routeRagInventory._getInventoryMandate filterte UserConnection mit recordFilter={"mandateId": ...}, aber UserConnection hat kein mandateId-Feld → SQL-Error. Fix: Mandate-Members via UserMandate-Junction holen, dann deren getUserConnections(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) and POST /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 _enrichFoldersWithMixed and _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 auf NULL und dann den Master, deshalb kann aggregate nach einem User-Toggle nicht 'mixed' bleiben. (H2/H8) Initial-Render-Bug: sequentieller for ... await im Auto-Expand-Effekt loeste Cancellation-Race aus -- erstes setNodes triggerte cleanup, weitere defaultExpanded-Knoten blieben "expanded ohne Children". Fix: Promise.all(...) parallel + atomares Single-setNodes. Zusaetzlich autoExpandedRef.current.clear() in _loadRoot (StrictMode-Doppelmount + manuelle Refresh tauglich). (H3) PUT /api/files/{id} 404: Route hatte keinen RequestContext, interfaceDbManagement.getInterface(currentUser) ohne mandate/featureInstance scope -> RBAC-Filter excludiert File. Fix: Context-Dep + scope-pass-through bei update_file und delete_file; move_folder akzeptiert sowohl parentId als auch targetParentId aus dem Body. (H4) Neuer Folder erschien initial auf Legacy-Top-Level: FolderFileProvider.createChild(parentId=null, ...) setzt jetzt parentId = _SYNTH_ROOT_ID('own') damit der neue Folder unter / rendert. (H5) +-Button pro Folder im FormGeneratorTree: neue onCreateChild?: (parentId: string) => void-Prop in TreeNodeRow + verdrahtetem _createFolderAt(parentId) Handler in der Hauptkomponente; sichtbar im Hover-Action-Slot fuer alle Folders mit provider.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 hatte oe-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-datasources 403te Cross-Mandate-Erstellung (Workspace mandate A, Feature mandate B beides user-zugaenglich), _ensureRecord schluckte den Fehler still. Fix: Cross-Mandate-Block entfernt, statt dessen getFeatureAccess(userId, body.featureInstanceId)-Validierung; mandateId der neuen FDS = wsMandateId (= Workspace-Tenancy, konsistent mit Tree-Filter). (H10 = G5) Persistenter Expand-State umgesetzt: WorkspaceUserSettings.uiTreeExpansion: Dict[str, List[str]] Backend-Field; neue Routen GET/PUT /api/workspace/{instanceId}/ui-tree-expansion/{scope}; FE-Hook useTreeExpansion(instanceId, scope) mit 600 ms Debounce-PUT; FormGeneratorTree Props expandedIds?: string[] | null + onExpandedIdsChange?: (ids) => void (controlled mode); SourcesTab (scope 'sources'), FilesTab (scopes 'filesOwn' + 'filesShared') verdrahtet. Bei null (kein Record) Default-Verhalten + erster Toggle erstellt den Settings-Record; bei Array gewinnt persistierte Liste ueber Backend-defaultExpanded-Hints. Tests: Backend services+routes 107/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.json referenziert jetzt auch tsconfig.test.json; Testfile bekam expliziten import React, afterEach, @testing-library/jest-dom/vitest. 139 -> 0 Lints; Tests 50/50 weiterhin gruen. (G2) Off-State der neutralize/ragIndexEnabled-Buttons: filter: grayscale(1); opacity: .45 im OFF-Zustand -- offenes Schloss + greyed-Brain klar als "deaktiviert" lesbar. (G3a) Bug _browseChildren: Childs erbten parentKey=ds|...|/ statt des aufgerufenen svc|...; Children erschienen daher nie im FE-Tree. Fix: parentKey als optionaler Parameter durchgereicht; Dispatcher uebergibt den asked-for-Key. (G3b) Per-Field-Neutralize fuer Feature-Tabellen: fdsTable.hasChildren=True bei vorhandener meta.fields-Liste; neuer Knoten-Typ fdsField (Dispatcher fdstbl|fi|table -> _featureTableFields). Effektiver Field-Neutralize = parent.neutralize OR field IN parent.neutralizeFields. Toggle: UdbSourcesProvider.patchNeutralize splittet die Batch nach Kind und ruft fuer fdsField PATCH /api/datasources/{id}/neutralize-fields mit der mutierten Liste; neutralizeFields ist im Tree-Payload mitgesendet -- kein Extra-GET. Scope/RAG auf Feldebene bewusst nicht editierbar. +3 neue Backend-Tests in TestFeatureTableFields. (G4) FilesTab synthetischer "/"-Root pro Ownership: Provider mappt parentId=null auf [__filesRoot:<own|shared>] (defaultExpanded=true); reale Top-Level-Items werden Children. moveNodes mit Synth-Root-Ziel re-mapt auf parentId/folderId=null (= Drop auf "/"); patchScope/patchNeutralize mit Synth-Root-Id materialisieren ueber API alle Top-Level-Folders+Files und setzen pro Folder cascadeChildren=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 fuer neutralize und ragIndexEnabled wieder 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 in cascadeResetDescendants(rec, flag)); rein UI-Issue. (b) Top-Level-Layout flach: synthetische Wrapper srcRoot + mandateRoot entfernt. _topLevel emittiert direkt [personalRoot, mgrp|m1, mgrp|m2, ...]. Mandate-Groups haben nun parentKey=None. (c) TreeNode.defaultExpanded?: boolean als generisches Tree-Feature (one-shot pro Node-Id ueber autoExpandedRef); BE markiert personalRoot und alle Mandate-Groups mit defaultExpanded=True -- UI oeffnet bis zur Datenquellen-Ebene ohne User-Klick. (d) Icon-Reihenfolge in FormGeneratorTree (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 ohne dataSourceId; Klick triggert lazy _ensureRecord -> onOpenSettings. (f) SourcesTab setzt title={t('Datenquellen')} als Section-Header. Tests: Backend test_buildTree.py 16/16 + test_inheritFlags.py 72/72 -> 88/88 gruen. Frontend FormGeneratorTree.test.tsx 50/50 (+defaultExpanded-Tests) + UdbSourcesProvider.test.ts 16/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 in SourcesTab.tsx an einem State-Race (StrictMode-Doppelmount × mountedRef-Frueh-Abort × paralleler expansionSignature-useEffect, vier sichtbare POSTs) erstickte. Diagnose via temporaerem _buildTree.getChildrenForParents-INFO-Log: Backend liefert sauber counts={'__root__': 6} -- Bug war ausschliesslich auf der ad-hoc-Renderer-Seite. Backend (_buildTree.py): synthetische Container srcRoot (Top-Level), personalRoot, mandateRoot mit neuem _syntheticNode Helper und displayOrder-Sort-Hint; _topLevel schrumpft auf [srcRoot], _srcRootChildren emittiert [personalRoot, mandateRoot], _personalRootChildren und _mandateRootChildren enthalten die alte Connections-/Mandate-Logik mit korrigierten parentKey. Dispatcher in getChildrenForParents matcht parentKey == _KEY_*_ROOT vor dem Decode-Pfad. +7 neue TestSyntheticRoots Tests, 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 setzt displayOrder vor folder-first. Dritter Flag-Button (_RAG_EMOJI, _ACTION_RAG) rendert nur wenn ragIndexEnabled !== undefined. _runAction ruft _refetchAllExpanded automatisch auf wenn refreshAfterAction=true; optimistic-Update-Pfad fuer FilesTab unveraendert. +10 neue Tests, Tree-Suite 51/51 gruen. Frontend SourcesTab: ad-hoc-Renderer mit _TreeNodeView, _FlagButton, eigenem pendingToggles-State, eigenem _fetchVisible-Pfad komplett geloescht. Neuer UdbSourcesProvider.tsx mappt Backend-UdbBackendNode auf generischen TreeNode<T> (Synthese-Container ohne Flag-Felder); haelt internen nodeCache: Map<key, UdbBackendNode> fuer Patch-Pfade; _ensureRecord POSTet /datasources oder /feature-datasources je nach kind; danach PATCH /api/datasources/{id}/{scope|neutralize|rag-index}. Neue SourcesTab.tsx ist 75 LOC duenner Wrapper: useMemo Provider + <FormGeneratorTree compact selectable={false} allowCreateFolder={false} refreshAfterAction /> + Settings-Modal-Anbindung ueber extraActions. +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 — behebt ingestion.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 Endpoint POST /api/workspace/{instanceId}/tree/children mit Body {parents: [null, ...expandedKeys]} liefert nodesByParent als flachen Map mit allen drei effective*-Werten (neutralize, scope, ragIndexEnabled als boolean|'mixed' bzw. string|'mixed') pre-computed auf der mode='aggregate'-Ebene. Neuer Orchestrator serviceKnowledge/_buildTree.py mit 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 -> sharepointFolder etc.) ist nun Backend-autoritativ. FE-Refactor: SourcesTab.tsx von ~2500 auf ~530 Zeilen reduziert. State nur noch childrenByParent: Map, expandedKeys: Set, pendingToggles: Set. Toggle-Flow strikt PATCH -> Refetch -> Render mit Spinner ueber dem Flag-Button bis API-Response zurueck ist. Generischer _TreeNodeView rekursiv fuer ALLE Kinds, generischer _FlagButton mit einheitlichem Mixed-Symbol (U+25E9, "square with diagonal lines") fuer alle drei Flags. RAG fuer FDS: _INHERITABLE_FDS_FLAGS enthaelt nun ragIndexEnabled; FeatureDataSource.ragIndexEnabled: Optional[bool] Field (Auto-Migration via ALTER TABLE ADD COLUMN); PATCH /api/datasources/{id}/rag-index akzeptiert via _findSourceRecord sowohl DS als auch FDS (Bootstrap-Job + Chunk-Purge bleiben DS-only); GET /feature-datasources liefert effectiveRagIndexEnabled; resolveEffectiveForFds um 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}, totes SourcesTab.module.css. Bewusste Reduzierung (User-Entscheidung): FDS-Records sind nicht mehr expandierbar (hasChildren: false fuer fdsTable); Tabellen-Ebene reicht. FeatureDataSource.recordFilter bleibt fuer API-Kompat erhalten. Tests: neu test_buildTree.py (10 gruen — Key-Coding, Effective-Triplets, Record-Lookup, Orchestrator-Smoke), +5 neue in test_inheritFlags.py::TestResolveEffectiveForFds (RAG inherits, RAG aggregate-mixed, _INHERITABLE_FDS_FLAGS enthaelt RAG) +1 in TestCascadeResetFdsRag. Resultat: 82/82 gruen; Frontend npx tsc --noEmit clean.
  • 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: getEffectiveFlag und getEffectiveFlagFds mit mode='walk'|'aggregate' — walk gibt immer konkret, aggregate gibt 'mixed' wenn Subtree divergiert. (2) cascadeResetDescendants/Fds jetzt bottom-up (deepest-first) für Crash-Sicherheit, Rückgabe List[str] statt int. (3) GET /datasources und /feature-datasources liefern computed effectiveNeutralize, effectiveScope, effectiveRagIndexEnabled pro Item. (4) PATCH-Response enthält resetDescendantIds + updatedAncestors fü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 auf getEffectiveFlag(mode='walk') umgestellt. (6) Frontend: Workarounds entfernt (_effectiveFlag, _findAncestorDs, _AUTHORITY_SOURCE_TYPES, prop-drilling inheritedScope/Neutralize), zentrale _readDsFlags/_readFdsFlags aus Backend-Werten, Toggle-Handler mit optimistic cascade via resetDescendantIds. (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) und ingestion.skipped.duplicate von INFO auf DEBUG, damit Daily-Resync / wiederholtes Durchlaufen nicht das App-Log flutet; Stuck-Triage via DEBUG auf modules.serviceCenter.services.serviceKnowledge.subWalkerHelpers bzw. 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 _findDs ignoriert (if (node.type === 'connection') return undefined) — Workaround aus dem Vortag, der eine andere Race-Condition verhindern sollte. Folge: ds === undefined für Connection-Nodes → _addAsDataSource-POST → Backend Upsert findet bestehenden DS via connectionId+path-Match und returnt dieselbe ID → PATCH erfolgreich → UI rendert aber weiter mit ds=undefined → opacity bleibt 0.35. Fix 1: _findDs matcht jetzt deterministisch via sourceType: für Connection-Nodes node.authority ('msft'/'google'/…), für Service-Nodes _SERVICE_TO_SOURCE_TYPE[node.service] ('sharepointFolder'/…). Zwei DS mit connectionId+path='/' aber unterschiedlichem sourceType (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. Backend getEffectiveFlag und cascadeResetDescendants filterten aber strikt auf sourceType==parentSourceType, also keine Vererbung über die Authority-Grenze hinweg. Fix 2: Neue Konstante _AUTHORITY_SOURCE_TYPES = {'local','google','msft','clickup','infomaniak'} in _inheritFlags.py und Mirror im Frontend. _findAncestorChain ergänzt um den ConnectionRoot als "äusseren" Ancestor (after all same-sourceType ancestors). cascadeResetDescendants cascadiert bei parentIsConnectionRoot=True über die GANZE Connection (cross-sourceType). Frontend _findAncestorDs analog. 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). Frontend npm run build + tsc --noEmit grü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 mit NULL = inherit, expliziter True/False (oder 'personal'/'mandate'/'platform'/'global' für scope). Backend: (1) Datenmodell DataSource.{neutralize,ragIndexEnabled,scope} und FeatureDataSource.{neutralize,scope} auf Optional[...] umgestellt; Migration script_db_migrate_datasource_inherit.py macht Spalten nullable (idempotent, additiv — bestehende Werte bleiben explizit, NEW records starten mit NULL). (2) Neuer zentraler Helper serviceKnowledge/_inheritFlags.py mit getEffectiveFlag(rec, flag, allDs) (path-traversal aufwärts, longest-prefix wins, defensiv connectionId UND sourceType als 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; /foo NICHT von /foobar/-Separator-Pflicht). (3) PATCH-Endpoints routeDataSources.{_updateDataSourceScope,_updateDataSourceNeutralize,_updateDataSourceRagIndex} akzeptieren Optional[bool|str] als Body-Wert: null → reset auf inherit (kein Cascade); true/false → explizit + Cascade-Reset aller Descendants. RAG-Endpoint zusätzlich: nur bei True Mini-Bootstrap-Job + _ensureConnectionKnowledgeFlag; nur bei False synchrone Chunk-Purge — null no-op. Audit-Log rag_index_toggled trägt cascadedDescendants Count. (4) Walker-Integration: _loadRagEnabledDataSources filtert auf effective ragIndexEnabled (via getEffectiveFlag) und schreibt resolved Werte für neutralize/scope direkt in das returned dict — Walker (Sharepoint/Outlook/Gdrive/Gmail/Clickup/Kdrive) bleiben unverändert und lesen weiter ds.get("neutralize", False). Alter subPolicyResolver.py zu Backward-Compat-Shim auf getEffectiveFlag deprecated. Frontend: UdbDataSource Interface mit boolean|null und string|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/_cyclePersonalScope entfernt. Tests: neuer test_inheritFlags.py mit 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. Bestehende test_knowledge_ingest_consumer.py 8/8 grün. Frontend npm run build grün, TypeScript clean. Pre-existing Test-Failures (nicht durch diesen PR): test_p1d_consent_prefs.py (5) — Python-3.13 asyncio-Deprecation + Schema-Drift ConnectionIngestionPrefs.neutralizeBeforeEmbed; test_bootstrap_sharepoint.py + test_bootstrap_gmail.py (5) — rufen bootstrapSharepoint/Gmail ohne dataSources= 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-Prop showRagSection. 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 in BackgroundJob.progressMessage schrieben und das Frontend es 1:1 rendert. Root-Cause: BackgroundWorker hat keinen Request-Sprach-Kontext (_CURRENT_LANGUAGE ist ContextVar pro Request), und progressMessage wird persistiert — wäre selbst dann gefroren, wenn der User später die Sprache wechselt. Architektur (regelkonform zu wiki/b-reference/gateway/architecture.md#i18n): Backend speichert strukturiert + übersetzt server-side beim Route-Read; Frontend rendert 1:1 — kein t() auf Backend-Werten. (1) Neue JSONB-Spalte BackgroundJob.progressMessageData = {key, params} (Migration script_db_migrate_backgroundjob_progress_data.py, additiv + idempotent). (2) JobProgressCallback.__call__ akzeptiert messageKey="LITERAL" + messageParams={…} und schreibt beides als JSON; zusätzlich rendert es einen DE-Fallback in progressMessage fü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-literale t("…") Calls: neues serviceKnowledge/_progressMessages.py (Side-Effect-Import in app.py lifespan, 5 RAG-Keys), Trustee 14 Keys in mainTrustee.py — KEINE Variable-Aufrufe von t() (Wiki-Regel #1: t(variable) ist verboten). (5) Neuer Helper i18nRegistry.resolveJobMessage(messageData) analog zu resolveText(value) — der einzige zulässige t(variable)-Pfad, weil er in der i18n-Infrastruktur lebt; nutzt _CURRENT_LANGUAGE aus dem Request-Kontext und substituiert Params via .format(**params). (6) routeJobs._serialiseJob und routeRagInventory rufen resolveJobMessage beim Read und schreiben das Ergebnis in progressMessage — Frontend bekommt einen fertigen, übersetzten String. (7) Frontend zurückgebaut: utils/jobProgressUtils.ts Helper gelöscht, DTOs (useBackgroundJob, connectionApi, trusteeApi) ohne progressMessageData-Feld, Render-Stellen (RagInventoryPage, RagRunningBadge, TrusteeAccountingSettingsView) lesen direkt job.progressMessage. Tests: 22/26 grün; die 4 Failures in test_knowledge_ingest_consumer.py sind pre-existing (verifiziert via git stash Diff). Frontend npm run build grü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" in b-reference/gateway/architecture.md mit 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 MB etc.) waren hartkodiert — User mit 500-MB-Folder konnte nur Code-Änderung machen; (2) FeatureDataSource hatte gar keinen Settings-Ort. Backend: JSONB-Spalte settings auf DataSource + FeatureDataSource (Migration script_db_migrate_datasource_settings.py, additiv + idempotent). Neues Modul serviceKnowledge/_ragLimits.py mit FILES_LIMITS_DEFAULT / CLICKUP_LIMITS_DEFAULT als zentrale Source-of-Truth — die alten MAX_*_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-supplied limits=-Parameter, damit Test-/Caller-Overrides weiter gewinnen (test_bootstrap_maxTasks_caps_ingestion=3 bleibt 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 in routeDataSources.py: PATCH /api/datasources/{id}/settings (akzeptiert nur Top-Level-Key ragLimits, unknown → 400, positive Ints only, Owner-only/Mandate-Admin, Audit-Log datasource_settings_changed) und GET /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ändiges basis-Objekt mit Annahmen/Formel/Notes). Frontend: Neues ⚙️-Icon pro Node im UnifiedDataBar/SourcesTab.tsx (vor dem 🧠) öffnet den neuen DataSourceSettingsModal.tsx mit drei klar abgegrenzten Sektionen: (1) ConnectionknowledgeIngestionEnabled-Toggle via patchKnowledgeConsent (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 der RagInventoryPage.tsx vom amber Partial-Banner (stoppedAtLimit) via neuen "Limit anpassen"-Button geöffnet → User hat direkten Pfad vom Symptom zur Behebung. Workspace-Route GET /api/workspace/{instanceId}/connections liefert jetzt knowledgeIngestionEnabled mit, damit der Modal-Initial-Toggle korrekt vorbelegt. Tests: 12 neue Unit-Tests in tests/unit/services/test_ragLimits.py + 6 in test_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). Frontend npm run build grün, keine neuen Lint-Errors. Doku: b-reference/gateway/ai-agent.md (Abschnitt "Konfigurierbare RAG-Limits"), TOPICS.md (neuer Eintrag). Verbleibende Hard-Limits in subConnectorSyncOutlook/Gmail.py haben 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 knowledgeIngestionEnabled nur als generische "Ja/Nein"-Spalte der FormGeneratorTable — kein Toggle-Element. Neu: zwei CustomActions (FaToggleOn/FaToggleOff, je nach State sichtbar via visible-Filter), Klick ruft patchKnowledgeConsent/api/connections/{id}/knowledge-consent und 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._updateDataSourceRagIndex propagierte bisher nicht auf die Parent-Connection. Neuer Helper _ensureConnectionKnowledgeFlag(rootIf, connectionId) setzt forward-only UserConnection.knowledgeIngestionEnabled=True, sobald min. eine DataSource auf ragIndexEnabled=true toggelt — 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 mit knowledgePreferences). 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 _bootstrapJobHandler in subConnectorIngestConsumer.py die Sub-Service-Results in ein wrappendes Dict packt ({"authority", "connectionId", "sharepoint": {...}, "outlook": {...}} für msft; analog für drive/gmail/clickup/kdrive). routeRagInventory._buildConnectionInventory griff aber auf Top-Level result.stoppedAtLimit/indexed/etc. zu — alle None. 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ür stoppedAtLimit/limits). Verifiziert anhand Job 2374aecd-3e17-460a-a13e-530f9f1115e6: bytesProcessed=209894527maxBytes=209715200, jetzt korrekt als stoppedAtLimit="maxBytes" an die UI durchgereicht. Diagnose-Skript gateway/scripts/debug_rag_job_result.py zeigt 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._buildConnectionInventory zählte bisher len(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. Neue interfaceDbKnowledge.countChunksByFileIds() macht eine einzige Aggregat-SQL SELECT "fileId", COUNT(*) FROM "ContentChunk" WHERE "fileId" = ANY(%s) GROUP BY "fileId" (kein Vector-Body geladen), die Response trägt jetzt fileCount UND chunkCount pro DataSource + totalFiles/totalChunks pro Connection. (2) RagInventoryPage.tsx / connectionApi.ts zeigen 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: return ohne Log + ohne Marker im Bootstrap-Result → User sah "Sync erfolgreich" obwohl 706 Dateien fehlten. Fix: neuer _recordLimitStop()-Helper in allen 4 Connectoren setzt BootstrapResult.stoppedAtLimit (1. exhausted Budget), schreibt 1 WARNING in den Log und liefert das Feld + die effektiven limits im _finalizeResult Dict an BackgroundJob.result. routeRagInventory reicht lastSuccess.stoppedAtLimit/limits/bytesProcessed ans Frontend durch. Neuer amber partialBanner auf der RagInventoryPage warnt mit "Limit maxBytes=200 MB (200 MB verarbeitet) erreicht — Weitere Dateien wurden NICHT indexiert" und bietet "Erneut indexieren". Verifiziert anhand local/logs/log_app_20260517.log: SharePoint-Sync hat genau bei bytesProcessed=209_894_527 ≥ MAX_BYTES_DEFAULT (209_715_200) gestoppt (Kumulative Summe der 25 indizierten Dateigrößen = 200.17 MB). ClickUp hat bei skippedDup=500 >= maxTasks=500 gestoppt. 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ür system/DB_PASSWORD_SECRET >10 Decrypts/s, das Brute-Force-Schutz-Rate-Limit warf ValueError: Decryption rate limit exceededrouteRagInventory._getInventoryPlatform HTTP 500. Hot-Path war mainBackgroundJobService._getDb(), das pro Call APP_CONFIG.get("DB_PASSWORD_SECRET") evaluiert (eager arg eval), bevor getCachedConnector ü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 S3S6 abgeschlossen (c-work/2-build/2026-05-postgres-connection-pool.md). S3: getCachedConnector Docstring präzisiert (Cache = Wrapper-Recycling + DB-Init-Spam-Schutz, Pool = echte Connection-Verwaltung). S4: Shutdown-Hook closeAllPools() in gateway/app.py lifespan als letzter Schritt nach Feature-onStop-Hooks. S5: Neuer Test-File gateway/tests/unit/connectors/test_connectorDbPostgre_pool.py mit 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=500ms triggert QueryCanceled und gibt Connection sauber zurück, Pool-Identity pro (host, db, port), closeAllPools leert Registry. Beim ersten Lauf entdeckt: psycopg2-Pool wirft PoolError sofort bei Exhaustion statt zu blockieren → borrowConn() um bounded Wait-Retry erweitert (_BORROW_WAIT_TIMEOUT_S=30s, _BORROW_WAIT_BACKOFF_S=50ms). Alter test_connectorDbPostgre_failLoud.py auf das neue borrowConn-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._FakeDb brauchte borrowCursor-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-Stub borrowCursor auch in test_folderRbac._FakeDb ergä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: DatabaseConnector hielt eine psycopg2-Connection pro Instanz und teilte sie via getCachedConnector(...) über den gesamten FastAPI-Thread-Pool und über asyncio-Tasks. psycopg2-Connections sind NICHT thread-safe — paralleler Zugriff aus z.B. RAG-Polling, routeI18n, mainBackgroundJobService und Hintergrund-Jobs führte zu another command in progress und — viel schlimmer — unendlichem Block in recv() (kein statement_timeout gesetzt). Das self._lock in DatabaseConnector war 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) mit psycopg2.pool.ThreadedConnectionPool pro (host, db, port), lazy-init, thread-safe (min=2, max=20 per DB_POOL_MAX_CONN, statement_timeout=30s, connect_timeout=10s). Jede DB-Operation borrowed eine Connection via neuem db.borrowConn()-Context-Manager (auto-commit/rollback/return); db.borrowCursor() als 1:1-Ersatz für das alte with db.connection.cursor() as cursor: Pattern. getCachedConnector bleibt API-kompatibel, Connector-Wrapper sind nun leichtgewichtig (kein per-instance Socket). Backward-Compat-Shim db.connection (no-op commit()/rollback()/closed, RuntimeError auf cursor() 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_connection als No-Op gehalten (Pool re-connectet selbständig). Public Shutdown-Hook closeAllPools() 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 | AddConnectionWizard Admin-Consent-Button war NoOp: ConnectionsPage hat das onMsftAdminConsent-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/adminconsent an — 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/callback ergänzt — Fehlen führte zu AADSTS50011; Multi-Tenant-Hinweis: Admin Consent gilt pro Tenant).

2026-05-15

  • 2026-05-15 | fix | gateway | subAiCallLooping.py: fehlender Top-Level-Import extractJsonString (und repairBrokenJson) im Modul-Header ergänzt. Bei getContexts()-Success (jsonParsingSuccess=True, overlapContext='') flog ein NameError, wurde vom zu breiten except Exception als "completePart not serializable" geschluckt, hat mergeFailCount hochgezählt und nach 3 Iterationen leeren String zurückgegeben — Folge: subStructureFilling bekam "" und meldete tryParseJson failed: Expecting value / No elements produced. Zusätzlich except-Hygiene: (json.JSONDecodeError, KeyError, TypeError) → WARNING + retry (erwartete Daten-Probleme), generischer except Exception → ERROR mit exc_info=True und 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 einen FakeFeatureDataProvider (in-memory BenchmarkFixture, kein DB-Setup) und schreibt Markdown + JSON-Report nach local/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_LEGACY geparkt. featureDataAgent._buildSchemaContext nutzt _loadFeatureOntologyBlock() bevorzugt (Fallback auf _loadFeatureDomainHints); _buildValidatorForFeature() verkabelt Validator+Ontologie automatisch (Single Source of Truth). Eval-only Override POWERON_DISABLE_FEATURE_ONTOLOGY=1. Side-Fix: aggregateTable exponiert jetzt filters im 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 in test_trusteeOntology.py (Descriptor, Compiler, Validator-Integration, mainTrustee-Hook, _buildValidatorForFeature); test_featureDataAgent_schema.py um Ontology-Pfad + Eval-Override erweitert. Working-Doc verschoben nach c-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-Muster getAgentDomainHintsgetAgentOntology).
  • 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üft browseTable/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-Halluzination SUM(closingBalance) × 7 Jahre × 13 Perioden ≈ 90× Saldo deterministisch ab), ORDER_BY_INVALID. Neues Datenmodell datamodelOntology.py mit QueryValidationError, 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] und ToolCallLog.validationFailureCode: Optional[str] zu datamodelAgent.py ergänzt (LLM bekommt machine-readable Repair-Hint, Audit-Log behält Kurz-String). agentLoop._computeRepairCounters aggregiert pro Sub-Agent-Run validationFailures, repairAttempts, successAfterRepair aus den ToolCallLog-Einträgen und legt sie auf AgentTrace + ins AGENT_SUMMARY-Event (Eval-Harness-Ready). Tool-Descriptions der drei Sub-Agent-Tools erklären das errorDetails-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) und b-reference/frontend-nyla/architecture.md (RagInventoryPage, UDB 4. Button, RagRunningBadge, AddConnectionWizard) aktualisiert, beide Pläne nach 4-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 in datamodelAgent.py statt JSON-in-error-String; (B) Repair-Telemetrie wandert von aiAuditLogger in AgentTrace/ToolCallLog (per-Run-Aggregation passt nicht in per-Call-Audit-Log); (C) Eval-Fixture als Python-Loader + Pydantic/recordCreate statt fixture.sql (konsistent mit Trustee-Tests); (D) AC#3 als repairConversionRate ≥ 0.8 über Repair-Triggered-Subset präzisiert, nicht als End-Accuracy; (E) Doc-Sync-Liste um b-reference/gateway/features/trustee.md und d-guides/coding-conventions.md erweitert. 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, nicht async 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 dem startJob _runJob via create_task registriert → asyncio.run schliesst 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 auf async def umgestellt und await 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 jetzt lastSuccess mit {jobId, finishedAt, indexed, skippedDuplicate, skippedPolicy, failed, durationMs} plus lastError.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. RagInventoryPage und RagRunningBadge pollen 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-Operation DatabaseConnector(...) 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 → _initializeSystemTable und 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 jetzt getCachedConnector() (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 in connectorDbPostgre.initDbSystem von INFO auf DEBUG gesenkt + um db/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; auditLogger ist 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_killer in mainBackgroundJobService.killZombieJobs() markiert RUNNING-Jobs ohne Progress-Update >30 min als ERROR und beendet so auf Dauer hängende Bootstraps. (2) Neuer Helper subWalkerHelpers.py (downloadWithTimeout 60s, extractWithTimeout 90s via asyncio.to_thread+wait_for, ingestWithTimeout 60s, logItemStart) — alle Walker (sharepoint, kdrive, gdrive, gmail, outlook, clickup) loggen jetzt vor jedem Item walker.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 avatarFileId in TeamsbotConfig/TeamsbotUserSettings und defaultAvatarFileId in TeamsbotMeetingModule. 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.ts rendert Bilder per drawImage() auf den Canvas, Videos per <video>-Element mit Loop. Für Videos wird FPS auf 15 erhöht und contentHint='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 keinen status in die DB, weil CreateMeetingModuleRequest kein status-Feld hat und recordCreate bei Dict-Input keine Pydantic-Defaults anwendet. Frontend t(null) ergab [null]. Fix: (1) Route setzt data.setdefault("status", "active"), (2) getModules setzt fehlenden Status defensiv auf "active" für existierende Records, (3) Frontend-Fallback mod.status || 'Aktiv' als letzte Absicherung.
  • 2026-05-12 | fix | frontend-nyla | TeamsBot Director-Panel Sichtbarkeit: gleiches Whitelist-Problem wie zuvor beim Stop-Button. TeamsbotSessionView.tsx Z.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 mit status &&-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 in service._processAudioChunk entfernt. 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.30.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, Default de-DE) wird übergeben — TeamsbotUserSettings.language überschreibt TeamsbotConfig.language wie 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-tid darin. 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 denselben calling-right-side-panel-Container, der aria-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) plus BOT_AVATAR_BG_COLOR=#a8d4f0 / BOT_AVATAR_TEXT_COLOR=#1a3552 in src/config.ts, durchgereicht via audioProcedure.ts an den Init-Script-Payload mediaGetUserMediaPatch.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 um captureStream() 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 in TeamsbotSessionView.tsx Z.841 + TeamsbotDashboardView.tsx Z.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-Keys t('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-button ohne aria-pressed, der nicht togglt. Vorher: Selector-Liste nahm #chat-button als ersten Treffer und klickte 12× denselben falschen Button. Neu: alle visibility-gefilterten Chat-Hint-Kandidaten in Page-Evaluate gesammelt, Toggle-Buttons (mit aria-pressed) bevorzugt, geklickte Keys getrackt — derselbe Button wird nie zweimal geklickt, Loop wechselt zum nächsten Kandidaten. Sprachunabhängig (DE/EN-Hints chat/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 Klasse vdi-occlusion ist im neuen Calling-Layout Permanent-Marker auf calling-right-side-panel und message-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 (kein aria-pressed, kein data-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 UND aria-pressed ∈ {true,false}, sprachunabhängig) und liest dessen aria-pressed als Quelle der Wahrheit — fixt den Auth-Toggle-Loop. Im Auth-Layout existieren mehrere "chat"-aria Buttons (Side-Nav-Einträge "Chats", "Meeting chats", Tab-Items tab-item-com.microsoft.chattabs.*), aber nur der echte Meeting-Chat-Toggle hat aria-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 mit UPR-Page-Errors. Light-meetings-Pfad (message-pane-layout mit vdi-occlusion-Klasse oder offsetHeight=0) bleibt als Schicht 2 für Anon (kein aria-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: Dockerfile ergänzt um RUN npx playwright install --with-deps chrome (lädt Google Chrome stable + alle apt-Deps an Playwright-bekannten Pfad) und ENV BOT_BROWSER_CHANNEL=chrome. docker-compose.yml setzt BOT_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: botBrowserChannel in config.ts, an chromium.launch({ channel }) in orchestrator._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.ts periodischer Scan promoviert target zu document wenn der Chat-Container (message-pane-layout) offsetHeight=0 hat ODER Selectoren 0 Treffer liefern, aber global [class*="fui-ChatMessage"] existiert (light-meetings rendert Chat-Bubbles in paralleler DOM-Branche). Zusätzlich Root-Cause-Guard if (!text && author !== 'Unknown') in beiden Pfaden (MutationObserver Strategy 1 + periodischer Scan) restauriert — verhindert dass strukturelle Fragmente ohne Author als Unknown: 22:04 Transcripts 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; __audioCaptureAttachTrack als window-exponierter Builder; startCapture() setzt Flag erst nach _setState('in_meeting') und iteriert getReceivers() aller connected PCs für bereits existierende Audio-Spuren. Label-Filter mainAudio-* 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 SourcesTab 4. Toggle-Button (🧠 ragIndexEnabled) mit Vererbung; RagRunningBadge Floating-Komponente (Polling, Job-Dropdown); WorkspaceRagInsightsPage physisch gelöscht; ConnectionsPage AdminConsent+Infomaniak Standalone-Buttons entfernt (nur noch via Wizard).
  • 2026-05-12 | docs | wiki | b-reference/gateway/ai-agent.md Abschnitt "RAG Consent & Control" ergänzt (Prinzipien, Datenmodell, Walker-Architektur, API, Frontend-Komponenten, Vererbung); TOPICS.md RAG-C&C-Eintrag.
  • 2026-05-12 | feat | gateway, frontend-nyla | RAG Consent & Control: Phase AD implementiert. Backend: DataSource.autoSyncragIndexEnabled (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); neuer subPolicyResolver.py (Tree-Vererbung); neue Routes /knowledge-consent, /knowledge-preferences, /knowledge-stop, /datasources/{id}/rag-index; neuer routeRagInventory (4 Endpoints); GET /connections/ liefert Knowledge-Felder; WorkspaceRagInsights Route+Permission gelöscht. Frontend: AddConnectionWizard vereinfacht (connector-aware Steps, MSFT AdminConsent + Infomaniak PAT integriert, keine Kostenschätzung/Prefs); connectionApi.ts neue Methoden + bereinigte Types; neue RagInventoryPage + CSS; pageRegistry + App.tsx Route + Navigation-Eintrag; FeatureView rag-insights Mapping 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 (autoSync ungenutzt → safe rename; cancelJob-API fehlt; routeDataConnections GET liefert Knowledge-Felder nicht; PATCH-Pattern aus routeDataSources als 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 via neutralizeFields[]); Walker iteriert nur über ragIndexEnabled=true DataSources; 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); globale Start > Nutzung > RAG-Inventar Seite; Wizard ohne Kostenschätzung/Preferences; Löschung der workspace-scoped WorkspaceRagInsightsPage.

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 to modules?moduleId= with expand + scroll highlight; canonical b-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.excludeAllTools flag fuer tool-freie Turns; generischer RAG-Session-Cache in agentLoop (TTL 120s / 5 Msgs); CommCoach nutzt beides fuer fluessige Coaching-Gespraeche
  • 2026-05-10 | fix | gateway | RAG-Cache-Bug: doppelter workflowId-Parameter in _getOrRefreshRag behoben (Keyword-Kollision)
  • 2026-05-10 | fix | gateway | CommCoach TTS: _TTS_WORD_LIMIT von 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) an agentLoop durchgereicht; CommCoach conversational turns nutzen PriorityEnum.SPEED fuer schnellere Modellauswahl
  • 2026-05-10 | fix | gateway | interfaceDbManagement.getInterface Singleton 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 anlegen dialog + Meeting starten; nav icons for assistant/modules; FEATURE_REGISTRY tab 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: startSession binds moduleId with validation; DB migration M2 TeamsbotMeetingModule.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 + safe AudioContext.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 from result_end_time; WS open + end_of_single_utterance replumbing. CommCoach uses latest_short + lightweight + single-utterance; Teamsbot passes audioFormat=linear16. Chirp/v2 evaluation tracked in wiki/c-work/1-plan/stt-chirp-v2-evaluation.md.
  • 2026-05-10 | fix | gateway | CommCoach: conversational turns use operationType=DATA_QUERY + priority=SPEED for faster model selection (gpt-5.4-mini instead of gpt-5.5); model selector speed priority weight scaled from /10 to *100 to 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 documentTitle style separate from headings.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}.envenv-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: open durch 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.listRelations fuer direkte Abfrage der Beziehungstabelle (Filter: issueId, relationType, pagination)
  • 2026-05-07 | feat | gateway | redmine.listTickets: offset-Parameter ergaenzt fuer echte Pagination; Response liefert offset + hasMore statt truncated

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() durch useConfirm-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 sessionId instead of session.id causing 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 durch moduleType ersetzt, description-Feld bleibt. TeamsBot-Plan ergaenzt: Namenskonvention startedByUserId dokumentiert. 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: context Feld zeigte Prompt statt Input-Context. actionNodeExecutor.py baute out["context"] falsch aus promptText + extractedContext zusammen. Wenn AI ein Binary-Dokument erzeugte (z.B. Excel), war extractedContext leer und context wurde identisch mit prompt. Jetzt wird der tatsaechliche aufgeloeste context-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. _WorkspaceTab pollt fetchWorkspaceRunDetail alle 3s solange Run-Status nicht terminal. Stoppt automatisch bei completed/failed/cancelled.
  • 2026-05-03 | fix | gateway | executeCode Sandbox: type entblockt, io restricted, Modul-Liste dynamisch. type() aus _PYTHON_BLOCKED_BUILTINS entfernt. import io liefert eingeschraenktes Modul (nur StringIO/BytesIO, kein io.open). Tool-Beschreibung dynamisch aus SANDBOX_ALLOWED_MODULES generiert. type() war faelschlich in _PYTHON_BLOCKED_BUILTINS (harmlos ohne exec/eval). StringIO/BytesIO als 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 jetzt docItem:/docList: Prefix korrekt via from_string_list (war: Prefix blieb in documentId, erzeugte Doppel-Prefix bei to_string()). (2) process.py: DocumentItemReference wird nur im Automation2-Kontext (kein Chat-Workflow) an _resolve_file_refs_to_content_parts geroutet; im Agent-Kontext fliessen sie korrekt durch getChatDocumentsFromDocumentList (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: style Keyword 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 nach 4-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 done gesetzt. 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.typeFilter in types.ts; FormGeneratorTree.tsx filtert selectedIds nach Typ und zeigt Counts pro Button. FolderFileProvider.tsx liefert zwei getrennte Batch-Aktionen (Ordner-Cascade-Delete vs. File-Delete/Batch-Delete). FilesPage tree-table Sync wiederhergestellt: selectedFolderId filtert 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.tsx rewritten from FormGeneratorTable to two FormGeneratorTree sections (Eigene/Geteilt mit mir) with drag-drop upload, refresh-by-key, and workflow-import on node click. FilesPage.tsx updated with split-view layout: 300px tree panel (left, own+shared trees) and FormGeneratorTable (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; FileFolder Pydantic + FileItem.folderId in datamodelFiles.py; Stub getOwnFolderTree/getSharedFolderTree; Routen GET /api/files/folders/tree (leere Liste) + Folder-Mutationen 501 bis Stage 1.B; migrate_folders_to_groups.py nach modules/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, DnD application/x-poweron-tree-items, Backend-Attribut-Resolution) zur Konsolidierung der ~8 parallelen Tree-Implementierungen. Recovery der Folder/File-Funktionen ueber Modell A (FileFolder + FileItem.folderId reaktivieren; DB-Schema unveraendert). RBAC-/Sichtbarkeitsmodell verbindlich: Default-Scope personal; Sharing nur ueber Owner-Scope-Patch; geteilte Objekte read-only fuer Nicht-Owner (analog updateFile/deleteFile); UI rendert in FilesTab/FilesPage zwei getrennte Trees (Eigene/CRUD + Geteilt mit mir/read-only); Files ohne sichtbaren Folder-Kontext fallen in den Root mit contextOrphan-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) auf FormGeneratorTree. FormGeneratorTable.groupingConfig bleibt unveraendert. Kein FormGeneratorChart -- Berichte = FormGeneratorReport (Komponenten-Zeile in b-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 auf done, Header status: 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" fuer documentList in ai.prompt, ai.summarizeDocument, ai.translateDocument, ai.convertDocument (gateway/modules/features/graphicalEditor/nodeDefinitions/ai.py). Zwei neue sichtbare Parameter auf ai.prompt: context (dataRef, beliebiger Upstream-Output, wird vom Action zu JSON serialisiert) + documentTheme (select, finance/legal/...). Action-Definition ai.process (gateway/modules/workflows/methods/methodAi/methodAi.py) deklariert context und documentTheme jetzt 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: bestehender DataRefRenderer + DataPicker rendern die JSON-DataRef-Werte direkt. Runtime unveraendert -- resolveParameterReferences verarbeitet {"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, renderDocument style-Param). Phase 3: Alle 5 Renderer auf Style-Lookups + Inline-Runs umgestellt. Phase 4: Inline-Bilder in Paragraph/Tabelle/Liste. Phase 5: allowedModels in AiCallOptions + _calculateEffectiveModels im AI-Gate. Phase 5a: WorkspaceUserSettings Persistenz (GET/PUT Endpoint). Phase 5b: modelMultiSelect im FlowEditor + Workspace-Settings UI. Phase 6: Trustee-Templates mit requireNeutralization + 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.py Template: 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, executeGraph Placeholder-Substitution ({{featureInstanceId}}), Scheduler-Durchreichung, _copyTemplateWorkflows explizites Setzen, idempotente Boot-Backfill-Migration. Phase 2: FlowEditor CanvasHeader "Ziel-Instanz" Dropdown mit FeatureStore-Integration, Save/Load mit targetFeatureInstanceId. Phase 3: Neuer Backend-Endpoint GET /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): executeGraph hat keine Placeholder-Substitution (muss neu gebaut werden), _copyTemplateWorkflows setzt featureInstanceId nicht im Payload (implizit via GE-Interface), TrusteeAbschlussView hat kein resultText/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-Ordner gateway/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-shot async def -> def Codemod, Refactor durch), i18n_rekey_plaintext_keys.py (Frontend Klartext-Keys, Migration durch siehe 4-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 in gateway/scripts/ (inkl. neues script_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 verwaisten FileContentIndex-Rows ohne mandateId/featureInstanceId -> via --purge-rag-orphans bereinigt -> Re-Audit 5/5 GREEN. Dann entfernt aus gateway/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). In interfaceDbKnowledge.py: aggregateMandateRagTotalBytes-Fallback-Block (try/except mit FileItem-ID-Korrelation aus Management-DB, ~27 Zeilen) entfernt -- die Funktion bleibt aktiv, da sie 4 externe Caller hat. Ersatz: neuer Helper gateway/modules/interfaces/_legacyMigrationTelemetry.py mit 4 lese-only WARN-Checks (gleiche Logik wie Audit-Skript, prozessweit gecached) wird am Ende von initBootstrap einmalig aufgerufen -- falls je doch Restbestand auftauchen sollte (alter DB-Restore o.ae.), gibt's klare WARN-Logs mit Routine-Name + IDs. Tests tests/unit/bootstrap/test_mandateNameMigration.py (8 Tests) und tests/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 in 1-plan/, jetzt direkt in 4-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: templateTextarea fuer Freitext mit {{nodeId.path}}-Variablen (DataPicker-Insert); email.draftEmail.context und ai.prompt.aiPrompt nutzen ihn statt reiner Textarea -- Aufloesung ausschliesslich via bestehendes resolveParameterReferences (kein Loop-Spezialcode im Executor). Loop-Preview-Enrichment + IfElse/AI-responseData-Picker bleiben. Unit-Test test_legacy_string_template_loop_current_item_nested in test_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) + generischer WorkflowRunWorkspace-Tab unter /automations als Single-Source-of-Truth fuer Workflow-Resultate, plus Pflicht-Binding Workflow.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 unter 4-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 mit TrainingModule-Datenmodell (Rename CoachingContext) + 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 neuer MeetingModule-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 in 1-plan/)

  • 2026-04-29 | fix | gateway | checkForDuplicateFile macht jetzt einen RBAC-Cross-Check und liefert keine "Geister-Duplicate" mehr aus. Ursache des File with ID ... not found-Fehlers in downloadFromDataSource direkt nach Duplicate detected for user ...: interfaceDbComponent wird ueber serviceHub ohne featureInstanceId initialisiert, checkForDuplicateFile faellt deshalb auf den mandateId-Filter zurueck und benutzte db.getRecordset (kein RBAC) -- damit konnte er ein File aus einer FREMDEN featureInstance returnen. Der nachfolgende updateFile-Aufruf prallte dann am RBAC-gefilterten getFile ab und crashte den ganzen Tool-Call. Sauberer Fix an der Wurzel: nach dem Recordset-Treffer zwingend self.getFile(fileId) als RBAC-Cross-Check; wenn None, gilt als kein Duplicate fuer den aktuellen Scope und der Caller (saveUploadedFile/createFile) erstellt eine frische per-Scope-Kopie. Damit entfaellt jeglicher Workaround in updateFile (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 in wiki/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 erzeugten downloadFromDataSource, writeFile mode=create, renderDocument, generateImage und createChart zwar eine FileItem (via saveUploadedFile/saveGeneratedFile), liessen den Workflow-Document-Graph aber unberuehrt -- statt eines ChatDocument floss nur ein sideEvent fileCreated an die UI. Folge: getChatDocumentsFromDocumentList (und damit ai_summarizeDocument / ai_process / context_extractContent / context_neutralizeData) konnte die FileItem-IDs nicht aufloesen, weil der Resolver ausschliesslich workflow.messages[*].documents[*].id matcht. 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) in coreTools/_helpers.py, der intern eine ChatMessage (Rolle assistant, Status step, generierter documentsLabel) inklusive einem ChatDocument (mit roundNumber/taskNumber/actionNumber aus dem aktiven Workflow) via chatService.storeMessageWithDocuments persistiert -- exakt das Pattern, das workflowProcessor.persistTaskResult und methodTrustee.extractFromFiles schon 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> fuer readFile/Embeds). Tool-Descriptions + conversationManager.buildSystemPrompt ergaenzt um die explizite Anweisung "use docItem: in documentList, NOT the file id, NOT a {"documents":[...]} wrapper". Zusatzlich: mainServiceAgent.runAgent propagiert das Workflow-Object jetzt in alle Service-Contexts (chat._context.workflow etc.) -- bisher tat das nur workflowManager._propagateWorkflowToContext, weshalb der Agent ueber die Workspace-Route ohne aktiven Workflow-Context lief und chatService._workflow None war. Folge: der Helper konnte ohne diesen Propagations-Fix nie greifen. Die in der vorhergehenden Session eingebaute RBAC-tolerante updateFile-Try/Except-Schleife in _downloadFromDataSource ist jetzt obsolet und wieder ausgebaut -- mit korrektem ChatDocument-Bind kommt der featureInstanceId ueber den Workflow-Pfad und die Duplicate-File-RBAC-Probleme verschwinden an der Wurzel. Pattern-Doc neu unter wiki/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_neutralizeData akzeptieren jetzt LLM-typische Dict-Wrapper-Formate fuer documentList. Der Agent serialisiert documentList regelmaessig als {"documents":[{"id":"<uuid>","name":"<file>"}]} (Folge der type=DocumentList-Schema-Definition, das LLMs als generic Object lesen). Bisher fielen alle drei Actions in den else: 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 Helper coerceDocumentReferenceList(value) in datamodelDocref.py der ALLE praktisch vorkommenden Shapes parst -- None, str, DocumentReferenceList, list[str], list[dict mit id/documentId/label], dict mit "documents"/"references"/"items"/"files"-Wrapper, und dict mit id/documentId (single item). Alle vier Aufrufstellen (process.py + extractContent.py + neutralizeData.py x2) auf den Helper umgezogen; die Inline-ActionDocument-Sonderbehandlung in process.py bleibt 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 in mainServiceChat.listFiles behoben. interfaceDbComponent.getAllFiles() returnt seit dem Pydantic-Refactor List[dict] (jeder Eintrag ist ein FileItem.model_dump() mit Label-Spalten), aber mainServiceChat.listFiles() griff weiter mit fileItem.fileName / fileItem.id zu (Pydantic-Style) -- daher 'dict' object has no attribute 'fileName' und 'dict' object has no attribute 'id' aus dem listFiles-Agent-Tool. Komplette Methode auf .get(...) umgestellt; Type-Annotation in getAllFiles (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, wo 12 die kDrive-File-ID einer .html-Datei ist), brachten browseDataSource und downloadFromDataSource bisher Folgefehler: (1) Browse rief blind /2/drive/{driveId}/files/{fileId}/files auf -> kDrive antwortet 400 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 dann segments[-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.browse holt vor dem Children-Listing die Item-Metadata (/files/{id}); bei type=file wird ein Single-Entry mit Name/Size/MimeType/Modified zurueckgegeben statt children aufzurufen. (c) KdriveAdapter.download benutzt 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. saveUploadedFile returnt bei Hash+Name-Match das EXISTIERENDE FileItem -- das kann aber in einem anderen featureInstanceId/Folder-Scope leben als die aktuelle Anfrage. Die nachfolgenden updateFile-Aufrufe (featureInstanceId/neutralize/folderId) prallten dann am RBAC-gefilterten getFile ab und warfen File with ID ... not found -- obwohl der Download korrekt war (File ist in der DB, addressierbar via fileItem.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/contactFolder werden jetzt korrekt auf die Connector-Services kdrive/calendar/contact gemappt. Der SourcesTab.tsx schreibt diese FE-seitigen Source-Type-Literals beim Anhaengen einer Datenquelle ans DataSource-Record; _dataSourceTools._resolveDataSource (und parallel routeFeatureWorkspace._SOURCE_TYPE_TO_SERVICE) hatten aber nur Eintraege fuer SharePoint/OneDrive/Drive/Outlook/Gmail/FTP/ClickUp -- daher kamen Service 'kdriveFolder' not available. Options: ['kdrive', 'calendar', 'contact'] aus browseDataSource/searchDataSource/downloadFromDataSource sobald der Agent eine Infomaniak/Calendar/Contact-Quelle anfasste. Beide Maps um die drei Eintraege erweitert; DataSource.sourceType-Field-Description ergaenzt; Inline-Kommentar im _dataSourceTools.py warnt vor Drift gegenueber FE und _SERVICE_MAP. Bestehende DataSource-Records funktionieren ohne Migration (das sourceType-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}/download antwortet bandwidth-bedingt mit 302 Found -> presigned CDN URL (Standard fuer File-Bytes); unser _infomaniakDownload-Helper hatte aber allow_redirects=False (kopiert vom _infomaniakGet-Helper, wo das wichtig ist um nicht versehentlich auf OAuth-Login-Pages zu landen). Folge: jeder kDrive-Download lieferte None -> Tool result: downloadFromDataSource FAILED -> Download returned empty im Agent-Log. Fix: nur fuer Downloads allow_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 weiter allow_redirects=False, damit nicht-PAT-faehige Routes als 302 sichtbar 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: temperature wird 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 mit 400 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 auf claude-opus-4-7/-sonnet-4-7/-haiku-4-7 und claude-*-5* -> temperature weglassen. Wirkt in allen drei Anthropic-Pfaden (callAiBasic, callAiBasicStream, callAiImage). Aeltere Modelle (Claude 4.5/4.6) bekommen temperature weiter 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: user ist (statt account_admin). Live-Beweis vom User mit Files in https://ksuite.infomaniak.com/1696919/kdrive/app/drive/2980592/files/11: das Drive haengt korrekt an account_id 1696919, aber /2/drive?account_id=1696919 antwortet trotzdem 200 [] -- empty, weil dieser Endpoint zur Drive-Manager-Admin-Sicht gehoert (filtered auf account_admin: true) und nicht zur Endbenutzer-Sicht. Direkt-Aufrufe wie /2/drive/2980592/files funktionieren fuer denselben User mit role: user einwandfrei (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 den drive-Scope (verifiziert mit PAT der accounts-Scope explizit nicht hat). Implementierung: (a) Neuer Helper listAccessibleDrives(token) -> List[dict] im connectorInfomaniak.py -- ein einzelner /2/drive/init?with=drives-Call, raised InfomaniakIdentityError mit Scope-Message wenn drive-Scope fehlt. (b) KdriveAdapter haelt jetzt _drives: Optional[List[Dict]] (statt _accountId/_accountIds); _listDrives() mappt direkt aus dem gecachten Init-Response. (c) submit_infomaniak_token validiert in zwei Schritten: listAccessibleDrives (drive-Scope) und resolveOwnerIdentity (workspace:calendar/workspace:contact-Scope). (d) Der zwischenzeitliche resolveAccessibleAccountIds() + accounts-Scope-Workaround wieder ENTFERNT (war eine Sackgasse: /1/accounts listet 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 (accounts raus). Doku: Status-Tabelle, Validation-Section und "How the kDrive adapter discovers your drives" komplett auf den init-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}/event 302t 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-Constraint range_must_be_lower_than_3_months) -- Adapter waehlt jetzt fix 90-Tage-Window (heute -30 / +60), URL-Encoding via urllib.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 mit 500 unexpected_error und .../export 302t zu OAuth -- beide Detail-Endpoints sind also nicht PAT-faehig. Listing dagegen funktioniert, liefert aber per Default nur Stammdaten -- ohne with=emails,phones,addresses,details kommen Email/Phone/Adresse leer. Loesung: ContactAdapter holt das Listing mit dem with-Param und rendert die .vcf selbst 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 _safeFileName aus dem Calendar-Adapter zu modullokal hochgezogen, von beiden Adaptern genutzt; ungenutzte import re/import json-Inline-Imports raus. kDrive-Adapter ist im Live-Test korrekt: /2/drive?account_id=1696919 antwortet 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_id ist 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: der KdriveAdapter las connection.externalId als account_id-Quelle, und bei kaputten Submits konnte dort der Token-Fingerprint ("pat-59ee48d9") statt der account_id stehen. Saubere Loesung statt Fingerprint-Migration: (a) Neuer modullokaler Helper resolveOwnerIdentity(token) -> InfomaniakOwnerIdentity im connectorInfomaniak.py -- versucht PIM Calendar (workspace:calendar-Scope), faellt auf PIM Contacts (workspace:contact-Scope) zurueck, raised InfomaniakIdentityError wenn keine Owner-Records gefunden. (b) KdriveAdapter hat keinen accountId-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 -- externalId ist reiner UI-State. (c) submit_infomaniak_token ruft denselben resolveOwnerIdentity() als Pre-Flight-Check, dann /2/drive?account_id={resolved} als sauberer 200-Probe. Der frueher noetige _probeScope-422-Tolerance-Hack ist entfallen. (d) getServiceAdapter hat keine kDrive-Sonderbehandlung mehr; alle drei Adapter werden uniform mit accessToken konstruiert. (e) _PIM_PREFIX ist auf Modul-Ebene definiert; CalendarAdapter und ContactAdapter haben keine Klassen-Konstanten mehr. Konsequenz: jede existierende Infomaniak-Connection arbeitet ohne User-Aktion sofort wieder, auch wenn externalId historisch einen Fingerprint enthaelt -- der Adapter zieht die account_id deterministisch 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.googleDataScopes um calendar.readonly + contacts.readonly erweitert, msftDataScopes um Calendars.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; $search fuer query). (c) connectorMsft.ContactsAdapter (Graph: me/contactFolders + virtueller default-Ordner fuer me/contacts, me/contactFolders/{id}/contacts?$orderby=displayName, .vcf als vCard-3.0 selbstgebaut mit N/FN/ORG/TITLE/EMAIL/TEL/ADR/NOTE). Helper _eventToIcs, _contactToVcard, _safeFileName, _personLabel plus _icsEscape/_icsDateTime. (d) connectorGoogle.CalendarAdapter (Calendar v3: users/me/calendarList, calendars/{id}/events?singleEvents=true&orderBy=startTime, .ics aus Event-Detail). (e) connectorGoogle.ContactsAdapter (People API: contactGroups + virtueller all-Folder ueber people/me/connections, fuer Gruppen people:batchGet?resourceNames=..., Search via people:searchContacts, .vcf aus personFields=names,emailAddresses,phoneNumbers,organizations,addresses,biographies). (f) _SERVICE_MAP von beiden Connectoren um "calendar"/"contact" ergaenzt; routeFeatureWorkspace und routeFeatureGraphicalEditor Service-Label-/Icon-Maps um kdrive, calendar, contact ergaenzt, damit die UDB sinnvolle Anzeigen macht. (g) Reconnect-Flow: POST /api/connections/{id}/connect akzeptiert optionalen Body {"reauth": true} und haengt &reauth=1 an die Auth-URL. routeSecurityMsft.auth_connect setzt bei reauth=1 prompt=consent (sonst select_account/login), routeSecurityGoogle.auth_connect droppt bei reauth=1 include_granted_scopes=true damit 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, ConnectionsPage zeigt fuer aktive MSFT/Google/ClickUp-Connections einen FaSyncAlt-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: temperature fuer GPT-5.x / o-Serie aus dem Payload nehmen. Symptom im Log: jede AI-Anfrage failt mit HTTP 400 Unsupported value: 'temperature' does not support 0.2 with this model. Only the default (1) value is supported., der Failover spricht 14 Modelle durch und schreibt Recorded 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 zur max_tokens -> max_completion_tokens-Restriction -- nur den Default (1). Wir senden aber unverhandelt temperature=0.2 aus jedem AiModel-Eintrag. Fix: Helper _supportsCustomTemperature(modelName) und in callAiBasic/callAiBasicStream/callAiImage den Key nur conditional ins Payload aufnehmen (Modellnamen mit Praefix gpt-5, o1, o3, o4 lassen ihn weg). Der vom User im UI gesetzte Override ueber AiCallOptions.temperature wird 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 zu login.infomaniak.com/authorize (nur OAuth-Web-Session, Bearer-PAT wird abgelehnt); mail.infomaniak.com/api/mail/?account_id=... -> 301 zu http://mail.infomaniak.com:5000 (interner Cyrus-IMAP-Port, von aussen nicht erreichbar). Der workspace: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-Scope workspace:contact und Bearer-Auth 200 + 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. Neuer ContactAdapter 1:1 analog CalendarAdapter: browse("/") -> Adressbuecher, browse("/{bookId}") -> Kontakte (Display-Name, Email, Phone, Organization in Metadata), download("/{bookId}/{contactId}") -> .vcf via /contact/{id}/export mit 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, ContactAdapter in _SERVICE_MAP registriert. Frontend: SourcesTab kennt contact-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/drive braucht ein account_id-Query-Arg, sonst 422 account_id required. Fix: account_id einmalig beim Token-Submit aus dem Calendar-PIM-Endpoint (https://calendar.infomaniak.com/api/pim/calendar -- liefert account_id, user_id, Anzeigename) ziehen, in UserConnection.externalId persistieren und ueber InfomaniakConnector.getServiceAdapter als Konstruktor-Parameter in den KdriveAdapter injizieren. /1/profile (haette user_info-Scope verlangt) und /1/mail (existiert nicht: 404 nginx) raus aus den Probes. (b) _probeScope toleriert jetzt 4xx ausser 401/403 (z.B. 422 validation_failed) als "Scope ist da, Endpoint braucht nur weitere Args". (c) Neuer CalendarAdapter (browse -> Calendars/Events ueber calendar.infomaniak.com/api/pim/calendar, download -> .ics via /event/{id}/export, JSON-Fallback). _infomaniakGet und _infomaniakDownload akzeptieren ein optionales baseUrl, sodass Calendar gegen calendar.infomaniak.com und kDrive gegen api.infomaniak.com laufen koennen. (d) MailAdapter aus _SERVICE_MAP entfernt: mail.infomaniak.com/api/mail redirected mit 302 zu login.infomaniak.com/authorize, akzeptiert also keine PATs; gleiches gilt fuer contacts.infomaniak.com/api/pim/contact. Beide Scopes werden weiterhin in grantedScopes gespeichert, damit kuenftige Adapter ohne Token-Rotation aufgeschaltet werden koennen. (e) Frontend: SourcesTab kennt calendar-Icon, -Color und _SERVICE_TO_SOURCE_TYPE-Mapping; PAT-Modal in ConnectionsPage zeigt 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/authorize akzeptiert nur Identity-Scopes (openid, profile, email, phone); Versuche mit kdrive/mail-Scopes quittieren mit error=invalid_scope. Datenzugriff geht ausschliesslich ueber manuell im Manager erstellte PATs. Umbau: (a) Backend routeSecurityInfomaniak komplett neu -- ein Endpoint POST /api/infomaniak/connections/{id}/token, validiert PAT via GET 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_token entfernt, AuthAuthority.INFOMANIAK aus den Background-Refresh-Filtern raus -- PATs sind langlebig. (c) oauthProviderConfig.infomaniakDataScopes + infomaniakDataScopesForRefresh entfernt. (d) routeDataConnections.connect_service antwortet bei Infomaniak jetzt mit 400 + Hinweis auf den PAT-Endpoint. (e) Env-Cleanup: Service_INFOMANIAK_DATA_CLIENT_ID/SECRET und Service_INFOMANIAK_OAUTH_REDIRECT_URI aus .env + env_dev/int/prod[_forgejo].env raus. (f) Frontend: useConnections.createInfomaniakConnectionAndAuth (OAuth-Popup) ersetzt durch createInfomaniakConnection + submitInfomaniakToken; ConnectionsPage zeigt PAT-Modal mit Schritt-Anleitung + Deeplink zu manager.infomaniak.com/v3/ng/accounts/token/list; Cancel rollt PENDING-Connection per DELETE zurueck. (g) Doku: wiki/d-guides/infomaniak-oauth-setup.md geloescht, wiki/d-guides/infomaniak-token-setup.md neu. (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/semanticSearch haben bisher jede Exception per except 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 Exception DatabaseQueryError(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 ueber cursor.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-hoc isinstance-Branches haben oder mit Postgres-Errors abstuerzen (siehe Trustee-Bug). Neues Modul gateway/modules/workflows/processing/shared/parameterValidation.py mit InvalidActionParameterError(ValueError) + validateAndCoerceParameters(actionDef, parameters). Zentral aufgerufen in ActionExecutor.executeAction -- gilt fuer alle Aufrufpfade (Agent, Workflow-Graph, REST). Logik:
      1. Required-Parameter erzwungen (typisierter Fehler statt opaque downstream).
      2. Ref-Schemas (FeatureInstanceRef/ConnectionRef/...) -- Dict mit id wird auf String-UUID kollabiert; Pass-Through fuer bereits-Strings; Dict ohne id raisst kontrolliert.
      3. 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 in actionToolAdapter eingebaute Ref-Normalisierung wurde komplett entfernt (Single Source of Truth in parameterValidation). 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).
  • 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) exponiert FeatureInstanceRef/ConnectionRef absichtlich als typisiertes Objekt mit id+Diskriminator (featureCode/authority), damit der LLM bei mehreren Instanzen die richtige picken kann -- aber die Action-Implementierungen verwenden den Wert direkt als String-UUID in recordFilter={"featureInstanceId": <value>, ...}. Der LLM uebergibt korrekt das Dict {id, featureCode, label, mandateId}, Postgres-Adapter scheitert mit can'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 in actionToolAdapter (Ref-Dict -> id-String). Diese Adapter-Normalisierung wurde im Folgeschritt zur zentralen parameterValidation migriert (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) closingBalance ist bereits ein Saldo pro Periode -- der Agent rief aggregateTable(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 Praefix 102x folgen und periodMonth=0 das Jahres-Total bedeutet. Fix in zwei Teilen: (a) generische Regel in featureDataAgent._buildSchemaContext System-Prompt -- "NEVER apply SUM/AVG to columns that already represent a balance, closing/opening total or aggregate" mit konkreten Beispielen closingBalance/openingBalance/debitTotal/creditTotal; (b) Pro-Feature-Hook getAgentDomainHints() -> str in mainXxx.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 _loadFeatureDomainHints nutzt loadFeatureMainModules() und ist tolerant gegen fehlende Hooks/Module. Unit-Tests in tests/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: Automation2WorkflowView erstellt 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 er TrusteeDataJournalLine.debitAmount/creditAmount ohne Datumsfilter (JournalLine hat gar kein bookingDate!) statt die Periode-bezogenen TrusteeDataAccountBalance.closingBalance zu nutzen; ISO-Date-Strings wurden gegen Float-Unix-Timestamps gefiltert (bookingDate <= '2025-12-31'). Fix in featureDataAgent._buildSchemaContext: pro Tabelle wird jetzt der zugehoerige Pydantic-Klasse via MODEL_REGISTRY resolved und pro selektiertem Feld eine angereicherte Zeile gerendert -- Python-Typ aus field.annotation, deutsches Label aus json_schema_extra.label, Description aus Field(description=...), FK-Target aus fk_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 in tests/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.py mit KdriveAdapter+MailAdapter (httpx, OAuth-Bearer, Path-Konvention /{driveId}/{fileId} bzw. /{mailboxId}/{folderId}/{uid}), routeSecurityInfomaniak.py mit _FLOW_CONNECT-only (kein Login -- pure DATA_CONNECTION), Token-Refresh via tokenManager.refreshInfomaniakToken + tokenRefreshService._refresh_infomaniak_token, connectorResolver-Registry-Eintrag, Authority-Map/Labels/Dispatch in routeDataConnections, Router-Mount in app.py. Refresh-Token-Persistierung holt bei fehlendem refresh_token-Response aus dem letzten gespeicherten Token (analog Google). Frontend: connectionApi.ts Authority-Typ erweitert, useConnections.createInfomaniakConnectionAndAuth + infomaniak_connection_success/error-Event-Listener, ConnectionsPage mit Infomaniak-Button (FaCloud), SourcesTab Icons/Colors/Service-Mapping fuer infomaniak/kdrive/mail -- inkl. Fix der bisher fehlenden ClickUp-Eintraege in _SERVICE_ICONS + _SERVICE_TO_SOURCE_TYPE. Setup-Guide unter wiki/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 Workspace maxAgentRounds. Im int-System brachen Trustee-Saldo-Queries deshalb mit Maximum rounds reached. Progress after 8 rounds ab, obwohl der Parent-Agent z.B. mit 25 Runden konfiguriert war. Fix: agentLoop._executeToolCalls propagiert jetzt parentMaxRounds + parentMaxCostCHF ueber den Tool-Context; _featureSubAgentTools._queryFeatureInstance liest sie aus und reicht sie an runFeatureDataAgent(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 effektive maxRounds/maxCostCHF zur 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=true filtert Scan-Resultate; OrphanCleanAllRequest.excludeUserFks filtert clean-all. Frontend: Checkbox neben Nur 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_tokens durch max_completion_tokens ersetzt in callAiBasic und callAiBasicStream. Hintergrund: OpenAI lehnt max_tokens fuer gpt-5.x / o-series Modelle mit HTTP 400 unsupported_parameter ab (Use 'max_completion_tokens' instead). Im Log log_app_20260426.log (L741-764) sichtbar: gpt-5.4-nano failover scheiterte sofort, ModelSelector wechselte auf claude-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.py Helper: registriert die TTF einmalig bei reportlab, scannt deren cmap, und wrapEmojiSpansInXml umschliesst zusammenhaengende Emoji-Runs (codepoint >= U+2000 ∧ in cmap) mit <font name="NotoEmoji">…</font> — nestet sauber in <b>/<i>/<font name="Courier">. rendererPdf._markdownInlineToReportlabXml wendet 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 in test_renderer_pdf_smoke.py
  • 2026-04-26 | fix | gateway | FK Orphan-Scanner loeschte korrekte Trustee-Workflows: AutoWorkflow.templateSourceId enthaelt teils Sentinel-IDs (z.B. "trustee-receipt-import" aus featureModule.getTemplateWorkflows()), die absichtlich keine DB-Zeile haben — wurden faelschlich als Orphans markiert und mit force=true (oder unter 50%-Schwelle) geloescht. Neuer softFk: True Flag in fk_target: fkRegistry.FkRelationship traegt das Flag, databaseHealth._scanOrphans/_cleanOrphans/_listOrphans ueberspringen soft FKs komplett (kein Display, kein Cleanup). Label-Resolution unveraendert. templateSourceId als softFk: True markiert. Wiki b-reference/platform/database-architecture.md aktualisiert
  • 2026-04-26 | refactor | gateway+frontend-nyla | Letzte 4 hardcoded Cell-Label-Stellen entfernt: (1) RoleView.scopeType (select mit frontend_options System-Template/Template/Mandant) + RoleView.userCount -> AdminMandateRolesPage zieht Attribute jetzt von RoleView, kein lokaler scopeType-Formatter mehr; (2) Invitation.expiredFlag als Pydantic @computed_field (live aus expiresAt+time.time()) mit frontend_format_labels=["Ja","-","Nein"]; (3) Invitation.emailSent -> emailSentFlag umbenannt + neues emailSentAt-Feld (Persistenz im DB-Record), routeInvitations.create_invitation setzt beide nach erfolgreichem Mailversand; (4) TrusteePositionView mit syncStatus (select Ausstehend/Synchronisiert/Fehler/Abgebrochen) + syncErrorMessage -> routeFeatureTrustee.get_positions enriched Rows aus TrusteeAccountingSync, useTrustee lookt Attribute via neuem attributesEntityName-Override, TrusteePositionsView hat eigenen Sync-State + Custom-Renderer geloescht. attributeUtils.getModelAttributeDefinitions und i18nRegistry.@i18nModel verarbeiten jetzt auch model_computed_fields (Labels + frontend_format_labels werden 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) aus GraphicalEditorWorkflowsPage, GraphicalEditorTemplatesPage, AutomationsDashboardPage, ComplianceAuditPage ersatzlos geloescht. Stattdessen Pydantic-Modelle (AutoWorkflow.active|sharedReadOnly|isTemplate|notifyOnFailure|templateScope, AutoRun.status, AutoStep.status, AutoTask.status, AutoVersion.status, Automation2WorkflowView.isRunning, AuditLogEntry.success) mit frontend_format_labels/frontend_options ausgestattet. resolveColumnTypes merged jetzt auch label und options aus dem Backend; FormGeneratorTable rendert Cells UND Filter-Dropdowns ueber column.options automatisch — Pages duerfen Labels nicht mehr im Frontend hardcoden
  • 2026-04-26 | feat | frontend-nyla | FormGeneratorTable + columnTypeResolver: ColumnConfig.options (aus frontend_options der Pydantic-Felder) ist jetzt erste Klasse; Cell-Renderer und Filter-Liste resolven Value -> Label automatisch; column.label ist optional und wird vom Backend-Attribut gefuellt
  • 2026-04-26 | fix | gateway+frontend-nyla | GraphicalEditor Workflows-Tabelle: createdAt-Alias aus routeFeatureGraphicalEditor.get_workflows entfernt — Frontend nutzt nun das kanonische sysCreatedAt. GraphicalEditorWorkflowsPage + GraphicalEditorTemplatesPage holen Attribute jetzt von Automation2WorkflowView (mit frontend_type=timestamp fuer sysCreatedAt/lastStartedAt und frontend_type=number fuer runCount); Spalten haben explizit sortable/filterable gesetzt — fehlende Sort-Icons und Zahl-statt-PeriodPicker behoben. Automation2Workflow-TS-Interface auf sysCreatedAt umgestellt
  • 2026-04-26 | refactor | frontend-nyla | RealEstate Parcels+Projects + GraphicalEditor Workflows+Templates: apiEndpoint auf den jeweiligen Listenroute gesetzt — Backend-Routen unterstuetzen mode=filterValues&column=X und mode=ids ueber handleFilterValuesInMemory/handleIdsInMemory; FormGeneratorTable holt Filter-Werte jetzt sauber vom Backend (kein Local-Mode mehr noetig)
  • 2026-04-26 | feat | gateway | routeFeatureGraphicalEditor: /workflows und /templates Endpunkte unterstuetzen jetzt mode=filterValues&column=X und mode=ids (FormGeneratorTable Backend-Pattern) ueber handleFilterValuesInMemory/handleIdsInMemory aus routeHelpers
  • 2026-04-26 | fix | frontend-nyla | AdminLanguagesPage: hookData.fetchFilterValues implementiert (offizielles Pattern fuer In-Memory-Tabellen ohne Backend-Endpunkt) — distinct Filter-Werte aus displayRows mit Cross-Filter-Support; ersetzt das zuvor versuchte FormGeneratorTable-Local-Mode
  • 2026-04-26 | revert | frontend-nyla | FormGeneratorTable: Local-Mode-Fallback in getUniqueValuesForColumn und das Entfernen der console.warn rueckgaengig gemacht — silent Fallbacks verstossen gegen das Prinzip "klare Datenstrukturen + Modelle im Backend"; Tabellen muessen stattdessen apiEndpoint (Backend) oder hookData.fetchFilterValues (explizit) setzen
  • 2026-04-26 | fix | frontend-nyla | AutomationsDashboardPage Workflows-Tab: Spalten isRunning und runCount als sortable + filterable markiert (Backend unterstuetzt JOIN-basierte Sortierung/Filterung dieser computed fields)
  • 2026-04-26 | fix | gateway | Automation2 ExecutionEngine: AutoRun.startedAt wird jetzt in createRun gesetzt; AutoRun.completedAt wird in updateRun automatisch gesetzt sobald Status terminal wird (completed/failed/stopped/cancelled); routeWorkflowDashboard.stopRun setzt completedAt ebenfalls. Bisher wurden diese Felder nie befuellt — daher waren started/completed Spalten in der Runs-Tabelle leer
  • 2026-04-26 | fix | frontend-nyla | PeriodPicker in FormGeneratorTable: Preset-Kind (thisMonth, thisQuarter etc.) wird im Filter-Wert mitgespeichert, damit es beim Round-Trip erhalten bleibt und isValueAllowed nicht faelschlicherweise auf ytd zurueckfaellt
  • 2026-04-26 | fix | gateway | routeAudit: 500-Fehler bei Datumsfilter behoben — PaginationParams(pageSize=999999) verletzte le=1000-Constraint; nutzt jetzt model_construct + SortField-Konvertierung
  • 2026-04-26 | refactor | gateway | 5 Pattern-Inkonsistenzen aus FormGeneratorTable-Audit behoben: routeDataUsers stiller Fallback entfernt; routeFeatureRealEstate Projekte+Parzellen nutzen jetzt applyFiltersAndSort statt nur Sorting; routeAdminRbacRules custom filter/sort durch shared Helper ersetzt + enrichRowsWithFkLabels ergaenzt
  • 2026-04-26 | fix | frontend-nyla | ComplianceAuditPage: Fallback-Formatter fuer instanceLabel und username zeigen jetzt NA(uuid) statt abgeschnittener UUID ohne Kontext
  • 2026-04-26 | fix | gateway | aicoreModelRegistry: Race-Condition in refreshModels behoben — Lock verhindert konkurrierende Refreshes; harmlose Duplikate (gleicher Name+Connector) werden toleriert statt als Fehler geworfen
  • 2026-04-26 | fix | gateway | routeDataFiles: mode=filterValues nutzt jetzt enrichRowsWithFkLabels + handleFilterValuesInMemory statt direktem getDistinctColumnValues — FK-Spalten (mandateId, featureInstanceId) zeigen wieder Labels statt UUIDs
  • 2026-04-26 | fix | gateway | routeFeatureTrustee: 3x mode=filterValues (Documents, Positions, generisch) von getDistinctColumnValuesWithRBAC auf enrichRowsWithFkLabels + handleFilterValuesInMemory umgestellt — FK-Spalten (organisationId, roleId, userId, contractId etc.) zeigen Labels statt UUIDs; generischer Endpunkt nutzt zusaetzlich _buildFeatureInternalResolvers fuer Feature-interne FKs
  • 2026-04-26 | fix | gateway | routeAudit: _enrichUserAndInstanceLabels setzt jetzt NA(uuid) als Fallback statt None fuer nicht aufloesbare FeatureInstance/User-IDs — Filter-Dropdown fuer Feature-Instanz war leer weil alle Labels None waren
  • 2026-04-26 | fix | gateway | Zwei Filter-Bugs: (1) applyFiltersAndSort in routeHelpers: value is None filtert jetzt auf leere Felder statt den Filter zu ueberspringen ("Leer"-Option funktioniert); (2) routeAudit._applySortFilterSearch durch Delegation an shared applyFiltersAndSort ersetzt — Datumsbereich-Filter (between-Operator) und Null-Filter funktionieren jetzt konsistent
  • 2026-04-26 | fix | gateway | Stille except Exception-Fallbacks in mode=filterValues entfernt: 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: enrichRowsWithFkLabels fehlte im mode=filterValues-Pfad bei 8 Routen (routeDataConnections, routeInvitations, routeAdminFeatures, routeSubscription, routeFeatureRealEstate x2); Wiki fk-label-resolution.md mit Filter-Enrichment-Regel fuer AI-Agent ergaenzt
  • 2026-04-26 | refactor | gateway | FK-Metadaten konsolidiert: alle Datamodels nutzen fk_target mit Pflicht-Keys db/table/labelField; fk_model/fk_label_field entfernt; _BUILTIN_FK_RESOLVERS["UserInDB"]; _buildLabelResolversFromModel skip ohne labelField; attributeUtils setzt displayField nur bei gesetztem labelField; validateFkTargets() Startup-Validierung in fkRegistry.py + app.py lifespan; Wiki fk-label-resolution.md + database-architecture.md aktualisiert
  • 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), ::timestamp auf ::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_LABELS in attributeTypeMapper.ts; FormStartNodeConfig, FormNodeConfig, FieldBuilderEditor beziehen Feldtypen aus zentraler Library statt hardcoded Listen; ClickUp-spezifische Typen (clickup_status, clickup_tasks) und zugehoerige UI (Connection-Picker, Status-Hinweis) entfernt; shared FormField-Typ auf AttributeType + generisches options umgestellt; TriggerFormFieldRow eliminiert; clickupFormSync.ts geloescht (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) in datamodelViews.py; createdAt/createdBy Aliase in Invitation- und Billing-DTOs auf sysCreatedAt/sysCreatedBy standardisiert; _COL_MAP-Remapping in interfaceDbBilling entfernt; 7 Admin/Billing/Compliance-Seiten beziehen Spaltentypen via resolveColumnTypes + fetchAttributes('<ViewModelName>') statt hardcoded type: — 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 resolveColumnTypes statt type: attr.type im Column-Map
  • 2026-04-26 | feat | gateway | attributeUtils.getModelClasses: Feature-datamodel*.py unter modules/features/** rekursiv importieren (Trustee, Teamsbot, GraphicalEditor, …) fuer /api/attributes/{entityType}
  • 2026-04-26 | refactor | frontend-nyla | Workflow-Seiten (GraphicalEditorWorkflowsPage, AutomationsDashboardPage) beziehen Spaltentypen via resolveColumnTypes + fetchAttributes vom Backend statt hardcoded type: im Frontend; neuer Shared-Utility columnTypeResolver.ts
  • 2026-04-26 | feat | frontend-nyla | attributesApi.AttributeDefinition.type nutzt AttributeType aus attributeTypeMapper; Mapper um Backend-Typ object (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 *OnTs von number auf timestamp; Redmine DTOs (RedmineSyncResultDto, RedmineSyncStatusDto, RedmineConfigDto); UsageStatistics.periodStart mit frontend_type: "date"; alle frontend_type: "datetime" auf "timestamp" (Audit, AuthEvent, GraphicalEditor Auto*, Messaging sentAt) — konsistent mit attributeTypeMapper.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 — numerische gt/gte/lt/lte/between mit ::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 ausserhalb filterDropdownOptions (Popover nicht durch overflow-y: auto geclippt)
  • 2026-04-26 | fix | gateway | TrusteeDataJournalEntry.bookingDate: Optional[str] -> Optional[float] (unix timestamp); Konvertierung in _persistJournal via _isoDateToTimestamp (ValueError bei ungueltigem Datum, kein Fallback); _aggregateLocalMovements liest 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/syncedAt bekommt frontend_type: "timestamp", lastSyncDateFrom/lastSyncDateTo frontend_type: "date" — damit Frontend Date-Filter statt Text anzeigt
  • 2026-04-26 | fix | frontend-nyla | FormGeneratorTable: Filter-Dropdown per useLayoutEffect als position: fixed in den Viewport geklemmt; Audit-Timestamp-Spalten (sysCreatedAt etc.) bei numerischem type als Datums-UI + kein distinct-Fetch
  • 2026-04-26 | feat | frontend-nyla | FormGeneratorTable: typbezogene Spaltenfilter — Zahlen (integer/int/number/float) mit Operator (=, >, >=, <, <=, Zwischen) und Anwenden; Datum-Filter mit CSS-Panel; kein filterValues-Fetch mehr fuer bool/date/number-Spalten
  • 2026-04-26 | fix | gateway | routeHelpers._matchesBetween: numerische from/to nach fehlgeschlagenem Datums-Parse (korrekte BETWEEN-Logik fuer Zahlenspalten); connectorDbPostgre: gt/gte/lt/lte und between auf INTEGER/DOUBLE PRECISION mit ::double precision statt lexikographischem TEXT-Vergleich

2026-04-25

  • 2026-04-25 | feat | * | Phase 4 FK: frontend_fk_* und FormGenerator-fkSource/Client-Cache entfernt; fk_label_field + displayField only; _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; neues AccountingPeriodBalance-Modell + getAccountBalances-Methode in BaseAccountingConnector; 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() in routeHelpers.py — bulk-resolved FK-Labels als {field}Label-Spalten pro Row; _resolveMandateLabels/_resolveInstanceLabels/_resolveUserLabels liefern None statt ID bei fehlender Aufloesung; routeWorkflowDashboard, routeAudit, routeBilling (Transactions + Billing-Aggregation), routeSubscription auf zentrale Funktion migriert (or mid[:8] / or uid[:8] / or iid-Fallbacks entfernt)
  • 2026-04-25 | feat | gateway | FK-Resolution Phase 2 (B2): _enrichedFilterValues in routeWorkflowDashboard liefert {value, label} Objekte fuer FK-Spalten (mandateId, featureInstanceId) — Frontend zeigt Labels im Filter-Dropdown ohne separate fkSource-Aufloesung; Leerwerte (null) fuer "(Leer)"-Filter inkludiert
  • 2026-04-25 | fix | gateway+frontend | FK-Resolution Korrektur: routeWorkflowDashboard runs/workflows-Enrichment benennt mandateIdLabelmandateLabel um (Frontend-Interface-Kompatibilitaet); AutomationsDashboardPage Spalten mandateId/featureInstanceId nutzen displayField: 'mandateLabel'/'instanceLabel'
  • 2026-04-25 | feat | gateway | FK-Resolution Phase 2 (B1): getDistinctColumnValues + getDistinctColumnValuesWithRBAC + _extractDistinctValues + _distinctColumnValues liefern null als 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 rendert row[displayField] statt row[key], CSV nutzt displayField; fkSource/fkDisplayField als @deprecated markiert (Legacy-Pfad funktioniert weiterhin)
  • 2026-04-25 | feat | frontend-nyla | FK-Resolution Phase 3 (B3): FilterValuesList akzeptiert string | null | {value, label} Eintraege; FilterValue-Typ eingefuehrt; _normalizeFilterValue normalisiert 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) und routeDataMandates wirft 400 bei kaputtem JSON statt silent default; runsByStatus/Run-Enrichment in /metrics + /workflows propagieren DB-Fehler statt logger.warning+200; delete_system_workflow Callback-Trigger meldet Listener-Bugs (500 statt except: pass); routeBilling._isAdminOfMandate/_isMemberOfMandate und routeSubscription._assertMandateAdmin fail-loud (kein "DB-Down → 403"-Mask mehr); Stripe Subscription.retrieve im Checkout-Webhook re-raised statt silent skip
  • 2026-04-25 | fix | gateway | Fallback-Cleanup Phase 1 (D2): routeInvitations Rollen-Zuweisung — addRoleToFeatureAccess/addRoleToUserMandate sind bereits idempotent, daher try/except: pass # Role might already be assigned entfernt → echte FK-/DB-Fehler beim Einladungs-Akzept werden jetzt sichtbar
  • 2026-04-25 | fix | frontend-nyla | Fallback-Cleanup Phase 1 (D3+D4): AutomationsDashboardPage._handleExecute zeigt "Workflow gestartet" nur noch, wenn die 1s-Beobachtungs-Phase weder Erfolg noch Fehler beobachtet hat (kein Doppel-Toast "gestartet" + "fehlgeschlagen" mehr); _loadMetrics toast-t Backend-Fehler statt nur console.error; Automation2FlowEditor.handleWorkflowRename zeigt Fehler-Toast statt unsichtbarem console.error
  • 2026-04-25 | feat | frontend-nyla | FormGeneratorTable: Leerwert-Filter (Leer) in allen Filter-Dropdowns — filtert auf IS NULL OR = '' (Backend unterstützt bereits null in Pagination-Filtern); Filter-Icon/Clear-Button erkennen null-Filter korrekt via key 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: anywhere als Safety-Net auf .nodeConfigPanel; Bound-Chip/Vorschlag-Button mit whitespace: 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-Test GraphicalEditorKeepAlive.test.tsx
  • 2026-04-25 | fix | frontend-nyla | DataPicker: per createPortal nach document.body (entkoppelt von .nodeConfigPanel button-Primary-Override); neues List-Row-Layout/Theme (dataPickerNodeHeader neutral), 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-Button min-width; Version-Zeile getrennt; retryButton-Margin im Toolbar-Panel neutralisiert
  • 2026-04-25 | fix | gateway | Trustee-Template trustee-receipt-import: documentList als DataRef extract→process→sync (Pick-not-Push), nicht leere Listen; Unit-Test test_trustee_template_workflows.py
  • 2026-04-25 | feat | gateway | Trustee + Redmine Nodes auf typisierten FeatureInstanceRef[<code>]-Param + frontendType: featureInstance migriert (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 fuer frontendType: 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.name statt der ausschweifenden Description (Tooltip enthaelt vollen Text); hidden-Pflicht-Params werden zentral in findRequiredErrors gefiltert (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.md archiviert; Folge-Track-Doc 2026-04-feature-instance-ref-adapter-migration.md direkt in 4-done/ als erledigt
  • 2026-04-25 | docs | wiki | Changelog-Konvention im _CHANGELOG.md eingefuehrt; in README.md + doc-sync.mdc referenziert