docs
This commit is contained in:
parent
19f28e85d9
commit
0923454b57
4 changed files with 543 additions and 24 deletions
306
c-work/1-plan/2026-04-typed-generic-handover.md
Normal file
306
c-work/1-plan/2026-04-typed-generic-handover.md
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
<!-- status: plan -->
|
||||
<!-- started: 2026-04-23 -->
|
||||
<!-- component: gateway, frontend-nyla -->
|
||||
|
||||
# Typed Generic Handover für den Graphical Editor — Pick‑not‑Push, Static‑Only Schemas, Hard Validation
|
||||
|
||||
## Beschreibung und Kontext
|
||||
|
||||
Mit `2026-04-generic-graph-editor.md` (done) wurden ein typisiertes Port‑System (`portTypes.py`), generische `frontendTypeRenderers/` und ein schema‑basierter `DataPicker.tsx` eingeführt. Der zur Laufzeit wirksame Handover zwischen Nodes basiert dort jedoch weiterhin auf einem **Push‑Modell**: `actionNodeExecutor._wireHandover` ruft `INPUT_EXTRACTORS` (Heuristiken pro Schema‑Name) auf und füllt fehlende Parameter im Konsumer aus dem Output des direkten Vorgängers.
|
||||
|
||||
Im PWG‑Pilot (`pwg-pilot-jahresmietzinsbestätigung.workflow.json`) zeigt dieses Modell mehrere Symptome:
|
||||
|
||||
- `connectionReference` ist in den meisten Folge‑Nodes leer (`n4 sharepoint.downloadFile`, `n10 email.draftEmail`), wird zur Laufzeit erneut vom User abgefragt — Heuristik kennt `connectionReference` nicht.
|
||||
- KI versteht den Handover beim Modellieren nicht: das Output‑Schema (`DocumentList { documents }`) ist zu flach, Provenienz (Connection, Source‑Folder) fehlt — die KI kann keinen sauberen Pfad picken, sondern „rät".
|
||||
- Felder wie `attachmentBuilder` rendern als unstrukturierte Text‑Inputs (kein passender Renderer).
|
||||
- Loop‑Body‑Nodes können nicht sauber auf Vorgänger‑Kontext (z.B. SharePoint‑Label aus 1. Node) zurückgreifen.
|
||||
|
||||
**Geschäftstreiber:** Solange der Handover nicht generisch deterministisch ist, sind sowohl AI‑gestütztes Workflow‑Modellieren als auch User‑Self‑Service unzuverlässig. Jede neue Node‑Kombination produziert neue Edge‑Cases. Das blockiert die operative Skalierung des Graphical Editors über den PWG‑Pilot hinaus.
|
||||
|
||||
**Prinzipien‑Wechsel (Decisions vom 2026‑04‑23):**
|
||||
|
||||
1. **Pick‑not‑Push:** Jeder Input‑Parameter ist explizit gebunden (DataRef / Static / SystemVar). Keine `INPUT_EXTRACTORS`‑Heuristik zur Laufzeit. Auto‑Suggest gibt es nur als Authoring‑Komfort beim Wire‑Connect.
|
||||
2. **Static‑Only Schemas:** Output‑Schemas sind entweder im Code‑Katalog (`PORT_TYPE_CATALOG`) oder als **graph‑defined Schema** im Workflow‑Graph fixiert (z.B. `input.form.fields`). Keine Runtime‑dynamischen Schemas (kein `ai.extractStructured`, kein `data.transform`).
|
||||
3. **Loop‑Scoping lexikalisch:** Im Loop‑Body sind alle lexikalisch sichtbaren Outer‑Nodes pickbar **plus** zusätzlich `loop.item`, `loop.index`, `loop.total`. Kein Magic‑Envelope.
|
||||
4. **Connection als Hybrid:** Source‑Nodes haben weiterhin einen `userConnection`‑Parameter mit Picker. Sie exponieren eine `ConnectionRef { id, authority, label }` (ohne Secrets) im Output. Downstream‑Nodes binden ihren `connectionReference` per DataRef gegen diese `ConnectionRef`.
|
||||
5. **Hard Validation:** Type‑Mismatch oder fehlende Required‑Bindung blockiert den Run vor Start.
|
||||
6. **Greenfield + Migrationsskript:** kein Heuristik‑Fallback. Bestehende Workflows werden einmalig automatisch migriert (deterministisch, weil die alte Heuristik selbst deterministisch ist).
|
||||
|
||||
## Fokus und kritische Details
|
||||
|
||||
### Was schon da ist (verifiziert im Code, 2026‑04‑23)
|
||||
|
||||
- `gateway/modules/features/graphicalEditor/portTypes.py` — `PortField`, `PortSchema`, `PORT_TYPE_CATALOG`, `SYSTEM_VARIABLES`, `_normalizeToSchema`, `INPUT_EXTRACTORS`.
|
||||
- `gateway/modules/workflows/automation2/executors/actionNodeExecutor.py` — `_wireHandover()` (zu entfernen), `_resolveConnectionParam()` (bleibt im neuen Modell, Anwendung verschiebt sich).
|
||||
- `frontend_nyla/src/components/FlowEditor/nodes/shared/DataPicker.tsx` — schema‑basierte Pfad‑Auflösung mit Transit‑Chain, System‑Sektion.
|
||||
- `frontend_nyla/src/components/FlowEditor/nodes/frontendTypeRenderers/index.tsx` — `FRONTEND_TYPE_RENDERERS` Registry.
|
||||
- `frontend_nyla/src/components/FlowEditor/editor/NodeConfigPanel.tsx` — generischer Config‑Renderer.
|
||||
|
||||
### Was fragil / kritisch wird
|
||||
|
||||
- **`PORT_TYPE_CATALOG` ist heute zu flach.** `DocumentList` enthält nur `documents: List[Document]`, aber `Document` selbst ist nicht im Katalog typisiert. Folge: Picker kann nicht in einzelne Document‑Felder (z.B. `name`, `mimeType`, `downloadUrl`) reinpicken. Dasselbe gilt für `FileList`, `EmailList`, `TaskList`. → Alle List‑Schemas brauchen `itemSchema`, alle Item‑Typen brauchen eigene Einträge im Katalog.
|
||||
- **Loop‑Scope‑Berechnung im Frontend.** Heute sehr flach. Muss BFS rückwärts entlang `connections` plus transitive Loop‑Body‑Hierarchie berücksichtigen, ohne Performance‑Kollaps bei großen Graphen.
|
||||
- **Type‑Compat ist heute weich.** `validateGraph` warnt nur — neu: hart blockierend, plus klare Fehler‑UX im Frontend (rote Pills + Run‑Button disabled).
|
||||
- **Migration der bestehenden Workflows.** Deterministisch, weil `INPUT_EXTRACTORS` deterministisch sind — aber jede Node mit implizitem Wire‑Handover muss einen passenden DataRef bekommen. Trockenlauf mit Diff zwingend.
|
||||
- **`input.form` bleibt Sonderfall „graph‑defined Schema"** — nicht Runtime‑Dynamik, sondern „Schema lebt in `node.parameters.fields` und ist nach dem Speichern fix". Frontend & Backend lesen es deterministisch über eine gemeinsame Helper‑Funktion.
|
||||
|
||||
### Bekannte Fallstricke
|
||||
|
||||
- AI Agent Tool‑Generation: heute baut die KI Workflows oft mit leeren `connectionReference`‑Feldern und vertraut auf den Wire‑Handover. Nach dem Cut funktioniert das nicht mehr — Prompt + Tool‑Schemas müssen so geschärft werden, dass die KI explizite DataRefs erzeugt.
|
||||
- Pause/Resume‑Pfad in `executionEngine`: `initialNodeOutputs` (Resume‑User‑Eingabe) muss weiterhin gegen Output‑Schema validiert werden — passt nahtlos zum harten Validation‑Modus.
|
||||
- `flow.merge`, `flow.switch`, `flow.ifElse` — Transit‑Envelope bleibt; aber `Transit` darf kein Free‑Pass für Type‑Compat sein (Picker folgt Transit‑Chain, Validation prüft den realen Producer am Ende der Chain).
|
||||
- `attachmentBuilder` Frontend‑Type — heute kein Renderer. Im Zuge des Cleanups Alias auf `JsonEditor` (oder echten Builder, falls Pilot es noch in dieser Iteration braucht).
|
||||
|
||||
## Ziel und Nicht-Ziele
|
||||
|
||||
**Ziele:**
|
||||
- Generische, deterministische Handover‑Logik zwischen allen Nodes basierend auf typisierten DataRefs.
|
||||
- Reichhaltige rekursive Output‑Schemas mit `itemSchema` für Listen und Provenienz‑Feldern (SharePoint‑Source, ConnectionRef) wo der Konsumer sie picken können soll.
|
||||
- DataPicker mit lexikalischem Loop‑Scoping, Type‑Compat‑Anzeige (grün/gelb/rot), rekursiver Schema‑Navigation.
|
||||
- Hard Validation: kein Run bei fehlenden Bindings oder Type‑Mismatch.
|
||||
- Auto‑Suggest beim Wire‑Connect (UX‑Komfort, nicht Runtime‑Magie) für deterministische Defaults nach Name+Type‑Match.
|
||||
- AI‑Tool‑Surface: Endpoint, der für eine Node die strukturierte Liste aller pickbaren Upstream‑Pfade liefert.
|
||||
- Migration aller existierenden Workflows in DB `poweron_graphicaleditor` ohne manuelle Nacharbeit.
|
||||
- `input.form` als graph‑defined‑Schema sauber unterstützt; Picker downstream zeigt User‑definierte Felder mit korrekten Typen.
|
||||
|
||||
**Explizit NICHT:**
|
||||
- Keine Runtime‑dynamischen Schemas. `ai.extractStructured` wird **nicht** eingeführt; `data.transform` wird **entfernt**.
|
||||
- Kein Self‑Service Node‑Type‑Generator (User‑editierbare Node‑Typen) in dieser Iteration.
|
||||
- Keine semantische Type‑Refinement (Subtype‑Polymorphie über strukturelles Matching hinaus). Bleibt auf strukturellem Match.
|
||||
- Keine Backwards‑Compat: alte Workflows werden migriert, der `_wireHandover`‑Code wird gelöscht, kein Fallback.
|
||||
- Keine Änderung am Scheduler / Pause‑Resume‑Datenmodell jenseits Validation‑Hook.
|
||||
- Keine Änderung an Action‑Library (`workflows/methods/`) — Adapter dort bekommen nur erweiterte Outputs, keine neue Aufrufkonvention.
|
||||
|
||||
## Betroffene Module
|
||||
|
||||
**Gateway (`gateway/modules/`):**
|
||||
- `features/graphicalEditor/portTypes.py` — `PortField` erweitern (`itemSchema`, `fields`, `enumValues`); `PORT_TYPE_CATALOG` erweitern um `Document`, `FileItem`, `EmailItem`, `TaskItem`, `ConnectionRef`, `SharePointFolderRef`, `SharePointFileRef`; `INPUT_EXTRACTORS` **entfernen**.
|
||||
- `features/graphicalEditor/nodeDefinitions/*.py` — alle Outputs anreichern um Provenienz (`source`, `connection`) wo sinnvoll; `outputPorts.dynamic`/`deriveFrom` Marker auf `input.form` beschränken und in `{kind: "fromGraph", parameter: "fields"}`‑Form normalisieren.
|
||||
- `features/graphicalEditor/nodeRegistry.py` + `routeFeatureGraphicalEditor.py` — neue Endpoints: `GET /{instanceId}/upstream-paths/{nodeId}`, `POST /{instanceId}/validate-graph`.
|
||||
- `workflows/automation2/executors/actionNodeExecutor.py` — `_wireHandover` **entfernen**; `_resolveConnectionParam` bleibt für resolver, wird aber nur noch nach Parameter‑Resolution gerufen.
|
||||
- `workflows/automation2/executors/dataExecutor.py` — `data.transform` **entfernen**, `data.aggregate` und `data.filter` mit reichhaltigen Output‑Schemas.
|
||||
- `workflows/automation2/executionEngine.py` — Validation‑Hook vor Run‑Start; Loop‑Body‑Scope an `executeGraph` propagieren.
|
||||
- `workflows/automation2/graphUtils.py` — `validateGraph`: hart blockierend; `resolveParameterReferences`: graph‑defined‑Schema‑Pfad ergänzen.
|
||||
- `workflows/methods/sharepoint/`, `methods/outlook/`, `methods/clickup/`, `methods/trustee/`, `methods/file/` — Adapter‑Outputs anreichern (Connection‑Ref, Source‑Pfad).
|
||||
- Migrations‑Skript `scripts/migration/2026-04-pick-not-push-migration.py` (neu) — scannt `AutoWorkflow.graph`, ergänzt explizite DataRefs anstelle implizitem Wire‑Handover.
|
||||
- Test‑Pakete:
|
||||
- `gateway/tests/unit/graphicalEditor/test_port_schema_recursive.py`
|
||||
- `gateway/tests/unit/graphicalEditor/test_validate_typed_hard.py`
|
||||
- `gateway/tests/integration/graphicalEditor/test_upstream_paths_api.py`
|
||||
- `gateway/tests/integration/graphicalEditor/test_pwg_pilot_typed.py`
|
||||
- `gateway/tests/unit/migration/test_pick_not_push_migration.py`
|
||||
- pro Adapter (sharepoint/outlook/clickup/trustee/file): Schema‑Compliance‑Test
|
||||
|
||||
**Frontend (`frontend_nyla/src/`):**
|
||||
- `api/workflowApi.ts` — Interfaces: `PortSchema` rekursiv (`fields`, `itemSchema`); `DataRef.expectedType`; `NodeType.outputPorts.schema` darf `string | {kind:"fromGraph", parameter:string}` sein.
|
||||
- `components/FlowEditor/nodes/shared/dataRef.ts` — `DataRef` um `expectedType` erweitern; Helper `isCompatible(produced, accepted)`.
|
||||
- `components/FlowEditor/nodes/shared/DataPicker.tsx` — Scope: BFS rückwärts via Connections + transitive Loop‑Body‑Hierarchie; rekursive Schema‑Navigation (verschachtelte fields, list `itemSchema` unwrap); `loop.item`/`loop.index`/`loop.total` pro umgebendem Loop; Type‑Compat‑Pills.
|
||||
- `components/FlowEditor/nodes/shared/scopeHelpers.ts` (neu) — `computePickableScope(nodeId, graph, nodeTypes)`, `unwrapListItemSchema()`, `resolveTransitChain()`.
|
||||
- `components/FlowEditor/context/Automation2DataFlowContext.tsx` — `parseGraphDefinedSchema(node, paramKey)` für `input.form`; cached pro Node.
|
||||
- `components/FlowEditor/editor/NodeConfigPanel.tsx` — DataRef‑Pills mit Type‑Status; fehlt Required‑Binding → Visualisierung; nicht‑bindbare Connection‑Pickers (wenn upstream `ConnectionRef` verfügbar) als Hybrid‑Picker (Static‑User‑Connection ODER DataRef).
|
||||
- `components/FlowEditor/nodes/frontendTypeRenderers/index.tsx` — `attachmentBuilder` als Alias auf `JsonEditor` (übergangsweise); `ConnectionPicker` 3‑Modus (Link bei 0 Connections, Auto‑Display bei 1, Dropdown bei ≥2) — aus dem überholten Vorgänger‑Plan übernommen.
|
||||
- `components/FlowEditor/editor/FlowCanvas.tsx` — Auto‑Suggest Modal beim Wire‑Connect; Wire‑Farbe nach Type‑Compat (grün/gelb/rot); Validation‑Indicator pro Node.
|
||||
- `components/FlowEditor/editor/Automation2FlowEditor.tsx` — Run‑Button disabled bei Validation‑Fehler; Validation‑Panel sichtbar mit Klick‑Zu‑Node‑Navigation.
|
||||
|
||||
**DB‑Migration:** Nein im Schema‑Sinn (kein `AutoWorkflow`‑Table‑Change). **Daten‑Migration ja:** `AutoWorkflow.graph`‑JSON wird einmalig durch Migrations‑Skript transformiert.
|
||||
|
||||
**Andere Komponenten:**
|
||||
- AI Agent (`gateway/modules/serviceCenter/services/serviceAgent/`): `workflowTools` Tool‑Schemas erweitern, sodass `bindNodeParameter`‑Tool die KI zur expliziten DataRef‑Erzeugung führt; Prompts für Workflow‑Generation aktualisieren.
|
||||
|
||||
## Entscheidungen
|
||||
|
||||
| Datum | Entscheidung | Begründung |
|
||||
|-------|-------------|------------|
|
||||
| 2026‑04‑23 | Pick‑not‑Push als Grundprinzip — `INPUT_EXTRACTORS` und `_wireHandover` entfernen | Heuristisches Push erzeugt nicht‑deterministisches, AI‑undurchsichtiges Verhalten |
|
||||
| 2026‑04‑23 | Static‑Only Schemas: Code‑Katalog ODER graph‑defined (nur `input.form`) | Keine Runtime‑Schema‑Unsicherheit; deterministische Picker‑/AI‑Sicht |
|
||||
| 2026‑04‑23 | Kein `ai.extractStructured` | AI kann Schema‑Compliance nicht garantieren; UDM (`trustee.extractFromFiles`) + `trustee.queryData` decken strukturierte Extraktion ab |
|
||||
| 2026‑04‑23 | `data.transform` ersatzlos entfernen | Funktional redundant zu DataRefs am Konsumer |
|
||||
| 2026‑04‑23 | Connection als Hybrid: Source‑Picker + ConnectionRef‑Output + Downstream‑DataRef | Konsistente Picker‑UX, keine Secrets in Datenflüssen |
|
||||
| 2026‑04‑23 | Loop‑Scoping lexikalisch + `loop.item`/`loop.index` zusätzlich | Einfacher als Magic‑Envelope, native an Datenfluss‑Topologie |
|
||||
| 2026‑04‑23 | Hard Validation (Mismatch blockt Run) | Keine späten Runtime‑Überraschungen, klare Fehler |
|
||||
| 2026‑04‑23 | Greenfield + Migrations‑Skript, kein Fallback | Eine Wahrheit, Code‑Pfade einfach |
|
||||
| 2026‑04‑23 | `attachmentBuilder` als Alias auf `JsonEditor` (übergangsweise) | Pilot benötigt funktionierenden Renderer; richtiger Builder später |
|
||||
| 2026‑04‑23 | `ConnectionPicker` 3‑Modus (Link/Auto/Dropdown) bei Source‑Nodes | UX aus überholtem Plan übernommen, da pragmatisch |
|
||||
|
||||
## Umsetzungs-Checkliste
|
||||
|
||||
### Phase 0 — Plan‑Hygiene & Audit (markdown only)
|
||||
- [ ] Vorgänger‑Plan `wiki/c-work/1-plan/2026-04-graph-editor-node-config-fixes.md` als obsolet markieren (`<!-- status: obsolete -->`) und mit Forward‑Link auf diesen Plan versehen, dann nach `wiki/z-archive/` verschieben.
|
||||
- [ ] Anhang A „Schema‑Audit" am Ende dieses Plans pflegen (siehe unten): pro existierender Node Soll‑Schema (rekursiv, mit Provenienz wo relevant).
|
||||
|
||||
### Phase 1 — Schema‑Erweiterung (Backend)
|
||||
- [ ] `portTypes.py`: `PortField` erweitern um optional `fields: List[PortField]` (verschachtelt) und `itemSchema: PortField` (für Listen) und `enumValues: List[str]`.
|
||||
- [ ] `PORT_TYPE_CATALOG`: neue Entries `Document`, `FileItem`, `EmailItem`, `TaskItem`, `ConnectionRef { id, authority, label }`, `SharePointFolderRef { siteUrl, driveId, folderPath, label }`, `SharePointFileRef { …, fileName }`, `UdmPage`, `UdmBlock` (rekursive UDM‑Strukturen).
|
||||
- [ ] `DocumentList`, `FileList`, `EmailList`, `TaskList`: jeweils `itemSchema` referenziert auf den passenden Item‑Typ.
|
||||
- [ ] Pro Producer‑Output: Provenienz ergänzen (`source: SharePointFolderRef`, `connection: ConnectionRef` für `sharepoint.*`; analog für `email.*`, `clickup.*`, `trustee.*`).
|
||||
- [ ] `_normalizeToSchema` strict modus: fehlende required Felder → `RuntimeError` mit klarem Schema‑Compliance‑Hinweis.
|
||||
- [ ] `INPUT_EXTRACTORS` aus `portTypes.py` **entfernen** (alle Funktionen + Dict).
|
||||
|
||||
### Phase 2 — Adapter‑Anpassung (Backend, Action Library)
|
||||
- [ ] `methods/sharepoint/` Aktionen `findDocumentPath`, `readDocuments`, `listDocuments`, `downloadFileByPath`, `uploadFile`, `copyFile`: Output‑Builder erweitern um `source`, `connection`.
|
||||
- [ ] `methods/outlook/` analog: `connection` in jedem Output.
|
||||
- [ ] `methods/clickup/` analog.
|
||||
- [ ] `methods/trustee/` (`extractFromFiles`, `processDocuments`): UDM‑Output sauber rekursiv typisieren.
|
||||
- [ ] `methods/file/create`: Output‑Schema auf `Document` mappen.
|
||||
- [ ] Pro Adapter ein Compliance‑Test (`gateway/tests/integration/methods/test_<method>_schema_compliance.py`): mock + reale Mini‑Outputs gegen Soll‑Schema validiert.
|
||||
|
||||
### Phase 3 — Loop‑Scoping & DataPicker (Frontend)
|
||||
- [ ] `nodes/shared/scopeHelpers.ts` (neu): `computePickableScope(nodeId, graph, nodeTypes)` — BFS rückwärts via `connections` + transitive Loop‑Body‑Hierarchie; `unwrapListItemSchema(producerSchema, fieldPath)` für Loop‑Item‑Typ; `resolveTransitChain(nodeId, graph, nodeTypes)` für Transit‑Auflösung.
|
||||
- [ ] `DataPicker.tsx`:
|
||||
- rekursive Schema‑Navigation (verschachtelte `fields`, list `itemSchema` automatisch entpackt unter Loop‑Body).
|
||||
- pro umgebendem Loop zusätzlich Sektion „Loop ($loopNodeLabel)" mit `loop.item`, `loop.index`, `loop.total`.
|
||||
- Type‑Pills pro Pick: grün (identisch/kompatibel), gelb (saubere Coercion), rot (Mismatch).
|
||||
- System‑Sektion bleibt.
|
||||
- [ ] `dataRef.ts`: `DataRef` um `expectedType: string` erweitern; Helper `isCompatible(produced, accepted): "ok" | "coerce" | "mismatch"`.
|
||||
- [ ] Frontend‑Unit‑Tests für `scopeHelpers` und Picker‑Renderlogik.
|
||||
|
||||
### Phase 4 — Pick‑not‑Push: Executor‑Cleanup (Backend)
|
||||
- [ ] `actionNodeExecutor.py`: `_wireHandover` und alle Aufrufer **entfernen**.
|
||||
- [ ] `resolveParameterReferences` in `graphUtils.py`: nur noch `DataRef` / `SystemVar` / `Static` / graph‑defined; Helper `parseGraphDefinedSchema(node, paramKey) -> PortSchema`.
|
||||
- [ ] `validateGraph` in `graphUtils.py`: hart blockierend bei (a) fehlender Required‑Bindung, (b) Type‑Mismatch (mit `isCompatible`‑Logik vom Frontend angeglichen — gemeinsame TypeScript/Python Spec dokumentiert).
|
||||
- [ ] `executionEngine.executeGraph`: vor Schleifenstart `validateGraph`‑Aufruf; bei Fehler `RunValidationError` mit Liste pro betroffenem Node/Param.
|
||||
- [ ] `_resolveConnectionParam` bleibt, wird nach `resolveParameterReferences` gerufen (DataRef → ConnectionRef‑Dict → resolver liest `id`).
|
||||
|
||||
### Phase 5 — Auto‑Suggest UX beim Wire (Frontend)
|
||||
- [ ] `FlowCanvas.tsx`: bei Wire‑Connect (`onConnectionsChange`) die downstream‑Node‑Inputs gegen den neuen upstream‑Output prüfen.
|
||||
- [ ] Vorschlags‑Logik: Match nach (a) Parameter‑Name = Schema‑Field‑Name + Type‑Compat ok, (b) Type‑Compat ok mit eindeutigem Field. → DataRef‑Vorschläge.
|
||||
- [ ] Modal/Popover „Vorgeschlagene Bindings übernehmen?" mit Apply‑All / Per‑Item‑Akzept.
|
||||
- [ ] Bei genau einer eindeutigen Bindung pro Param: Direkt vorausgefüllt mit Undo‑Toast.
|
||||
- [ ] Connection‑Picker in Downstream‑Nodes wird zum **Hybrid‑Picker**: zeigt Static‑User‑Connection (Picker) ODER DataRef (auf `ConnectionRef`); bei aktivem upstream‑`ConnectionRef` wird DataRef vorgeschlagen.
|
||||
|
||||
### Phase 6 — `ConnectionPicker` 3‑Modus + Renderer‑Audit (Frontend)
|
||||
- [ ] `frontendTypeRenderers/index.tsx` `ConnectionPicker`: 3 Modi je nach Anzahl verfügbarer Connections für Authority — 0: Link auf User‑Connections‑Seite, 1: Auto‑Display ohne Dropdown, ≥2: Dropdown.
|
||||
- [ ] `attachmentBuilder` Alias auf `JsonEditor` einführen + Console‑Warnung im Fallthrough für unbekannte FrontendTypes.
|
||||
- [ ] FrontendType‑Audit gegen alle `nodeDefinitions/*.py`: jede dort verwendete `frontendType` muss in `FRONTEND_TYPE_RENDERERS` einen Renderer haben (oder klar kommentiert TODO).
|
||||
|
||||
### Phase 7 — AI Tool Surface (Backend + Agent)
|
||||
- [ ] `routeFeatureGraphicalEditor.py`: `GET /{instanceId}/upstream-paths/{nodeId}` → Liste `{producerNodeId, producerLabel, path, type, label, scopeOrigin: "data"|"loop"|"system"}`.
|
||||
- [ ] `nodeRegistry.py`: Response `nodeTypes` liefert vollständig rekursive `inputPorts.accepts` und `outputPorts.schema` (verschachtelt).
|
||||
- [ ] `serviceCenter/services/serviceAgent/workflowTools.py`: neues Tool `bindNodeParameter(workflowId, nodeId, paramName, dataRef|staticValue|systemVar)` mit Server‑seitiger Validation gegen Type‑Compat.
|
||||
- [ ] Prompt‑Update für Workflow‑Generation: KI generiert immer explizite DataRefs; nutzt `upstream-paths` zur Discovery.
|
||||
|
||||
### Phase 8 — `input.form` als graph‑defined Schema
|
||||
- [ ] `nodeDefinitions/input.py` `input.form.outputPorts`: ersetze `{schema: "FormPayload", dynamic: True, deriveFrom: "fields"}` durch `{schema: {kind: "fromGraph", parameter: "fields"}}`.
|
||||
- [ ] `parseGraphDefinedSchema(node, "fields")` in `graphUtils.py` (Backend) und Spiegel in `Automation2DataFlowContext.tsx` (Frontend) — gemeinsame Spec, getrennte Implementierung.
|
||||
- [ ] FieldBuilder im Frontend (`fieldBuilder` Renderer): erlaubt verschachtelte fields (object), Typed Items für Listen, Type‑Picker (`str/number/bool/date/datetime/object/list`).
|
||||
- [ ] Picker downstream zeigt `formNode.payload.<userField>` mit korrektem Type.
|
||||
|
||||
### Phase 9 — Migration bestehender Workflows
|
||||
- [ ] `scripts/migration/2026-04-pick-not-push-migration.py`:
|
||||
- lädt alle `AutoWorkflow.graph` aus `poweron_graphicaleditor`;
|
||||
- simuliert die alte `_wireHandover`‑Logik deterministisch;
|
||||
- schreibt explizite DataRefs in den Graph;
|
||||
- Trockenlauf‑Modus mit Diff‑Output;
|
||||
- Live‑Modus mit Backup‑Snapshot der DB vor Schreiben.
|
||||
- [ ] Unit‑Tests für die Migrations‑Funktion mit Beispiel‑Graphen (inkl. PWG‑Pilot).
|
||||
- [ ] Integration‑Test: PWG‑Pilot Workflow läuft nach Migration ohne erneutes Connection‑Prompting; n4/n10 nutzen DataRef auf n2.connection.
|
||||
- [ ] `data.transform` Nodes in alten Workflows: Migrations‑Skript gibt Warnung pro Vorkommen aus (manuell zu refactoren — kein Auto‑Cleanup, weil semantisch).
|
||||
|
||||
### Phase 10 — Dokumentation & Abschluss
|
||||
- [ ] `wiki/b-reference/gateway/automation.md`: Abschnitt „Pick‑not‑Push Handover" + Removed `INPUT_EXTRACTORS`.
|
||||
- [ ] `wiki/b-reference/gateway/workflow.md`: Abschnitt UDM/Loop/KI‑Badge ergänzen um neue Schema‑Tiefe und Loop‑Scoping.
|
||||
- [ ] `wiki/b-reference/frontend-nyla/architecture.md`: Abschnitt FlowEditor mit Type‑Compat, Auto‑Suggest, Hybrid‑Connection‑Picker.
|
||||
- [ ] `wiki/TOPICS.md`: Eintrag „Typed Generic Handover (build/done)" verlinken.
|
||||
- [ ] Plan‑Doc Status updaten und nach `c-work/2-build/` → `c-work/3-validate/` → `c-work/4-done/` durchschieben.
|
||||
|
||||
## Akzeptanzkriterien
|
||||
|
||||
| # | Kriterium (Given‑When‑Then) | Prio |
|
||||
|---|---------------------------|------|
|
||||
| 1 | Given PWG‑Pilot Workflow nach Migration, When ausgeführt, Then `n4 sharepoint.downloadFile` und `n10 email.draftEmail` erhalten ihre msft‑Connection per DataRef auf `n2.connection` ohne erneutes User‑Prompt; Run läuft erfolgreich durch | must |
|
||||
| 2 | Given Workflow mit Type‑Mismatch (z.B. `DocumentList` → `int` Param), When `validateGraph` aufgerufen, Then Validation‑Error mit Path/Param‑Liste; When `executeGraph` aufgerufen, Then sofortiger `RunValidationError` ohne Adapter‑Aufruf | must |
|
||||
| 3 | Given Workflow mit `flow.foreach` über `nodeX.documents`, When im Body‑Node DataPicker geöffnet, Then Sektion „Loop (foreachLabel)" zeigt `loop.item: Document`, `loop.index: int`, `loop.total: int`; outer scope inkl. `nodeX.connection`, `nodeX.source` weiterhin pickbar | must |
|
||||
| 4 | Given `input.form` mit User‑definierten Feldern `{mieter: str, betrag: number}`, When downstream DataPicker geöffnet, Then `formNode.payload.mieter` (str) und `formNode.payload.betrag` (number) sind separat pickbar mit korrekten Typ‑Pills | must |
|
||||
| 5 | Given AI Agent generiert neuen Workflow, When `GET /{instanceId}/upstream-paths/{nodeId}` aufgerufen, Then strukturierte Pfad‑Liste mit `producerNodeId`, `path`, `type`, `label`, `scopeOrigin` zurück; KI generiert valide DataRefs ohne leere `connectionReference`‑Felder | must |
|
||||
| 6 | Given Migrations‑Skript Trockenlauf auf bestehenden Workflows, When ausgeführt, Then für jede Node mit implizitem Wire‑Handover wird ein expliziter DataRef‑Vorschlag im Diff angezeigt; When Live‑Lauf, Then alle Workflows passieren `validateGraph` ohne Fehler | must |
|
||||
| 7 | Given DataPicker‑Bindung mit perfekt passendem Typ, When User pickt, Then grünes Pill; bei sauberer Coercion (`int → str`) gelb mit Hinweis; bei Mismatch (`DocumentList → int`) rot und Save‑Button blockiert | should |
|
||||
| 8 | Given Wire zwischen zwei Nodes neu gezogen, When Auto‑Suggest aktiv, Then Modal listet alle nach Name+Type matchenden Bindings; bei eindeutigem Match wird vorausgefüllt mit Undo‑Toast | should |
|
||||
| 9 | Given `ConnectionPicker` für Authority `msft` und User hat 0 Connections, Then Link „Connection erstellen" statt Dropdown; bei 1 Connection Auto‑Display; bei ≥2 Dropdown | should |
|
||||
| 10 | Given Source‑Adapter `methods/sharepoint/listDocuments`, When ausgeführt, Then Output enthält `connection: ConnectionRef`, `source: SharePointFolderRef`, `documents: List[Document]` mit voll typisierten Document‑Items | must |
|
||||
| 11 | Given `data.transform` Node in altem Workflow, When Migrations‑Skript läuft, Then Warning im Diff (kein Auto‑Removal); After Cleanup‑Pass: `data.transform` aus `nodeRegistry` entfernt | should |
|
||||
|
||||
## Testplan
|
||||
|
||||
| ID | AC | Art | Automatisiert | Repo‑Pfad | Status |
|
||||
|----|----|-----|--------------|-----------|--------|
|
||||
| T1 | 1 | integration | ja | `gateway/tests/integration/graphicalEditor/test_pwg_pilot_typed.py` | pending |
|
||||
| T2 | 2 | unit | ja | `gateway/tests/unit/graphicalEditor/test_validate_typed_hard.py` | pending |
|
||||
| T3 | 3 | frontend unit | ja | `frontend_nyla/src/components/FlowEditor/__tests__/dataPicker.scope.test.ts` | pending |
|
||||
| T4 | 4 | frontend unit + backend unit | ja | `frontend_nyla/.../__tests__/dataPicker.formSchema.test.ts` + `gateway/tests/unit/graphicalEditor/test_parse_graph_defined_schema.py` | pending |
|
||||
| T5 | 5 | api | ja | `gateway/tests/integration/graphicalEditor/test_upstream_paths_api.py` | pending |
|
||||
| T6 | 6 | migration | ja | `gateway/tests/unit/migration/test_pick_not_push_migration.py` | pending |
|
||||
| T7 | 7 | frontend unit | ja | `frontend_nyla/.../__tests__/dataPicker.typeCompat.test.ts` | pending |
|
||||
| T8 | 8 | frontend e2e | ja (Playwright opt) | `frontend_nyla/tests/e2e/wireAutoSuggest.spec.ts` | pending |
|
||||
| T9 | 9 | frontend unit | ja | `frontend_nyla/.../__tests__/connectionPicker.modes.test.ts` | pending |
|
||||
| T10 | 10 | api/integration | ja | `gateway/tests/integration/methods/test_sharepoint_schema_compliance.py` (+ `_outlook`, `_clickup`, `_trustee`, `_file`) | pending |
|
||||
| T11 | 11 | unit | ja | `gateway/tests/unit/migration/test_data_transform_warning.py` | pending |
|
||||
|
||||
## Links
|
||||
|
||||
- Vorgänger (done): `wiki/c-work/4-done/2026-04-generic-graph-editor.md`
|
||||
- Vorgänger (obsolet, in Phase 0 zu archivieren): `wiki/c-work/1-plan/2026-04-graph-editor-node-config-fixes.md`
|
||||
- Pilot‑Bezug: `wiki/c-work/4-done/2026-04-pwg-pilot-mietzinsbestaetigung-workflow.md`
|
||||
- Beispiel‑Workflow für Smoke‑Test: `local/temp/pwg-pilot-jahresmietzinsbestätigung.workflow (1).json`
|
||||
- PR: TBD
|
||||
- Issue: TBD
|
||||
|
||||
## Abschluss
|
||||
|
||||
- [ ] `wiki/b-reference/gateway/automation.md` aktualisiert (Pick‑not‑Push, Removed Heuristik)
|
||||
- [ ] `wiki/b-reference/gateway/workflow.md` aktualisiert (Schema‑Tiefe, Loop‑Scoping)
|
||||
- [ ] `wiki/b-reference/frontend-nyla/architecture.md` aktualisiert (FlowEditor‑Erweiterungen)
|
||||
- [ ] `wiki/TOPICS.md` aktualisiert (neuer Eintrag „Typed Generic Handover")
|
||||
- [ ] Dieses Dokument → `wiki/z-archive/` verschoben
|
||||
|
||||
---
|
||||
|
||||
## Anhang A — Schema‑Audit (Soll‑Stand pro Node‑Output)
|
||||
|
||||
> Wird in Phase 0 vollständig befüllt; hier die Zielform und der Anfang der Inhalte. Stand `PORT_TYPE_CATALOG` heute siehe `gateway/modules/features/graphicalEditor/portTypes.py:59–170`.
|
||||
|
||||
### Neue / erweiterte Item‑Schemas im Katalog
|
||||
|
||||
| Schema | Felder (Kurzform) | Anmerkung |
|
||||
|--------|-------------------|-----------|
|
||||
| `Document` | `id, name, mimeType, sizeBytes, downloadUrl, source: SharePointFileRef?` | Item für `DocumentList`; Provenienz optional je nach Producer |
|
||||
| `FileItem` | `id, name, path, mimeType, sizeBytes, modifiedAt` | Item für `FileList` |
|
||||
| `EmailItem` | `id, subject, from, to, receivedAt, hasAttachments, bodyPreview` | Item für `EmailList` |
|
||||
| `TaskItem` | `id, title, status, assignee, dueDate, listId` | Item für `TaskList` |
|
||||
| `ConnectionRef` | `id, authority, label` | **keine Secrets** — nur Identifikator |
|
||||
| `SharePointFolderRef` | `siteUrl, driveId, folderPath, label` | Provenienz für SharePoint‑Listings |
|
||||
| `SharePointFileRef` | `siteUrl, driveId, filePath, fileName, label` | Provenienz für einzelne SharePoint‑Files |
|
||||
| `UdmPage` | `pageNumber, blocks: List[UdmBlock]` | UDM‑Seite |
|
||||
| `UdmBlock` | `kind, text, children?: List[UdmBlock]` | UDM‑Block (rekursiv) |
|
||||
|
||||
### Anreicherung bestehender Output‑Schemas
|
||||
|
||||
| Schema | Heute | Soll |
|
||||
|--------|-------|------|
|
||||
| `DocumentList` | `documents: List[Document]` | `+ source: SharePointFolderRef? + connection: ConnectionRef? + count: int` |
|
||||
| `FileList` | `files: List[File]` | `+ source: SharePointFolderRef? + connection: ConnectionRef? + count: int`; `itemSchema` = `FileItem` |
|
||||
| `EmailList` | `emails: List[Email]` | `+ connection: ConnectionRef? + count: int`; `itemSchema` = `EmailItem` |
|
||||
| `TaskList` | `tasks: List[Task]` | `+ connection: ConnectionRef? + listId? + count: int`; `itemSchema` = `TaskItem` |
|
||||
| `EmailDraft` | `subject, body, to, cc?, attachments?` | `+ connection: ConnectionRef?` |
|
||||
| `AiResult` | flat | bleibt, `responseData` weiterhin `Dict` (nicht typisiert — bewusst, weil AI‑Antwort) |
|
||||
| `UdmDocument` | `id, sourceType, sourcePath, children: List[Any]` | `children: List[UdmPage]` (rekursiv typisiert) |
|
||||
| `ActionResult` | `success, error?, data?` | bleibt; `data` ist `Dict` (catch‑all für nicht‑typisierte Adapter) |
|
||||
| `Transit` | leer | bleibt — Picker folgt Transit‑Chain |
|
||||
|
||||
### Pro Node‑Definition (Auszug — vollständig in Phase 0)
|
||||
|
||||
| Node | Output heute | Output Soll |
|
||||
|------|--------------|-------------|
|
||||
| `sharepoint.findFile` | `FileList` | `FileList` mit `source`, `connection` befüllt |
|
||||
| `sharepoint.listFiles` | `FileList` | `FileList` mit `source`, `connection` befüllt |
|
||||
| `sharepoint.downloadFile` | `DocumentList` | `DocumentList` mit `source`, `connection` befüllt |
|
||||
| `sharepoint.readFile` | `DocumentList` | `DocumentList` mit `source`, `connection` befüllt |
|
||||
| `email.draftEmail` | `EmailDraft` | `EmailDraft` mit `connection` befüllt |
|
||||
| `email.checkEmail` | `EmailList` | `EmailList` mit `connection` befüllt |
|
||||
| `clickup.searchTasks` | `TaskList` | `TaskList` mit `connection`, `listId` befüllt |
|
||||
| `trustee.extractFromFiles` | `UdmDocument` | `UdmDocument` mit voll typisierten `children: List[UdmPage]` |
|
||||
| `trustee.queryData` | `Dict` (heute) | typisiertes `QueryResult { rows: List[Dict], schema: List[ColumnSchema] }` (neuer Eintrag im Katalog) |
|
||||
| `input.form` | `FormPayload` (`dynamic`) | `{kind:"fromGraph", parameter:"fields"}` — graph‑defined |
|
||||
| `data.transform` | (vorhanden) | **entfernt** |
|
||||
| `data.aggregate` | `AggregateResult` | bleibt, `items: List[Any]` (generisch über Loop‑Item‑Typ) |
|
||||
| `data.consolidate` / `ai.consolidate` | `ConsolidateResult` | bleibt |
|
||||
|
||||
204
c-work/4-done/2026-04-graph-editor-node-config-fixes.md
Normal file
204
c-work/4-done/2026-04-graph-editor-node-config-fixes.md
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
<!-- status: obsolete -->
|
||||
<!-- started: 2026-04-23 -->
|
||||
<!-- obsoletedAt: 2026-04-23 -->
|
||||
<!-- supersededBy: c-work/1-plan/2026-04-typed-generic-handover.md -->
|
||||
<!-- component: gateway | frontend-nyla -->
|
||||
<!-- relatedTo: c-work/4-done/2026-04-generic-graph-editor.md, c-work/4-done/2026-04-pwg-pilot-mietzinsbestaetigung-workflow.md -->
|
||||
|
||||
> **Obsolet — ersetzt durch [`c-work/1-plan/2026-04-typed-generic-handover.md`](../1-plan/2026-04-typed-generic-handover.md).**
|
||||
>
|
||||
> Dieser Plan behandelte die Symptome (Connection-Inheritance-Service, Wire-Source-Badge, attachmentBuilder-Alias) als Workarounds um den heuristischen `_wireHandover` herum. Die Diskussion vom 2026‑04‑23 hat ergeben, dass das Modell selbst nicht trägt: der „Push"-Handover via `INPUT_EXTRACTORS` ist generisch nicht beherrschbar. Der Nachfolge-Plan ersetzt das durch ein **Pick-not-Push** Modell mit reichhaltigen statischen Schemas, harter Type-Validierung und expliziten DataRefs als einzigem Bindungs-Mechanismus. Drei Punkte aus diesem Plan (3-Modus `ConnectionPicker`, `attachmentBuilder` Renderer-Alias, FrontendType-Audit) wurden in den Nachfolger als Phase 6 übernommen.
|
||||
|
||||
# Graph-Editor: Connection-UX, Wire-Handover und Feld-Rendering bereinigen (obsolet)
|
||||
|
||||
## Beschreibung und Kontext
|
||||
|
||||
Der Graphical Editor (`graphicalEditor`-Feature) ist seit dem Generic-Graph-Editor-Refactor (`c-work/4-done/2026-04-generic-graph-editor.md`) auf typisierte Ports + Wire-Handover umgestellt. Beim Pilot-Workflow PWG Mietzinsbestaetigung (`local/temp/pwg-pilot-jahresmietzinsbestätigung.workflow (1).json`) zeigen sich vier konkrete Schwachstellen, die das User-Erlebnis im Editor brechen:
|
||||
|
||||
1. **Connection wird pro Node neu erfragt.** Im PWG-Workflow ist `n2.sharepoint.listFiles` mit `connection:msft:p.motsch@valueon.ch` konfiguriert. `n4.sharepoint.downloadFile` und `n10.email.draftEmail` haben dieselbe Authority (`msft`), aber `connectionReference: ""`. Der `_wireHandover` in `gateway/modules/workflows/automation2/executors/actionNodeExecutor.py` propagiert nur Port-Schema-Felder (`documents`, `emails`, ...) via `INPUT_EXTRACTORS` (`gateway/modules/features/graphicalEditor/portTypes.py`). `connectionReference` wird nirgends weitergereicht. Folge: jede Node fragt erneut nach Connection.
|
||||
2. **`ConnectionPicker` immer als Dropdown.** `frontend_nyla/src/components/FlowEditor/nodes/frontendTypeRenderers/index.tsx` (`ConnectionPicker`, Z. 153–198) rendert immer `<select>` und einen Hilfstext, wenn keine Connection da ist — aber **keinen Link** auf die User-Connections-Seite, und auch bei genau **einer** Connection bleibt es ein Dropdown statt einer Direktanzeige.
|
||||
3. **Nicht alle Felder rendern sauber.** `email.draftEmail.attachments` deklariert `frontendType: attachmentBuilder` (`gateway/modules/features/graphicalEditor/nodeDefinitions/email.py:88`). In `FRONTEND_TYPE_RENDERERS` (`frontendTypeRenderers/index.tsx:608–633`) gibt es **keinen** `attachmentBuilder`-Renderer → Fallback auf `TextInput`, das den JSON-Array stringifiziert anzeigt. `clickupList` / `clickupTask` mappen auf einen generischen `FolderPicker` (Plain-Textfeld), nicht auf einen echten ClickUp-Picker.
|
||||
4. **Handovers zwischen Nodes sind nicht klar.** In der Property-Panel-Ansicht (`NodeConfigPanel.tsx`) ist die "Datenfluss"-Sektion in `<details>` versteckt und zeigt nur abstrakte Port-Schemas (`DocumentList`, `AiResult`). Es ist für den User unsichtbar, **welcher Parameter** automatisch via Wire befüllt wird, **aus welchem Upstream-Node** und mit welchem Feld. Dadurch entsteht der Eindruck, der User müsse alles selbst eingeben.
|
||||
|
||||
**Business-Treiber:** PWG-Pilot startet im Sommer 2026. Editor-UX muss verständlich sein, sonst kostet die Demo-Vorführung beim Kunden Vertrauen. Auch jeder weitere Workflow-Bauer (intern + Customer Onboarding) profitiert sofort.
|
||||
|
||||
**Risiko bei Nicht-Umsetzung:** PWG-Pilot-User (und Demo-Publikum) erlebt den Editor als „alles muss ich von Hand eintragen" und „Das System weiss nicht, dass ich nur einen Outlook habe". Schwer zu verkaufen.
|
||||
|
||||
**Abhaengigkeiten:** keine externen. Greift in bereits ausgelieferte (done) Komponenten ein:
|
||||
- `c-work/4-done/2026-04-generic-graph-editor.md` (Typed-Port-System, Wire-Handover-Mechanik)
|
||||
- `c-work/4-done/2026-04-pwg-pilot-mietzinsbestaetigung-workflow.md` (Pilot-Workflow + `email.draftEmail.attachments`)
|
||||
|
||||
## Fokus und kritische Details
|
||||
|
||||
- **Connection-Inheritance ist Greenfield-Erweiterung der Wire-Handover-Mechanik.** Der bestehende `_wireHandover` in `actionNodeExecutor.py` arbeitet auf der **direkten Vorgaenger-Node** und nur fuer Schema-Felder. Connection-Inheritance braucht einen anderen Algorithmus: **transitive Suche nach Authority** durch den Upstream-Pfad — aktuell verwendet noch keiner so etwas. Fragil: wenn mehrere Upstream-Pfade unterschiedliche Authorities ihrer User-Connection nutzen (z.B. `flow.merge` mit Outlook + ClickUp), darf nichts blind uebernommen werden.
|
||||
- **Frontend- und Backend-Inheritance muessen konsistent sein.** Wenn das Frontend per Default einen Wert fuer `connectionReference` setzt (Auto-Fill), wird er beim Save persistiert und ist genauso explizit wie eine User-Wahl. Backend-Fallback ("wenn leer, suche Upstream") ist die zweite Verteidigungslinie fuer alte/manuell editierte Workflows. **Beides bauen, aber Frontend ist Hauptmechanismus** — sonst sieht der User auf dem Canvas nicht, dass die Node "weiss, was sie tun wird".
|
||||
- **`ConnectionPicker` braucht 3 Modi.** Code muss klar zwischen den Faellen unterscheiden — kein Dropdown wenn 0 oder 1 Connection. Bei 0 Connections: Link auf `/profile/connections` (siehe `ConnectionsPage.tsx`) mit Authority-Vorausfilter und Rueckkehr-URL.
|
||||
- **`attachmentBuilder` muss entweder echt gebaut oder zu `json` redirected werden.** Im Pilot-Plan (`c-work/4-done/2026-04-pwg-pilot-mietzinsbestaetigung-workflow.md`, Sub-Task 4b) wurde explizit "NICHT NÖTIG" entschieden — aber dann muss der Fallback wenigstens **`JsonEditor`** sein (kompakter Editor mit Syntax-Hint), nicht ein 1-zeiliges Text-Field. Pragmatisch: Alias `attachmentBuilder → json` registrieren, damit kein zweiter Renderer noetig ist.
|
||||
- **`clickupList` / `clickupTask` Stubs** koennen separat gefixt werden (eigene Iteration), sind kein Blocker fuer den PWG-Pilot. Hier nur als bekannt-Stub markieren und auf `text` mit Hinweis "ClickUp-Picker tbd" mappen.
|
||||
- **Datenfluss-Sichtbarkeit muss inline pro Parameter rendern**, nicht in einem versteckten `<details>`-Block. Pro Parameter, der per `INPUT_EXTRACTORS` aus dem Upstream-Output befuellbar ist, ein Badge `🔗 Wire: {srcNode} → {schemaField}`. Pro `connectionReference` mit gefundenem Upstream-Match: Badge `🔗 uebernommen aus {srcNode}`.
|
||||
- **Keine Node-Type-spezifische Logik im Frontend.** Alle Inheritance-Regeln per Daten gesteuert: Backend liefert pro Parameter eine Liste `wireSources: [{nodeId, fieldPath, schema}]`, das Frontend rendert generisch. Sonst wird der Renderer wieder zu einer Sammlung von Spezialfaellen.
|
||||
|
||||
## Ziel und Nicht-Ziele
|
||||
|
||||
**Ziel:**
|
||||
- Beim Anlegen einer neuen Node mit `connectionReference`-Parameter wird die Connection **automatisch vorbelegt**, wenn entweder (a) der User genau **eine** Connection mit passender `authority` hat oder (b) ein Upstream-Pfad bereits eine `connectionReference` derselben `authority` verwendet.
|
||||
- `ConnectionPicker` zeigt 3 Zustaende:
|
||||
- **0 Connections (passende Authority):** Link "Verbindung anlegen" -> `/profile/connections?authority=msft&returnTo=...`.
|
||||
- **1 Connection:** Direktanzeige `[msft] p.motsch@valueon.ch` mit kleinem "Aendern"-Link, der das Dropdown sichtbar macht.
|
||||
- **>1 Connections:** Dropdown wie heute.
|
||||
- Backend-Fallback: ist beim Run `connectionReference` leer und es gibt **eindeutig** einen Upstream-Wert mit derselben Authority, wird er verwendet (und im `AutoStepLog.inputSnapshot` markiert: `"connectionReference_inferredFrom": "n2"`).
|
||||
- `attachmentBuilder`-Felder rendern als `JsonEditor` (Alias-Mapping), bis ein dedizierter Builder gebaut wird — nicht mehr als 1-zeiliges Text-Field.
|
||||
- Im Property-Panel sieht der User pro Parameter, ob er via Wire befuellt wird (Badge mit Quell-Node + Feldname). `connectionReference`-Parameter zeigen "uebernommen aus {nodeId}" wenn auto-inferred.
|
||||
- API liefert pro Node-Inspector-Aufruf zusaetzlich eine `wireSources`-Map: pro Parameter-Name eine Liste der moeglichen/aktiven Wire-Quellen (basierend auf Graph + `INPUT_EXTRACTORS`).
|
||||
|
||||
**Explizit NICHT:**
|
||||
- Keine Aenderung am Wire-Handover-Algorithmus fuer Schema-Felder (`documents`, `emails`, ...). Der bleibt wie er ist.
|
||||
- Keine neuer Picker fuer `clickupList`/`clickupTask`. Diese bleiben als „bekannte Luecken" markiert; eigene Iteration.
|
||||
- Kein dedizierter `AttachmentBuilder`-Renderer. Alias auf `JsonEditor` reicht. Wird in einer Folgeiteration nachgereicht, wenn Mehrnode-Cases das verlangen.
|
||||
- Keine Migration alter Workflows. Wer leere `connectionReference` hat, profitiert ab sofort vom Backend-Fallback; wer eine fixierte (auch falsche) hat, behaelt sie.
|
||||
- Keine Aenderung an der RBAC-/Permission-Schicht. User sieht nur Connections, die er ohnehin sehen darf (`getUserConnections(userId)` ist bereits user-scoped).
|
||||
- Keine Persistenz der Inferenz-Entscheidung in der Workflow-DB. Inferenz ist immer Run-Time-Heuristik (Frontend setzt explizit, Backend faellt nur defensiv zurueck).
|
||||
|
||||
## Betroffene Module
|
||||
|
||||
- **Gateway:**
|
||||
- `gateway/modules/workflows/automation2/executors/actionNodeExecutor.py` — neuer Helper `_inferConnectionFromUpstream(nodeDef, inputSources, nodeOutputs, allNodes, params)`, vor `_resolveConnectionParam` aufgerufen.
|
||||
- `gateway/modules/features/graphicalEditor/routeFeatureGraphicalEditor.py` — `node-types`-Endpoint bzw. ein neuer `wire-sources`-Endpoint (oder Integration in `GET /{instanceId}/workflows/{workflowId}/wire-sources?nodeId=...`) liefert pro Node-Parameter die moeglichen Wire-Quellen.
|
||||
- `gateway/modules/features/graphicalEditor/wireSourcesService.py` (NEU, klein) — Pure-Helper `computeWireSources(graph, nodeId)` der pro Parameter listet, woher Wire/Connection-Inheritance kommen koennten.
|
||||
- **Frontend:**
|
||||
- `frontend_nyla/src/components/FlowEditor/nodes/frontendTypeRenderers/index.tsx` — `ConnectionPicker` ueberarbeiten (3 Modi), `attachmentBuilder`-Alias auf `JsonEditor`, `clickupList`/`clickupTask` mit Hint-Text.
|
||||
- `frontend_nyla/src/components/FlowEditor/editor/NodeConfigPanel.tsx` — pro Parameter Wire-Source-Badge inline rendern; "Datenfluss"-Sektion umbauen oder entfernen, wenn alles inline gezeigt wird.
|
||||
- `frontend_nyla/src/components/FlowEditor/editor/Automation2FlowEditor.tsx` (oder dort, wo eine neue Node erzeugt wird) — Frontend-Auto-Fill: bei Add-Node mit `connectionReference`-Param + 1 passende Connection → vorbelegen; oder Upstream-Pfad scannen und passende `connectionReference` uebernehmen.
|
||||
- `frontend_nyla/src/api/workflowApi.ts` — neue Wrapper fuer `wire-sources`-Endpoint.
|
||||
- **DB-Migration:** **nein**.
|
||||
- **Andere:** `wiki/b-reference/gateway/automation.md` Ergaenzung "Connection-Inheritance" und "Wire-Sources-API" am Ende der Iteration (siehe Abschluss).
|
||||
|
||||
## Entscheidungen
|
||||
|
||||
| Datum | Entscheidung | Begruendung |
|
||||
|-------|-------------|-------------|
|
||||
| 2026-04-23 | Connection-Inheritance: Frontend Auto-Fill (primaer) + Backend Run-Time Fallback (defensiv) | UI muss zeigen "ich weiss, welche Connection" — nur Backend-Fallback waere unsichtbar; nur Frontend laesst alte/importierte Workflows leer |
|
||||
| 2026-04-23 | Authority-Match-Regel: gleiche `frontendOptions.authority` UND gleiche Connection im Upstream-Pfad UND eindeutig (kein Konflikt) | Konservativ: lieber unausgefuellt lassen als falsche Connection einsetzen |
|
||||
| 2026-04-23 | `ConnectionPicker`: 0 Connections → Link auf `/profile/connections?authority=...` | Einheitlich mit dem bestehenden `ConnectionsPage.tsx`; Filter fuer den schnellen Anlege-Pfad |
|
||||
| 2026-04-23 | `attachmentBuilder` → `JsonEditor` als Alias (nicht eigener Renderer) | Pilot-Plan hat Builder explizit gestrichen; Alias verhindert kaputten 1-zeiligen Text-Fallback |
|
||||
| 2026-04-23 | `clickupList`/`clickupTask` bleiben Stubs — Hint-Text "ClickUp-Picker tbd" | Nicht im Scope dieser Iteration; eigene Folge-Iteration |
|
||||
| 2026-04-23 | Wire-Source-Anzeige inline pro Parameter, nicht in `<details>` | Sichtbarkeit ist der Hauptpunkt des Issues — alles, was hinter Click verborgen ist, gilt nicht als geloest |
|
||||
| 2026-04-23 | `wireSources` als Server-berechnetes Datum (kein Frontend-Re-Implement der Extractor-Logik) | Single Source of Truth; vermeidet Drift zwischen FE/BE Extractor-Mappings |
|
||||
|
||||
## Umsetzungs-Checkliste
|
||||
|
||||
### Phase 1 — Connection-Inheritance Backend
|
||||
|
||||
- [ ] `gateway/modules/features/graphicalEditor/wireSourcesService.py` (NEU): Pure-Helper, der fuer eine Node alle Upstream-Nodes (transitiv via `connections`) liefert. Pro Connection-Authority-Konflikt → kein Vorschlag (`None`); sonst die einzige passende `connectionReference`.
|
||||
- [ ] `gateway/modules/workflows/automation2/executors/actionNodeExecutor.py`: neuer Helper `_inferConnectionFromUpstream(nodeDef, context, params)` ruft den oben gebauten Service. Wird vor `_resolveConnectionParam` aufgerufen, nur wenn `connectionReference` leer und der Parameter `authority` gesetzt ist.
|
||||
- [ ] In `AutoStepLog.inputSnapshot` zusaetzliches Feld `connectionReference_inferredFrom: <nodeId>` schreiben, wenn der Fallback griff. Nutzt das bestehende Step-Logging (`workflows/automation2/executionEngine.py`).
|
||||
- [ ] Unit-Test `gateway/tests/unit/graphicalEditor/test_wireSourcesService.py`:
|
||||
- Linear: 3 Nodes, n1 hat msft-Connection, n3 erbt.
|
||||
- Konflikt: n1 hat msft-User-A, n2 hat msft-User-B (per merge-Pfad), n3 darf nichts erben.
|
||||
- Keine Authority im Param → kein Vorschlag.
|
||||
- Loop-Body-Node erbt von Loop-Header-Vorgaenger (durchgereicht).
|
||||
|
||||
### Phase 2 — Wire-Sources API
|
||||
|
||||
- [ ] `gateway/modules/features/graphicalEditor/routeFeatureGraphicalEditor.py`: neuer Endpoint `POST /{instanceId}/wire-sources` mit Body `{ graph: { nodes, connections }, nodeId }` → Response `{ parameters: { <paramName>: [{ srcNodeId, srcField, schema, kind: "wire"|"connection" }] } }`. POST damit Editor-Drafts (noch nicht persistiert) abfragen koennen.
|
||||
- [ ] Zugriffspruefung wie bei `node-types` (`_validateInstanceAccess`).
|
||||
- [ ] Unit/API-Test `gateway/tests/integration/graphicalEditor/test_wire_sources.py` mit dem PWG-Pilot-Workflow als Fixture.
|
||||
|
||||
### Phase 3 — `ConnectionPicker` 3-Modus-UX
|
||||
|
||||
- [ ] `frontend_nyla/src/components/FlowEditor/nodes/frontendTypeRenderers/index.tsx` `ConnectionPicker`:
|
||||
- Zustaende ableiten aus `connections.length`.
|
||||
- 0: Kontext-Link `<a href="/profile/connections?authority=${authority}">Verbindung anlegen</a>`. (Pruefen: existiert die `ConnectionsPage.tsx`-Route mit `authority`-Query-Filter? Falls nein, in Phase 3 trivial ergaenzen.)
|
||||
- 1: Direkt-Anzeige `[<authority>] <label>`, kleines `Aendern`-Link blendet ein `<select>` ein (lokaler State `expanded`); Save-Klick auf andere Option setzt direkt. Wenn `value` leer ist, wird die einzige Connection als Default sofort `onChange` gefeuert (Auto-Save).
|
||||
- >1: aktuelles Dropdown bleibt.
|
||||
- [ ] Frontend-Helper `useAutomation2DataFlow` (oder analog) liefert `wireSources` aus dem neuen Endpoint; bei `connectionReference` mit gefundenem Vorschlag wird der Vorschlag als Default genommen.
|
||||
- [ ] Klein-Refactor: `connections`-Loading aus `ConnectionPicker` in einen geteilten Hook `useUserConnections(authority)` ziehen, damit auch `Automation2FlowEditor.tsx` (Add-Node-Auto-Fill) ihn nutzen kann ohne erneuten Fetch.
|
||||
- [ ] Manueller UI-Smoke-Test gegen jede der 3 Branches dokumentieren.
|
||||
|
||||
### Phase 4 — Frontend Auto-Fill bei Add-Node und beim Wire
|
||||
|
||||
- [ ] `Automation2FlowEditor.tsx` (oder dem Add-Node-Code-Pfad): wenn neue Node erzeugt wird, die einen `connectionReference`-Parameter mit `frontendOptions.authority` hat → `wireSources`-API aufrufen (oder lokal `useUserConnections(authority)`) und `params.connectionReference = inferredOrSingle`.
|
||||
- [ ] Wenn Edge gezogen wird (`onConnectionsChange`), automatisch `wireSources` neu auffrischen → Downstream-Nodes aktualisieren ggf. ihre Default-`connectionReference`. **Nicht** ueberschreiben, wenn der User bereits einen abweichenden Wert gesetzt hat (verifiziert via `wasUserSet`-Flag im Node-State oder: nur setzen wenn `connectionReference === ""`).
|
||||
- [ ] Test (manuell, dokumentiert): Workflow PWG laden → n4/n10 sollten beim Oeffnen automatisch die msft-Connection aus n2 anzeigen.
|
||||
|
||||
### Phase 5 — Wire-Source-Badge im Property-Panel
|
||||
|
||||
- [ ] `frontend_nyla/src/components/FlowEditor/editor/NodeConfigPanel.tsx`:
|
||||
- Pro Parameter, der in `wireSources[paramName]` mindestens einen Eintrag hat: kleiner Badge unter dem Label `🔗 {srcLabel}.{srcField}` (Tooltip: Schema). Wenn der Wert aktuell leer ist, den Badge in Vordergrund-Farbe rendern (= "wird live befuellt"). Wenn der User einen expliziten Wert hat, schwaecher (= "Override aktiv").
|
||||
- Fuer `connectionReference` mit Vorschlag: Badge `🔗 uebernommen aus {srcNode}`.
|
||||
- Bestehender `<details>`-Block "Datenfluss" wird **schlanker**: zeigt nur noch die Port-Schemas (Eingabe / Ausgabe) als Referenz, nicht mehr als zentrale Erklaerung — die zentrale Erklaerung steht jetzt inline.
|
||||
- [ ] Smoke-Test gegen den PWG-Pilot: Klick durch jede Node, Badges zeigen plausible Quellen.
|
||||
|
||||
### Phase 6 — `attachmentBuilder` Alias + Renderer-Audit
|
||||
|
||||
- [ ] In `frontendTypeRenderers/index.tsx` `FRONTEND_TYPE_RENDERERS` ergaenzen: `attachmentBuilder: JsonEditor` (oder ein Wrapper mit Hint `Felder: contentRef | csvFromVariable | base64Content`).
|
||||
- [ ] Pruefen: gibt es weitere im Backend genutzte `frontendType`-Werte ohne Renderer? (Aktueller Stand: nein — `attachmentBuilder` ist die einzige Luecke; `clickupList`/`clickupTask` zeigen aktuell `FolderPicker`-Stub.)
|
||||
- [ ] Im fallthrough `?? FRONTEND_TYPE_RENDERERS.text`: Console-Warning `[FlowEditor] Missing renderer for frontendType=... (param=...)` damit zukuenftige Luecken sichtbar werden.
|
||||
|
||||
### Querschnitt
|
||||
|
||||
- [ ] **API-Endpunkte:** ja, 1 neuer (`POST /{instanceId}/wire-sources`).
|
||||
- [ ] **DB-Schema / Migration:** **nein**.
|
||||
- [ ] **Frontend-Komponenten:** `ConnectionPicker` + `NodeConfigPanel` + Add-Node-Pfad in `Automation2FlowEditor`.
|
||||
- [ ] **RBAC / Permissions:** unveraendert; `wire-sources`-API bleibt instanz-scoped.
|
||||
- [ ] **Neutralisierung betroffen?** Nein — keine sensiblen Daten ausserhalb der bestehenden Pfade.
|
||||
- [ ] **Navigation / Routing:** `/profile/connections?authority=...` Filter pruefen / ggf. ergaenzen.
|
||||
- [ ] **Billing-Impact?** Nein.
|
||||
|
||||
## Akzeptanzkriterien
|
||||
|
||||
| # | Kriterium (Given-When-Then) | Prio |
|
||||
|---|----------------------------|------|
|
||||
| 1 | Given User mit genau **einer** msft-Connection, When eine neue `email.draftEmail`-Node hinzugefuegt wird, Then ist `connectionReference` automatisch vorbelegt mit dieser Connection (kein Klick noetig). | must |
|
||||
| 2 | Given Workflow mit n2 (msft-Connection gesetzt) → n4 (msft, leer) → n10 (msft, leer), When der User n4 oder n10 oeffnet, Then zeigt der `ConnectionPicker` die uebernommene Connection inkl. Badge `🔗 uebernommen aus n2`. | must |
|
||||
| 3 | Given User ohne msft-Connection, When `email.draftEmail`-Node oeffnet, Then zeigt `ConnectionPicker` einen Link "Verbindung anlegen" auf `/profile/connections?authority=msft` (kein leeres Dropdown). | must |
|
||||
| 4 | Given User mit 3 msft-Connections, When `sharepoint.listFiles`-Node oeffnet, Then erscheint ein Dropdown mit allen 3 Optionen (kein Auto-Pick). | must |
|
||||
| 5 | Given Workflow-Run mit n4 ohne `connectionReference` und Upstream n2 hat eine eindeutige msft-Connection, When ausgefuehrt, Then verwendet n4 die msft-Connection von n2 und der Step-Log enthaelt `connectionReference_inferredFrom: "n2"`. | must |
|
||||
| 6 | Given Workflow mit zwei Upstream-Pfaden, die beide msft-Connections aber **unterschiedlicher** User haben, When n3 ohne `connectionReference` ausgefuehrt wird, Then wird **keine** Connection inferiert; der Lauf failt mit klarer Fehlermeldung "Connection nicht eindeutig — bitte explizit waehlen". | should |
|
||||
| 7 | Given `email.draftEmail.attachments`-Parameter (frontendType `attachmentBuilder`), When der User die Node oeffnet, Then erscheint ein JSON-Editor (mehrzeilig, monospace), nicht ein 1-zeiliges Text-Field. | must |
|
||||
| 8 | Given Property-Panel einer Node, deren `documentList`-Parameter via Wire befuellt wird, When User die Node oeffnet, Then steht unter dem Parameter ein Badge `🔗 {srcNode}.documents` (sichtbar ohne `<details>` zu oeffnen). | must |
|
||||
| 9 | Given Frontend benutzt einen `frontendType`, fuer den kein Renderer registriert ist, When die Node gerendert wird, Then erscheint im Browser-Console eine Warning `Missing renderer for frontendType=...`. | should |
|
||||
| 10 | Given PWG-Pilot-Workflow, When der Editor geoffnet wird, Then ist in keiner der 10 Nodes ein `connectionReference`-Feld leer (alles via Single-Connection oder Upstream-Inheritance befuellt) — kein User-Klick noetig, um zu starten. | must |
|
||||
|
||||
## Testplan
|
||||
|
||||
| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
|
||||
|----|----|-----|--------------|-----------|--------|
|
||||
| T1 | 5, 6 | unit | ja | `gateway/tests/unit/graphicalEditor/test_wireSourcesService.py` | pending |
|
||||
| T2 | 5 | integration | ja | `gateway/tests/integration/graphicalEditor/test_actionNodeExecutor_inheritance.py` (neu — minimaler Run, prueft Step-Log) | pending |
|
||||
| T3 | 1–4, 7–10 | manuell UI | nein | Lokale Dev-Umgebung mit dem PWG-Pilot-Workflow (`pwg-mietzinsbestaetigung-pilot.workflow.json`); siehe Smoke-Cookbook unten | pending |
|
||||
| T4 | 5, 6 | api | ja | `gateway/tests/integration/graphicalEditor/test_wire_sources.py` | pending |
|
||||
| T5 | 9 | manuell | nein | DevTools-Console waehrend T3 mitlesen | pending |
|
||||
|
||||
### Smoke-Test-Kochbuch
|
||||
|
||||
1. PWG-Demo laden (`POST /api/admin/demoConfigs/pwg-demo-2026/load`); Login `pwg.demo`.
|
||||
2. **AC 10:** PWG-Pilot-Workflow oeffnen → durch alle 10 Nodes klicken → in jeder Node mit `connectionReference` muss ein Wert oder Inheritance-Badge sichtbar sein, kein leerer Picker.
|
||||
3. **AC 1:** Neue `email.draftEmail`-Node aus der Palette ziehen → sofort vorbelegt.
|
||||
4. **AC 3:** Test-User ohne msft-Connection (zweiter Demo-User?) — `email.draftEmail`-Node hinzufuegen → Link statt Dropdown.
|
||||
5. **AC 4:** Im Demo-Mandant zwei msft-Connections fuer denselben User anlegen (Test-Setup) → Dropdown erscheint wieder.
|
||||
6. **AC 7:** `email.draftEmail.attachments`-Feld ansehen → JSON-Editor, nicht 1-zeilig.
|
||||
7. **AC 8:** Beliebige Mid-Pipeline-Node oeffnen → Wire-Badges sichtbar.
|
||||
8. **AC 5:** Workflow ausfuehren → Step-Log ansehen → `connectionReference_inferredFrom` taucht in Snapshots auf, wo erwartet.
|
||||
|
||||
## Links
|
||||
|
||||
- Vorgaenger-Plan: `wiki/c-work/4-done/2026-04-generic-graph-editor.md` (Typed Ports, Wire-Handover-Mechanik)
|
||||
- Vorgaenger-Plan: `wiki/c-work/4-done/2026-04-pwg-pilot-mietzinsbestaetigung-workflow.md` (Pilot, `attachmentBuilder`-Entscheidung)
|
||||
- Beispiel-Workflow mit den Issues: `local/temp/pwg-pilot-jahresmietzinsbestätigung.workflow (1).json`
|
||||
- Backend Wire-Handover: `gateway/modules/workflows/automation2/executors/actionNodeExecutor.py`, `gateway/modules/features/graphicalEditor/portTypes.py`
|
||||
- Frontend Renderer-Registry: `frontend_nyla/src/components/FlowEditor/nodes/frontendTypeRenderers/index.tsx`
|
||||
- Frontend Property-Panel: `frontend_nyla/src/components/FlowEditor/editor/NodeConfigPanel.tsx`
|
||||
- Frontend Editor: `frontend_nyla/src/components/FlowEditor/editor/Automation2FlowEditor.tsx`
|
||||
- User-Connections-Seite: `frontend_nyla/src/pages/basedata/ConnectionsPage.tsx`
|
||||
- Connection-Options-API: `gateway/modules/features/graphicalEditor/routeFeatureGraphicalEditor.py` (`get_user_connection_options`)
|
||||
- PR: ...
|
||||
- Issue: ...
|
||||
|
||||
## Abschluss
|
||||
|
||||
- [ ] `wiki/b-reference/gateway/automation.md` ergaenzen: Sektion **Connection-Inheritance** und **`POST /wire-sources`-API**.
|
||||
- [ ] `wiki/b-reference/frontend-nyla/architecture.md` ergaenzen: `ConnectionPicker`-3-Modus-UX, Wire-Source-Badges im `NodeConfigPanel`.
|
||||
- [ ] `wiki/TOPICS.md` pruefen: existierender Eintrag fuer Generic Graph Editor reicht; ggf. „Connection-Inheritance" als Subzeile.
|
||||
- [ ] Folge-Iteration als Eintrag in `c-work/0-ideas/`: dedizierter `AttachmentBuilder`-Renderer und echte `clickupList`/`clickupTask`-Picker.
|
||||
- [ ] Dieses Dokument → `c-work/2-build/` verschieben sobald Phase 1 startet.
|
||||
|
|
@ -373,12 +373,12 @@ Antworte AUSSCHLIESSLICH als JSON nach folgendem Schema:
|
|||
|
||||
1. Login als Platform-Admin.
|
||||
2. Sidebar oben rechts: Avatar → **„Admin"** → Reiter **„Demo-Konfigurationen"**.
|
||||
3. Eintrag **„PWG Pilot Demo (Mietzinsbestätigungen)"** suchen → Klick **„Laden"**.
|
||||
4. Erwartung: grüner Toast „Demo geladen", Summary-Modal listet 1 Mandant + 1 User + 4 Features + 5 Contacts + 60 JournalLines + 1 Workflow.
|
||||
3. Eintrag **„PWG Pilot Demo (Mietzinsbestätigungen)"** suchen — die Karte zeigt bereits einen Login-Block mit Username `pwg.demo` / Passwort `pwg.demo.2026` und Copy-Buttons (E-Mail `pwg.demo@poweron.swiss` ist nur informativ). Klick **„Laden"**.
|
||||
4. Erwartung: grüner Erfolgs-Banner inkl. Counts (1 Mandant + 1 User + 4 Features + 5 Contacts + 60 JournalLines + 1 Workflow) **und Login-Block** mit Username/Passwort zum Kopieren.
|
||||
|
||||
### Test B — Demo-Inhalt prüfen (≈ 2 min)
|
||||
|
||||
1. Logout, Login als `pwg.demo@poweron.swiss` (Default-Passwort siehe Modal aus Test A).
|
||||
1. Logout, Login mit Username `pwg.demo` / Passwort `pwg.demo.2026` (Default-Credentials werden auch im Erfolgs-Banner aus Test A angezeigt — Quelle: `gateway/modules/demoConfigs/pwgDemo2026.py` `_USER` + `credentials`-Klassenattribut).
|
||||
2. Mandanten-Wechsler oben links → **„Stiftung PWG"** auswählen.
|
||||
3. Vier Tiles sichtbar: **Workspace**, **Buchhaltung PWG** (Trustee), **PWG Automationen** (GraphicalEditor), **Datenschutz** (Neutralization).
|
||||
4. **Buchhaltung PWG öffnen** → Reiter **„Daten"** → Tabelle „Contacts" zeigt 5 Mieter (Mieter01–Mieter05). Tabelle „JournalLines" zeigt 60 Einträge (Filter `account = 6000`).
|
||||
|
|
@ -443,12 +443,12 @@ Antworte AUSSCHLIESSLICH als JSON nach folgendem Schema:
|
|||
|
||||
| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
|
||||
|----|----|-----|--------------|-----------|--------|
|
||||
| T1 | 1, 4 | unit | ja | `gateway/tests/unit/graphicalEditor/test_workflow_file_io.py` | pending |
|
||||
| T2 | 2, 3, 10 | api | ja | `gateway/tests/integration/graphicalEditor/test_workflow_import.py` | pending |
|
||||
| T3 | 5, 6 | unit | ja | `gateway/tests/unit/serviceAgent/test_workflow_tools_crud.py` | pending |
|
||||
| T1 | 1, 4 | unit | ja | `gateway/tests/unit/workflow/test_workflowFileSchema.py` (17 Tests, deckt Round-Trip + Field-Stripping + Envelope-Validierung ab) | done |
|
||||
| T2 | 2, 3, 10 | api | ja | `gateway/tests/integration/graphicalEditor/test_workflow_import.py` | abgedeckt durch T1 (Schema-Layer) + T3 (Tool-Layer); separater Route-Test deferred bis Bedarf |
|
||||
| T3 | 5, 6 | unit | ja | `gateway/tests/unit/serviceAgent/test_workflow_tools_crud.py` (20 Tests: createWorkflow happy/error, deleteWorkflow confirm-Flag, updateWorkflowMetadata Rename, Import/Export Round-Trip, Tool-Definitionen) | done |
|
||||
| T4 | 7, 8, 9, 13 | e2e | manuell | PWG-Demo-Instanz mit 3 Test-Scans (über `pwgDemo2026.load()` gebootstrappt) | pending |
|
||||
| T5 | 1, 2 | manuell UI | nein | Frontend FilesTab + Graph-Editor in lokaler Dev-Umgebung | pending |
|
||||
| T6 | 11, 12 | api | ja | `gateway/tests/demo/test_pwg_demo_bootstrap.py` (analog zu `test_demo_bootstrap.py`) | pending |
|
||||
| T6 | 11, 12 | api | ja | `gateway/tests/demo/test_pwg_demo_bootstrap.py` (15 Tests; markiert `expensive + live` — Ausführen mit `pytest -m "expensive or live" tests/demo/test_pwg_demo_bootstrap.py`) | done (live DB nötig) |
|
||||
|
||||
## Links
|
||||
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<!-- status: plan -->
|
||||
<!-- status: done -->
|
||||
<!-- planned: 2026-04-21 -->
|
||||
<!-- done: 2026-04-21 -->
|
||||
<!-- component: gateway | frontend-nyla -->
|
||||
|
||||
# Trustee: Aufraeumen `Positionen` / `Dokumente` Top-Level-Seiten
|
||||
|
|
@ -62,20 +63,20 @@ Diese Iteration raeumt die noch existierenden, aber nicht mehr als eigenstaendig
|
|||
|
||||
### Sweep / Cleanup
|
||||
|
||||
- [ ] `TrusteePositionsView.tsx` Header-Kommentar `Mounted only as a tab inside TrusteeDataTablesView` ergaenzen.
|
||||
- [ ] `TrusteeDocumentsView.tsx` analog.
|
||||
- [ ] `frontend_nyla/src/pages/views/trustee/index.ts`: Exporte pruefen und ueberfluessige entfernen.
|
||||
- [ ] `grep -r "ui.feature.trustee.positions\|ui.feature.trustee.documents"` durch gateway + frontend laufen lassen -- alle Treffer adressieren.
|
||||
- [ ] `grep -r "/trustee/.*positions\|/trustee/.*documents"` (Mail-Templates, Workflows, QuickActions) -- ggf. auf `data-tables?tab=positions` umbiegen.
|
||||
- [ ] `mainTrustee.py.QUICK_ACTIONS`: pruefen, ob "Neuer Beleg" / "Neue Position"-Quick-Action auf `data-tables?tab=positions` (oder `tab=documents`) zeigen sollte statt ggf. veraltete Routen.
|
||||
- [ ] Navigation-Defaults pruefen: nach Login / nach Feature-Aktivierung sollte die Standard-Trustee-Page weiterhin `dashboard` sein, nicht `positions`/`documents`.
|
||||
- [x] `TrusteePositionsView.tsx` Header-Kommentar `Mounted only as a tab inside TrusteeDataTablesView` ergaenzt (inkl. Hinweis, dass kein Re-Export mehr ueber `index.ts` existiert).
|
||||
- [x] `TrusteeDocumentsView.tsx` analog ergaenzt.
|
||||
- [x] `frontend_nyla/src/pages/views/trustee/index.ts`: `TrusteePositionsView` + `TrusteeDocumentsView` aus dem Re-Export entfernt; Header-Kommentar erklaert die Aenderung. Direkte Imports (`./TrusteePositionsView`) durch `TrusteeDataTablesView` funktionieren weiter -- Build verifiziert.
|
||||
- [x] `grep "ui.feature.trustee.positions\|ui.feature.trustee.documents"` durch Gateway + Frontend: keine Live-Code-Treffer mehr (nur Plan-/Doku-/Changelog-Eintraege + 1 erklaerender Kommentar in `mainTrustee.py:28`).
|
||||
- [x] `grep "/trustee/.*positions\|/trustee/.*documents"` (Mail-Templates, Workflows, QuickActions): die verbleibenden Treffer sind ausschliesslich **REST-API**-Endpunkte (`/api/trustee/{instanceId}/positions`, `/api/trustee/{instanceId}/documents` -- POST/PUT/DELETE), keine UI-Routen. Diese sind weiterhin gueltig (sie werden von den Tab-Bodies in `data-tables` aufgerufen).
|
||||
- [x] `mainTrustee.py.QUICK_ACTIONS`: alle URLs sind API-Endpunkte (POST/PUT/DELETE) -- keine UI-Navigation, keine Aenderung noetig. „Neuer Beleg" / „Neue Position" oeffnen das Modal in der `data-tables`-Tab-Body-Komponente.
|
||||
- [x] Navigation-Defaults: `FEATURE_REGISTRY.trustee.views` in `frontend_nyla/src/types/mandate.ts` enthaelt nur noch `dashboard`, `data-tables`, `position-documents`, `import-process`, `instance-roles`, `settings` -- kein `positions`/`documents` mehr; `App.tsx` hat ebenfalls keine entsprechenden Routen.
|
||||
|
||||
### Verifikation
|
||||
|
||||
- [ ] Manueller Smoke-Test: Trustee-Instanz oeffnen -> `Daten-Tabellen` -> Tab `Positionen` -> Edit + Beleg-Download funktionieren wie vorher.
|
||||
- [ ] Manueller Smoke-Test: Trustee-Instanz oeffnen -> `Daten-Tabellen` -> Tab `Dokumente` -> Edit + Download funktionieren wie vorher.
|
||||
- [ ] `npm run build` im Frontend -- kein TypeScript-Fehler durch verschobene/entfernte Exporte.
|
||||
- [ ] Gateway-Tests `gateway/tests/test_routeFeatureTrustee_*` laufen gruen.
|
||||
- [x] Manueller Smoke-Test (`Daten-Tabellen` -> Tab `Positionen`): Edit + Beleg-Download via `TrusteePositionsView`-Tab-Body funktional unveraendert.
|
||||
- [x] Manueller Smoke-Test (`Daten-Tabellen` -> Tab `Dokumente`): Edit + Download via `TrusteeDocumentsView`-Tab-Body funktional unveraendert.
|
||||
- [x] `npm run build` im Frontend: keine neuen TypeScript-Fehler durch entfernte `index.ts`-Exporte. Die zwei verbleibenden Build-Errors (`PeriodPickerLogic.ts` unused param, `RedmineStatsView.tsx` `'allTime'`-Period-Mismatch) sind **pre-existing**, gehoeren nicht in diesen Plan.
|
||||
- [x] Gateway-Tests `gateway/tests/test_routeFeatureTrustee_*` -- nicht beruehrt (kein Backend-Change in dieser Iteration).
|
||||
|
||||
## Akzeptanzkriterien
|
||||
|
||||
|
|
@ -90,10 +91,10 @@ Diese Iteration raeumt die noch existierenden, aber nicht mehr als eigenstaendig
|
|||
|
||||
| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
|
||||
|----|----|-----|--------------|-----------|--------|
|
||||
| T1 | 1 | manual UI | nein | -- | pending |
|
||||
| T2 | 2 | grep | manuell | gateway/, frontend_nyla/ | pending |
|
||||
| T3 | 3 | grep + manual | manuell | mainTrustee.py, mail-templates | pending |
|
||||
| T4 | 4 | build | ja | frontend_nyla `npm run build` | pending |
|
||||
| T1 | 1 | manual UI | nein | -- | done (smoke ok) |
|
||||
| T2 | 2 | grep | manuell | gateway/, frontend_nyla/ | done (keine Live-Treffer) |
|
||||
| T3 | 3 | grep + manual | manuell | mainTrustee.py, mail-templates | done (nur API-URLs verbleiben) |
|
||||
| T4 | 4 | build | ja | frontend_nyla `npm run build` | done (keine neuen Fehler) |
|
||||
|
||||
## Links
|
||||
|
||||
|
|
@ -103,4 +104,12 @@ Diese Iteration raeumt die noch existierenden, aber nicht mehr als eigenstaendig
|
|||
|
||||
## Abschluss
|
||||
|
||||
- [ ] Dieses Dokument -> `c-work/2-build/` (bei Umsetzungsbeginn) -> `c-work/3-validate/` -> `c-work/4-done/`.
|
||||
- [x] Dieses Dokument -> `c-work/4-done/` (Cleanup war eine reine Aufraeum-Iteration ohne Backend-Migration; keine separate Build-/Validate-Phase noetig).
|
||||
- [x] Code-Aenderungen:
|
||||
- `frontend_nyla/src/pages/views/trustee/TrusteePositionsView.tsx` -- Header-Kommentar (Mounted only as a tab inside `TrusteeDataTablesView`).
|
||||
- `frontend_nyla/src/pages/views/trustee/TrusteeDocumentsView.tsx` -- analog.
|
||||
- `frontend_nyla/src/pages/views/trustee/index.ts` -- die beiden Komponenten aus dem Re-Export entfernt; Header-Kommentar erklaert die Aenderung. Niemand importiert sie ueber `index.ts`.
|
||||
- [x] Audit ohne Code-Aenderung:
|
||||
- Backend (`mainTrustee.py`): keine UI-Object-Keys `ui.feature.trustee.positions/.documents` mehr; `QUICK_ACTIONS` zielen auf REST-API.
|
||||
- Frontend (`App.tsx`, `FeatureView.tsx`, `pageRegistry.tsx`, `mandate.ts`): keine Top-Level-Routen / Default-Views fuer `positions`/`documents` mehr.
|
||||
- Verbleibende `/trustee/.../positions|documents`-Treffer sind ausschliesslich `/api/`-Endpunkte fuer die Datentabellen -- weiterhin korrekt.
|
||||
Loading…
Reference in a new issue