wiki/c-work/4-done/2026-06-automation-system-component.md

48 KiB
Raw Blame History

WorkflowAutomation als System-Komponente — graphicalEditor raus aus dem Feature-Modell

Migration Status: COMPLETE (2026-06-08). Alle graphicalEditor-Code-Referenzen eliminiert. Code aus features/graphicalEditor/, workflows/automation2/, workflows/scheduler/ verschoben nach modules/workflowAutomation/{editor,engine,scheduler}/. Originale gelöscht, __init__.py-Shims als Safety-Net. Test-Imports, DEPRECATED-Kommentare, Store/RBAC-Namespace, Demo-Configs, Frontend-Kommentare/Logs bereinigt. graphicalEditorRunFileLogger.pyrunFileLogger.py. datamodelFeatureGraphicalEditor.py gelöscht. Frontend-Monolith gesplittet (D1-D3). RBAC-Migration als idempotente Boot-Routine. Verbleibend: AC5 per-Node Billing + AC7 Run-as-Principal (Scope CustomerCases), automatisierte Tests T1-T5 (pending), Smoke-Test Scheduler (manuell bei Deploy).

Treiber: Entscheid aus c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md / …-step3-features-plan.md A0.4. Dort wurde die Entkopplung als Roadmap markiert; sie wird vorgezogen, weil sie sonst die Solution-Schicht (Ownership/RBAC/Billing) später erneut einholt.

Namens-Konvention: Die System-Komponente heisst WorkflowAutomation (Code-Token WorkflowAutomation/workflowAutomation) — semantisch eindeutig und gut greppbar. Das generische Wort «Automation» ist im Bestand schon mehrfach belegt (AutomationsDashboardPage, routeAutomationWorkspace, /automations, workflows/automation2) und bleibt dort unverändert. UI-Label (kundensichtbar): «Workflow-Automation» / «Automatisierung».

Beschreibung und Kontext

graphicalEditor ist heute ein Hybrid: formal ein Feature (Discovery, TEMPLATE_ROLES graphicalEditor-*, Store-Eintrag, FeatureInstance pro Mandant, per-Instanz-API /api/workflows/{instanceId}/…), architektonisch aber mandanten- und feature-übergreifende Orchestrierungs-Infrastruktur:

  • Kein getDataObjects() — keine Domänen-/Kundendaten; AutoWorkflow/AutoRun sind Orchestrierungs-Metadaten (eigene DB poweron_graphicaleditor).
  • Einziges Feature mit onStart/onStop — bootet beim App-Start den globalen Scheduler (Email-Poller startet on-demand via emailPoller.ensureRunning, gestoppt in onStop).
  • Scheduler/Engine liegen ohnehin unter modules/workflows/ (System), nicht im Feature.
  • getWorkflows() filtert nur nach mandateId («cross-instance»); ein Graph referenziert legitim mehrere Features/Instanzen über per-Node FeatureInstanceRef.
  • Cross-Mandate-Ops-Sicht existiert bereits: AutomationsDashboardPage (/automations, Tabs Workflows/Runs/Details) ← routeWorkflowDashboard.py (/api/system/workflow-runs), RBAC über Mandats-Mitgliedschaft + Platform-Admin — ganz ohne GE-FeatureInstance.

Business-Treiber: Die Solution-Schicht (CustomerCases) verankert Ownership an Mandant + Run-as-Principal (A0.1). Solange graphicalEditor als Feature mit per-Instanz-RBAC/Billing geführt wird, kollidiert jede Solution mit einem erfundenen «Host-Owner». Wir lösen die Wurzel: WorkflowAutomation = System-Komponente mit eigener Navigations-Gruppe «Workflow-Automation» (mehrere Tab-Seiten, mandanten-/feature-übergreifend strukturiert an einem Ort) und sauberem Daten-/RBAC-Modell.

Risiko, wenn NICHT gemacht: doppelte Wahrheit (Feature-Instanz-RBAC vs. mandatsweite Realität), Billing fix auf graphicalEditor statt auf berührte Instanz, per-Instanz-URLs ({instanceId}) zementieren das Feature-Modell, und die Solution-Schicht erbt den Designfehler.

Code-Stand nach Import-Refactoring (2026-06-05/06)

Das Backend wurde zwischenzeitlich auf eine Layer-Hierarchie L0L7 refactored (shared=L0, datamodels=L1, connectors=L2, dbHelpers=L3, interfaces/system/security/auth=L4, serviceCenter/workflows/features=L5, routes=L6, app=L7; Quelle: local/notes/refernce-analysis/platform-core-import-analyse.md). Das ändert mehrere Plan-Annahmen — vieles ist schon erledigt; das GE↔Engine-Coupling wurde dort explizit auf diesen Plan vertagt («Deferred: WorkflowAutomation»).

Schon erledigt (Plan-Schritte entfallen/reduziert):

  • Contracts + Models liegen in L1: PORT_TYPE_CATALOG/PRIMITIVE_TYPESdatamodels/datamodelPortTypes.py; AutoWorkflow/AutoVersion/AutoRun/AutoStepLog/AutoTaskdatamodels/datamodelWorkflowAutomation.py (kanonisch, Re-Export-Shim features/graphicalEditor/datamodelFeatureGraphicalEditor.py, 7 Caller). → Das geplante «Shared Contracts»-Modul ist faktisch datamodels (L1); kein neues workflowContracts/ nötig.
  • Feature-Lifecycle-Hooks existieren: mainGraphicalEditor.onInstanceCreate() (Template-Copy, ex interfaceFeatures._copyTemplateWorkflows), onMandateDelete() (Cascade, ex interfaceDbApp), onBootstrap() (Seeding, ex interfaceBootstrap) — dynamisch via shared/featureDiscovery.loadFeatureMainModules(). → Plan-Touchpoints in interfaceFeatures/interfaceDbApp/interfaceBootstrap sind jetzt Feature-Hooks.
  • Weitere Verschiebungen: NAVIGATION_SECTIONSdatamodels/datamodelNavigation.py; EventManagershared/eventManager.py; parseInlineRunsshared/documentUtils.py; serviceHubserviceCenter/serviceHub.py; Service-Exceptions → datamodels/serviceExceptions.py; WorkflowStoppedException/checkWorkflowStoppedshared/workflowState.py.

Explizit auf diesen Plan vertagt (Deferred-Liste):

  • features.graphicalEditor → workflows (21) + workflows → features.graphicalEditor (40) → Ziel 0 (kollabiert, sobald Editor + Engine ein Modul sind).
  • serviceCenter → features.graphicalEditor (5×, serviceAgent/workflowTools.py).
  • interfaces/interfaceDbManagement.py:936 (lazy → workflowArtifactVisibility).
  • Re-Export-Shims entfernen: datamodelFeatureGraphicalEditor.py (7 Caller), workflows/processing/shared/stateTools.py (7 Caller).
  • Boundary-Leck besteht weiter (Delaminierung offen): PauseForHumanTaskError (automation2/executors/inputExecutor.py) und coerceDocumentDataToBytes (automation2/executors/actionNodeExecutor.py) werden von methods/methodContext/actions/setContext.py bzw. methods/methodFile/actions/create.py top-level importiert → vor Engine-Umzug extrahieren (PauseForHumanTaskErrordatamodels/serviceExceptions.py, coerceDocumentDataToBytesshared/documentUtils.py).

