wiki/c-work/4-done/2026-04-feature-instance-ref-adapter-migration.md
2026-06-02 09:42:12 +02:00

172 lines
9.9 KiB
Markdown

<!-- status: done -->
<!-- lastUpdated: 2026-04-25 -->
<!-- lastReviewed: 2026-04-25 -->
<!-- owner: ai-agent -->
<!-- related: z-archive/c-work/2026-04-node-typization-audit.md, c-work/4-done/2026-04-typed-action-architecture.md, c-work/4-done/2026-04-typed-action-followups.md -->
# FeatureInstanceRef-Adapter-Migration & Graph-Editor UI-Cleanup (2026-04-25)
> Restbestand aus dem Node-Typisierungs-Audit (jetzt z-archiv).
> Ziel: keine `frontendType: "hidden"` Pflichtfelder mehr, klare UI-Texte,
> theme-konformer DataPicker, optionale Schema-Ansicht fur Sysadmins.
## Auslosender Befund
Bei der Audit-Umsetzung wurde die _strukturelle_ Korrektur (PORT_TYPE_CATALOG /
Typed Action Architecture) durchgezogen — die _Anwendung_ in den
`nodeDefinitions/*.py` jedoch nur teilweise. Trustee + Redmine fuhren
weiter `featureInstanceId: string, hidden, required=True`, was im Editor
zu **Phantom-Pflichtfeldern** ("Pflichtfelder ohne Quelle: Trustee Feature-
Instanz-ID"), unklarer Fehler-Banner und einem nicht-bedienbaren Knoten
fuhrt.
Zusatzlich zeigte der Screenshot 2026-04-25 zwei UI-Probleme die unabhangig
mitgenommen werden:
- DataPicker-Modal mit nicht lesbaren Farb-Kombinationen
- "Schema (Typ-Referenz)" und ausschweifende `description`-Texte
(`erarbeitete Dokumentenliste eines Upstream-Producers …`) in der
End-User-View
## Anpassungs-Liste (zum Abhaken)
### A. Audit archiviert ✅
- [x] `wiki/c-work/1-plan/2026-04-node-typization-audit.md` ->
`wiki/z-archive/c-work/2026-04-node-typization-audit.md`
- [x] Forward-Link auf Typed Action Architecture + dieses Track-Doc
- [x] Changelog-Eintrag
### B. Backend — `featureInstanceId` typisieren
#### B1. Neuer Frontend-Type + Endpoint
- [x] `routeFeatureGraphicalEditor.py`: neuer Endpoint
`GET /api/workflows/{instanceId}/options/feature.instance?featureCode=<code>&enabledOnly=true`
- Antwort: `{ options: [{ value: "<id>", label: "<label> ([code])" }] }`
- Auflosung uber `getRootInterface().getFeatureInstancesByMandate(mandateId, enabledOnly=True)`
- Filter `featureCode` Pflicht (sonst 400, sonst Datenflut)
- [x] `_LEGACY_RENDERERS_THAT_HANDLE_BINDINGS` (`NodeConfigPanel.tsx`) erweitert: `'featureInstance'`
#### B2. Trustee-Nodes (5 Stuck) — `platform-core/.../nodeDefinitions/trustee.py`
| Node | aktuell | neu |
|-------------------------------------|--------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|
| `trustee.refreshAccountingData` | `featureInstanceId: string, hidden, required` | `featureInstanceId: FeatureInstanceRef[trustee], frontendType: featureInstance, frontendOptions: {featureCode: trustee}` |
| `trustee.extractFromFiles` | dito | dito |
| `trustee.processDocuments` | dito; `documentList` description aufraumen (Dev-Justifikation) | dito + description = `t("Dokumentenliste — gebunden via DataRef.")` |
| `trustee.syncToAccounting` | dito; `documentList` ebenfalls | dito |
| `trustee.queryData` | dito | dito |
Alle 5 Nodes umgesetzt via wiederverwendbarem `_TRUSTEE_INSTANCE_PARAM`-Dict
(siehe `trustee.py`). Bestaetigt durch
`tests/unit/graphicalEditor/test_featureInstanceRef_node_definitions.py`.
#### B3. Redmine-Nodes (6 Stuck) — `platform-core/.../nodeDefinitions/redmine.py`
- [x] `redmine.readTicket`
- [x] `redmine.listTickets`
- [x] `redmine.createTicket`
- [x] `redmine.updateTicket`
- [x] `redmine.getStats`
- [x] `redmine.runSync`
Alle 6 via `_REDMINE_INSTANCE_PARAM`-Dict, `featureInstanceId` ->
`FeatureInstanceRef[redmine]` mit
`frontendType: "featureInstance", frontendOptions: {"featureCode": "redmine"}`.
#### B4. Beobachtete `frontendType: hidden`-Restbestande (out-of-scope, in
2026-05 oder eigenem Track-Doc adressieren — hier nur dokumentiert)
| Datei | Param | Typ aktuell | Anmerkung |
|------------------|----------------|-------------|-----------------------------------------------------------------|
| `ai.py` | `documentList` | `string` | Korrekt: ueber `dataRef` gebunden, `string` lugt nur den DataPicker |
| `email.py` | `documentList`, `emailContent` | `string` | dito |
| `sharepoint.py` | `content` | `string` | dito |
| `clickup.py` | `content` | `string` | dito |
| `context.py` | `documentList` | `string` | dito |
| `file.py` | `context` | `string` | dito |
> Diese Faelle sind _nicht_ Phantom-Pflichtfelder (sie sind
> entweder optional oder werden korrekt via DataRef gebunden), losen aber
> die "Schema (Typ-Referenz)"-Verwirrung mit aus. Strukturell sind sie
> Kandidaten fur `frontendType: "dataRef"` mit prazisem `type:
> "List[ActionDocument]"` etc. — eigene Iteration.
### C. Frontend — Renderer & Safety Net
- [x] `FeatureInstancePicker.tsx` (Modell: `ConnectionPicker`):
- Lade `/api/workflows/{instanceId}/options/feature.instance?featureCode=<code>`
- 0 Ergebnisse: Hinweis _"Keine {code}-Instanz im aktiven Mandanten — bitte in der Admin-Konsole anlegen."_
- 1 Ergebnis: Auto-Pick (`autoSingleRef`-Guard)
- N Ergebnisse: `<select>` mit Default-Option `"{code}-Mandant wählen"`
- [x] `frontendTypeRenderers/index.tsx`:
- Import + Eintrag in `FRONTEND_TYPE_RENDERERS`: `featureInstance: FeatureInstancePicker`
- Eintrag in `_LEGACY_RENDERERS_THAT_HANDLE_BINDINGS` (im `NodeConfigPanel.tsx`-Set)
- [x] **Safety Net direkt in `paramValidation.ts/findRequiredErrors`**:
hidden-Pflicht-Parameter werden zentral gefiltert, damit Banner,
FlowCanvas-Badges und Run-Button-`blockedReason` synchron bleiben.
Zusatzlich `_shouldUseRequiredPicker` (`NodeConfigPanel.tsx`) liefert
fruh `false` fur `frontendType === 'hidden'` und die Render-Schleife
uberspringt die Zeile komplett (`return null`).
### D. Editor-Verbose-Toggle (Issue 1)
- [x] `CanvasHeader.tsx`:
- Sysadmin-Check via `getUserDataCache()?.isSysAdmin === true`
- Checkbox _"Schema-Details"_ rechts neben Workspace-Button,
nur wenn Sysadmin (gestrichelter Rahmen, Tooltip mit Erklaerung)
- Wert in `localStorage('flowEditor.verboseSchema')`
- [x] `Automation2FlowEditor.tsx`: `verboseSchema` state + persist-effekt,
als Prop runtergereicht an `CanvasHeader` und `NodeConfigPanel`
- [x] `NodeConfigPanel.tsx`: `<details>`-Block "Schema (Typ-Referenz, Sysadmin-
Ansicht)" und Parameter-Typ-Badges nur, wenn `verboseSchema === true`.
PortField-Liste + Header-Spans zusatzlich auf CSS-Variablen umgestellt.
### E. DataPicker-Theming (Issue 3)
- [x] `DataPicker.tsx`: alle hardcoded Farben (`#555`, `#888`, `#999`, `#666`)
-> CSS-Variablen (`var(--text-secondary)`, `var(--text-tertiary)`,
`var(--bg-secondary)`, `var(--border-color)`)
- [x] Inline-Tags (`expectedParamType`-Badge, "Nur kompatible"-Label,
Schema-Hint, Type-Hint hinter Leaves) auf CSS-Klassen
`dataPickerLeafType`, `dataPickerNodeSchemaHint` umgezogen
- [x] `Automation2FlowEditor.module.css`:
- Hover-Safety-Net `.dataPickerLeaf:hover * { color: inherit; }`
keine grauen Type-Hints mehr auf blauem Hover-Hintergrund
- Neue `.dataPickerLeafType`, `.dataPickerNodeSchemaHint`,
`.dataPickerIterateBtn` mit theme-konformen Variablen
### F. Banner-Klartext (Issue 4)
- [x] `NodeConfigPanel.tsx`: Banner _"Pflichtfelder ohne Quelle"_ zeigt
jetzt `param.name` (kurze Maschinenkennung), die volle Beschreibung
hangt als mehrzeiliger `title=`-Tooltip am Banner
- [x] `RequiredAttributePicker.tsx`: nutzt `getLabel(param.description)`
bereits korrekt; Justifikationen (`erarbeitete Dokumentenliste …`) sind
fortan nur noch eine Datenfrage in den `nodeDefinitions` und betreffen
diesen Banner nicht mehr (description-Saeuberung in B2/B3 erledigt)
### G. Tests
- [x] `platform-core/tests/unit/graphicalEditor/test_featureInstanceRef_node_definitions.py`:
parametrized fuer alle Trustee+Redmine-Nodes — Typ ist
`FeatureInstanceRef[<code>]`, frontendType `featureInstance`,
`frontendOptions.featureCode` korrekt; plus Regression-Guard gegen
Re-Einfuehrung der `string + hidden`-Form (13 Testfaelle)
- [x] `platform-core/tests/unit/graphicalEditor/test_route_options_feature_instance.py`:
Smoke-Test, dass der Endpoint `GET /api/workflows/{instanceId}/options/feature.instance`
registriert ist und `featureCode` Pflicht ist (2 Testfaelle)
- [x] `ui-nyla/.../paramValidation.test.ts`: neuer Fall
_"skips required params with frontendType='hidden' (UI safety net)"_
- [ ] (Optional, Folge-Iteration) FeatureInstancePicker.test.tsx mit msw
fur 0/1/N-Antworten; aktuell durch das Renderer-Pattern abgedeckt
(ConnectionPicker hat dasselbe Modell, dort existieren Smoke-Tests)
### H. Wrap-up
- [x] Track-Doc nach `c-work/4-done/` verschieben
- [x] Eintrag in `c-work/_CHANGELOG.md`
- [ ] (Folge-Aufgabe) `b-reference/platform-core/workflow.md` um Abschnitt
_"FeatureInstanceRef adapter binding"_ erweitern; eigenes Mini-Track
oder bei naechster Workflow-Doku-Iteration mitnehmen