wiki/c-work/4-done/2026-04-gateway-int-stability-and-bugfixes.md
2026-06-02 09:42:12 +02:00

131 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- status: done -->
<!-- started: 2026-04-08 -->
<!-- implemented: 2026-04-11 -->
<!-- component: gateway -->
# Gateway: INT-Stabilität — Analyse (Log) und Fix-Plan
## Beschreibung und Kontext
Beim Testen der Applikation auf der **Integrations-Instanz (INT)** mit **mehreren parallelen Nutzern** wurden Symptome im Gateway-Log sichtbar (u. a. `gateway_log_2026-04-08T11-14-17-514Z.log`). Ziel dieses Dokuments ist eine **codebezogene Ursachenanalyse** und ein **Umsetzungs- und Testplan** — ohne die Themen mit Architektur-Storys zu vermischen.
**Business-Treiber:** Zuverlässiger Multi-User-Betrieb (Upload/Index, Workspace-Agent, Outlook-Tools, Knowledge/Neutralisierung) und weniger „sporadische" Fehler, die Support-Zeit kosten.
**Risiko bei Nicht-Umsetzung:** Weiterhin nicht reproduzierbar wirkende Permission-Fehler nach erfolgreicher Verarbeitung, fehlgeschlagene OpenAI-Streaming-Calls wegen Tool-Schema, nutzloser Outlook-Tool-Flow bei UUID-Referenzen, Crashes/Fail-Safe-Sprünge bei Bild-only-Indexierung.
**Abhängigkeiten:** Änderungen betreffen primär `platform-core`; keine zwingende Frontend-Änderung, ausser Tool-Beschreibungen/UX explizit angepasst werden.
## Fokus und kritische Details
### Thema A — Management-Interface: globaler Singleton
- **Fragil:** `interfaceDbManagement.getInterface()` liefert eine **gemeinsame** `ComponentObjects`-Instanz (`"default"`); jeder Aufruf setzt `setUserContext` auf demselben Objekt.
- **Edge Case:** Async-Pfade (z. B. `_autoIndexFile` mit `await knowledgeService.indexFile`) — zwischen Start und `updateFile` kann ein anderer Request den Kontext überschreiben → `PermissionError` auf `FileItem.update` trotz erfolgreicher Indexierung.
- **Code:** `platform-core/modules/interfaces/interfaceDbManagement.py`, `platform-core/modules/routes/routeDataFiles.py` (`_autoIndexFile`).
- **Fix:** `_autoIndexFile` holt `mgmtInterface` nach dem letzten `await` frisch. Singleton bleibt bestehen — vollständige Ablösung ist separates Architektur-Thema.
### Thema B — Agent-Tool-JSON-Schema: Arrays ohne `items`
- **Fragil:** `ActionToolAdapter` mappt `List[str]` auf JSON-Schema `type: array` **ohne** `items`.
- **Edge Case:** OpenAI lehnt Tools mit HTTP 400 ab (*array schema missing items*); Failover zu anderen Providern maskiert das Problem.
- **Code:** `platform-core/modules/serviceCenter/services/serviceAgent/actionToolAdapter.py`; betroffene Aktion u. a. `ai.process` (`methodAi.py`, Parameter `documentList`).
- **Fix:** Neues `_ARRAY_ITEMS_MAPPING` ordnet Python-Array-Typen dem korrekten `items`-Schema zu. `_convertParameterSchema` setzt bei `type: "array"` automatisch `items` (Fallback: `{"type": "string"}`).
### Thema C — Outlook: Referenzformat vs. Lookup
- **Fragil:** `listConnections` zeigt u. a. `id: <uuid>`; `getUserConnectionFromConnectionReference` parst nur `connection:{authority}:{username}`.
- **Edge Case:** Modell übergibt UUID an Outlook-Tools → „Connection not found".
- **Code:** `coreTools/_connectionTools.py`, `mainServiceChat.getUserConnectionFromConnectionReference`, `methodOutlook/helpers/connection.py`.
- **Fix:** `listConnections` gibt jetzt `connection:{authority}:{username}` aus statt UUIDs. `getUserConnectionFromConnectionReference` hat UUID-Fallback: wenn Format nicht `connection:…`, wird nach Connection-ID gesucht.
### Thema D — Knowledge: `_neutralSvc` bei nur Bildern
- **Bug:** `_neutralSvc` wird nur im Zweig mit Textobjekten gesetzt; Bild-Neutralisierung nutzt `_neutralSvc` danach — bei **keinen** Textobjekten → `UnboundLocalError` (im Log als fail-safe sichtbar).
- **Code:** `platform-core/modules/serviceCenter/services/serviceKnowledge/mainServiceKnowledge.py` (`indexFile`).
- **Fix:** `_neutralSvc` wird vor Text- und Bild-Block initialisiert (`None`), sobald `_shouldNeutralize` wahr ist. Bild-Block prüft `_neutralSvc` in der Bedingung.
### Thema E — Workspace: Mandats-Kontext aus zwei Quellen
- **Fragil:** `_getChatInterface` nutzt `context.mandateId`; `ServiceCenterContext` für den Agent nutzt Mandat aus `_validateInstanceAccess` (Instanz).
- **Edge Case:** Unterschiedliche `interfaceDbChat`-Cache-Keys für „denselben" Workspace → seltene Inkonsistenzen (Workflow sichtbar / nicht sichtbar).
- **Code:** `platform-core/modules/features/workspace/routeFeatureWorkspace.py`.
- **Fix:** `_getChatInterface` akzeptiert optionalen `mandateId`-Parameter. **Alle 34** `_validateInstanceAccess`-Aufrufe entpacken den Return-Wert. Alle `_getChatInterface`- und `ServiceCenterContext`-Aufrufe nutzen die validierte Instanz-`mandateId`.
### Thema F — Chat: `createMessage` / `getWorkflow` → None
- **Fragil:** `getWorkflow` liefert `None` bei leerem RBAC-Recordset **und** bei Exceptions beim Validieren des `ChatWorkflow`-Modells; `createMessage` meldet pauschal „No access to workflow".
- **Edge Case:** Agent-Lauf endet „complete", Persistenz der Assistant-Message schlägt fehl — Ursache ohne besseres Logging schwer trennbar.
- **Code:** `platform-core/modules/interfaces/interfaceDbChat.py`.
- **Fix:** `getWorkflow` unterscheidet RBAC-leer (`debug`: "RBAC filter or not found") vs. Validierungsfehler (`error`: "data validation failed"). `createMessage` loggt `warning` mit Verweis auf Ursache.
## Ziel und Nicht-Ziele
- **Ziel:** Die oben genannten **konkreten** Defekte/Risiken beheben oder absichern; INT- und Last-Szenarien reproduzierbar testen; Logging dort verbessern, wo die Ursache heute verschleiert wird.
- **Explizit NICHT:** Grossrefactor des gesamten Service-Centers; neue Features; umfassende Wiki-b-reference Pflege (erst nach Abschluss laut README-Lebenszyklus).
## Betroffene Module
- **Gateway:** `interfaceDbManagement`, `routeDataFiles`, `actionToolAdapter`, `mainServiceChat`, `mainServiceKnowledge`, `routeFeatureWorkspace`, `interfaceDbChat`, Agent-Core-Tools (`_connectionTools`), optional `connection.py` (Outlook).
- **Frontend:** nein (ausser spätere Texte/Hinweise für Connection-Referenz — optional).
- **DB-Migration:** nein (für diese Fixes nicht erwartet).
- **Andere Komponenten:** nein.
## Entscheidungen
| Datum | Entscheidung | Begründung |
|-------|-------------|------------|
| 2026-04-08 | Plan-Dokument angelegt | INT-Log + Code-Review; Umsetzung folgt in `2-build`. |
| 2026-04-11 | Themen AF umgesetzt (pragmatische Fixes) | Kein Grossrefactor Singleton; stattdessen Re-Acquire nach `await` + konsistente `mandateId`-Übergabe. |
## Umsetzungs-Checkliste (Fix-Reihenfolge empfohlen)
- [x] **D** `_neutralSvc` / Bildpfad in `mainServiceKnowledge.indexFile` absichern — `_neutralSvc` wird vor Text- und Bild-Block initialisiert; Bild-Block prüft `_neutralSvc` in der Bedingung. Datei: `serviceKnowledge/mainServiceKnowledge.py`.
- [x] **B** JSON-Schema für `List[str]` / `List[int]` in `actionToolAdapter` — neues `_ARRAY_ITEMS_MAPPING`; `_convertParameterSchema` setzt bei `type: "array"` automatisch `items`. Datei: `serviceAgent/actionToolAdapter.py`.
- [x] **C** Connection-Lookup: `listConnections` gibt `connection:{authority}:{username}` aus statt UUIDs; `getUserConnectionFromConnectionReference` hat UUID-Fallback. Dateien: `coreTools/_connectionTools.py`, `mainServiceChat.py`.
- [x] **A** Management-Interface: pragmatischer Fix — `_autoIndexFile` holt `mgmtInterface` nach dem letzten `await` frisch. Singleton bleibt; vollständige Ablösung ist separates Architektur-Thema. Datei: `routes/routeDataFiles.py`.
- [x] **E** Workspace `mandateId`: `_getChatInterface` akzeptiert optionalen `mandateId`-Parameter; alle 34 `_validateInstanceAccess`-Aufrufe entpacken den Return-Wert; alle `_getChatInterface`- und `ServiceCenterContext`-Aufrufe nutzen die validierte Instanz-`mandateId`. Datei: `features/workspace/routeFeatureWorkspace.py`.
- [x] **F** `getWorkflow` / `createMessage` Logging: `getWorkflow` unterscheidet RBAC-leer (`debug`) vs. Validierungsfehler (`error`); `createMessage` loggt `warning` mit Verweis auf Ursache. Datei: `interfaces/interfaceDbChat.py`.
Weitere Checkliste aus Template:
- [x] API-Endpunkte — keine Signaturänderung; `_getChatInterface` hat neuen optionalen Parameter (intern)
- [x] DB-Schema / Migration — nein (nicht nötig)
- [x] Frontend-Komponenten — nein
- [x] RBAC / Permissions — keine Änderung; Fix E stellt sicher, dass Cache-Keys konsistent sind
- [x] Neutralisierung betroffen? — ja (Thema D, behoben)
- [x] Navigation / Routing — nein
- [x] Billing-Impact? — nein
## Akzeptanzkriterien
| # | Kriterium (Given-When-Then) | Prio | Status |
|---|---------------------------|------|--------|
| AC1 | Given eine Datei mit nur Bild-`contentObjects` und aktiver Neutralisierung, When `indexFile` läuft, Then kein `UnboundLocalError` und definiertes Verhalten (OK/skip mit Log). | must | **done** |
| AC2 | Given generiertes Tool-Schema für `ai_process`, When es an die OpenAI-kompatible API geht, Then `documentList` ist ein `array` **mit** `items` (kein 400 wegen fehlender `items`). | must | **done** |
| AC3 | Given `listConnections` liefert eine Verbindungs-Referenz, When ein Outlook-Tool dieselbe Referenz nutzt, Then Verbindung wird aufgelöst (Format `connection:…` oder UUID-Fallback). | must | **done** |
| AC4 | Given zwei parallele Uploads/Auto-Index-Läufe unterschiedlicher User, When Indexierung endet, Then `updateFile(..., active)` schlägt nicht wegen **fremdem** User-Kontext fehl. | must | **done** (Re-Acquire) |
| AC5 | Given Workspace-Stream mit gültiger Instanz, When Chat-Interface und Agent-Chat-Service erzeugt werden, Then identische effektive `mandateId`/`featureInstanceId`-Kombination für den Chat-Cache. | should | **done** |
| AC6 | Given `getWorkflow` scheitert an Datenvalidierung, When `createMessage` läuft, Then Log enthält **ursächliche** Exception, nicht nur „No access". | should | **done** |
## Testplan
| ID | AC | Art | Automatisiert | Repo-Pfad / Methode | Status |
|----|----|-----|--------------|---------------------|--------|
| T1 | AC1 | unit | ja | `platform-core/tests/...``indexFile` mit Mock neutralization, nur image `contentObjects` | pending |
| T2 | AC2 | unit | ja | Test: `_buildToolDefinition` / Schema für `ai_process` → assert `properties.documentList.items` | pending |
| T3 | AC3 | unit/integration | ja/teils | `getUserConnectionFromConnectionReference(uuid)` vs. `connection:msft:user@…` | pending |
| T4 | AC4 | integration | empfohlen | Zwei parallele Requests gegen INT oder lokaler Stress-Skript + assert File-Status | pending |
| T5 | AC5 | integration | optional | Request ohne Header-Mandat, mit Instanz-ID — ein Log-Punkt für effektive Chat-Keys | pending |
| T6 | AC6 | manuell/log | teils | Nach Fix: künstlich kaputtes Workflow-Datum in DB oder temporärer Log-Level | pending |
## Links
- PR: (nach Umsetzung)
- Issue: (falls extern getrackt)
- Ausgangs-Log (lokal): `local/debug/gateway_log_2026-04-08T11-14-17-514Z.log`
## Abschluss
- [x] Alle Themen AF umgesetzt (2026-04-11)
- [ ] b-reference/ aktualisiert — z. B. `b-reference/platform-core/architecture.md` nur wenn Architektur-Entscheid (Singleton) dauerhaft geändert wird
- [ ] TOPICS.md aktualisiert (falls neues Thema)