Fokus und kritische Details

  • Kein Big-Bang. Parallel-Pfade bauen (mandatsweite API neben {instanceId}-API), dann umschalten, dann Feature-Mantel entfernen. Jede Phase ist für sich lauffähig.
  • Scheduler-Boot ist fragil. Er hängt am Feature-onStart (app.py-Lifespan iteriert alle Feature-Module). Vor dem Entfernen des Feature-Mantels muss der Boot in einen System-Lifespan-Hook umziehen, sonst startet der Scheduler nicht mehr.
  • featureInstanceId hat heute zwei Bedeutungen: (a) GE-Owner/RBAC-Scope auf AutoWorkflow, (b) Daten-Scope der Ausführung (targetFeatureInstanceId + per-Node FeatureInstanceRef). Nur (a) wird abgebaut; (b) bleibt — es ist die Cross-Feature-Referenz.
  • Kaum DDL nötig (Code-verifiziert). Tabellen werden ohne NOT NULL (ausser id-PK) und ohne DB-FKs angelegt (connectorDbPostgre.py _create_table_from_model); FKs sind app-level (fkRegistry, app.py validateFkTargets). Heisst: featureInstanceId ist schon jetzt DB-nullable → «nullable machen» ist nur Optional[str] im Pydantic-Modell (datamodelFeatureGraphicalEditor.py) + Query-/Code-Anpassungen, keine Migration. runAsPrincipal = additives ADD COLUMN (von _ensureTableExists abgedeckt). Echte Arbeit = Application-Logik (Routen/Queries, die featureInstanceId voraussetzen), nicht Schema.
  • Bestehende Daten grandfathern. AutoWorkflow-Zeilen tragen featureInstanceId; FeatureAccess-Grants und per-Instanz-Rollen existieren. Datenmigration als einmaliges Skript (Muster: scripts/script_migrate_feature_instance_refs.py; Cascade-Vorbild: routeWorkflowDashboard._cascadeDeleteAutoWorkflow). Migration muss diese erhalten/überführen, nicht löschen.
  • RBAC-Präzedenz nutzen — aber sie deckt nur Lesen. routeWorkflowDashboard.py (_scopedWorkflowFilter/_getAdminMandateIds + isPlatformAdmin) ist ein Read/List/Delete-Muster — kein Create/Update/Publish/Execute. Die 39 _validateInstanceAccess-Sites in routeFeatureGraphicalEditor.py sind grösstenteils Write/Execute; dafür braucht es einen eigens entworfenen Helper _validateWorkflowAccess(workflow, context, action) (read vs. write), nicht 1:1 das Dashboard-Muster. system-Pseudo-Feature (instantiable=False) ist die Vorlage für Katalog-/RBAC-Registrierung ohne Instanzen.
  • Shared Contracts schon in L1, Node-Katalog noch beim Editor. PORT_TYPE_CATALOG liegt seit dem Refactoring in datamodels/datamodelPortTypes.py (erledigt). Der Node-Katalog (STATIC_NODE_TYPES) ist noch unter features/graphicalEditor/nodeDefinitions/ und wird cross-layer genutzt (system/i18nBootSync.py, serviceAgent/workflowTools.py) — er zieht mit dem Editor in die Komponente. Offenes Boundary-Leck: zwei Helfer (PauseForHumanTaskError, coerceDocumentDataToBytes) liegen in automation2.executors, werden aber von methods/ importiert → vor dem Engine-Umzug delaminieren.
  • Zwei UI-Oberflächen sauber trennen (siehe «Verhältnis zur Solution-Schicht»): die WorkflowAutomation-Gruppe (technische Orchestrierung, cross-mandate, für Power-User/Admins) vs. die kundenseitige «Lösungen»-Surface pro Host-Feature (bleibt eingebettet, Präsentation).

Ziel und Nicht-Ziele

  • Ziel: graphicalEditor als System-Komponente WorkflowAutomation führen — eigene Top-Level-Navigationsgruppe mit Tab-Seiten (Editor · Vorlagen · Workflows · Läufe · Tasks), mandanten-/feature-übergreifend.
  • Ziel: Mandatsweite API + RBAC (kein {instanceId} als RBAC-Anker), Scheduler-Boot als System-Lifespan, DB-Scoping auf Mandant + Principal (statt GE-Owner-Instanz).
  • Ziel: Bestehende Workflows/Runs/Tasks und Grants verlustfrei migrieren.
  • Ziel: Fundament legen für die Solution-Schicht (A0.1) — Solutions hängen an Mandant + Run-as-Principal, nicht an einer GE-Instanz.
  • Explizit NICHT: Graph-Format/Node-Semantik ändern (modules/workflows/automation2/* bleibt funktional gleich). Ausnahme: per-Node-Billing-Attribution (AC5) ist eine bewusste, lokal begrenzte Executor-Änderung (berührte FeatureInstanceRef in den recordUsage-Kontext threaden) — kein Graph-/Semantik-Umbau.
  • Explizit NICHT: den geteilten Workflow-Execution-Layer (workflows/methods/, workflows/processing/) in die Komponente ziehen — er bleibt unter modules/workflows/ (Chats/Agents nutzen ihn ohne Automation).
  • Explizit NICHT: die kundenseitige «Lösungen»-Surface in diesem Plan bauen (→ CustomerCases-Pläne; dieser Plan liefert nur das Substrat).
  • Explizit NICHT: per-Node FeatureInstanceRef / targetFeatureInstanceId (Daten-Scope) abschaffen.
  • Explizit NICHT: DB-Engine/Datenbankname wechseln (poweron_graphicaleditor bleibt).
  • Explizit NICHT: bestehende «Automation»-Code-Namen umbenennen (AutomationsDashboardPage, routeAutomationWorkspace, workflows/automation2) — nur die neue Komponente trägt das Token WorkflowAutomation.

Zielarchitektur (Kurz)

VORHER (Feature):
  Nav: Mandant → graphicalEditor-Instanz → {editor, templates, tasks}
  API: /api/workflows/{geInstanceId}/...   RBAC: FeatureAccess auf GE-Instanz
  DB : AutoWorkflow.featureInstanceId = GE-Owner (RBAC-Scope)
  Boot: graphicalEditor.onStart → Scheduler

NACHHER (System-Komponente WorkflowAutomation):
  Nav: Top-Level-Gruppe «Workflow-Automation» (einmal) → Tabs {Editor, Vorlagen, Workflows, Läufe, Tasks}
       + Mandanten-/Instanz-Picker in der Seite (cross-mandate)
  API: /api/workflow-automation/...        RBAC: Mandats-Mitgliedschaft + System-Rollen + isPlatformAdmin
  DB : AutoWorkflow.mandateId + runAsPrincipal (Owner); featureInstanceId → entfällt als RBAC-Anker
       targetFeatureInstanceId + per-Node FeatureInstanceRef bleiben (Daten-Scope)
  Boot: System-Lifespan (app.py) → Scheduler

Namensgebung & modulare Struktur

Name der System-Komponente: WorkflowAutomation (UI-Label «Workflow-Automation» / «Automatisierung»). graphicalEditor ist nicht der Name der Komponente, sondern ein Modul darin (der Graph-/Flow-Editor). Begründung für WorkflowAutomation: semantisch eindeutig + als Token greppbar (das generische «Automation» ist im Code mehrfach belegt und bleibt). (Verworfen: «Automation» allein — mehrdeutig; «Orchestration» — neuer Begriff ohne Code-Verankerung.)

Die Komponente bündelt die bestehenden, heute verstreuten Automation-Teile (features/graphicalEditor/, workflows/automation2/, workflows/scheduler/) plus die kommende L3/L4-Schicht zu einem nachvollziehbaren, modularen System. Den geteilten Workflow-Execution-Layer (workflows/methods/, workflows/processing/) bündelt sie nicht — der bleibt eigenständig (siehe Abgrenzung unten). Jedes Modul hat eine klare Verantwortung und mappt auf die L2L4-Schichten der Architektur.

L Modul Verantwortung
L2 editor (= heute graphicalEditor Authoring) Graph/Flow-Authoring, Node-Registry, Adapter, Editor-UI-Backend (konsumiert Shared Contracts)
L2 engine (= heute workflows/automation2/) Graph-Ausführungs-Runtime (Graph → Run)
L2 scheduler Zeit-/Event-Trigger, Email-Poller
L3 solutions konfigurierte Workflows (Solution-Modell, Settings-Injektion)
L4 launcher Katalog/Vorlagen + «neue Automation» (Template/AI) + Template-Instanziierung
L4 monitoring Läufe, Tasks, Logs (Ops-Sicht)

NICHT Teil der Komponente (geteilt, Code-verifiziert) — Komponente konsumiert abwärts:

  • L1 Toolbox (Execution) = workflows/methods/ (generische Actions) + workflows/processing/ (ActionExecutor, methodDiscovery, modes) — von Chats/Agents genutzt. (Feature-eigene Actions liegen seit Refactoring beim Feature, z. B. features/trustee/workflows/.)
  • Contracts/Models = datamodels (L1, bereits erledigt): datamodelPortTypes.py (PORT_TYPE_CATALOG), datamodelWorkflowAutomation.py (AutoWorkflow…). Die Komponente konsumiert L1, besitzt sie nicht. (Der Node-Katalog STATIC_NODE_TYPES liegt noch beim Editor und zieht mit ihm um.)

Platform (platform-core/modules/workflowAutomation/)

modules/workflowAutomation/              # NEU — die Automation-Komponente
├─ mainWorkflowAutomation.py      # System-Registrierung (instantiable=False) + Lifespan-Hook (Scheduler-Boot; Poller-Stop) + Lifecycle-Hooks (onMandateDelete/onBootstrap)
│                                 #   Models kanonisch in datamodels/datamodelWorkflowAutomation.py (L1) — Komponente importiert sie
├─ routes/                        # mandatsweite API /api/workflow-automation/{workflows,versions,runs,tasks,nodes,solutions,...}
├─ editor/                        # L2 — Graph-Editor-Backend (nodeRegistry, nodeAdapter, adapterValidator) — konsumiert Shared Contracts
├─ engine/                        # L2 — Graph-Ausführung (heute workflows/automation2/: executionEngine, executors, graphUtils, runEnvelope, scheduleCron)
├─ scheduler/                     # L2 — Scheduler + emailPoller (heute workflows/scheduler/ + graphicalEditor/emailPoller.py)
├─ solutions/                     # L3 — solutionService, datamodelSolution (Settings-Injektion, run-as-Principal)
└─ launcher/                      # L4 — Katalog/Templates + AI-Erstellung + Template-Instanziierung

modules/workflows/                       # BLEIBT — geteilter Execution-Layer (NICHT Teil der Komponente)
├─ methods/                       # L1-Toolbox — generische Actions (methodAi/Sharepoint/Outlook/File/Context/Clickup/Jira/Redmine)
├─ processing/                    # ActionExecutor, methodDiscovery, modes/adaptive, workflowProcessor
└─ workflowManager.py            # Chat-/Agent-seitige Workflow-Verarbeitung

modules/datamodels/                      # BLEIBT — Contracts/Models (L1, bereits dorthin refactored)
├─ datamodelPortTypes.py         # PORT_TYPE_CATALOG / PRIMITIVE_TYPES
└─ datamodelWorkflowAutomation.py# AutoWorkflow / AutoVersion / AutoRun / AutoStepLog / AutoTask (kanonisch)

Abgrenzung Komponente ↔ Contracts ↔ Execution (Code-verifiziert, korrigiert). Drei Schichten, strikt abwärts: Komponente → Shared Contracts → Execution-Layer.

  • In die Komponente: workflows/automation2/ (Graph-Engine) → engine/; workflows/scheduler/scheduler/; graphicalEditor/{nodeRegistry, adapterValidator, emailPoller, Editor-Backend}editor//scheduler/.
  • Bleibt geteilt unter modules/workflows/: methods/ (Actions), processing/ (ActionExecutor, methodDiscovery, modes/, adaptive/, workflowProcessor) — genutzt von Chats/Agents (serviceAgent/{actionToolAdapter,mainServiceAgent}, serviceAi/*, serviceGeneration/*) ohne Automation.
  • Contracts/Models: PORT_TYPE_CATALOG + AutoWorkflow… liegen bereits in datamodels/ (L1, durchs Refactoring); Komponente konsumiert sie. Der Node-Katalog (STATIC_NODE_TYPES) liegt noch beim Editor und zieht mit ihm um (cross-Caller: system/i18nBootSync.py, serviceAgent/workflowTools.py beachten).
  • Korrektur eines früheren Fehlers (weiterhin gültig): «automation2 wird von Chats nicht importiert» war falsch und ist noch nicht behoben. methods/methodFile/actions/create.py (→ coerceDocumentDataToBytes) + methods/methodContext/actions/setContext.py (→ PauseForHumanTaskError) importieren automation2.executors top-level — geladen via methodDiscovery im Chat-/Agent-Pfad. Diese zwei Helfer vor dem Engine-Umzug extrahieren (→ datamodels/serviceExceptions.py bzw. shared/documentUtils.py), sonst importiert Shared aufwärts in die Komponente.

Guard-Test: sicherstellen, dass modules.workflows.{methods,processing} + modules.serviceCenter importierbar sind, ohne modules.workflowAutomation.* zu laden. Migration nur der Automation-Teile (Re-Export/Shims; ~20 Importer von workflows.automation2/scheduler). Kein funktionaler Umbau der Engine (Ausnahme: per-Node-Billing, AC5).

UI (ui-nyla/src/)

pages/workflowAutomation/
├─ WorkflowAutomationHubPage.tsx  # Container: Top-Level-Gruppe «Workflow-Automation», Tabs, Mandanten-/Instanz-Scope-Selector
└─ tabs/
   ├─ LauncherTab.tsx             # L4 — Katalog/Neu (Vorlage oder AI)
   ├─ SolutionsTab.tsx            # L3 — konfigurierte Solutions (Admin/Power-User-Sicht)
   ├─ EditorTab.tsx               # L2 — Graph-Editor (Keep-Alive)
   ├─ WorkflowsTab.tsx            # alle Workflows (cross-mandate/-feature)
   ├─ RunsTab.tsx                 # L4 — Läufe/Monitoring
   └─ TasksTab.tsx                # Human-Tasks
components/workflowAutomation/
├─ FlowEditor/                    # heute components/GraphicalEditor/
├─ Launcher/
├─ Solutions/
└─ Monitoring/
api/workflowAutomationApi.ts      # /api/workflow-automation/... (ersetzt workflowApi {instanceId}-Pfade)
  • Eine Top-Level-Nav-Gruppe «Workflow-Automation» (nicht pro Mandant/Instanz); Tabs via ?tab= deeplinkbar (Muster AutomationsDashboardPage).
  • Abgrenzung zur kundenseitigen «Lösungen»-Surface: Der SolutionsTab hier ist die Admin/Power-User-Sicht über alle Solutions; die kundenseitige SolutionsView (L4) bleibt pro Host-Feature eingebettet (Trustee usw.) und zeigt nur die für diesen Kontext konfigurierten Solutions. Beide nutzen api/workflowAutomationApi.ts.

Verhältnis zur Solution-Schicht (CustomerCases)

  • WorkflowAutomation-Gruppe = Substrat-UI (Power-User/Admin): roher Editor, Templates, alle Workflows/Läufe/Tasks über Mandanten/Features.
  • «Lösungen»-Surface = kundenseitig, pro Host-Feature eingebettet (Trustee usw.) — konsumiert dasselbe Substrat, zeigt aber nur konfigurierbare Solutions. Bleibt wie in den CustomerCases-Plänen.
  • Beide hängen am gleichen Modell: Mandant + Run-as-Principal, nicht an einer GE-Instanz. Dieser Plan ist die Voraussetzung für A0.1/A0.2.

Betroffene Module

  • Gateway (platform-core):
    • app.py — Scheduler/Email-Poller-Boot in System-Lifespan (statt Feature-onStart).
    • modules/workflows/scheduler/mainScheduler.py — Boot-Aufruf; JOB_ID_PREFIX/_CALLBACK_NAME ("graphicalEditor.*") sind in Job-IDs persistiert → Literale behalten oder Job-IDs migrieren (in-memory APScheduler, Re-Sync beim Boot → risikoarm); if not instanceId-Guard entfernen (s. Phase 1); Run-as-Principal statt globalem event-Sysadmin (A0.1).
    • Delaminierung zuerst (Phase 0.5): PauseForHumanTaskErrordatamodels/serviceExceptions.py, coerceDocumentDataToBytesshared/documentUtils.py (Re-Export-Shim in automation2/executors/). Contracts (portTypes, Models) sind bereits in datamodels (L1). Erst dann ist der Engine-Umzug aufwärts-importfrei.
    • modules/workflows/{automation2,scheduler}/ → in die Komponente: automation2workflowAutomation/engine/, schedulerworkflowAutomation/scheduler/ (Re-Export-Shims). automation2 = die Graph-Engine, kein funktionaler Umbau (Ausnahme: per-Node-Billing-Kontext, AC5).
    • modules/workflows/{methods,processing}/ bleiben geteilt (Execution-Layer), datamodels/ bleibt L1 — nicht verschieben.
    • modules/features/graphicalEditor/ → konzeptionell nach modules/workflowAutomation/editor/ führen; mainGraphicalEditor.py: getFeatureDefinition/TEMPLATE_ROLES/onStart entfernen bzw. zu System-Registrierung umbauen (instantiable=False, Vorbild mainSystem.py).
    • modules/features/graphicalEditor/routeFeatureGraphicalEditor.py — neue mandatsweite Routen /api/workflow-automation/...; die 39 _validateInstanceAccess-Sites bewusst auf einen neuen _validateWorkflowAccess(workflow, context, action) (read vs. write) migrieren — Read-Scoping vom Dashboard, Write/Execute eigens entworfen, isPlatformAdmin-Bypass. _validateTargetInstance zusätzlich um Mandatsgrenze ergänzen (AC8, heute nur FeatureAccess).
    • modules/routes/routeSystem.py — GE-Hardcode in _getFeatureUiObjects entfernen; neuen statischen Nav-Block workflowAutomation ausliefern.
    • modules/datamodels/datamodelNavigation.pyNAVIGATION_SECTIONS (post-Refactoring hier, nicht mehr in mainSystem.py): Block id="workflowAutomation" (order ~25) ergänzen; ui.system.workflowAutomation.*-Objekte; Store-Eintrag resource.store.graphicalEditor entfernen.
    • modules/features/graphicalEditor/mainGraphicalEditor.py onInstanceCreate() — heute Template-Copy bei FeatureInstance-Erstellung (stempelt {{featureInstanceId}}/targetFeatureInstanceId, auch Trustee/Redmine). Ohne GE-Instanz entfällt der Hook-Trigger → Template-Instanziierung explizit in den launcher/-Flow verlagern (inkl. Demo-Bootstrap); Trustee/Redmine-Platzhalter-Vertrag beachten.
    • modules/features/graphicalEditor/mainGraphicalEditor.py onMandateDelete() (Cascade) / onBootstrap() (Seeding) — sind bereits Feature-Hooks (ex interfaceDbApp/interfaceBootstrap); ziehen mit der Komponente um, Cascade auf mandatsweit umstellen.
    • modules/interfaces/interfaceRbac.pyTABLE_NAMESPACE (8 Einträge: AutoWorkflow/AutoVersion/AutoRun/AutoStepLog/AutoTask + Legacy Automation2*): Option B — Namespace feature.graphicalEditor beibehalten + System-DATA-Objekte ergänzen. (Ein Flip auf system.workflowAutomation verwaist bestehende AccessRule/Rollen-Zeilen; nur mit zwingend gekoppeltem Migrations-Skript im selben Deploy.)
    • modules/interfaces/interfaceBootstrap.py — Store-Grant + ggf. neue System-Rollen workflowAutomation-* (Hook-Aufruf bleibt; GE-Wissen ist dynamisch via loadFeatureMainModules).
    • modules/features/graphicalEditor/mainGraphicalEditor.py getGraphicalEditorServicesfeatureCode/featureInstanceId im Hub (jetzt serviceCenter/serviceHub.py): Billing per-Node auf berührte Instanz (A0.2, Executor-Change), Mandate = mandateId.
    • serviceCenter/.../toolboxRegistry.py + serviceCenter/services/serviceAgent/workflowTools.pyfeatureCode="graphicalEditor"workflowAutomation; workflowTools ist der verbleibende serviceCenter → features.graphicalEditor (5×, deferred) → entfällt mit Umzug.
    • Weitere GE-Importer (Deferred-Liste): system/i18nBootSync.py (zieht STATIC_NODE_TYPES — mit Node-Katalog mitziehen), routeSystem.py (UI_OBJECTS + Dashboard-_ensureTableExists), routeAdminFeatures.py, interfaceDbManagement.py:936 (lazy workflowArtifactVisibility), interfaceFeatureGraphicalEditor.getAllWorkflowsForScheduling (Lesepfad von Scheduler und Dashboard — stabil halten/shimmen); Re-Export-Shims datamodelFeatureGraphicalEditor.py (7) + processing/shared/stateTools.py (7) entfernen.
  • Frontend (ui-nyla):
    • src/components/Navigation/MandateNavigation.tsxblock.id === 'workflowAutomation' als eigene Top-Level-Gruppe rendern (analog admin).
    • src/App.tsx/workflow-automation/*-Routen (Hub + ?tab= Deeplinks); Redirects der alten /mandates/.../graphicalEditor/.../*.
    • src/pages/AutomationsDashboardPage.tsx → in WorkflowAutomationHubPage mit Tabs überführen (Workflows, Läufe, Editor, Vorlagen, Tasks).
    • src/pages/FeatureView.tsxgraphicalEditor aus VIEW_COMPONENTS entfernen.
    • src/pages/views/graphicalEditor/* — von useInstanceId()/useCurrentInstance() auf expliziten Mandanten-/Instanz-Picker (Scope-Selector) umstellen.
    • src/config/keepAliveRoutes.tsx — Editor-Keep-Alive-Pfad auf /workflow-automation/editor umziehen.
    • src/config/pageRegistry.tsx — Icons für page.system.workflowAutomation.*.
    • src/api/workflowApi.ts — URLs /api/workflows/{instanceId}/…/api/workflow-automation/….
    • Cross-Links: TrusteeAnalyseView/TrusteeAbschlussView (/automations?tab=…), Store.tsx (GE-Karte entfernen).
  • DB-Migration: minimal — runAsPrincipal = additives ADD COLUMN; featureInstanceId ist bereits DB-nullable (kein DDL, keine DB-FK; nur Pydantic Optional + Code); Daten-/Grant-Backfill via Skript. Kein Namespace-Flip (Option B).
  • Andere: RBAC (System-Objekte/-Rollen, FeatureAccess-Grants migrieren, GE-Feature-Rollen entfallen), Billing (per-Node-Attribution), Demo-Configs (pwgDemo2026/investorDemo2026), Tests, .cursor/rules/* (s. Abschluss).

Entscheidungen

Datum Entscheidung Begründung
2026-06-05 System-Komponente heisst WorkflowAutomation (Token WorkflowAutomation/workflowAutomation); UI-Label «Workflow-Automation» semantisch eindeutig + greppbar; generisches «Automation» bleibt für Bestand
2026-06-05 graphicalEditor = ein Modul (editor) innerhalb von WorkflowAutomation graphEditor ist nur das Authoring-Element
2026-06-05 Automation ≠ Workflow-Execution. methods/processing bleiben geteilter Layer unter modules/workflows/; nur automation2 (engine) + scheduler + graphicalEditor wandern in die Komponente Chats/Agents nutzen den Execution-Layer ohne Automation; Abwärts-Abhängigkeit Komponente→Execution (Code-belegt)
2026-06-07 Contracts/Models in datamodels (L1) statt neuem workflowContracts/ — durchs Import-Refactoring bereits erledigt (datamodelPortTypes, datamodelWorkflowAutomation) Layer-Hierarchie L0L7; Komponente konsumiert L1 abwärts
2026-06-07 Delaminierung zweier Helfer (PauseForHumanTaskErrordatamodels/serviceExceptions.py, coerceDocumentDataToBytesshared/documentUtils.py) aus automation2.executors vor Engine-Umzug Boundary-Leck besteht weiter: Shared methods/ importiert sie heute aufwärts
2026-06-07 Plan an Import-Refactoring (2026-06-05/06) angeglichen; Deferred-Liste aus import-analyse.md als Scope übernommen refactor hat GE↔Engine-Coupling explizit an diesen Plan delegiert
2026-06-05 RBAC-Namespace Option B (beibehalten + System-DATA-Objekte), kein Flip verhindert verwaiste AccessRule/Rollen-Zeilen
2026-06-05 Eigener Write-RBAC-Helper _validateWorkflowAccess (read/write) für die 39 Sites; GE-Feature-Rollen entfallen, Modell = Mandats-Mitgliedschaft/-Admin + isPlatformAdmin Dashboard-Muster deckt nur Lesen; instantiable=False ⇒ keine Feature-Instanz-Rollen mehr
2026-06-05 Modulares System (editor/engine/scheduler/solutions/launcher/monitoring), gemappt auf L2L4; L1 (Actions/Execution) + Contracts bleiben geteilt wartbar/nachvollziehbar; bündelt heute verstreute Automation-Teile + L3/L4
2026-06-05 Code nach modules/workflowAutomation/ (Platform) bzw. pages/workflowAutomation/ + components/workflowAutomation/ (UI); schrittweise via Re-Export-Shims sauberer Schnitt; Imports brechen nicht
2026-06-05 graphicalEditor wird System-Komponente (Feature-Mantel entfällt) kein DATA, eigene DB für alle Features, globaler Scheduler-Boot → ist Infrastruktur
2026-06-05 Eigene Top-Level-Nav-Gruppe «Workflow-Automation» mit Tab-Seiten strukturiert an einem Ort, cross-mandate/-feature; nicht als Feature-Seite
2026-06-05 Scheduler-/Poller-Boot in System-Lifespan (app.py) statt Feature-onStart Boot von der Feature-Plug-in-Mechanik lösen
2026-06-05 API mandatsweit /api/workflow-automation/…; RBAC = Mandats-Mitgliedschaft + System-Rollen + isPlatformAdmin {instanceId} als RBAC-Anker abbauen; bestehende Dashboard-Muster wiederverwenden
2026-06-05 AutoWorkflow.featureInstanceId verliert RBAC-Bedeutung; mandateId+runAsPrincipal = Owner; targetFeatureInstanceId/per-Node-Ref bleiben A0.1/A0.2; Daten-Scope bleibt funktional
2026-06-05 Migration phasenweise, parallel (kein Big-Bang); Bestand grandfathern Risiko begrenzen, jederzeit lauffähig
2026-06-05 DB-Name poweron_graphicaleditor bleibt YAGNI; Rename = unnötiges Risiko

Umsetzungs-Checkliste

Phase A — Code-Migration (Copy to new locations + re-export shims):

  • A2: modules/workflows/automation2/*.pymodules/workflowAutomation/engine/ (executionEngine, graphUtils, runEnvelope, scheduleCron, graphicalEditorRunFileLogger, pickNotPushMigration, featureInstanceRefMigration, workflowArtifactVisibility, clickupTaskUpdateMerge, udmUpstreamShapes) (2026-06-07)
  • A2: modules/workflows/automation2/executors/*.pymodules/workflowAutomation/engine/executors/ (actionNodeExecutor, inputExecutor, flowExecutor, triggerExecutor, ioExecutor, dataExecutor) (2026-06-07)
  • A3: modules/workflows/scheduler/mainScheduler.pymodules/workflowAutomation/scheduler/mainScheduler.py (2026-06-07)
  • A5: modules/features/graphicalEditor/{portTypes,adapterValidator,nodeRegistry,nodeAdapter,switchOutput,entryPoints,conditionOperators,upstreamPathsService,_workflowFileSchema}.pymodules/workflowAutomation/editor/ (2026-06-07)
  • A5: modules/features/graphicalEditor/nodeDefinitions/*.pymodules/workflowAutomation/editor/nodeDefinitions/ (2026-06-07)
  • A5: modules/features/graphicalEditor/emailPoller.pymodules/workflowAutomation/scheduler/emailPoller.py (2026-06-07)
  • Re-export shims created at old __init__.py locations for backward compatibility

Phase F — Delete old originals (cleanup):

  • F1: Deleted all individual .py files from modules/features/graphicalEditor/ (shims: interfaceFeatureGraphicalEditor.py, mainGraphicalEditor.py; originals: portTypes, adapterValidator, nodeRegistry, nodeAdapter, switchOutput, entryPoints, conditionOperators, upstreamPathsService, _workflowFileSchema, emailPoller + all nodeDefinitions/*.py) (2026-06-07)
  • F2: Deleted all individual .py files from modules/workflows/automation2/ and executors/ (executionEngine, graphUtils, runEnvelope, scheduleCron, graphicalEditorRunFileLogger, pickNotPushMigration, featureInstanceRefMigration, workflowArtifactVisibility, clickupTaskUpdateMerge, udmUpstreamShapes + 6 executor files) (2026-06-07)
  • F3: Deleted modules/workflows/scheduler/mainScheduler.py (2026-06-07)
  • F4: nodeDefinitions/__init__.py converted to re-export shim (imports STATIC_NODE_TYPES from new location)
  • F4: routeWorkflowAutomation.py imports updated to modules.workflowAutomation.editor._workflowFileSchema
  • automation2/__init__.py, automation2/executors/__init__.py, scheduler/__init__.py retained as re-export shims → backward compat for remaining importers
  • datamodelFeatureGraphicalEditor.py gelöscht (keine Caller mehr) (2026-06-08)
  • Test file imports (tests/unit/, tests/integration/, tests/demo/) updated to canonical modules.workflowAutomation.* paths (2026-06-08)

Phase D — Frontend Struktur (D1-D3):

  • D1: WorkflowAutomationPage.tsx monolith (1566 lines) split into pages/workflowAutomation/ with Hub + 5 tab components + types.ts (2026-06-08)
  • D2: Editor views re-exported from pages/workflowAutomation/views/ (2026-06-08)
  • D3: FlowEditor components re-export shim at components/workflowAutomation/FlowEditor/ (2026-06-08)

Phase A10 — RBAC Namespace Migration (Boot-integriert):

  • _migrateRbacNamespace() as idempotent routine in onBootstrap() — migrates AccessRule objectKeys from feature.graphicalEditor to system.workflowAutomation on every boot (2026-06-08)
  • TABLE_NAMESPACE in interfaceRbac.py updated from feature.graphicalEditor to system.workflowAutomation (2026-06-08)
  • Standalone script scripts/script_db_migrate_rbac_workflow_automation.py retained as manual fallback (2026-06-07)

Cleanup — Stale DEPRECATED-Bereinigung:

  • Stale DEPRECATED-Kommentare entfernt: i18nBootSync.py (2x), workflowTools.py (5x) — Imports zeigen bereits auf modules.workflowAutomation.* (2026-06-08)
  • resource.store.graphicalEditorresource.store.workflowAutomation in interfaceBootstrap.py + mainSystem.py (2026-06-08)
  • toolboxRegistry.py: featureCode="graphicalEditor""workflowAutomation" (2026-06-08)
  • datamodelFeatureGraphicalEditor.py gelöscht (toter Re-Export-Shim, keine Caller) (2026-06-08)
  • nodeDefinitions/__init__.py: DEPRECATED-Label durch neutrales Shim-Label ersetzt (2026-06-08)
  • routeWorkflowAutomation.py: fehlender DatabaseConnector-Import ergänzt (Boot-Fix) (2026-06-08)
  • routeWorkflowAutomation.py: staler Import modules.workflows.automation2.runEnvelopemodules.workflowAutomation.engine.runEnvelope (2026-06-08)
  • graphicalEditorRunFileLogger.pyrunFileLogger.py umbenannt + alle 4 Import-Stellen aktualisiert (2026-06-08)
  • graphicalEditorDatabase Alias in interfaceWorkflowAutomation.py entfernt (kein Caller) (2026-06-08)
  • Alle verbliebenen graphicalEditor-Kommentare/Docstrings in 7 Backend-Dateien neutralisiert (2026-06-08)
  • Demo-Configs: graphicalEditor aus Feature-Listen entfernt (pwgDemo2026.py, investorDemo2026.py) (2026-06-08)
  • Frontend: console.error('[graphicalEditor]'[workflowAutomation] (6 Stellen), Kommentare aktualisiert (2026-06-08)
  • _FEATURES_WITH_EDITOR: 'graphicalEditor' entfernt (WA ist kein Feature; nur 'workspace' verbleibt) (2026-06-08)
  • Test-Dateien: graphicalEditor aus Parametrize-Listen und Assertions entfernt (2026-06-08)
  • UDB-Surface 'graphEditor''workflowAutomation' (UnifiedDataBar.tsx, FilesTab.tsx, Automation2FlowEditor.tsx) (2026-06-08)
  • Automation2FlowEditor.tsx: 12 stale instanceId-Parameter aus API-Calls entfernt (API war bereits migriert) (2026-06-08)
  • FilesTab.tsx: importWorkflowFromFile Signatur korrigiert (stale instanceId entfernt) (2026-06-08)
  • Log-Prefixe [automations][workflowAutomation] in RunsTab.tsx + WorkflowsTab.tsx (2026-06-08)
  • Dead code entfernt: WorkflowTasksPage.tsx (942 LOC), WorkflowTasks.module.css (2026-06-08)
  • UDB generifiziert: UdbSurfacestring (kein hardcoded Feature-Enum mehr); Workflow-Import-Logik aus FilesTab.tsx entfernt → Consumer (Automation2FlowEditor) uebernimmt via onFileSelect; onWorkflowImportedFromFile Prop entfernt (2026-06-08)

Phase 0 — Scheduler-Boot entkoppeln (risikoarm, zuerst):

  • Scheduler-Start in System-Lifespan (app.py, nach setSchedulerMainLoop/eventManager.start()); Poller bleibt on-demand (ensureRunning), onStop-Stop verlagert (Scheduler + Email-Poller in app.py Shutdown Schritt 3.5); GE-onStart/onStop entfernt (2026-06-07)
  • Routen-Registrierung via loadFeatureMainModules() weiterhin aktiv (Feature-Mantel noch da)
  • Smoke: bestehende (grandfathered) geplante Runs feuern weiterhin, auch ohne GE-Feature-Instanz im Mandanten → manuell testen bei nächstem Deploy

Phase 0.5 — Delaminierung (vor jedem Code-Umzug):

  • portTypes/PORT_TYPE_CATALOG delaminierenerledigt durch Refactoring (datamodels/datamodelPortTypes.py, L1)
  • Kanonische Models nach L1erledigt (datamodels/datamodelWorkflowAutomation.py)
  • PauseForHumanTaskError + PauseForEmailWaitErrordatamodels/serviceExceptions.py (kanonisch); Re-Export-Shim in automation2/executors/inputExecutor.py; Caller methods/methodContext/actions/setContext.py umgebogen (2026-06-07)
  • coerceDocumentDataToBytes + _looksLikeAsciiBase64Payloadshared/documentUtils.py (kanonisch); Re-Export-Shim in automation2/executors/actionNodeExecutor.py; Caller methods/methodFile/actions/create.py umgebogen (2026-06-07)
  • Guard-Test: modules.workflows.{methods.methodContext.actions.setContext, methods.methodFile.actions.create} importierbar ohne modules.workflows.automation2.* → bestätigt, kein automation2-Modul transitiv geladen (2026-06-07)
  • Node-Katalog (STATIC_NODE_TYPES, features/graphicalEditor/nodeDefinitions/): moved to workflowAutomation/editor/nodeDefinitions/; old __init__.py converted to re-export shim; cross-Caller system/i18nBootSync.py + serviceAgent/workflowTools.py work via shim (2026-06-07)

Phase 1 — Mandatsweite API + System-RBAC (parallel zur Bestands-API):

  • AutoWorkflow.runAsPrincipal in datamodels/datamodelWorkflowAutomation.py ergänzt (Optional[str], nullable, softFk → UserInDB)
  • System-RBAC + Nav-Block: workflowAutomation Section (order 25) mit 5 UI-Objekten (ui.system.workflowAutomation.{workflows,editor,templates,runs,tasks}) in datamodelNavigation.py; automatisch von _buildUiObjectsFromNavigation in RBAC-Katalog aufgenommen
  • Neue Routen routeWorkflowAutomation.py: /api/workflow-automation/{workflows,versions,runs,tasks,steps} (10 Endpunkte) mandatsweit; Write-RBAC-Helper _validateWorkflowAccess(context, workflow, action) (read = mandate-member, write/execute/delete = mandate-admin), isPlatformAdmin-Bypass; registriert in app.py
  • Scheduler von featureInstanceId entkoppelt: if not instanceId-Guard in mainScheduler._syncScheduledWorkflows entfernt; instanceId default "" statt skip; Bestand läuft weiter
  • Runtime-Mandatsvalidierung beim FeatureInstanceRef-Auflösen: _validateFeatureInstanceMandates() in executionEngine.py nach materializeFeatureInstanceRefs() — defence-in-depth warning-log bei cross-mandate-Referenzen (A0.2)

Phase 2 — UI «Workflow-Automation»-Gruppe:

  • Nav-Block workflowAutomation in datamodels/datamodelNavigation.py (NAVIGATION_SECTIONS) — bereits in Phase 1 erledigt
  • /workflow-automation-Route + WorkflowAutomationPage.tsx Hub-Seite mit Tabs (Workflows · Läufe · Tasks), ?tab=-Deeplinks; Import in App.tsx
  • Icons in pageRegistry.tsx für page.system.workflowAutomation.* registriert (FaSitemap, FaProjectDiagram, FaCopy, FaPlay, FaTasks)
  • MandateNavigation.tsx: extraStaticBlocks-Logik — unbekannte statische Blöcke werden als eigene Nav-Sektionen gerendert (nicht mehr in System-Block gemergt)
  • Kontext-Selector (Alle Mandanten / Mandant X) im Hub — BillingDataView-Pattern; selectedMandateId an alle Tabs (2026-06-08)
  • Editor-Entkopplung: mandateId ist primaerer Kontext; instanceId nur noch Access-Gate fuer Workspace-Datasource-APIs (2026-06-08)
  • WorkflowsTab/RunsTab: Server-seitige Mandantenfilterung via mandateId-Query-Param (2026-06-08)
  • TasksTab im Hub verdrahtet (neue API /api/workflow-automation/tasks) (2026-06-08)
  • WorkflowsTab Edit-Navigation korrigiert: /workflow-automation?tab=editor&workflowId=... (statt mandate-scoped Feature-Route) (2026-06-08)
  • _FEATURES_WITH_EDITOR: 'workflowAutomation' entfernt (ist kein Feature) (2026-06-08)
  • Dead code entfernt: WorkflowTasksPage.tsx (942 LOC, instance-scoped legacy), WorkflowTasks.module.css (2026-06-08)
  • Keep-Alive fuer Editor-Tab: separate Iteration (aktuell wird der gesamte Hub kept-alive)

Phase 3 — DB & Datenmigration:

  • AutoWorkflow.featureInstanceIdOptional[str] (default=None, softFk=True); Pydantic-only, kein DDL — Spalte bereits DB-nullable
  • Cascade-Delete: _cascadeDeleteAutoWorkflow in routeWorkflowDashboard.py ist bereits mandatsweit (löscht nach workflowId, unabhängig von featureInstanceId)

Phase 4 — Feature-Mantel deprecaten (nicht entfernen — Koexistenz):

  • GE-Hardcode in routeSystem.py als DEPRECATED markiert (bleibt für bestehende Feature-Instanzen)
  • Import-Umstellung: routeWorkflowDashboard.py, routeAutomationWorkspace.py, routeSystem.py importieren Models aus kanonischer datamodels.datamodelWorkflowAutomation statt aus features.graphicalEditor.datamodelFeatureGraphicalEditor
  • Bestehende Feature-Routen /api/workflows/{instanceId}/… bleiben aktiv (Koexistenz mit neuer mandatsweiter API)
  • Feature-Registration (getFeatureDefinition, UI_OBJECTS, Store) bleibt — wird erst bei vollständiger Migration entfernt

Abschluss:

  • _CHANGELOG.md aktualisiert

Akzeptanzkriterien

# Kriterium (Given-When-Then) Prio
1 Given ein Mandant ohne GE-FeatureInstanz, When ein bestehender (grandfathered) geplanter Workflow fällig ist, Then feuert der Scheduler (Boot via System-Lifespan). (Instanz-freie Workflows: erst nach Phase-1-Scheduler-Entkopplung.) must
2 Given ein User mit Mandats-Mitgliedschaft, When er «Workflow-Automation» öffnet, Then sieht er eine Top-Level-Gruppe mit Tabs (Editor/Vorlagen/Workflows/Läufe/Tasks) — nicht pro Mandant/Instanz dupliziert must
3 Given mehrere Mandanten/Features, When er Workflows/Läufe ansieht, Then sind sie cross-mandate/-feature gelistet, RBAC-gefiltert (Mandats-Admin/isPlatformAdmin) must
4 Given Bestands-Workflows/Runs/Tasks, When migriert wurde, Then bleiben sie aufrufbar/ausführbar; targetFeatureInstanceId unverändert wirksam must
5 Given ein Run über mehrere Trustee-Instanzen, When er läuft, Then bucht recordUsage je Node die berührte Instanz (nicht fix graphicalEditor) must
6 Given kein graphicalEditor-Feature mehr, When der Store geöffnet wird, Then erscheint keine GE-Karte; bestehende Mandanten verlieren keine Workflows must
7 Given ein geplanter Run, When er ausgeführt wird, Then unter definierter Automations-Identität (nicht globaler Sysadmin); Reads nur im RBAC-Umfang des Principals must
8 Given die neue API, When ein Node eine fremd-mandatige Instanz-UUID trägt, Then Laufzeit-Fehler (Mandatsgrenze) should

Testplan

ID AC Art Automatisiert Repo-Pfad Status
T1 1 integration ja platform-core/tests/.../scheduler pending
T2 3 api ja platform-core/tests/.../workflowAutomation pending
T3 4 migration ja platform-core/tests/.../migration pending
T4 5 unit ja platform-core/tests/.../billing pending
T5 2 e2e/manual nein ui-nyla pending

Offene Fragen

  1. RBAC-Granularität (grösstenteils entschieden): Modell = Mandats-Mitgliedschaft + Mandats-Admin + isPlatformAdmin; GE-Feature-Rollen (graphicalEditor-*) entfallen. Offen nur: brauchen Power-User ohne Admin eine eigene System-Rolle workflowAutomation-user, oder genügt Mandats-user? (Feature-Instanz-Rollen sind keine Option mehr — instantiable=False + rbac-role-separation.mdc.)
  2. API-Pfad: /api/workflow-automation/… neu vs. bestehendes /api/system/workflow-runs ausbauen — konsolidieren? Entschieden (2026-06-08): /api/workflow-automation/… ist der kanonische Pfad. routeWorkflowAutomation.py registriert alle Endpunkte dort. /api/system/workflow-runs bleibt als Legacy-Alias (Dashboard).
  3. Run-as-Principal-Verwaltung: Ersteller-Identität vs. dedizierter Service-Principal (siehe CustomerCases offene Frage #1).
  4. Alt-URLs: wie lange Redirects der {instanceId}-Pfade halten (Bookmarks/Deeplinks)?
  5. Datei-/Doku-Rename: dieses Plan-Dokument ggf. auf …-workflowautomation-system-component.md umbenennen (aktuell …-automation-system-component.md) — Konsistenz vs. Referenz-Churn.
  • Architektur/Entscheid: c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md (A0.4), …-step3-features-plan.md (A0)
  • Prior Art: c-work/4-done/2026-04-automation-unification.md, 2026-04-automation-central-admin.md, 2026-04-generic-graph-editor.md
  • Code (Backend): modules/workflowAutomation/{editor,engine,scheduler}/, modules/datamodels/{datamodelPortTypes,datamodelWorkflowAutomation,datamodelNavigation}.py, modules/routes/{routeWorkflowAutomation,routeWorkflowDashboard,routeAutomationWorkspace,routeSystem}.py, app.py
  • Import-/Layer-Stand (Refactoring 2026-06-05/06, inkl. Deferred-Liste für diese Komponente): local/notes/refernce-analysis/platform-core-import-analyse.md
  • Code (Frontend): ui-nyla/src/pages/AutomationsDashboardPage.tsx, components/Navigation/MandateNavigation.tsx, pages/FeatureView.tsx, App.tsx
  • RBAC: b-reference/platform/rbac.md, .cursor/rules/rbac-role-separation.mdc, .cursor/rules/feature-instance-scoping.mdc

Abschluss

  • b-reference/platform/workflowAutomation.md: Kanon-Seite aktualisiert (Code-Pfade, API, RBAC, Navigation) (2026-06-08)
  • .cursor/rules/rbac-role-separation.mdc + feature-instance-scoping.mdc: WorkflowAutomation als dokumentierte Ausnahme eingetragen (2026-06-08)
  • topics-todo.md aktualisiert (WorkflowAutomation = System-Komponente, DONE) (2026-06-08)
  • features/graphicalEditor/ Verzeichnis komplett gelöscht (keine Dateien, keine Caller) (2026-06-08)
  • Cross-Import Assessment:
    • workflows -> features.graphicalEditor (~40 Imports): eliminiert — alle Imports auf modules.workflowAutomation.* (2026-06-08)
    • serviceCenter -> features.graphicalEditor (5x workflowTools): eliminiert — kanonische Pfade (2026-06-08)
    • interfaces/interfaceDbManagement.py:936 -> workflowArtifactVisibility: erledigt — modules.workflowAutomation.engine.workflowArtifactVisibility (2026-06-08)
    • Re-Export-Shims: datamodelFeatureGraphicalEditor.py gelöscht; stateTools.py Shim bleibt (7 Caller via processing/shared/, nicht Teil dieser Migration) (2026-06-08)
    • Keine from modules.features.graphicalEditor oder from modules.workflows.automation2 Imports mehr im gesamten Codebase (verifiziert via grep) (2026-06-08)
  • Lazy Imports in workflows/ reduzieren (separates Refactoring-Thema, nicht Teil dieser Migration)
  • Dieses Dokument → 4-done/ verschieben