From b66bb51df53f9bfbbbc32911cab01658d0b20bd0 Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Mon, 6 Apr 2026 00:46:32 +0200
Subject: [PATCH] DOcu updated
---
TOPICS.md | 23 +-
...-2025-10.md => 2025-10-investor-detail.md} | 0
....jpg => platform-01-platform-overview.jpg} | Bin
...ory.jpg => platform-02-customer-story.jpg} | Bin
...em.jpg => platform-03-workflow-system.jpg} | Bin
...platform-04-microservice-architecture.jpg} | Bin
...system.jpg => platform-05-rbac-system.jpg} | Bin
...re.jpg => platform-06-ui-architecture.jpg} | Bin
...form-07-big-picture-and-future-vision.jpg} | Bin
...g_picture.css => platform-big-picture.css} | 0
.../investor/{logo2.png => poweron-logo.png} | Bin
.../{doc_referenzen.html => referenzen.html} | 0
.../{doc_user_main.html => user-main.html} | 0
...Sync.html => ai-extraktion-buha-sync.html} | 0
.../market/langdock-markteinschaetzung.md | 36 +-
...on.pdf => langdock-markteinschaetzung.pdf} | Bin
.../market/playground-marketing-pitch.md | 2 +-
a-strategy/product-strategy.md | 6 +-
a-strategy/product-vision.md | 71 ++
...smodell.pdf => 2026-02-24-preismodell.pdf} | Bin
...rOn_Roadmap.pdf => 2026-02-24-roadmap.pdf} | Bin
...ntation.html => roadmap-presentation.html} | 0
a-strategy/roadmap.md | 2 +-
b-reference/gateway/automation.md | 124 +-
b-reference/gateway/billing.md | 25 +-
b-reference/platform/database-architecture.md | 271 +++++
b-reference/platform/platform-diagrams.md | 14 +-
b-reference/platform/rbac.md | 346 +++++-
c-work/1-plan/2026-03-web-image-search.md | 398 +-----
.../1-plan/2026-04-automation-unification.md | 1067 +++++++++++++++++
d-guides/coding-conventions.md | 65 +-
...sicht.drawio => instanzenuebersicht.drawio} | 0
...nübersicht.svg => instanzenuebersicht.svg} | 0
.../{poweron_sec.kdbx => poweron-sec.kdbx} | Bin
d-guides/dev-setup.md | 72 +-
d-guides/encrypt-env-secrets.md | 10 +-
d-guides/google-oauth-setup.md | 29 +-
d-guides/testing-strategy.md | 103 +-
e-compliance/neutralisierung-detail.md | 8 +-
e-compliance/security-overview.md | 4 +-
.../a-strategy}/investor/application-doc.md | 0
.../a-strategy}/investor/customer-value.md | 0
.../investor/doc_investor_general.html | 0
.../a-strategy}/investor/product-doc.md | 0
.../investor/product-summary-slides.md | 0
.../Dev-Ops-Budget-Pace-VR-Sitzung.html | 0
... - Your AI Colleague in Every Meeting.html | 0
.../doc_playground_marketing_pitch.html | 0
.../market/doc_produktestrategie.html | 0
.../b-reference}/automation-business-spec.md | 0
.../b-reference}/automation-data-model.md | 0
.../c-work}/2026-03-cursor-style-chat.md | 0
.../c-work}/2026-03-workflow-editor.md | 0
53 files changed, 2153 insertions(+), 523 deletions(-)
rename a-strategy/investor/{investor-doc-2025-10.md => 2025-10-investor-detail.md} (100%)
rename a-strategy/investor/images/{doc_platform_01_platform_overview.jpg => platform-01-platform-overview.jpg} (100%)
rename a-strategy/investor/images/{doc_platform_02_customer_story.jpg => platform-02-customer-story.jpg} (100%)
rename a-strategy/investor/images/{doc_platform_03_workflow_system.jpg => platform-03-workflow-system.jpg} (100%)
rename a-strategy/investor/images/{doc_platform_04_microservice_architecture.jpg => platform-04-microservice-architecture.jpg} (100%)
rename a-strategy/investor/images/{doc_platform_05_rbac_system.jpg => platform-05-rbac-system.jpg} (100%)
rename a-strategy/investor/images/{doc_platform_06_ui_architecture.jpg => platform-06-ui-architecture.jpg} (100%)
rename a-strategy/investor/images/{doc_platform_07_big_picture_and_future_vision.jpg => platform-07-big-picture-and-future-vision.jpg} (100%)
rename a-strategy/investor/{doc_platform_big_picture.css => platform-big-picture.css} (100%)
rename a-strategy/investor/{logo2.png => poweron-logo.png} (100%)
rename a-strategy/investor/{doc_referenzen.html => referenzen.html} (100%)
rename a-strategy/investor/{doc_user_main.html => user-main.html} (100%)
rename a-strategy/market/{AI-Extraktion und BUHA-Sync.html => ai-extraktion-buha-sync.html} (100%)
rename a-strategy/market/{langdock-markteinschaetzung-poweron.pdf => langdock-markteinschaetzung.pdf} (100%)
create mode 100644 a-strategy/product-vision.md
rename a-strategy/roadmap-2026-02/{20260224_PowerOn_Preismodell.pdf => 2026-02-24-preismodell.pdf} (100%)
rename a-strategy/roadmap-2026-02/{20260224_PowerOn_Roadmap.pdf => 2026-02-24-roadmap.pdf} (100%)
rename a-strategy/roadmap-2026-02/{roadmap_presentation.html => roadmap-presentation.html} (100%)
create mode 100644 b-reference/platform/database-architecture.md
create mode 100644 c-work/1-plan/2026-04-automation-unification.md
rename d-guides/deployment/{Instanzenübersicht.drawio => instanzenuebersicht.drawio} (100%)
rename d-guides/deployment/{Instanzenübersicht.svg => instanzenuebersicht.svg} (100%)
rename d-guides/deployment/{poweron_sec.kdbx => poweron-sec.kdbx} (100%)
rename {a-strategy => z-archive/a-strategy}/investor/application-doc.md (100%)
rename {a-strategy => z-archive/a-strategy}/investor/customer-value.md (100%)
rename {a-strategy => z-archive/a-strategy}/investor/doc_investor_general.html (100%)
rename {a-strategy => z-archive/a-strategy}/investor/product-doc.md (100%)
rename {a-strategy => z-archive/a-strategy}/investor/product-summary-slides.md (100%)
rename {a-strategy => z-archive/a-strategy}/market/Dev-Ops-Budget-Pace-VR-Sitzung.html (100%)
rename {a-strategy => z-archive/a-strategy}/market/Nyla - Your AI Colleague in Every Meeting.html (100%)
rename {a-strategy => z-archive/a-strategy}/market/doc_playground_marketing_pitch.html (100%)
rename {a-strategy => z-archive/a-strategy}/market/doc_produktestrategie.html (100%)
rename {b-reference/gateway => z-archive/b-reference}/automation-business-spec.md (100%)
rename {b-reference/gateway => z-archive/b-reference}/automation-data-model.md (100%)
rename {c-work/1-plan => z-archive/c-work}/2026-03-cursor-style-chat.md (100%)
rename {c-work/1-plan => z-archive/c-work}/2026-03-workflow-editor.md (100%)
diff --git a/TOPICS.md b/TOPICS.md
index 5e61803..f30790d 100644
--- a/TOPICS.md
+++ b/TOPICS.md
@@ -1,4 +1,4 @@
-
+
# Themen-Index für AI-Kontext
@@ -32,15 +32,32 @@ Lade immer zuerst diese Datei. Dann gezielt die passende(n) Referenz-Datei(en).
| Thema | Datei | Wann laden |
|-------|-------|------------|
| Neutralisierung | b-reference/platform/neutralization.md | Datenschutz, AI-Call-Pipeline, Failsafe |
-| RBAC | b-reference/platform/rbac.md | Berechtigungen, Mandate- und Feature-Rollen |
+| RBAC | b-reference/platform/rbac.md | 4-Stufen-Modell, Template-Rollen, Resolution, Datenmodell |
+| Datenbank-Architektur | b-reference/platform/database-architecture.md | Interface-Pattern, Connector, Auto-Init, DB-Liste |
| Navigation | b-reference/platform/navigation.md | Menü-Struktur, Admin-Seiten, API |
+## Aktive Arbeiten (c-work)
+
+| Thema | Datei | Wann laden |
+|-------|-------|------------|
+| Automation Unification | c-work/1-plan/2026-04-automation-unification.md | Refactoring v1/v2/Workspace |
+| Web Image Search | c-work/1-plan/2026-03-web-image-search.md | WEB_SEARCH_MEDIA Feature |
+
## Prozess & Betrieb
| Thema | Datei | Wann laden |
|-------|-------|------------|
| Coding-Regeln | d-guides/coding-conventions.md | Naming, Patterns, Anti-Patterns |
| Testing-Strategie | d-guides/testing-strategy.md | Testpyramide, AC-Format, Test-Pfade |
-| Deployment | d-guides/deployment.md | Release-Prozess, Environments |
| Dev-Setup | d-guides/dev-setup.md | Lokale Umgebung starten |
+| Secrets-Verschluesselung | d-guides/encrypt-env-secrets.md | Env-Dateien verschluesseln |
+| Google OAuth | d-guides/google-oauth-setup.md | OAuth Auth/Data Apps einrichten |
+| Security-Migration | d-guides/security-migration-guide.md | JWT Cookie Migration |
| Doc-Sync Cursor-Rule | d-guides/doc-sync.mdc | Cursor-Regel installieren, Doku-Workflow |
+
+## Compliance & Sicherheit
+
+| Thema | Datei | Wann laden |
+|-------|-------|------------|
+| Sicherheitsuebersicht | e-compliance/security-overview.md | Kunden/Audit: DSGVO, RBAC, Verschluesselung |
+| Neutralisierung Detail | e-compliance/neutralisierung-detail.md | Technische Neutralisierungs-Flows |
diff --git a/a-strategy/investor/investor-doc-2025-10.md b/a-strategy/investor/2025-10-investor-detail.md
similarity index 100%
rename from a-strategy/investor/investor-doc-2025-10.md
rename to a-strategy/investor/2025-10-investor-detail.md
diff --git a/a-strategy/investor/images/doc_platform_01_platform_overview.jpg b/a-strategy/investor/images/platform-01-platform-overview.jpg
similarity index 100%
rename from a-strategy/investor/images/doc_platform_01_platform_overview.jpg
rename to a-strategy/investor/images/platform-01-platform-overview.jpg
diff --git a/a-strategy/investor/images/doc_platform_02_customer_story.jpg b/a-strategy/investor/images/platform-02-customer-story.jpg
similarity index 100%
rename from a-strategy/investor/images/doc_platform_02_customer_story.jpg
rename to a-strategy/investor/images/platform-02-customer-story.jpg
diff --git a/a-strategy/investor/images/doc_platform_03_workflow_system.jpg b/a-strategy/investor/images/platform-03-workflow-system.jpg
similarity index 100%
rename from a-strategy/investor/images/doc_platform_03_workflow_system.jpg
rename to a-strategy/investor/images/platform-03-workflow-system.jpg
diff --git a/a-strategy/investor/images/doc_platform_04_microservice_architecture.jpg b/a-strategy/investor/images/platform-04-microservice-architecture.jpg
similarity index 100%
rename from a-strategy/investor/images/doc_platform_04_microservice_architecture.jpg
rename to a-strategy/investor/images/platform-04-microservice-architecture.jpg
diff --git a/a-strategy/investor/images/doc_platform_05_rbac_system.jpg b/a-strategy/investor/images/platform-05-rbac-system.jpg
similarity index 100%
rename from a-strategy/investor/images/doc_platform_05_rbac_system.jpg
rename to a-strategy/investor/images/platform-05-rbac-system.jpg
diff --git a/a-strategy/investor/images/doc_platform_06_ui_architecture.jpg b/a-strategy/investor/images/platform-06-ui-architecture.jpg
similarity index 100%
rename from a-strategy/investor/images/doc_platform_06_ui_architecture.jpg
rename to a-strategy/investor/images/platform-06-ui-architecture.jpg
diff --git a/a-strategy/investor/images/doc_platform_07_big_picture_and_future_vision.jpg b/a-strategy/investor/images/platform-07-big-picture-and-future-vision.jpg
similarity index 100%
rename from a-strategy/investor/images/doc_platform_07_big_picture_and_future_vision.jpg
rename to a-strategy/investor/images/platform-07-big-picture-and-future-vision.jpg
diff --git a/a-strategy/investor/doc_platform_big_picture.css b/a-strategy/investor/platform-big-picture.css
similarity index 100%
rename from a-strategy/investor/doc_platform_big_picture.css
rename to a-strategy/investor/platform-big-picture.css
diff --git a/a-strategy/investor/logo2.png b/a-strategy/investor/poweron-logo.png
similarity index 100%
rename from a-strategy/investor/logo2.png
rename to a-strategy/investor/poweron-logo.png
diff --git a/a-strategy/investor/doc_referenzen.html b/a-strategy/investor/referenzen.html
similarity index 100%
rename from a-strategy/investor/doc_referenzen.html
rename to a-strategy/investor/referenzen.html
diff --git a/a-strategy/investor/doc_user_main.html b/a-strategy/investor/user-main.html
similarity index 100%
rename from a-strategy/investor/doc_user_main.html
rename to a-strategy/investor/user-main.html
diff --git a/a-strategy/market/AI-Extraktion und BUHA-Sync.html b/a-strategy/market/ai-extraktion-buha-sync.html
similarity index 100%
rename from a-strategy/market/AI-Extraktion und BUHA-Sync.html
rename to a-strategy/market/ai-extraktion-buha-sync.html
diff --git a/a-strategy/market/langdock-markteinschaetzung.md b/a-strategy/market/langdock-markteinschaetzung.md
index cea69f3..ddd52f1 100644
--- a/a-strategy/market/langdock-markteinschaetzung.md
+++ b/a-strategy/market/langdock-markteinschaetzung.md
@@ -1,4 +1,4 @@
-# Markteinschaetzung: Langdock (Berlin) vs. PowerON
+# Markteinschaetzung: Langdock (Berlin) vs. PowerOn
**Dokument:** Markt- und Wettbewerbsanalyse mit strategischer Empfehlung
**Stand:** 23. Maerz 2026
@@ -10,9 +10,9 @@
**Langdock** ist eine horizontale Enterprise-KI-Adoptionsplattform (Chat, Workflows, Agents, Integrationen, API) mit Fokus auf sichere, modellagnostische KI fuer das gesamte Unternehmen. Sitz Berlin, tausende Kunden, schnelles Wachstum.
-**PowerON** positioniert sich auf poweron.swiss als *"The Swiss Pocket Knife of AI for SMEs"* -- eine universelle KI-Plattform fuer Schweizer KMU mit DSGVO-Compliance und Schweizer Hosting. Im Code steckt deutlich mehr: eine mandantenfaehige SaaS-Plattform mit RBAC, Feature-Instanzen, Billing/Subscription, vertikalen Fachmodulen (Treuhand, Immobilien, CommCoach) und einem einzigartigen **Daten-Neutralisierungs-Feature**.
+**PowerOn** positioniert sich auf poweron.swiss als *"The Swiss Pocket Knife of AI for SMEs"* -- eine universelle KI-Plattform fuer Schweizer KMU mit DSGVO-Compliance und Schweizer Hosting. Im Code steckt deutlich mehr: eine mandantenfaehige SaaS-Plattform mit RBAC, Feature-Instanzen, Billing/Subscription, vertikalen Fachmodulen (Treuhand, Immobilien, CommCoach) und einem einzigartigen **Daten-Neutralisierungs-Feature**.
-**Kernbefund:** Die oeffentliche Positionierung von PowerON ueberschneidet sich staerker mit Langdock als noetig. Das Produkt hat genuegend einzigartige Tiefe, um sich klar abzugrenzen -- die Botschaft muss geschaerft werden.
+**Kernbefund:** Die oeffentliche Positionierung von PowerOn ueberschneidet sich staerker mit Langdock als noetig. Das Produkt hat genuegend einzigartige Tiefe, um sich klar abzugrenzen -- die Botschaft muss geschaerft werden.
---
@@ -44,7 +44,7 @@
---
-## 3. PowerON -- Oeffentliche Positionierung (poweron.swiss)
+## 3. PowerOn -- Oeffentliche Positionierung (poweron.swiss)
### 3.1 Claim und Zielgruppe
@@ -86,7 +86,7 @@ Im Code existiert dafuer ein eigenes Feature-Modul (`neutralization`) mit Playgr
---
-## 4. PowerON -- Realitaet im Code (ueber die Homepage hinaus)
+## 4. PowerOn -- Realitaet im Code (ueber die Homepage hinaus)
Die Codebase zeigt erheblich mehr Tiefe als die Website kommuniziert:
@@ -115,13 +115,13 @@ Die Codebase zeigt erheblich mehr Tiefe als die Website kommuniziert:
### 4.3 Gap: Homepage vs. Code
-Die Website zeigt PowerON als **generische KI-Plattform**. Der Code offenbart eine **spezialisierte SaaS mit Branchen-Features, Abrechnungslogik und tiefer Mandantenfaehigkeit** -- davon erfaehrt der Besucher von poweron.swiss aktuell nichts.
+Die Website zeigt PowerOn als **generische KI-Plattform**. Der Code offenbart eine **spezialisierte SaaS mit Branchen-Features, Abrechnungslogik und tiefer Mandantenfaehigkeit** -- davon erfaehrt der Besucher von poweron.swiss aktuell nichts.
---
-## 5. Ueberschneidungen PowerON vs. Langdock
+## 5. Ueberschneidungen PowerOn vs. Langdock
-| Thema | Langdock | PowerON |
+| Thema | Langdock | PowerOn |
|-------------------------|-----------------------------------|-----------------------------------------------|
| Firmenweite KI-Nutzung | Kerngeschaeft | Workspace, Chatbot, Teamsbot |
| Chat & Konversationen | Chat-Produkt | Chatbot + Workspace-Editor |
@@ -131,13 +131,13 @@ Die Website zeigt PowerON als **generische KI-Plattform**. Der Code offenbart ei
| Integrationen | Viele Standard-Integrationen | M365, Google, Jira, ClickUp, SharePoint, DB |
| Governance / Security | EU-Hosting, DSGVO | Schweizer Hosting, DSGVO, RBAC, Neutralisierung|
-**Die generische KI-Schicht ueberschneidet sich stark.** Wer nur "ChatGPT im Unternehmen" sucht, sieht PowerON und Langdock in der gleichen Kategorie -- wobei Langdock dort durch Marktgroesse und Bekanntheit dominiert.
+**Die generische KI-Schicht ueberschneidet sich stark.** Wer nur "ChatGPT im Unternehmen" sucht, sieht PowerOn und Langdock in der gleichen Kategorie -- wobei Langdock dort durch Marktgroesse und Bekanntheit dominiert.
---
-## 6. Klare Unterschiede (PowerON-Vorteile)
+## 6. Klare Unterschiede (PowerOn-Vorteile)
-| Dimension | PowerON | Langdock |
+| Dimension | PowerOn | Langdock |
|----------------------------|----------------------------------------------|---------------------------------|
| **Daten-Neutralisierung** | 5-Stufen-Prozess, eigenes Feature | Nicht vorhanden |
| **Schweizer Hosting** | 100% Schweiz, lokale Datensouveraenitaet | EU (nicht CH-spezifisch) |
@@ -151,13 +151,13 @@ Die Website zeigt PowerON als **generische KI-Plattform**. Der Code offenbart ei
### 7.1 Kernproblem der aktuellen Positionierung
-Die Homepage positioniert PowerON als **generische KI-Plattform** -- genau dort, wo Langdock (und Microsoft Copilot, und Google Gemini for Workspace, und dutzende weitere) bereits mit massiv mehr Ressourcen, Brand und Kundenstamm unterwegs sind.
+Die Homepage positioniert PowerOn als **generische KI-Plattform** -- genau dort, wo Langdock (und Microsoft Copilot, und Google Gemini for Workspace, und dutzende weitere) bereits mit massiv mehr Ressourcen, Brand und Kundenstamm unterwegs sind.
Ein Drei-Personen-Team kann dieses Rennen nicht auf der generischen Ebene gewinnen. Jede Stunde, die in "wir sind auch ein KI-Chat mit Workflows" investiert wird, ist eine Stunde, in der Langdock mit tausenden Kunden und Millionen-Revenue den gleichen Pitch perfektioniert.
### 7.2 Empfohlene Richtung: Vertikale KI-SaaS mit Neutralisierungs-Moat
-**PowerON sollte sich als vertikale, mandantenfaehige KI-SaaS positionieren -- nicht als generische KI-Plattform.**
+**PowerOn sollte sich als vertikale, mandantenfaehige KI-SaaS positionieren -- nicht als generische KI-Plattform.**
Die empfohlene Positionierung stuetzt sich auf drei Saeulen:
@@ -165,7 +165,7 @@ Die empfohlene Positionierung stuetzt sich auf drei Saeulen:
Die Daten-Neutralisierung ist das Feature, das kein Wettbewerber in dieser Form hat. Statt es als eines von fuenf technischen Features aufzulisten, sollte es das **zentrale Verkaufsargument** werden:
-- *"PowerON ist die einzige KI-Plattform, bei der LLMs niemals Ihre sensiblen Daten sehen -- garantiert durch einen 5-Stufen-Neutralisierungsprozess."*
+- *"PowerOn ist die einzige KI-Plattform, bei der LLMs niemals Ihre sensiblen Daten sehen -- garantiert durch einen 5-Stufen-Neutralisierungsprozess."*
- Besonders relevant fuer: Treuhand, Kanzleien, Gesundheitswesen, Finanzdienstleister, oeffentliche Verwaltung.
- Alle anderen Features (Chat, Automation, Workspace) werden **unter dem Neutralisierungs-Dach** vermarktet, nicht daneben.
@@ -173,7 +173,7 @@ Die Daten-Neutralisierung ist das Feature, das kein Wettbewerber in dieser Form
Der Code enthaelt bereits Treuhand, Immobilien und CommCoach. Diese Module gehoeren sichtbar auf die Website und in den Pitch:
-- Dedizierte Landing Pages pro Branche: "PowerON fuer Treuhandbueros", "PowerON fuer Immobilienverwaltungen".
+- Dedizierte Landing Pages pro Branche: "PowerOn fuer Treuhandbueros", "PowerOn fuer Immobilienverwaltungen".
- Jede Branchenseite zeigt den konkreten Workflow: Dokument rein, Neutralisierung, KI-Verarbeitung, Ergebnis zurueck -- mit branchenspezifischem Vokabular.
- Der Feature-Store und das Mandantenmodell sind dabei die **technische Grundlage**, nicht der Marketing-Lead.
@@ -198,7 +198,7 @@ Der Code enthaelt bereits Treuhand, Immobilien und CommCoach. Diese Module gehoe
### 7.4 Wovon ich abrate
1. **Breites Integrations-Rennen:** Langdock hat Dutzende Integrationen; dieses Rennen zu gewinnen ist mit kleinem Team unrealistisch. Besser: die vorhandenen Integrationen (M365, SharePoint, Google) **tief und zuverlaessig** halten und pro Branche gezielt erweitern (z. B. ABACUS/Bexio fuer Treuhand).
-2. **"KI-Chat fuer alle":** Das ist Langdocks Kernmarkt. PowerON gewinnt nicht, indem es den gleichen Pitch macht, sondern indem es den Pitch **spezifischer** macht.
+2. **"KI-Chat fuer alle":** Das ist Langdocks Kernmarkt. PowerOn gewinnt nicht, indem es den gleichen Pitch macht, sondern indem es den Pitch **spezifischer** macht.
3. **Feature-Breite vor Feature-Tiefe:** Lieber drei Branchen exzellent bedienen als zehn Features halb fertig zeigen (vgl. `features.feature5.title`-Platzhalter auf der Homepage).
### 7.5 Mittelfristiger Zielzustand (6-12 Monate)
@@ -212,13 +212,13 @@ Der Code enthaelt bereits Treuhand, Immobilien und CommCoach. Diese Module gehoe
## 8. Zusammenfassung in einem Satz
-> PowerON sollte aufhoeren, Langdocks Spiel zu spielen ("generische KI fuer alle"), und stattdessen das eigene Spiel spielen: **sichere, neutralisierte KI fuer regulierte Schweizer Branchen** -- ein Markt, den Langdock strukturell nicht adressiert.
+> PowerOn sollte aufhoeren, Langdocks Spiel zu spielen ("generische KI fuer alle"), und stattdessen das eigene Spiel spielen: **sichere, neutralisierte KI fuer regulierte Schweizer Branchen** -- ein Markt, den Langdock strukturell nicht adressiert.
---
## 9. Quellen und Methodik
-- **PowerON:** Homepage poweron.swiss (Stand Maerz 2026) sowie Codeanalyse gateway und frontend_nyla.
+- **PowerOn:** Homepage poweron.swiss (Stand Maerz 2026) sowie Codeanalyse gateway und frontend_nyla.
- **Langdock:** Oeffentliche Website langdock.com und Produktunterseiten, Presseartikel (Stand Maerz 2026).
- Keine vertraulichen Materialien verwendet. Fuer verbindliche Pricing- und SLA-Vergleiche ist Herstellerkontakt noetig.
diff --git a/a-strategy/market/langdock-markteinschaetzung-poweron.pdf b/a-strategy/market/langdock-markteinschaetzung.pdf
similarity index 100%
rename from a-strategy/market/langdock-markteinschaetzung-poweron.pdf
rename to a-strategy/market/langdock-markteinschaetzung.pdf
diff --git a/a-strategy/market/playground-marketing-pitch.md b/a-strategy/market/playground-marketing-pitch.md
index fc9a71d..8285154 100644
--- a/a-strategy/market/playground-marketing-pitch.md
+++ b/a-strategy/market/playground-marketing-pitch.md
@@ -30,7 +30,7 @@
1) **🔒 Neutralizer (Datenschutz-First)**
- **Automatische Anonymisierung** sensibler Daten vor der KI-Verarbeitung
- **DSGVO-konform**, transparente Regeln – du bestimmst, was neutralisiert wird
- - **Validierungs-Roadmap**: Level 1 Datenschutz jetzt; Level 2 kontextueller IP-Schutz folgt mit externem Validat/Cert (ETH/HSG/Partner)
+ - **Validierungs-Roadmap**: Level 1 Datenschutz jetzt; Level 2 kontextueller IP-Schutz folgt mit externem Validator/Zertifizierung (ETH/HSG/Partner)
2) **♾️ Unlimitierte Verarbeitung**
- **Keine Token-Limits** – Dokumente jeder Grösse verarbeiten
diff --git a/a-strategy/product-strategy.md b/a-strategy/product-strategy.md
index 552c978..5bf5fb4 100644
--- a/a-strategy/product-strategy.md
+++ b/a-strategy/product-strategy.md
@@ -106,7 +106,7 @@ PowerOn ist eine **Multi-Agent-KI-Plattform für Enterprise-Workflows** mit inte
### 2.2 Alleinstellungsmerkmale (USP)
#### **1. Integrierter Datenschutz-Neutralisierer**
-- **Einzigartig**: Erste Plattform mit eingebautem Datenschutz-Schutz
+- **Einzigartig**: Erste Plattform mit eingebautem Datenschutz-Neutralisierer
- **Vorteil**: Unternehmen können KI nutzen ohne Datenschutzrisiken
- **Differenzierung**: Kein Konkurrent bietet diese Funktionalität
@@ -169,7 +169,7 @@ PowerOn ist eine **Multi-Agent-KI-Plattform für Enterprise-Workflows** mit inte
- **3 Workflow-Modi**:
- **Learning-Mode**: Iterative Plan-Act-Observe-Refine-Schleife
- **Actionplan-Mode**: Batch-Planung mit sequenzieller Ausführung
- - **Automation-Mode**: Automatisierte vordefinierte Workflosw
+ - **Automation-Mode**: Automatisierte vordefinierte Workflows
- **Adaptive Learning Engine**: Lernt aus Validierungsergebnissen und passt Prompts an
- **Intelligente Task-Planung**: Automatische Aufschlüsselung komplexer Anfragen in ausführbare Schritte
- **Echtzeit-Validierung**: Kontinuierliche Qualitätskontrolle und automatische Verbesserungen
@@ -701,7 +701,7 @@ Wir sind aktuell im Monat 10 des Projekts und haben noch 2 Monate bis zur Seed-R
#### **KI-Services**
- **OpenAI**: GPT-4, DALL-E, Whisper
- **Anthropic**: Claude, Constitutional AI
-- **Google**: PaLM, Bard, Vertex AI
+- **Google**: Gemini, Vertex AI
- **Azure**: Cognitive Services, OpenAI Service
---
diff --git a/a-strategy/product-vision.md b/a-strategy/product-vision.md
new file mode 100644
index 0000000..0375b07
--- /dev/null
+++ b/a-strategy/product-vision.md
@@ -0,0 +1,71 @@
+
+
+
+# PowerOn PORTA -- Produktvision
+
+## Was ist PowerOn PORTA?
+
+PowerOn PORTA ist eine **Multi-Agent-KI-Plattform für Enterprise-Workflows** mit integriertem Datenschutz-Neutralisierer. Die Plattform ermöglicht Unternehmen, KI-Transformation zu beschleunigen, ohne Datenschutzrisiken einzugehen.
+
+**PORTA** = **P**owerful **O**rchestration & **R**eal-**T**ime **A**utomation
+
+## Value Proposition
+
+| Problem | PowerOn-Lösung |
+|---------|---------------|
+| 80% der Unternehmen können ChatGPT/Copilot nicht nutzen wegen Datenschutz | Integrierter Datenschutz-Neutralisierer: sensible Daten verlassen nie das Unternehmen |
+| Token-Limits bei grossen Dokumenten | Unlimitierte Verarbeitung durch intelligente Chunking-Strategien |
+| Isolierte KI-Services arbeiten nicht zusammen | Einheitliche Plattform mit nahtloser Integration aller Services |
+| Komplexe, unvorhersehbare Pricing-Modelle | Transparentes Pauschalpricing pro Monat/Jahr |
+| End-to-End-Workflows sind Expertensache | Schrittweise Integration, beginnend mit einfachen Use Cases |
+
+## Zielkunden
+
+- **Primär:** Mittelständische Unternehmen (100-2'000 MA) in datenschutz-sensitiven Branchen
+- **Branchen:** Finanzdienstleistungen, Treuhand, Immobilien, Professional Services, Healthcare
+- **Geografie:** DACH (initial), EU + US (Expansion)
+
+## Alleinstellungsmerkmale (USPs)
+
+1. **Datenschutz-Neutralisierer:** Einzige Plattform mit integrierter Echtzeit-Neutralisierung, die sensible Daten vor dem Verlassen des Unternehmens anonymisiert und nach Verarbeitung reanonymisiert.
+
+2. **Multi-Agent-Orchestrierung:** Spezialisierte KI-Agenten pro Aufgabe (Chat, Workflow, Voice, RAG, Automation), koordiniert durch eine zentrale Engine mit 40+ Tools.
+
+3. **Modellunabhängigkeit:** Integration mit Anthropic, OpenAI, Mistral, Perplexity, Tavily, Private LLM -- kein Vendor Lock-in, immer das beste Modell pro Aufgabe.
+
+4. **Feature-Store-Architektur:** Mandanten aktivieren Features modular (Workspace, Automation, CommCoach, Trustee etc.) -- skaliert von Einzelanwendung bis Full-Suite.
+
+5. **Voice-First:** Integrierte STT/TTS in den meisten Sprachen, nahtlos im Workflow nutzbar.
+
+## Technologie-Stack (Kurzübersicht)
+
+| Komponente | Technologie |
+|-----------|-------------|
+| Frontend Nyla | React/TypeScript, Vite |
+| Gateway | FastAPI, Python, PostgreSQL, pgvector |
+| Private LLM | Python, Ollama |
+| Teams Bot | TypeScript/Node.js |
+
+Detaillierte Architektur: → `b-reference/product.md`
+
+## Umsatzmodell
+
+- **SaaS-Abonnement:** Pauschal pro Monat/Jahr, Features modular zubuchbar
+- **Ziel-Bruttomarge:** 75-85% nach Skalierung
+- **Preismodell:** Nicht nutzungsbasiert pro Token, sondern unlimitiert innerhalb des Abonnements
+
+## Strategische Phasen
+
+| Phase | Zeitraum | Fokus |
+|-------|---------|-------|
+| Launch | 2025-2026 | Core-Plattform, 3-5 Referenzkunden, DACH |
+| Growth | 2026-2027 | Feature-Expansion, branchenspezifische Templates, Partner |
+| Scale | 2027+ | Internationalisierung, Agenten-Marktplatz, Branchenlösungen |
+
+## Verweise
+
+- Strategie & PMF: → `a-strategy/product-strategy.md`
+- Roadmap: → `a-strategy/roadmap.md`
+- Marktanalyse: → `a-strategy/market/`
+- Investor-Zusammenfassung: → `a-strategy/investor/investor-summary.md`
+- Komponentenübersicht: → `b-reference/product.md`
diff --git a/a-strategy/roadmap-2026-02/20260224_PowerOn_Preismodell.pdf b/a-strategy/roadmap-2026-02/2026-02-24-preismodell.pdf
similarity index 100%
rename from a-strategy/roadmap-2026-02/20260224_PowerOn_Preismodell.pdf
rename to a-strategy/roadmap-2026-02/2026-02-24-preismodell.pdf
diff --git a/a-strategy/roadmap-2026-02/20260224_PowerOn_Roadmap.pdf b/a-strategy/roadmap-2026-02/2026-02-24-roadmap.pdf
similarity index 100%
rename from a-strategy/roadmap-2026-02/20260224_PowerOn_Roadmap.pdf
rename to a-strategy/roadmap-2026-02/2026-02-24-roadmap.pdf
diff --git a/a-strategy/roadmap-2026-02/roadmap_presentation.html b/a-strategy/roadmap-2026-02/roadmap-presentation.html
similarity index 100%
rename from a-strategy/roadmap-2026-02/roadmap_presentation.html
rename to a-strategy/roadmap-2026-02/roadmap-presentation.html
diff --git a/a-strategy/roadmap.md b/a-strategy/roadmap.md
index cceccd4..4c9da3f 100644
--- a/a-strategy/roadmap.md
+++ b/a-strategy/roadmap.md
@@ -17,7 +17,7 @@ Dieses Dokument beschreibt die vorhandenen Features der PowerOn-Plattform, das a
PowerOn ist eine **Multi-Mandanten-Plattform**:
-- **Mandatenmodell:** Jede Organisation/Kunde wird als Mandant abgebildet.
+- **Mandantenmodell:** Jede Organisation/Kunde wird als Mandant abgebildet.
- **Datenisolation:** Daten eines Mandanten sind strikt von anderen Mandanten getrennt.
- **Zugehörigkeitsprüfung:** Bei jedem Zugriff wird geprüft, ob der Nutzer dem Mandanten angehört (via `UserMandate`).
- **Request-Kontext:** `mandateId` und `featureInstanceId` werden über Header (`X-Mandate-Id`, `X-Feature-Instance-Id`) übergeben.
diff --git a/b-reference/gateway/automation.md b/b-reference/gateway/automation.md
index fa559fe..4e4e4b9 100644
--- a/b-reference/gateway/automation.md
+++ b/b-reference/gateway/automation.md
@@ -4,21 +4,19 @@
# Automation
-## Überblick
+## Ueberblick
-PowerOn hat **mehrere Automatisierungs-Spuren**, die sich die **gleiche Unified Action Library** (`workflows/methods/` + `ActionExecutor`) teilen, aber unterschiedliche **Persistenz**, **Scheduler** und **Execution Engines** nutzen. Die Business Spec beschreibt eine **Ziel-Architektur**: konsolidierte Plattform mit klarer Trennung Mandant / Feature / Feature-Instanz, skalierbarer **Toolbox**-Schicht für Agent-Tools und einem **vereinheitlichten Workflow-Datenmodell** (Draft/Published, Runs, Tracing).
+PowerOn hat **mehrere Automatisierungs-Spuren**, die sich die **gleiche Unified Action Library** (`workflows/methods/` + `ActionExecutor`) teilen, aber unterschiedliche **Persistenz**, **Scheduler** und **Execution Engines** nutzen. Die Business Spec beschreibt eine **Ziel-Architektur**: konsolidierte Plattform mit klarer Trennung Mandant / Feature / Feature-Instanz, skalierbarer **Toolbox**-Schicht fuer Agent-Tools und einem **vereinheitlichten Workflow-Datenmodell** (Draft/Published, Runs, Tracing).
**Leitentscheide (Business Spec):**
-- Keine Migration von Altdaten für Automation v1 (nicht produktiv); v1 bleibt bis zur Ablösung.
-- **Vier Säulen:** AI Service (Agent, Streaming, Neutralisierung, Failover), Graphical Editor (Flow + künftig Editor-Chat/UDB), Automation Scheduler (Cron/Events/Webhooks), **Unified Action Library** mit Toolboxes.
-- **Inkonsistenzen heute:** zwei Workflow-Datenwelten (v1 vs Automation2), zwei DB-Schemas, zwei Scheduler-Patterns, zwei Engines — Ausrichtung über Zielmodell und Übernahme bewährter v1-Scheduler-Patterns in Richtung v2.
+- Keine Migration von Altdaten fuer Automation v1 (nicht produktiv); v1 bleibt bis zur Abloesung.
+- **Vier Saeulen:** AI Service (Agent, Streaming, Neutralisierung, Failover), Graphical Editor (Flow + kuenftig Editor-Chat/UDB), Automation Scheduler (Cron/Events/Webhooks), **Unified Action Library** mit Toolboxes.
+- **Inkonsistenzen heute:** zwei Workflow-Datenwelten (v1 vs Automation2), zwei DB-Schemas, zwei Scheduler-Patterns, zwei Engines -- Ausrichtung ueber Zielmodell und Uebernahme bewaehrter v1-Scheduler-Patterns in Richtung v2.
---
-## Business Spec (Zusammenfassung)
-
-**Ist-Systeme:**
+## Ist-Systeme (Gateway, Stand 2026-04-05)
| System | Kurzbeschreibung |
|--------|------------------|
@@ -26,41 +24,9 @@ PowerOn hat **mehrere Automatisierungs-Spuren**, die sich die **gleiche Unified
| **Automation2** | n8n-Style Graph; Run/Task; Pause/Resume; Human-in-the-loop; weniger robuster Scheduler-Sync als v1. |
| **AI Workspace** | Chat-Agent mit vielen Tools + RAG; kein persistiertes Workflow-Modell wie im Graph-Editor. |
-**Gemeinsame technische Basis:** Alle genannten Pfade führen über **`ActionExecutor.executeAction()`** zur Method/Action Library; der Workspace-Agent mappt `dynamicMode`-Actions via **`ActionToolAdapter`** auf Tools; Automation2-Nodes tragen `_method` / `_action`.
+**Gemeinsame technische Basis:** Alle genannten Pfade fuehren ueber **`ActionExecutor.executeAction()`** zur Method/Action Library; der Workspace-Agent mappt `dynamicMode`-Actions via **`ActionToolAdapter`** auf Tools; Automation2-Nodes tragen `_method` / `_action`.
-**Toolbox-Konzept (Ziel):** Statt alle Tools flach zu exponieren, **thematische Toolboxes** (`core`, `ai`, `email`, `sharepoint`, `workflow`, …) mit Meta-Tool **`requestToolbox`** — Agent startet schlank, fordert Spezial-Toolboxes nach Bedarf; **`availableToolboxes`** ist pro Feature/RBAC/Connections filterbar.
-
-**Sub-Agents:** Datenintensive Features (z. B. Trustee) kapseln Schema-Wissen in einem **Feature Data Agent**; Main-Agent sieht ein aggregiertes Tool (`queryFeatureInstance`), nicht Dutzende Tabellen-Tools.
-
-**Agent-Run (State Machine, konzeptionell):** `IDLE` → `THINKING` → bei Tool-Calls `EXECUTING_TOOLS` → optional `TOOLBOX_ESCALATION` / `SUB_AGENT_CALL` → `COMPLETED` / `FAILED` / `CANCELLED` (Limits: `maxRounds`, `maxCostCHF`).
-
-**RBAC (Kurz):** Zwei getrennte Template-Systeme — **System-Template-Rollen** (Mandant: admin/user/viewer) vs **Feature-Template-Rollen** (Instanz: z. B. workspace-admin); keine Vermischung. Auflösung: höchste Priorität gewinnt bei DATA; View OR über Rollen der Top-Priorität; Item-Spezifität exact > prefix > generic.
-
----
-
-## Datenmodell (Zusammenfassung)
-
-**Gateway-Schichten (Data Model Doc):** Frontend → **Features** (instanzgebunden) → **Services** (request-scoped) → **Shared Infrastructure** (`workflows/methods`, `workflows/processing`, `workflows/automation2`, `interfaces`, `aicore`, `datamodels`, `security`).
-
-**Feature-Container-Pattern:** `features//` mit `main*.py` (FEATURE_CODE, UI/RESOURCE/TEMPLATE_ROLES), `routeFeature*.py`, `interfaceFeature*.py`, `datamodelFeature*.py`, optional `nodeDefinitions/`, `service*/`. Discovery über `registry.py` / `ServiceHub` ohne manuelles Wiring sämtlicher Router.
-
-**Ziel-Entitäten (vereinheitlichtes Workflow-Modell, Spec):**
-
-| Entität | Zweck |
-|---------|--------|
-| **Workflow** | Metadaten, Mandant/Instanz, `active`, optional `eventId` (Scheduler-Job), Zeiger auf aktuelle Version |
-| **WorkflowVersion** | Immutabler Snapshot: `graph` (Nodes/Connections), `invocations` (Trigger: manual, schedule, webhook, …), Status **draft / published / archived** |
-| **WorkflowRun** | Eine Ausführung: Status (pending → running → completed/failed/paused/cancelled), Trigger-Metadaten, `nodeOutputs`, Pause-/Resume-Kontext, Kostenfelder |
-| **RunStepLog** | Pro Node: Input-Snapshot, Output, Dauer, Fehler, Token-Nutzung |
-| **HumanTask** | Menschliche Zwischenaufgabe bei Pause (approval/form); Status pending → completed/cancelled/expired |
-
-**Invarianten (Zielmodell):** Pro Workflow höchstens **eine** `PUBLISHED` Version; Scheduler bindet an die veröffentlichte Version. Pause z. B. durch Human-Task-Nodes oder E-Mail-Warten; Resume mit geliefertem Ergebnis.
-
-**Toolbox-Datenmodell (Ziel):** `ToolboxDefinition` (id, label i18n, `tools[]`, optional `requiresConnection`), `ToolboxRegistry`, erweiterte `AgentConfig` mit `initialToolboxes` / `availableToolboxes`.
-
----
-
-## Automation v1 vs v2
+### Automation v1 vs v2 (Ist-Vergleich)
| Aspekt | Automation v1 | Automation2 (v2) |
|--------|----------------|------------------|
@@ -68,20 +34,74 @@ PowerOn hat **mehrere Automatisierungs-Spuren**, die sich die **gleiche Unified
| DB / Schema | `poweron_automation` | `poweron_automation2` |
| Scheduler | Inkrementell, Callback `automation.changed`, `eventId` auf `AutomationDefinition` | Full re-register, Callback `automation2.workflow.changed` |
| Engine | `WorkflowManager` + `WorkflowProcessor` + `modeAutomation` | `executionEngine.executeGraph` |
-| Stärken | Bewährtes Scheduling, Execution-Logs | Branching, Loops, Pause/Resume, visuelles Editing |
+| Staerken | Bewaehrtes Scheduling, Execution-Logs | Branching, Loops, Pause/Resume, visuelles Editing |
-**Konsolidierungsrichtung (Spec):** v1-Scheduler-Muster (inkrementell, Job-Handle, Reload+`active`-Check vor Run, capped Logs, `sysCreatedBy` für Kontext) in die v2-Welt übernehmen; einheitliches **Workflow/Version/Run**-Konzept langfristig über beide Welten.
+**Konsolidierungsrichtung (Spec):** v1-Scheduler-Muster (inkrementell, Job-Handle, Reload+`active`-Check vor Run, capped Logs, `sysCreatedBy` fuer Kontext) in die v2-Welt uebernehmen; einheitliches **Workflow/Version/Run**-Konzept langfristig ueber beide Welten.
---
-## Schlüssel-Dateien
+## Datenmodell
+
+### Ist: Konkrete Modelle (Gateway, Stand 2026-04-05)
+
+| Modell | Datei | DB | Beschreibung |
+|--------|-------|-----|-------------|
+| `AutomationDefinition` | `features/automation/datamodelFeatureAutomation.py` | `poweron_automation` | v1 Template mit `schedule`, `placeholders`, `eventId` |
+| `ChatWorkflow` | `datamodels/datamodelChat.py` | `poweron_chat` | v1 Execution-Artefakt (Status, Tasks, Messages) |
+| `Automation2Workflow` | `features/automation2/datamodelFeatureAutomation2.py` | `poweron_automation2` | v2 Graph mit `active`, inline `graph`, `invocations` |
+| `Automation2WorkflowRun` | gleiche Datei | `poweron_automation2` | v2 Run: Status `running`/`paused`/`completed`/`failed`, `nodeOutputs`, `context` |
+| `Automation2HumanTask` | gleiche Datei | `poweron_automation2` | Human-Task: Status `pending`/`completed`/`rejected` |
+
+**Hinweis:** Es gibt **keine** `WorkflowVersion`-Tabelle -- v2 speichert den Graph direkt in `Automation2Workflow`. Tracing ist `nodeOutputs` im Run, nicht ein separates `RunStepLog`-Entity.
+
+### Ziel: Vereinheitlichtes Workflow-Modell (Spec -- nicht implementiert)
+
+| Entitaet | Zweck | Heute approximiert durch |
+|----------|-------|--------------------------|
+| **Workflow** | Metadaten, Mandant/Instanz, `active`, `eventId`, Zeiger auf aktuelle Version | `Automation2Workflow` (ohne Versioning) |
+| **WorkflowVersion** | Immutabler Snapshot: `graph`, `invocations`, Status draft/published/archived | *nicht vorhanden* (Graph inline in Workflow) |
+| **WorkflowRun** | Ausfuehrung mit Status, Trigger, `nodeOutputs`, Kostenfelder | `Automation2WorkflowRun` (ohne Kostenfelder, Statusmenge abweichend) |
+| **RunStepLog** | Pro Node: Input, Output, Dauer, Fehler, Token | *nicht vorhanden* (approximiert durch `nodeOutputs`) |
+| **HumanTask** | Menschliche Aufgabe bei Pause; Status pending/completed/cancelled/expired | `Automation2HumanTask` (Status: `pending`/`completed`/`rejected`, kein `expired`) |
+
+**Invarianten (Zielmodell):** Pro Workflow hoechstens **eine** `PUBLISHED` Version; Scheduler bindet an die veroeffentlichte Version.
+
+### Toolbox-Datenmodell (Ziel -- nicht im Gateway implementiert)
+
+`ToolboxDefinition` (id, label i18n, `tools[]`, optional `requiresConnection`), `ToolboxRegistry`, erweiterte `AgentConfig` mit `initialToolboxes` / `availableToolboxes`.
+
+> Kein Match im Gateway-Code fuer `requestToolbox`, `ToolboxDefinition` oder `availableToolboxes` (Stand 2026-04-05).
+
+### Gateway-Schichten
+
+Frontend -> **Features** (instanzgebunden) -> **Services** (request-scoped) -> **Shared Infrastructure** (`workflows/methods`, `workflows/processing`, `workflows/automation2`, `interfaces`, `aicore`, `datamodels`, `security`).
+
+**Feature-Container-Pattern:** `features//` mit `main*.py` (FEATURE_CODE, UI/RESOURCE/TEMPLATE_ROLES), `routeFeature*.py`, `interfaceFeature*.py`, `datamodelFeature*.py`, optional `nodeDefinitions/`, `service*/`. Discovery ueber `registry.py` / `ServiceHub`.
+
+---
+
+## Ziel-Konzepte (Business Spec, nicht implementiert)
+
+**Toolbox-Konzept:** Statt alle Tools flach zu exponieren, **thematische Toolboxes** (`core`, `ai`, `email`, `sharepoint`, `workflow`, ...) mit Meta-Tool **`requestToolbox`** -- Agent startet schlank, fordert Spezial-Toolboxes nach Bedarf; **`availableToolboxes`** ist pro Feature/RBAC/Connections filterbar.
+
+**Sub-Agents:** Datenintensive Features (z. B. Trustee) kapseln Schema-Wissen in einem **Feature Data Agent**; Main-Agent sieht ein aggregiertes Tool (`queryFeatureInstance`), nicht Dutzende Tabellen-Tools.
+
+**Agent-Run (State Machine, konzeptionell -- nicht im Code):** `IDLE` -> `THINKING` -> bei Tool-Calls `EXECUTING_TOOLS` -> optional `TOOLBOX_ESCALATION` / `SUB_AGENT_CALL` -> `COMPLETED` / `FAILED` / `CANCELLED` (Limits: `maxRounds`, `maxCostCHF`).
+
+**RBAC (Kurz):** Zwei getrennte Template-Systeme -- **System-Template-Rollen** (Mandant: admin/user/viewer) vs **Feature-Template-Rollen** (Instanz: z. B. workspace-admin); keine Vermischung.
+
+---
+
+## Schluessel-Dateien
| Bereich | Typische Pfade (`gateway/modules/`) |
|---------|-------------------------------------|
| Action Library | `workflows/methods/`, `workflows/processing/` (`ActionExecutor`, `methodDiscovery`) |
| Automation v1 Feature | `features/automation/` |
-| Automation2 Feature | `features/automation2/`, `workflows/automation2/` |
-| Agent ↔ Actions | `serviceCenter/services/serviceAgent/` (u. a. Tool-Registrierung, `ActionToolAdapter`) |
+| Automation v1 Runtime | `workflows/automation/` (`mainWorkflow.py`, `subAutomationSchedule.py`) |
+| Automation2 Feature | `features/automation2/` |
+| Automation2 Runtime | `workflows/automation2/` (`executionEngine.py`, `subAutomation2Schedule.py`) |
+| Agent <-> Actions | `serviceCenter/services/serviceAgent/` (Tool-Registrierung, `ActionToolAdapter`) |
| Feature-Discovery | `system/registry.py`, `serviceHub/__init__.py` |
| RBAC | `interfaces/interfaceRbac.py`, `security/`, Rollen/AccessRules in Datamodels |
@@ -89,9 +109,9 @@ PowerOn hat **mehrere Automatisierungs-Spuren**, die sich die **gleiche Unified
## Regeln / Invarianten
-1. **Eine Action Library:** Änderungen an Methods/Actions betreifen Workspace, Automation v1, Automation2 und Agent-Tools gleichzeitig — Kompatibilität und `actionId`-Stabilität beachten.
-2. **RBAC strikt trennen:** Mandantenrollen vs Feature-Instanz-Rollen nicht mischen; Permissions über AccessRules und Prioritätsregeln.
-3. **Scheduler vs Editor:** Ausführung und Zeitplanung gehören zur **Scheduler-Säule**; der Graph ist **Version**-gebunden (Draft vs Published).
-4. **Tool-Skalierung:** Flache Tool-Listen skalieren nicht; Toolbox + `requestToolbox` + connection-basierte Verfügbarkeit sind das vorgesehene Gegenmittel.
-5. **Zielmodell vs Ist:** `Workflow` / `WorkflowVersion` / `WorkflowRun` in der Spec sind **Zielarchitektur** — Abgleich mit produktivem Schema bei Implementierungsarbeiten erforderlich.
+1. **Eine Action Library:** Aenderungen an Methods/Actions betreffen Workspace, Automation v1, Automation2 und Agent-Tools gleichzeitig -- Kompatibilitaet und `actionId`-Stabilitaet beachten.
+2. **RBAC strikt trennen:** Mandantenrollen vs Feature-Instanz-Rollen nicht mischen; Permissions ueber AccessRules und Prioritaetsregeln.
+3. **Scheduler vs Editor:** Ausfuehrung und Zeitplanung gehoeren zur **Scheduler-Saeule**; der Graph ist **Version**-gebunden (Draft vs Published).
+4. **Tool-Skalierung:** Flache Tool-Listen skalieren nicht; Toolbox + `requestToolbox` + connection-basierte Verfuegbarkeit sind das vorgesehene Gegenmittel (Ziel, nicht implementiert).
+5. **Zielmodell vs Ist:** `Workflow` / `WorkflowVersion` / `WorkflowRun` in der Spec sind **Zielarchitektur**. Ist-Modelle siehe oben (`Automation2Workflow`, `Automation2WorkflowRun` etc.). Abgleich bei Implementierungsarbeiten erforderlich.
6. **Neutralisierung / KI:** Plattformweit gelten die zentralen KI-Datenpfade (siehe `workflow.md` / Compliance); Automation nutzt dieselben Services wie der Rest des Gateways.
diff --git a/b-reference/gateway/billing.md b/b-reference/gateway/billing.md
index cceb717..1fa678c 100644
--- a/b-reference/gateway/billing.md
+++ b/b-reference/gateway/billing.md
@@ -1,4 +1,4 @@
-
+
@@ -24,27 +24,20 @@ Ohne gültige, zahlungswirksame Subscription (soweit implementiert) sollen **nur
- **Mandant** ist die zentrale Kostenstelle; Benutzer können mehreren Mandanten angehören — Verbrauch wird pro Mandant getrennt erfasst.
- Kosten entstehen an **AICore-Connectoren** (z. B. `anthropic`, `openai`, `perplexity`, `tavily`, `internal`); die erlaubte Provider-Liste ist dynamisch (Model Registry / Plugins).
-### Abrechnungsmodelle (`BillingSettings.billingModel`)
+### Abrechnungsmodell
-| Modell | Kostenstelle | Kurzbeschreibung |
-|--------|--------------|------------------|
-| `PREPAY_MANDATE` | Mandant | Gemeinsames Guthaben für alle User des Mandanten |
-| `PREPAY_USER` | User im Mandanten-Kontext | Eigenes Guthaben pro User; automatisches Startguthaben v. a. für **Root-Mandant** / Bootstrap (`defaultUserCredit`, z. B. 5 CHF) |
-| `UNLIMITED` | — | Keine Guthabenlimitierung (interne Mandanten) |
-
-- **`CREDIT_POSTPAY`** ist entfernt; gespeicherte Legacy-Werte werden beim Lesen auf **`PREPAY_MANDATE`** normalisiert (ohne separate DB-Migration).
-- **Audit-Hinweis:** Im Gateway-Kontext wird der operative Fokus als **PREPAY_MANDATE** (kein PREPAY_USER im Sinne des Standard-Mandanten-Produkts) geführt; **Root** bleibt im Konzept mit **PREPAY_USER** und Startguthaben beschrieben.
+Im Gateway gibt es aktuell **kein `billingModel`-Feld** auf `BillingSettings`. Das operative Modell ist faktisch **PREPAY_MANDATE** (gemeinsames Mandantenkonto). Konzeptionell waren weitere Modelle (`PREPAY_USER`, `UNLIMITED`, `CREDIT_POSTPAY`) vorgesehen — diese sind im Code nicht implementiert.
### Kernentitäten
-- **`BillingAccount`:** Guthaben (`balance` CHF), optional `userId` bei `PREPAY_USER`, `accountType` MANDATE | USER, `warningThreshold`, `enabled`.
+- **`BillingAccount`:** Guthaben (`balance` CHF), `mandateId`, optional `userId`, `warningThreshold`, `enabled`. Kein explizites `accountType`-Feld im Code — Mandant vs. User wird über Vorhandensein von `userId` unterschieden.
- **`BillingTransaction`:** `CREDIT` | `DEBIT` | `ADJUSTMENT`; Referenzen (`referenceType` / `referenceId`, `workflowId`, `featureInstanceId`, `aicoreProvider`). Mandanten-Kontext über **`BillingAccount.mandateId`** — Chat-Modelle bleiben user-owned ohne `mandateId` in `ChatWorkflow`; Zuordnung für Statistiken über Transaktionen.
-- **`BillingSettings`:** Modell, `defaultUserCredit`, `warningThresholdPercent`, `notifyEmails`, `notifyOnWarning`; Erweiterung **`stripeCustomerId`** (Organisation = Mandant, nicht einzelne Subscription).
+- **`BillingSettings`:** `warningThresholdPercent`, `notifyEmails`, `notifyOnWarning`, `stripeCustomerId` (Organisation = Mandant). Zusätzlich: `autoRechargeEnabled`, `rechargeAmountCHF`, `rechargeThresholdCHF` (Auto-Recharge) sowie Storage-Felder (`storageLimitGB`, `STORAGE_PRICE_PER_GB_CHF`).
- **`UsageStatistics`:** Aggregationen nach Periode, Provider und Feature (Konzept; Auswertung aus Transaktionen).
### Preise und Währung
-- Verrechnung in **CHF**; Plugin-seitig typisch **`calculatePriceCHF()`** mit dokumentiertem Aufschlag (Konzept: z. B. 50 % auf Provider-Kosten), Werte in den AICore-Plugins gepflegt.
+- Verrechnung in **CHF**; zentraler Aufschlag via `calculatePriceWithMarkup()` in `mainServiceBilling.py` mit `BILLING_MARKUP_PERCENT = 400` (Multiplikator ×5 auf Provider-Kosten). **Achtung:** Code-Kommentare referenzieren inkonsistent „Faktor 2.0" und „50 %", die Konstante ist aktuell 400 %.
### Provider-Steuerung (RBAC)
@@ -112,7 +105,9 @@ Referenz **Gateway-Audit** zu Prepaid-Beispielen: Trial **5 CHF**, Standard **10
| **PAST_DUE** | Zahlung fehlgeschlagen, Stripe-Retry-Phase |
| **EXPIRED** | Beendet (terminal) |
-**AI-Gate (Produktregel aus Mandanten-Konzept):** Für die Freigabe von AI-Calls gelten **`ACTIVE`** und **`TRIALING`**; bei **`PAST_DUE`**, **`EXPIRED`** und fehlender Subscription sind **AI-Calls blockiert** (auch wenn die Stripe-State-Maschine `PAST_DUE` als „Grace“ modelliert).
+**AI-Gate (Code-Stand 2026-04-05):** Im Code ist `PAST_DUE` Teil der operativen Statusmenge (`OPERATIVE_STATUSES = ACTIVE, TRIALING, PAST_DUE`). `_checkSubscription` in `mainServiceBilling.py` gibt fuer alle drei Status `None` (erlaubt) zurueck. AI-Calls werden bei `PAST_DUE` **nicht blockiert**. Nur `EXPIRED`, `PENDING`, `SCHEDULED` und fehlende Subscription blockieren AI.
+
+> Konzept vs. Code: Eine strengere Produktregel (PAST_DUE blockiert AI) war konzeptionell vorgesehen, ist aber aktuell nicht implementiert.
### Erlaubte Statusübergänge (Kernmenge)
@@ -176,7 +171,7 @@ Typische Trigger: Stripe-Webhooks (`checkout.session.completed`, `invoice.paymen
1. **Zwei Ebenen:** LLM-Verbrauch (Prepaid/Transaktionen) und Plattform-Subscription (Pläne, Stripe, Caps) — gemeinsames Gate vor AI-Calls.
2. **Mandant** ist die primäre Verrechnungseinheit für Usage; Transaktionen tragen den Mandanten-Kontext über das **BillingAccount**, nicht über Chat-Stammdaten.
-3. **Pro Mandant** höchstens eine operative Subscription **`ACTIVE`/`TRIALING`** für KI-Freigabe; **`PAST_DUE`** und **`EXPIRED`** blockieren AI gemäß Mandanten-Konzept.
+3. **Pro Mandant** hoechstens eine operative Subscription; `ACTIVE`, `TRIALING` und `PAST_DUE` gelten als **operativ** (AI erlaubt). Nur `EXPIRED`, `PENDING`, `SCHEDULED` und fehlende Subscription blockieren AI.
4. **Kündigung:** Nutzung bis **Ende der bezahlten Periode** (`recurring = false`, Stripe `cancel_at_period_end`); kein separater Status `CANCELLED`.
5. **Status-Änderungen** nur über definierte Transitionen mit **`subscriptionId`** — kein implizites Scannen nach „aktueller“ Zeile allein über `mandateId` bei Writes.
6. **Provider-Zugriff** über RBAC `resource.aicore.*`, konsistent mit Billing-Erfassung pro `aicoreProvider`.
diff --git a/b-reference/platform/database-architecture.md b/b-reference/platform/database-architecture.md
new file mode 100644
index 0000000..5c0daca
--- /dev/null
+++ b/b-reference/platform/database-architecture.md
@@ -0,0 +1,271 @@
+
+
+
+
+# Datenbank-Architektur
+
+## Ueberblick
+
+PowerOn verwendet **PostgreSQL** mit einer klaren Trennung: jedes Modul (App, Chat, Billing, Knowledge, Features) hat eine eigene physische Datenbank (`poweron_*`). Datenbank-Zugriffe laufen ueber **Interfaces** (`interfaceDb*.py`), die auf dem zentralen **DatabaseConnector** (`connectorDbPostgre.py`) aufbauen. Datenbanken und Tabellen werden **automatisch** beim ersten Zugriff erzeugt -- kein manuelles Schema-Management noetig.
+
+---
+
+## Architektur-Stack
+
+```
+Route / Service
+ |
+ v
+Interface (interfaceDb*.py)
+ |-- XxxObjects Klasse
+ |-- getInterface() Factory (cached)
+ |-- setUserContext() -> RBAC-Anbindung
+ |
+ v
+DatabaseConnector (connectorDbPostgre.py)
+ |-- Auto-Create Database
+ |-- Auto-Create/Extend Tables (aus Pydantic-Modellen)
+ |-- CRUD-Operationen (getRecordset, recordCreate, recordUpdate, recordDelete)
+ |
+ v
+PostgreSQL (+ pgvector Extension)
+```
+
+---
+
+## Datenbanken
+
+### Inventar
+
+| Datenbank | Modul / Zweck | Interface |
+|-----------|---------------|-----------|
+| `poweron_app` | Kernapplikation: UAM, Mandanten, Rollen, RBAC-Regeln, Navigation, Config | `interfaceDbApp.py` |
+| `poweron_chat` | Chat-Verlaeufe, Messages, Attachments | `interfaceDbChat.py` |
+| `poweron_management` | System-Management, Logs | `interfaceDbManagement.py` |
+| `poweron_knowledge` | RAG Knowledge-Store (mit pgvector) | `interfaceDbKnowledge.py` |
+| `poweron_billing` | Billing Accounts, Transactions, Usage | `interfaceDbBilling.py` |
+| `poweron_billing` | Subscriptions (gleiche DB wie Billing) | `interfaceDbSubscription.py` |
+| `poweron_workspace` | AI Workspace Feature-Daten | Feature-Interface |
+| `poweron_automation` | Automation v1 Workflows, Runs | Feature-Interface |
+| `poweron_automation2` | Automation v2 (Graph-Editor) Workflows, Runs | Feature-Interface |
+| `poweron_chatbot` | Chatbot Feature-Daten | Feature-Interface |
+| `poweron_trustee` | Trustee Feature-Daten | Feature-Interface |
+| `poweron_commcoach` | CommCoach Feature-Daten | Feature-Interface |
+| `poweron_neutralization` | Neutralisierungs-Daten | Feature-Interface |
+| `poweron_realestate` | RealEstate Feature-Daten | Feature-Interface |
+| `poweron_teamsbot` | Teams-Bot Feature-Daten | Feature-Interface |
+| `poweron_test` | Test-Datenbank | Nur in Tests |
+
+### Namenskonvention
+
+Feature-Datenbanken folgen dem Pattern `poweron_{featureCode.lower()}`. Der Datenbankname wird hart-codiert in der `_initializeDatabase()` Methode des jeweiligen Interfaces.
+
+### Konfiguration
+
+Verbindungsparameter kommen aus `APP_CONFIG` (config.ini / Environment):
+
+| Key | Beschreibung |
+|-----|-------------|
+| `DB_HOST` | PostgreSQL Host |
+| `DB_PORT` | PostgreSQL Port |
+| `DB_USER` | Datenbank-Benutzer |
+| `DB_PASSWORD_SECRET` | Passwort (ggf. verschluesselt) |
+| `DB_DATABASE` | Default-DB-Name (Standard: `poweron_app`) |
+
+---
+
+## Interface-Pattern
+
+Jedes Interface folgt einem einheitlichen Aufbau:
+
+### XxxObjects Klasse
+
+```python
+class AppObjects:
+ db: DatabaseConnector # Connector zur eigenen DB
+ rbac: RbacClass # RBAC-Integration
+ currentUser: dict # Aktueller Benutzer
+ mandateId: str # Aktueller Mandant
+ featureInstanceId: str # (nur bei Feature-Interfaces)
+```
+
+### _initializeDatabase()
+
+Setzt den Datenbanknamen und erstellt den Connector:
+
+```python
+def _initializeDatabase(self):
+ dbDatabase = "poweron_app" # hart-codiert pro Interface
+ self.db = DatabaseConnector(
+ host=APP_CONFIG.get("DB_HOST"),
+ database=dbDatabase,
+ user=APP_CONFIG.get("DB_USER"),
+ password=APP_CONFIG.get("DB_PASSWORD_SECRET"),
+ port=APP_CONFIG.get("DB_PORT")
+ )
+```
+
+### setUserContext()
+
+Bindet Benutzer und RBAC an die Instanz:
+
+```python
+def setUserContext(self, currentUser, mandateId):
+ self.currentUser = currentUser
+ self.userId = currentUser["id"]
+ self.mandateId = mandateId
+ self.rbac = RbacClass(self.db, dbApp=dbApp)
+ self.db.updateContext(self.userId)
+```
+
+**RBAC-Besonderheit:** `poweron_app` ist Sonderfall (`dbApp=self.db`), weil RBAC-Regeln selbst in `poweron_app` liegen. Alle anderen Interfaces nutzen `getRootDbAppConnector()` um Rules aus der App-DB zu lesen:
+
+```python
+dbApp = getRootDbAppConnector()
+self.rbac = RbacClass(self.db, dbApp=dbApp)
+```
+
+### getInterface() Factory
+
+Cached pro Kontext:
+
+| Interface | Cache-Key | Ergebnis |
+|-----------|-----------|----------|
+| App | `{mandateId}_{userId}` | `AppObjects` |
+| Chat | `{mandateId}_{featureInstanceId}_{userId}` | `ChatObjects` |
+| Billing | `{userId}_{mandateId}` | `BillingObjects` |
+| Knowledge | `"default"` (Singleton) | `KnowledgeObjects` |
+
+---
+
+## DatabaseConnector
+
+### Auto-Initialisierung
+
+Beim Erstellen eines `DatabaseConnector` (`initDbSystem()`):
+
+```
+1. _create_database_if_not_exists()
+ -> Verbindet sich zu DB "postgres"
+ -> Prueft pg_database auf Existenz
+ -> CREATE DATABASE "{name}" falls fehlend
+
+2. _create_tables()
+ -> Erstellt nur die _system Registry-Tabelle
+ -> Applikations-Tabellen werden lazy durch Interfaces erzeugt
+
+3. _connect()
+ -> psycopg2-Verbindung zur Ziel-DB
+
+4. _initializeSystemTable()
+ -> _ensureTableExists(SystemTable)
+```
+
+### Lazy Table Creation
+
+Tabellen werden **bei erstem Zugriff** automatisch aus Pydantic-Modellen erzeugt (`_ensureTableExists(model_class)`):
+
+- **Tabellenname** = Python-Klassenname des Pydantic-Modells (z.B. `Role`, `AccessRule`, `UserMandate`)
+- **Spalten** werden aus Modellfeldern abgeleitet
+- **JSONB** fuer komplexe Typen (dict, list, Pydantic-Submodelle)
+- **vector** fuer pgvector-Felder (Knowledge-Store)
+- **Additive Migration**: Wenn die Tabelle existiert, werden fehlende Spalten automatisch hinzugefuegt. Bestehende Spalten werden **nicht** geaendert oder entfernt.
+
+### Connector-Caching
+
+```python
+_get_cached_connector(host, database, port)
+```
+
+Wiederverwendet einen `DatabaseConnector` pro Datenbank-Identitaet (`host:database:port`). Genutzt von App, Management, Knowledge. Chat und Billing instanziieren direkt (kein Cache).
+
+### userId Context
+
+`userId` wird ueber eine `contextvar` am Connector gesetzt (`updateContext(userId)`). Damit werden System-Felder (`_createdBy`, `_updatedBy`) automatisch befuellt.
+
+---
+
+## RBAC-Integration in DB-Abfragen
+
+Die RBAC-Schicht greift direkt in Datenbank-Abfragen ein:
+
+### Kern-Funktionen in interfaceRbac.py
+
+| Funktion | Zweck |
+|----------|-------|
+| `getRecordsetWithRBAC()` | Listet Datensaetze mit RBAC-Filter in SQL WHERE |
+| `buildRbacWhereClause()` | Uebersetzt Access Levels in SQL-Bedingungen |
+| `buildDataObjectKey()` | Baut Keys wie `data.uam.UserInDB` fuer Rule-Lookup |
+| `TABLE_NAMESPACE` | Mapping von Modellnamen zu logischen Namespaces |
+
+### Namespace-Mapping
+
+`TABLE_NAMESPACE` ordnet Pydantic-Modellnamen logischen Bereichen zu:
+
+| Namespace | Modelle (Beispiele) |
+|-----------|-------------------|
+| `uam` | UserInDB, UserMandate, Role, AccessRule |
+| `chat` | ChatHistory, ChatMessage |
+| `files` | FileRecord, FileFolder |
+| `feature.trustee` | TrusteePosition, TrusteeDocument |
+| `feature.workspace` | Workspace-spezifische Modelle |
+
+### SQL-Filter nach Access Level
+
+| Level | SQL WHERE |
+|-------|-----------|
+| `a` (ALL) | Kein Filter |
+| `m` (MANDATE) | `mandateId = :mandateId` |
+| `o` (OWN) | `_createdBy = :userId` |
+| `n` (NONE) | `1=0` (kein Ergebnis) |
+
+---
+
+## System-Felder
+
+Jedes `PowerOnModel` erbt automatisch System-Felder:
+
+| Feld | Beschreibung | Schutz |
+|------|-------------|--------|
+| `id` | UUID, auto-generiert | Immutable |
+| `_createdBy` | userId des Erstellers | Immutable |
+| `_createdAt` | Zeitstempel Erstellung | Immutable |
+| `_updatedBy` | userId der letzten Aenderung | Auto-gesetzt |
+| `_updatedAt` | Zeitstempel letzte Aenderung | Auto-gesetzt |
+
+Felder mit fuehrendem `_` sind fuer Anwendungs-CUD geschuetzt -- der Connector erzwingt das unabhaengig von Access Rules.
+
+---
+
+## Feature-DB-Registrierung
+
+Features registrieren sich **nicht** in einer zentralen DB-Liste. Stattdessen:
+
+1. `registry.py` → `registerAllFeaturesInCatalog()` laedt Feature-Main-Module
+2. Jedes Feature-Main definiert seinen `FEATURE_CODE` und `dbDatabase`
+3. Der Datenbank-Name wird in `_initializeDatabase()` des Feature-Interfaces gesetzt
+4. Der `DatabaseConnector` erzeugt die DB automatisch beim ersten Zugriff
+
+### Admin-Sicht
+
+`routeSecurityAdmin.py` bietet eine API, die alle `poweron_%`-Datenbanken aus PostgreSQL auflistet -- fuer Systemadministration und Diagnostik.
+
+---
+
+## Schluessel-Dateien
+
+| Thema | Pfad |
+|-------|------|
+| PostgreSQL Connector | `gateway/modules/connectors/connectorDbPostgre.py` |
+| App-DB Interface | `gateway/modules/interfaces/interfaceDbApp.py` |
+| Chat-DB Interface | `gateway/modules/interfaces/interfaceDbChat.py` |
+| Management-DB Interface | `gateway/modules/interfaces/interfaceDbManagement.py` |
+| Knowledge-DB Interface | `gateway/modules/interfaces/interfaceDbKnowledge.py` |
+| Billing-DB Interface | `gateway/modules/interfaces/interfaceDbBilling.py` |
+| Subscription Interface | `gateway/modules/interfaces/interfaceDbSubscription.py` |
+| RBAC in DB-Schicht | `gateway/modules/interfaces/interfaceRbac.py` |
+| Feature-Interface (Template) | `gateway/modules/interfaces/interfaceFeatures.py` |
+| Bootstrap / DB-Seed | `gateway/modules/interfaces/interfaceBootstrap.py` |
+| DB-Migration Script | `gateway/scripts/script_db_export_migration.py` |
+| Admin DB-Listing | `gateway/modules/routes/routeSecurityAdmin.py` |
+| Datenmodelle (Pydantic) | `gateway/modules/datamodels/` |
diff --git a/b-reference/platform/platform-diagrams.md b/b-reference/platform/platform-diagrams.md
index 24ebc22..0c9c928 100644
--- a/b-reference/platform/platform-diagrams.md
+++ b/b-reference/platform/platform-diagrams.md
@@ -168,7 +168,7 @@ This diagram shows the complete microservices structure, organized into Core Ser
graph TB
subgraph "Core Services"
CHAT[self.services.chat
Chat & Conversation]
- WF_SVC[self.services.workflow
Workflow State]
+ WF_SVC[self.services.workflow
Runtime Workflow State
not a registered service]
UTILS[self.services.utils
Utilities]
end
@@ -185,6 +185,14 @@ graph TB
TICKET[self.services.ticket
Jira, ClickUp, etc.]
end
+ subgraph "Additional Services not shown"
+ AGENT[self.services.agent]
+ KNOWLEDGE[self.services.knowledge]
+ MESSAGING[self.services.messaging]
+ BILLING[self.services.billing]
+ SUBSCRIPTION[self.services.subscription]
+ end
+
subgraph "Security"
SEC_SVC[self.services.security
Auth, Authorization
Token Management]
end
@@ -415,7 +423,7 @@ graph TB
subgraph "Integration Points"
WF_DIR[gateway/modules/workflows/methods/]
- SVC_DIR[gateway/modules/services/]
+ SVC_DIR[gateway/modules/serviceCenter/services/]
CONN_DIR[gateway/modules/connectors/]
ROUTE_DIR[gateway/modules/routes/]
FEAT_DIR[gateway/modules/features/]
@@ -481,4 +489,4 @@ graph TB
---
-*Last updated: 2025*
+*Last updated: 2026-04-05 (audit: service paths, missing services, date corrected)*
diff --git a/b-reference/platform/rbac.md b/b-reference/platform/rbac.md
index 7a50e0d..cbe2c15 100644
--- a/b-reference/platform/rbac.md
+++ b/b-reference/platform/rbac.md
@@ -4,66 +4,334 @@
# RBAC-System
-## Überblick
+## Ueberblick
-Das Role-Based Access Control bündelt Berechtigungen in **Access Rules** pro Rollenlabel und **Kontext** (DATA, UI, RESOURCE). Auswertung erfolgt zentral über `interfaceRbac.py`; Zielbild laut Architekturdokumentation: möglichst **filternd in der Datenbank** statt voller Tabellen-Scans in Python. Nutzer können **mehrere Rollenlabels** gleichzeitig tragen; die effektive Berechtigung entsteht aus **Öffnungslogik (Union)** über alle Rollen.
+Das Role-Based Access Control baut auf vier Stufen auf: **System**, **Mandant**, **Feature** und **Feature-Instanz**. Berechtigungen werden in **Access Rules** pro Rollenlabel und Kontext (DATA, UI, RESOURCE) gebunden. Auswertung erfolgt zentral ueber `interfaceRbac.py`; Zielbild: moeglichst **filternd in SQL** statt vollstaendiger Tabellen-Scans in Python. Nutzer koennen mehrere Rollenlabels gleichzeitig tragen; die effektive Berechtigung entsteht aus **Oeffnungslogik (Union)** ueber alle Rollen.
-## Zwei getrennte Rollensysteme
+---
-| | **Mandantenrollen** | **Feature-Instanz-Rollen** |
-|--|---------------------|----------------------------|
-| **Labels (Beispiele)** | `admin`, `user`, `viewer` | `workspace-admin`, `workspace-user`, `workspace-viewer`, feature-spezifisch |
-| **Scope** | `mandateId` | `mandateId` + `featureCode` + `featureInstanceId` |
-| **Zuordnung** | `UserMandateRole` | `FeatureAccessRole` |
+## 4-Stufen-Hierarchie
-**Invariante:** Mandantenrollen und Feature-Instanz-Rollen **nicht vermischen** — kein Zuweisen eines Mandanten-Labels zu `FeatureAccessRole` oder umgekehrt.
+```
+System (PowerOn Platform)
+|
++-- System Template Rollen (isSystemRole=true, mandateId=null, featureCode=null)
+| Labels: "admin", "user", "viewer"
+| -> kopiert bei Mandant-Erstellung via copySystemRolesToMandate()
+|
++-- Feature Template Rollen (isSystemRole=false, mandateId=null, featureCode=X)
+| Labels: "workspace-admin", "workspace-user", "workspace-viewer",
+| "graphicalEditor-admin", "graphicalEditor-user", ...
+| -> kopiert bei Feature-Instanz-Erstellung via _copyTemplateRoles()
+|
++-- Mandant (Tenant)
+ +-- Mandate-Rollen (Instanzen der System Templates)
+ | mandateId=X, featureInstanceId=null, featureCode=null
+ | "admin", "user", "viewer"
+ | Zuordnung: UserMandateRole <- UserMandate <- User
+ |
+ +-- Feature-Instanz A (z.B. "AI Workspace Produktion")
+ | +-- Feature-Instanz-Rollen (Instanzen der Feature Templates)
+ | | mandateId=X, featureInstanceId=Y, featureCode="workspace"
+ | | "workspace-admin", "workspace-user", "workspace-viewer"
+ | | Zuordnung: FeatureAccessRole <- FeatureAccess <- User
+ | +-- Daten (Workflows, Files, Chats, ...)
+ |
+ +-- Feature-Instanz B (z.B. "Graphical Editor Dev")
+ +-- Feature-Instanz-Rollen
+ +-- Daten (Workflows, Runs, Tasks, ...)
+```
-Zusätzlich (Systemebene, laut RBAC-Dokument): globale Rollen wie **SysAdmin** / **SystemUser** für mandantenübergreifende Sonderfälle; Mandantenrollen **Admin** / **User** / **Viewer** für Zugriff innerhalb eines Mandats.
+### Sonderfaelle
-## Access Rules (DATA / UI / RESOURCE)
+- **SysAdmin**: Eine globale Rolle auf Root-Mandant-Ebene. Wird in `_initSysAdminRole()` beim Bootstrap angelegt -- keine Template-Kopie.
+- **SystemUser / EventUser**: Technische System-Accounts, nicht an echte Benutzer gebunden.
-### Kontexte
+---
-- **DATA:** Tabellen und Felder; CRUD über `read`, `create`, `update`, `delete` mit Access Levels `a` (all), `m` (my), `g` (group / Mandat), `n` (none); zusätzlich `view`.
-- **UI:** Sichtbarkeit/Aktivierung von Oberflächenelementen; relevant ist **`view`** (boolean). Item-Format: kaskadierender String (z. B. `playground.voice.settings`).
-- **RESOURCE:** Systemressourcen (KI-Modelle, Aktionen, …); ebenfalls primär **`view`**. Item-Format: kaskadierend (z. B. `ai.model.anthropic`).
+## Zwei getrennte Template-Rollen-Systeme
-### Spezifität (pro Rolle)
+Templates sind **Blaupausen**. Sie definieren welche Rollen und Berechtigungen ein neuer Mandant oder eine neue Feature-Instanz erhaelt. Die beiden Template-Systeme sind **vollstaendig getrennt** -- kein Kreuz-Zuweisen.
-Innerhalb **einer** Rolle gewinnt die **spezifischste** passende Regel (längster passender Präfix/exakter `item`) gegenüber generischen Regeln (`item = null`).
+### System Template Rollen (fuer Mandanten)
-### Mehrere Rollen
+| Feld | Wert |
+|------|------|
+| `isSystemRole` | `true` |
+| `mandateId` | `null` |
+| `featureInstanceId` | `null` |
+| `featureCode` | `null` |
+| `roleLabel` | `"admin"`, `"user"`, `"viewer"` |
+| Definiert in | `interfaceBootstrap.py` → `initRoles()` (Zeilen ~473-540) |
+| Kopier-Mechanismus | `copySystemRolesToMandate()` in `interfaceBootstrap.py` |
+| Ausgeloest bei | Mandant-Erstellung (`createMandate()`, `_provisionMandateForUser()`) |
+| Bootstrap-Sync | `_ensureAllMandatesHaveSystemRoles()` beim Startup |
-Über Rollen hinweg: **Union** — wenn eine Rolle nach interner Auflösung `view: true` liefert, gilt das Element als sichtbar/erlaubt (OR über Rollen). Für **DATA** werden die **freizügigsten** Stufen über Rollen kombiniert.
+### Feature Template Rollen (fuer Feature-Instanzen)
-### DATA: Öffnungsrechte (CUD vs. Read)
+| Feld | Wert |
+|------|------|
+| `isSystemRole` | `false` |
+| `mandateId` | `null` |
+| `featureInstanceId` | `null` |
+| `featureCode` | z.B. `"workspace"`, `"automation2"`, `"trustee"` |
+| `roleLabel` | z.B. `"workspace-admin"`, `"workspace-user"` |
+| Definiert in | `TEMPLATE_ROLES` in jedem Feature-Main (z.B. `mainWorkspace.py` Zeilen ~83-135) |
+| Sync in DB | `_syncTemplateRolesToDb()` bei `registerFeature()` |
+| Kopier-Mechanismus | `_copyTemplateRoles()` in `interfaceFeatures.py` (Zeilen ~209-304) |
+| Ausgeloest bei | Feature-Instanz-Erstellung (`createFeatureInstance(copyTemplateRoles=True)`) |
-- Ohne Leserecht (`read = n`) keine CUD.
-- Mit `read = m` sind CUD höchstens `m` oder `n`.
-- Mit `read = g` sind CUD höchstens `g`, `m` oder `n`.
-- Mit `read = a` sind alle Stufen für CUD zulässig.
+### TEMPLATE_ROLES Format (Beispiel Workspace)
-### Systemfelder (DATA)
+```python
+TEMPLATE_ROLES = [
+ {
+ "roleLabel": "workspace-admin",
+ "description": {"en": "Workspace Administrator", "de": "Workspace-Administrator"},
+ "accessRules": [
+ {"context": "UI", "item": "ui.feature.workspace", "view": True},
+ {"context": "RESOURCE", "item": "resource.feature.workspace", "view": True},
+ {"context": "DATA", "item": None, "read": "a", "create": "a", "update": "a", "delete": "a", "view": True}
+ ]
+ },
+ {
+ "roleLabel": "workspace-user",
+ "description": {"en": "Workspace User", "de": "Workspace-Benutzer"},
+ "accessRules": [
+ {"context": "UI", "item": "ui.feature.workspace", "view": True},
+ {"context": "RESOURCE", "item": "resource.feature.workspace", "view": True},
+ {"context": "DATA", "item": None, "read": "m", "create": "m", "update": "m", "delete": "m", "view": True}
+ ]
+ }
+]
+```
-Felder `id` und Namen mit führendem `_` sind für Anwendungs-CUD geschützt; Connector erzwingt das unabhängig von Access Rules.
+### Kopier-Invariante
-### Frontend-Optionen für Rollen
+Templates werden **nur bei Erstellung** kopiert. Spaetere Aenderungen an Templates werden **nicht** automatisch an bestehende Mandanten oder Feature-Instanzen propagiert. Fuer nachtraeglichen Sync existiert `syncRolesFromTemplate()` in `interfaceFeatures.py` -- aber dies muss explizit aufgerufen werden.
-`frontend_options` an Feldern kann statische Listen oder String-Referenzen (z. B. `"user.role"`) nutzen; dynamische Optionen über `/api/options/{optionsName}`. Typ-Hilfen: `gateway/modules/shared/frontendTypes.py`.
+---
-## Schlüssel-Dateien
+## Datenmodell
-| Rolle | Pfad |
+### Role
+
+```python
+class Role(PowerOnModel):
+ id: str # UUID, auto-generiert
+ mandateId: Optional[str] # null = Global/Template
+ featureInstanceId: Optional[str] # null = nicht Instanz-spezifisch
+ featureCode: Optional[str] # z.B. "workspace", "graphicalEditor"
+ roleLabel: str # z.B. "workspace-admin"
+ description: TextMultilingual # {"en": "...", "de": "..."}
+ isSystemRole: bool # true nur fuer System Template Rollen
+```
+
+**Immutable nach Erstellung:** `mandateId`, `featureInstanceId`, `featureCode` (erzwungen in `datamodelRbac.py`).
+
+### AccessRule
+
+```python
+class AccessRule(PowerOnModel):
+ id: str
+ roleId: str # FK -> Role
+ context: AccessRuleContext # DATA | UI | RESOURCE
+ item: Optional[str] # null = generic, oder spezifischer Key
+ view: bool
+ read: Optional[AccessLevel] # nur bei DATA relevant
+ create: Optional[AccessLevel]
+ update: Optional[AccessLevel]
+ delete: Optional[AccessLevel]
+```
+
+### AccessLevel
+
+```python
+class AccessLevel(str, Enum):
+ NONE = "n" # Kein Zugriff
+ OWN = "o" # Nur eigene Datensaetze (userId-Match)
+ MANDATE = "m" # Alle im gleichen Mandanten
+ ALL = "a" # Alle (mandantenuebergreifend, nur SysAdmin)
+```
+
+### Membership-Modelle
+
+```python
+class UserMandate(PowerOnModel):
+ userId: str
+ mandateId: str
+ enabled: bool
+
+class UserMandateRole(PowerOnModel):
+ userMandateId: str # FK -> UserMandate
+ roleId: str # FK -> Role (Mandate-Rolle)
+
+class FeatureAccess(PowerOnModel):
+ userId: str
+ featureInstanceId: str
+ enabled: bool
+
+class FeatureAccessRole(PowerOnModel):
+ featureAccessId: str # FK -> FeatureAccess
+ roleId: str # FK -> Role (Feature-Instanz-Rolle)
+```
+
+### ER-Diagramm (Vereinfacht)
+
+```
+User
+ |
+ +-- UserMandate (1:N)
+ | |
+ | +-- UserMandateRole (1:N) ---> Role (mandateId=X)
+ | |
+ | +-- AccessRule (1:N)
+ |
+ +-- FeatureAccess (1:N)
+ |
+ +-- FeatureAccessRole (1:N) ---> Role (featureInstanceId=Y)
+ |
+ +-- AccessRule (1:N)
+```
+
+---
+
+## Access-Rule-Kontexte
+
+### DATA
+
+Steuert CRUD-Berechtigungen auf Datenbank-Ebene.
+
+- **Item-Format**: Auto-generiert aus Tabellenname + Namespace (z.B. `data.uam.UserInDB`, `data.feature.trustee.TrusteePosition`)
+- **Prueft**: `read`, `create`, `update`, `delete` als Access Levels
+- **`view`**: Boolean, steuert Grundsichtbarkeit
+- **Mapping**: `TABLE_NAMESPACE` in `interfaceRbac.py` ordnet Modellnamen logischen Namespaces zu
+- **`buildDataObjectKey()`**: Baut Keys wie `data.{namespace}.{ModelName}` oder `data.feature.{featureCode}.{ModelName}`
+
+### UI
+
+Steuert Sichtbarkeit und Aktivierung von Oberflaechenelementen.
+
+- **Item-Format**: Kaskadierende Strings (z.B. `playground.voice.settings`, `ui.feature.workspace.editor`)
+- **Prueft**: Nur `view` (Boolean)
+- **Verwendung**: Navigation, Seitenleiste, Buttons, Tabs
+
+### RESOURCE
+
+Steuert Zugriff auf Systemressourcen.
+
+- **Item-Format**: Kaskadierende Strings (z.B. `ai.model.anthropic`, `resource.feature.workspace.execute`)
+- **Prueft**: Primaer `view` (Boolean)
+- **Verwendung**: KI-Modelle, Aktionen, Features
+
+---
+
+## Resolution-Algorithmus
+
+### Priority-System
+
+| Rollen-Typ | Scope | Priority |
+|------------|-------|----------|
+| **Global/Template** | `mandateId=null, featureInstanceId=null` | 1 (niedrigste) |
+| **Mandate-Rolle** | `mandateId=X, featureInstanceId=null` | 2 |
+| **Feature-Instanz-Rolle** | `mandateId=X, featureInstanceId=Y` | 3 (hoechste) |
+
+### Resolution-Ablauf
+
+1. **Rollen laden**: Mandate-Rollen via `UserMandate` → `UserMandateRole`; Feature-Rollen via `FeatureAccess` → `FeatureAccessRole` (`getRulesForUserBulk()` in `rbac.py`)
+2. **AccessRules laden** fuer alle gefundenen Rollen
+3. **Gruppierung** nach Priority-Stufe
+4. **Hoechste Prioritaet gewinnt** bei DATA-Permissions
+5. **View wird OR-verknuepft** ueber alle Rollen der hoechsten Prioritaetsstufe
+6. **Item-Spezifitaet** innerhalb einer Stufe: exact > prefix > generic (laengster passender Praefix gewinnt)
+
+### DATA: Oeffnungsrechte (CUD vs. Read)
+
+| Read-Level | Maximales CUD |
+|------------|---------------|
+| `n` (NONE) | Kein CUD moeglich |
+| `o` (OWN) | CUD hoechstens `o` oder `n` |
+| `m` (MANDATE) | CUD hoechstens `m`, `o` oder `n` |
+| `a` (ALL) | Alle Stufen fuer CUD zulaessig |
+
+### Mehrere Rollen (Union-Logik)
+
+Ueber Rollen hinweg gilt **Union** (OR): wenn eine Rolle nach interner Aufloesung `view: true` liefert, gilt das Element als sichtbar/erlaubt. Fuer DATA werden die **freizuegigsten** Stufen ueber Rollen kombiniert.
+
+### SQL-Integration
+
+`buildRbacWhereClause()` in `interfaceRbac.py` uebersetzt die aufgeloesten Access Levels in SQL-WHERE-Bedingungen:
+- `a`: Kein Filter
+- `m`: `WHERE mandateId = :mandateId`
+- `o`: `WHERE _createdBy = :userId`
+- `n`: `WHERE 1=0` (kein Zugriff)
+
+RBAC-gefilterte Abfragen laufen ueber `getRecordsetWithRBAC()`.
+
+---
+
+## Bootstrap-Ablauf
+
+Beim Gateway-Start (`initBootstrap()` in `interfaceBootstrap.py`):
+
+```
+1. initRootMandate() -- Root-Mandant sicherstellen
+2. _deduplicateRoles() -- Duplikate bereinigen, isSystemRole-Flags fixen
+3. initRoles() -- System Template Rollen (admin/user/viewer) anlegen
+4. initRbacRules() -- Default AccessRules auf Template-Rollen
+5. _ensureAllMandatesHaveSystemRoles()
+ -- copySystemRolesToMandate() fuer jeden Mandanten
+6. _initSysAdminRole() -- SysAdmin-Rolle auf Root-Mandant
+7. _ensureUiContextRules() -- UI-Kontext-Regeln pruefen
+8. Admin/Event-User sichern
+9. assignInitialUserMemberships()
+ -- UserMandate + UserMandateRole fuer Admin/SysAdmin
+```
+
+Danach bei Feature-Registrierung (`registerAllFeaturesInCatalog()` → `registerFeature()`):
+
+```
+10. _syncTemplateRolesToDb() -- Feature Template Rollen upserten
+ -- AccessRules fuer Templates synchronisieren
+```
+
+Bei Laufzeit:
+
+```
+- createMandate() -- copySystemRolesToMandate() fuer neuen Mandanten
+- createFeatureInstance() -- _copyTemplateRoles() fuer neue Feature-Instanz
+```
+
+---
+
+## Systemfelder (DATA)
+
+Felder `id` und Namen mit fuehrendem `_` (z.B. `_createdBy`, `_createdAt`) sind fuer Anwendungs-CUD geschuetzt. Der Connector erzwingt das unabhaengig von Access Rules.
+
+## Frontend-Optionen fuer Rollen
+
+`frontend_options` an Feldern kann statische Listen oder String-Referenzen (z.B. `"user.role"`) nutzen. Dynamische Optionen ueber `/api/options/{optionsName}`. Typ-Hilfen: `gateway/modules/shared/frontendTypes.py`.
+
+---
+
+## Schluessel-Dateien
+
+| Thema | Pfad |
|-------|------|
-| RBAC-Auswertung / DB-Schicht | `gateway/modules/interfaces/interfaceRbac.py` |
-| AccessRule- und Permission-Modelle | `gateway/modules/datamodels/` (u. a. RBAC-bezogene Modelle) |
-| Nutzer / Rollenlabels | User-Modell mit `roleLabels` (Multiselect, Union) |
-| Konzept & Feldsemantik | `wiki/z-archive/appdoc/doc_security_role_based_access.md` |
+| RBAC-Auswertung, SQL-Integration | `gateway/modules/interfaces/interfaceRbac.py` |
+| AccessRule/Permission-Modelle | `gateway/modules/datamodels/datamodelRbac.py` |
+| Membership-Modelle | `gateway/modules/datamodels/datamodelMembership.py` |
+| Bootstrap (System Templates, Copy) | `gateway/modules/interfaces/interfaceBootstrap.py` |
+| Feature-Template-Copy | `gateway/modules/interfaces/interfaceFeatures.py` |
+| Feature-Registrierung | `gateway/modules/system/registry.py` |
+| RBAC-Rule-Resolution | `gateway/modules/security/rbac.py` |
+| TEMPLATE_ROLES (Beispiel) | `gateway/modules/features/workspace/mainWorkspace.py` |
## Regeln / Invarianten
-- Mandanten- vs. Feature-Rollen **strikt trennen** (keine Kreuz-Zuweisung der Label-Typen).
-- **Spezifisch vor generisch** innerhalb einer Rolle; **Union** über Rollen.
-- UI/RESOURCE: Effektiv sichtbar nur, wenn nach Regelauflösung **`view: true`** (kein `hasAccess: false` in Navigationskonzept — nicht berechtigte UI-Einträge werden gar nicht geliefert).
-- DATA: Validierung der Regeln so, dass CUD nicht über dem jeweiligen Read-Level liegen.
-- Performance-Ziel: DATA-Zugriffe mit RBAC-Filter in SQL, nicht erst vollständige Tabellen in Python filtern.
+- Mandanten-Rollen und Feature-Instanz-Rollen **strikt trennen** (keine Kreuz-Zuweisung der Label-Typen)
+- Templates werden nur bei Erstellung kopiert -- keine automatische Propagierung
+- **Spezifisch vor generisch** innerhalb einer Rolle; **Union** ueber Rollen
+- UI/RESOURCE: Sichtbar nur wenn `view: true`; nicht berechtigte UI-Eintraege werden gar nicht geliefert
+- DATA: CUD darf nicht ueber dem jeweiligen Read-Level liegen
+- Performance-Ziel: DATA-Zugriffe mit RBAC-Filter in SQL
diff --git a/c-work/1-plan/2026-03-web-image-search.md b/c-work/1-plan/2026-03-web-image-search.md
index 240fd65..9969a9d 100644
--- a/c-work/1-plan/2026-03-web-image-search.md
+++ b/c-work/1-plan/2026-03-web-image-search.md
@@ -1,361 +1,83 @@
-# Refactoring Concept: Add WEB_SEARCH_MEDIA Operation Type
+
+
+
-## Executive Summary
+# Web Image Search -- WEB_SEARCH_MEDIA Operation Type
-**Refactoring Goal**: Add image search capability by introducing `WEB_SEARCH_MEDIA` operation type and Google Custom Search connector.
+## Beschreibung und Kontext
-**Current State**:
-- ✅ `WEB_SEARCH_DATA` already exists (replaces former `WEB_SEARCH`)
-- ✅ Tavily connector handles `WEB_SEARCH_DATA` for web page/content search
-- ✅ `AiCallPromptWebSearchData` model exists
+PowerOn unterstützt Web-Suche über den Tavily-Connector (`WEB_SEARCH_DATA`). Es fehlt eine dedizierte Bildersuche. Ziel ist ein neuer OperationType `WEB_SEARCH_MEDIA` mit Google Custom Search Connector, damit der AI Agent Bilder suchen und als ActionDocuments zurückgeben kann.
-**Target State**:
-- Add `WEB_SEARCH_MEDIA` operation type for image/media search
-- Create Google Custom Search connector for `WEB_SEARCH_MEDIA`
-- Create `AiCallPromptWebSearchMedia` model
-- Add `ai.searchImages` action using `WEB_SEARCH_MEDIA`
+**Business-Treiber:** Mandanten benötigen Bildmaterial (z.B. für Immobilien-Exposés, Marketing-Content) direkt im AI Workspace.
-**Estimated Complexity**: Medium (1-2 days development)
+**Risiko bei Nicht-Umsetzung:** Manuelle Bildersuche ausserhalb der Plattform, kein automatisierter Image-Workflow.
-**Integration Impact**: Low - additive changes, no breaking changes
+## Fokus und kritische Details
----
+- Google Custom Search API erfordert API Key + Search Engine ID mit aktivierter Image Search
+- Model-Selection muss `WEB_SEARCH_MEDIA` korrekt zum Google-Connector routen
+- Rückgabeformat: JSON-Array mit Image-URLs, konsistent mit Tavily-Format
+- Rate Limiting der Google API (100 queries/Tag im Free Tier)
-## 1. Current Architecture
+## Ziel und Nicht-Ziele
-### 1.1 Operation Types
+- **Ziel:** `WEB_SEARCH_MEDIA` OperationType in `OperationTypeEnum`
+- **Ziel:** Google Custom Search Connector (`aicorePluginGoogle.py`)
+- **Ziel:** `AiCallPromptWebSearchMedia` Pydantic Model
+- **Ziel:** `ai.searchImages` Action in `methodAi`
+- **Explizit NICHT:** Video-Suche, Tavily-Erweiterung, SharePoint-Integration
-**Current Operation Types** (`gateway/modules/datamodels/datamodelAi.py`):
-```python
-class OperationTypeEnum(str, Enum):
- # ... existing operations ...
-
- # Web Operations
- WEB_SEARCH_DATA = "webSearchData" # Web page search (Tavily) ✅ EXISTS
- WEB_CRAWL = "webCrawl" # Web crawl for a given URL
-```
+## Betroffene Module
-**Target Operation Types**:
-```python
-class OperationTypeEnum(str, Enum):
- # ... existing operations ...
-
- # Web Operations
- WEB_SEARCH_DATA = "webSearchData" # Web page search (Tavily) ✅ EXISTS
- WEB_SEARCH_MEDIA = "webSearchMedia" # Image/media search (Google) ⬅️ NEW
- WEB_CRAWL = "webCrawl" # Web crawl for a given URL
-```
+- Gateway: `modules/datamodels/datamodelAi.py`, `modules/aicore/aicorePluginGoogle.py` (NEU), `modules/services/serviceAi/mainServiceAi.py`, `modules/workflows/methods/methodAi/`
+- Frontend: keine (Agent nutzt Action intern)
+- DB-Migration: nein
+- Andere: Google Cloud Console Setup (API Key)
-### 1.2 Model Capabilities
+## Entscheidungen
-**Tavily Connector** (`gateway/modules/aicore/aicorePluginTavily.py`):
-- ✅ Registered for `WEB_SEARCH_DATA` (rating: 9)
-- ✅ Registered for `WEB_CRAWL` (rating: 10)
-- ❌ Does NOT support image search - designed for web/text content only
+| Datum | Entscheidung | Begründung |
+|-------|-------------|------------|
+| 2026-03-01 | Google Custom Search statt Tavily | Tavily unterstützt keine Bildersuche |
+| 2026-03-01 | Eigener Connector statt Tavily-Erweiterung | Saubere Trennung, unabhängige Skalierung |
-**Model Selection**:
-- Dynamic model selection routes based on `OperationTypeEnum` in `AiCallOptions`
-- Models register capabilities via `operationTypes` with ratings (1-10)
-- System automatically selects best model for each operation type
+## Umsetzungs-Checkliste
----
+- [ ] `WEB_SEARCH_MEDIA` in `OperationTypeEnum` hinzufügen
+- [ ] `AiCallPromptWebSearchMedia` Model erstellen
+- [ ] `aicorePluginGoogle.py` Connector implementieren
+- [ ] Connector in Discovery registrieren
+- [ ] `mainServiceAi.py` für `WEB_SEARCH_MEDIA` erweitern
+- [ ] `searchImages` Action erstellen
+- [ ] Action in `methodAi.py` registrieren
+- [ ] RBAC / Permissions: nicht betroffen (nutzt bestehende AI-Berechtigung)
+- [ ] Neutralisierung betroffen? nein
+- [ ] Navigation / Routing: nicht betroffen
+- [ ] Billing-Impact? prüfen (API-Kosten pro Query)
-## 2. Refactoring Plan
+## Akzeptanzkriterien
-### 2.1 Add WEB_SEARCH_MEDIA Operation Type
+| # | Kriterium (Given-When-Then) | Prio |
+|---|---------------------------|------|
+| 1 | Given ein AI Agent mit `searchImages` Tool, When der User "Suche Bilder von Zürich" eingibt, Then gibt der Agent eine Liste von Bild-URLs zurück | must |
+| 2 | Given kein Google API Key konfiguriert, When `WEB_SEARCH_MEDIA` aufgerufen wird, Then wird ein klarer Fehler zurückgegeben | must |
+| 3 | Given `maxResults=5` und `imageType=photo`, When die Suche ausgeführt wird, Then werden max. 5 Fotos zurückgegeben | should |
-**File**: `gateway/modules/datamodels/datamodelAi.py`
+## Testplan
-**Changes**:
-```python
-class OperationTypeEnum(str, Enum):
- # ... existing operations ...
-
- # Web Operations
- WEB_SEARCH_DATA = "webSearchData" # Web page search (Tavily)
- WEB_SEARCH_MEDIA = "webSearchMedia" # Image/media search (Google) ⬅️ ADD
- WEB_CRAWL = "webCrawl" # Web crawl for a given URL
-```
+| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
+|----|----|-----|--------------|-----------|--------|
+| T1 | 1 | integration | ja | gateway/tests/test_google_connector.py | pending |
+| T2 | 2 | unit | ja | gateway/tests/test_google_connector.py | pending |
+| T3 | 3 | api | ja | gateway/tests/test_search_images_action.py | pending |
-### 2.2 Create AiCallPromptWebSearchMedia Model
+## Links
-**File**: `gateway/modules/datamodels/datamodelAi.py`
+- Google Custom Search API: https://developers.google.com/custom-search/v1/overview
+- Bestehender Tavily Connector: `gateway/modules/aicore/aicorePluginTavily.py`
-**Add after `AiCallPromptWebSearchData`**:
-```python
-class AiCallPromptWebSearchMedia(BaseModel):
- """Structured prompt format for WEB_SEARCH_MEDIA operation - returns list of image URLs."""
-
- instruction: str = Field(description="Search instruction/query for finding relevant images")
- maxResults: Optional[int] = Field(default=10, description="Maximum number of images to return (default: 10)")
- imageType: Optional[str] = Field(default=None, description="Image type filter: 'photo', 'clipart', 'lineart', 'animated'")
- size: Optional[str] = Field(default=None, description="Image size filter: 'small', 'medium', 'large', 'xlarge'")
- color: Optional[str] = Field(default=None, description="Color filter: 'color', 'grayscale', 'transparent'")
- country: Optional[str] = Field(default=None, description="Two-digit country code (lowercase, e.g., ch, us, de, fr)")
- language: Optional[str] = Field(default=None, description="Language code (lowercase, e.g., de, en, fr)")
-```
+## Abschluss
-### 2.3 Create Google Custom Search Connector
-
-**New File**: `gateway/modules/aicore/aicorePluginGoogle.py`
-
-**Structure** (similar to `aicorePluginTavily.py`):
-```python
-class AiGoogle(BaseConnectorAi):
- """Google Custom Search connector for image search."""
-
- def getModels(self) -> List[AiModel]:
- """Get Google Custom Search model."""
- return [
- AiModel(
- name="google-custom-search",
- displayName="Google Custom Search",
- connectorType="google",
- apiUrl="https://www.googleapis.com/customsearch/v1",
- # ... model configuration ...
- operationTypes=createOperationTypeRatings(
- (OperationTypeEnum.WEB_SEARCH_MEDIA, 9)
- ),
- functionCall=self._routeWebOperation,
- # ...
- )
- ]
-
- async def _routeWebOperation(self, modelCall: AiModelCall) -> "AiModelResponse":
- """Route web operation based on operation type."""
- operationType = modelCall.options.operationType
-
- if operationType == OperationTypeEnum.WEB_SEARCH_MEDIA:
- return await self.webSearchMedia(modelCall)
- else:
- return AiModelResponse(
- content="",
- success=False,
- error=f"Unsupported operation type: {operationType}"
- )
-
- async def webSearchMedia(self, modelCall: AiModelCall) -> "AiModelResponse":
- """WEB_SEARCH_MEDIA operation - returns list of image URLs using Google Custom Search."""
- # Parse AiCallPromptWebSearchMedia from messages
- # Call Google Custom Search API with searchType=image
- # Return JSON array of image URLs (same format as Tavily for consistency)
-```
-
-**Key Implementation Points**:
-- Use Google Custom Search API with `searchType=image`
-- Return image URLs in JSON array format (consistent with Tavily)
-- Support filters: imageType, size, color, country, language
-- Handle API errors and rate limiting
-
-### 2.4 Update Service AI Handler
-
-**File**: `gateway/modules/services/serviceAi/mainServiceAi.py`
-
-**Update `_handleWebOperations()` method**:
-```python
-async def _handleWebOperations(
- self,
- prompt: str,
- options: AiCallOptions,
- opType: OperationTypeEnum,
- aiOperationId: str
-) -> AiResponse:
- """Handle WEB_SEARCH_DATA, WEB_SEARCH_MEDIA, and WEB_CRAWL operation types."""
- # Existing logic handles WEB_SEARCH_DATA and WEB_CRAWL
- # Add support for WEB_SEARCH_MEDIA
- if opType == OperationTypeEnum.WEB_SEARCH_DATA or opType == OperationTypeEnum.WEB_SEARCH_MEDIA or opType == OperationTypeEnum.WEB_CRAWL:
- # ... existing implementation ...
-```
-
-### 2.5 Add searchImages Action
-
-**New File**: `gateway/modules/workflows/methods/methodAi/actions/searchImages.py`
-
-**Implementation**:
-```python
-async def searchImages(self, parameters: Dict[str, Any]) -> ActionResult:
- """Search for images on the web using a prompt and return them as documents."""
- prompt = parameters.get("prompt")
- if not prompt:
- return ActionResult.isFailure(error="Search prompt is required")
-
- maxResults = parameters.get("maxResults", 5)
- imageType = parameters.get("imageType")
- size = parameters.get("size")
- color = parameters.get("color")
-
- # Build AiCallPromptWebSearchMedia
- searchPromptModel = AiCallPromptWebSearchMedia(
- instruction=prompt,
- maxResults=maxResults,
- imageType=imageType,
- size=size,
- color=color
- )
-
- # Call AI with WEB_SEARCH_MEDIA operation
- searchOptions = AiCallOptions(
- operationType=OperationTypeEnum.WEB_SEARCH_MEDIA,
- resultFormat="json"
- )
-
- # System will automatically route to Google connector
- searchResponse = await self.services.ai.callAiContent(
- prompt=searchPromptModel.model_dump_json(exclude_none=True, indent=2),
- options=searchOptions,
- outputFormat="json"
- )
-
- # Parse response to extract image URLs
- # Download images in parallel
- # Create ActionDocument for each image
- # Return ActionResult with list of documents
-```
-
-**Update**: `gateway/modules/workflows/methods/methodAi/methodAi.py`
-
-**Add action definition**:
-```python
-"searchImages": WorkflowActionDefinition(
- actionId="ai.searchImages",
- description="Search for images on the web using a prompt and return them as documents",
- dynamicMode=True,
- parameters={
- "prompt": WorkflowActionParameter(...),
- "maxResults": WorkflowActionParameter(...),
- "imageType": WorkflowActionParameter(...),
- "size": WorkflowActionParameter(...)
- },
- execute=searchImages.__get__(self, self.__class__)
-)
-```
-
----
-
-## 3. Implementation Steps
-
-### Phase 1: Add WEB_SEARCH_MEDIA Operation Type (30 min)
-
-1. ✅ Add `WEB_SEARCH_MEDIA = "webSearchMedia"` to `OperationTypeEnum`
-2. ✅ Create `AiCallPromptWebSearchMedia` model
-3. ✅ Update imports/exports
-
-### Phase 2: Create Google Connector (4-6 hours)
-
-1. ✅ Create `aicorePluginGoogle.py` file
-2. ✅ Implement `AiGoogle` connector class
-3. ✅ Implement `webSearchMedia()` method
-4. ✅ Register connector in connector discovery
-5. ✅ Test Google API integration
-6. ✅ Handle errors and rate limiting
-
-### Phase 3: Update Service Handlers (1-2 hours)
-
-1. ✅ Update `serviceAi/mainServiceAi.py` to handle `WEB_SEARCH_MEDIA`
-2. ✅ Ensure routing works correctly
-3. ✅ Test model selection routes to Google connector
-
-### Phase 4: Add searchImages Action (3-4 hours)
-
-1. ✅ Create `actions/searchImages.py`
-2. ✅ Implement image search logic
-3. ✅ Implement parallel image download
-4. ✅ Add action definition to `methodAi.py`
-5. ✅ Add to `actions/__init__.py`
-6. ✅ Write unit tests
-
-### Phase 5: Testing & Integration (2-3 hours)
-
-1. ✅ Test Google connector with real API
-2. ✅ Test searchImages action end-to-end
-3. ✅ Verify dynamic model selection
-4. ✅ Test error handling
-5. ✅ Integration testing
-
-**Total Estimated Time**: 1-2 days
-
----
-
-## 4. Configuration Requirements
-
-### 4.1 Environment Variables
-
-**Required**:
-- `GOOGLE_SEARCH_API_KEY` - Google Custom Search API key
-- `GOOGLE_SEARCH_ENGINE_ID` - Custom Search Engine ID
- - Note: Must enable "Image Search" in Google Custom Search Engine settings
-
-### 4.2 Google Custom Search Setup
-
-1. Create Google Custom Search Engine at https://programmablesearchengine.google.com/
-2. Enable "Image Search" in settings
-3. Get API key from Google Cloud Console
-4. Configure environment variables
-
----
-
-## 5. Files to Create/Modify
-
-### New Files
-- `gateway/modules/aicore/aicorePluginGoogle.py` - Google connector
-- `gateway/modules/workflows/methods/methodAi/actions/searchImages.py` - Image search action
-
-### Modified Files
-- `gateway/modules/datamodels/datamodelAi.py` - Add `WEB_SEARCH_MEDIA` and `AiCallPromptWebSearchMedia`
-- `gateway/modules/services/serviceAi/mainServiceAi.py` - Handle `WEB_SEARCH_MEDIA`
-- `gateway/modules/workflows/methods/methodAi/methodAi.py` - Add `searchImages` action
-- `gateway/modules/workflows/methods/methodAi/actions/__init__.py` - Export `searchImages`
-- Connector discovery module (if exists) - Register Google connector
-
----
-
-## 6. Testing Requirements
-
-### Unit Tests
-- Google connector `webSearchMedia()` method
-- `searchImages` action with various parameters
-- Error handling (API errors, rate limits, invalid responses)
-- Image download and validation
-
-### Integration Tests
-- End-to-end image search workflow
-- Dynamic model selection routes to Google connector
-- Multiple image downloads in parallel
-- Verify ActionDocuments are created correctly
-
----
-
-## 7. Risks & Mitigation
-
-| Risk | Impact | Probability | Mitigation |
-|------|--------|-------------|------------|
-| Google API setup complexity | Medium | Medium | Provide clear setup instructions, validate API keys at startup |
-| Dynamic model selection routing | Medium | Low | Thoroughly test operation type routing |
-| API rate limiting (Google) | Low | Medium | Implement retry logic with exponential backoff |
-| Missing connector registration | Medium | Low | Ensure connector is registered in discovery system |
-
----
-
-## 8. Dependencies
-
-- **Google Custom Search API** - REQUIRED
-- **Google API Client Library** - May need `google-api-python-client` package
-- **HTTP Client** - For image downloads (existing)
-- **Base64 Encoding** - Python standard library (no dependency)
-
----
-
-## 9. Success Criteria
-
-✅ `WEB_SEARCH_MEDIA` operation type exists
-✅ Google connector is registered and functional
-✅ `searchImages` action works end-to-end
-✅ Dynamic model selection routes `WEB_SEARCH_MEDIA` to Google connector
-✅ Images are downloaded and returned as ActionDocuments
-✅ All tests pass
-
----
-
-**Document Version**: 2.0
-**Last Updated**: 2026-01-01
-**Status**: Refactoring Concept - Ready for Implementation
+- [ ] b-reference/gateway/ai-agent.md aktualisiert (neuer OperationType)
+- [ ] TOPICS.md aktualisiert (falls neues Thema)
+- [ ] Dieses Dokument → z-archive/ verschoben
diff --git a/c-work/1-plan/2026-04-automation-unification.md b/c-work/1-plan/2026-04-automation-unification.md
new file mode 100644
index 0000000..2cd9c95
--- /dev/null
+++ b/c-work/1-plan/2026-04-automation-unification.md
@@ -0,0 +1,1067 @@
+
+
+
+
+# Automation Unification -- Konsolidierung v1/v2/Workspace
+
+## Beschreibung und Kontext
+
+PowerOn hat drei teilweise ueberlappende Automatisierungssysteme: Automation v1 (Template+Cron), Automation2 (n8n-Style Graph-Editor), und AI Workspace (Chat-Agent mit Tools). Alle nutzen die gleiche Action Library (`workflows/methods/` + `ActionExecutor`), aber unterschiedliche Persistenz, Scheduler und Execution Engines.
+
+**Business-Treiber:** Inkonsistenzen zwischen den Systemen (zwei DB-Schemas, zwei Scheduler-Patterns, zwei Engines) erhoehen den Wartungsaufwand und erschweren Feature-Paritaet.
+
+**Risiko bei Nicht-Umsetzung:** Wachsende Divergenz, doppelter Aufwand bei neuen Aktionen, inkonsistentes Verhalten fuer Endbenutzer.
+
+**Leitprinzipien:**
+- Keine Migration von Altdaten -- Automation v1 ist nicht produktiv, wird nicht migriert
+- Automation v1 bleibt bestehen, bis es durch das neue Feature abgeloest ist
+- Klare Datenmodelle mit definierten State Machines als stabile, erweiterbare Grundlage
+- Klare Trennung von Mandant/Feature/Feature-Instanz und zugehoeriger RBAC-Logik
+- Skalierbare AI-Tool-Architektur mit Toolboxes und Sub-Agents fuer 50-100+ Tools
+
+---
+
+## Ist-Analyse
+
+### Drei bestehende Systeme
+
+| System | Modell | Staerke | Schwaeche |
+|--------|--------|---------|-----------|
+| **Automation v1** | Template + Cron + Placeholders | Stabiles, bewaehrtes Scheduling mit Callback-basiertem Sync, inkrementeller Job-Registrierung, Execution-Logs | Kein visuelles Editing, kein Branching, starres Template-Modell |
+| **Automation2** | Graph-Editor (n8n-style) + Run/Task-Modell | Visuelles Modellieren, Branching, Loops, Human-in-the-loop, Pause/Resume, diverse Node-Typen | Kein AI-Chat im Editor, kein UDB-Zugang, Scheduler-Sync weniger robust als v1 |
+| **AI Workspace** | Chat-driven AI Agent mit Tools | Natural-language Interaktion, 40+ Core Tools + Action Tools, Streaming, RAG | Kein persistiertes Workflow-Modell, kein Scheduling |
+
+### Wer nutzt die Method/Action Library?
+
+Die `workflows/methods/` Library (methodAi, methodOutlook, methodSharepoint, etc.) ist die de facto gemeinsame Basis. Alle Systeme nutzen `ActionExecutor.executeAction()`:
+
+| Consumer | Pfad zur Action Library |
+|----------|------------------------|
+| **Workspace AI Agent** | `ActionToolAdapter` registriert `dynamicMode=True` Actions als Agent-Tools -> LLM waehlt Tool -> `ActionExecutor` |
+| **Automation2 Graph Engine** | `ActionNodeExecutor` liest `_method`/`_action` aus Node-Definition -> `ActionExecutor` |
+| **Automation v1** | `WorkflowProcessor` -> `modeAutomation` -> `ActionExecutor` |
+| **Workspace Dynamic Mode** | `WorkflowProcessor` -> `modeDynamic` -> AI plant Tasks -> `ActionExecutor` |
+
+### Wer nutzt die AI Tools?
+
+| Tool-Typ | Registrierung | Nutzung |
+|----------|--------------|---------|
+| **Core Tools** (40: readFile, webSearch, sendMail, etc.) | `_registerCoreTools()` | Workspace Agent, CommCoach Agent |
+| **Action Tools** (dynamicMode Actions) | `ActionToolAdapter.registerAll()` | Workspace Agent (toolSet-uebergreifend) |
+| **Graph Node Types** (ai.prompt, email.checkEmail, etc.) | `STATIC_NODE_TYPES` in `nodeDefinitions/` | Automation2 `executeGraph` |
+
+### Identifizierte Inkonsistenzen
+
+| # | Inkonsistenz |
+|---|-------------|
+| **I-1** | Zwei Datenmodelle: `AutomationDefinition` (v1) vs `Automation2Workflow` (v2) -- kein gemeinsames Workflow-Konzept |
+| **I-2** | Zwei Datenbanken: `poweron_automation` vs `poweron_automation2` |
+| **I-3** | Zwei Scheduler: v1 (inkrementell, callback `automation.changed`) vs v2 (full wipe + re-register, callback `automation2.workflow.changed`) |
+| **I-4** | Zwei Execution Engines: `WorkflowManager` + `WorkflowProcessor` vs `executionEngine.executeGraph` |
+| **I-5** | Kein AI-Chat im Graphical Editor |
+| **I-6** | `WorkspaceInput` ist nicht als wiederverwendbare Komponente extrahiert |
+| **I-7** | UDB nur in Workspace und CommCoach, nicht im Graphical Editor |
+| **I-8** | AI Tools skalieren nicht: 50+ Tools ohne Gruppierungslogik, alle werden dem LLM gleichzeitig exponiert |
+
+---
+
+## Ziel-Architektur: Vier Saeulen
+
+```
++----------------------------------------------------------------------+
+| POWERON UNIFIED PLATFORM |
+| |
+| +--------------+ +-----------------------+ +------------------+ |
+| | AI Service | | Graphical Editor | | Automation | |
+| | (Saeule 1) | | (Saeule 2) | | Scheduler | |
+| | | | | | (Saeule 3) | |
+| | - AI Gateway | | - Visual Flow Builder | | | |
+| | - Agent Loop | | - Node Palette | | - Cron Engine | |
+| | - Toolboxes | | - AI Chat Sidebar | | - Event Trigger | |
+| | - Sub-Agents | | - UDB Integration | | - Webhook Entry | |
+| | - Streaming | | - Tracing/Debug Log | | - Run History | |
+| | - Failover | | - Test Runner | | - Monitoring | |
+| | - Neutraliz. | | - Version Management | | - Notifications | |
+| +------+--------+ +-----------+-------------+ +--------+---------+ |
+| | | | |
+| +------v------------------------v---------------------------v----------+ |
+| | SAEULE 4: UNIFIED ACTION LIBRARY (Toolboxes) | |
+| | | |
+| | Toolbox "ai" | Toolbox "email" | Toolbox "files" | |
+| | ai.process | outlook.readEmails | context.extract | |
+| | ai.webResearch | outlook.searchEmails | context.neutralize | |
+| | ai.summarize | outlook.draftEmail | file.create | |
+| | ai.translate | outlook.sendDraft | context.transform | |
+| | | | | |
+| | Toolbox "sharepoint"| Toolbox "clickup" | Toolbox "jira" | |
+| | sharepoint.findDoc | clickup.searchTasks | jira.connect | |
+| | sharepoint.readDocs | clickup.createTask | jira.exportTickets | |
+| | sharepoint.upload | clickup.updateTask | jira.importTickets | |
+| | | | | |
+| | Toolbox "workflow" | Toolbox "trustee" | [future toolboxes] | |
+| | readWorkflowGraph | trustee.extract | slack.sendMessage | |
+| | addNode, removeNode | trustee.process | teams.postChannel | |
+| | connectNodes | trustee.syncAcctng | google.readDrive | |
+| +----------------------------------------------------------------------+ |
++------------------------------------------------------------------------+
+```
+
+### Saeule 1: AI Service (besteht, zu erweitern)
+
+**Status:** Kern bereit (`serviceAi` + `serviceAgent` + `aicore`).
+**Erweiterung:** Toolbox-Architektur fuer 50-100+ Tools (siehe Abschnitt Toolboxes).
+
+### Saeule 2: Graphical Editor (Feature "graphicalEditor")
+
+**Status:** Basis vorhanden (Automation2FlowEditor), zu erweitern.
+
+| # | Funktionalitaet | Status |
+|---|-----------------|--------|
+| 1 | **Visual Flow Builder** -- Canvas, Nodes, Connections, Branching, Loops | besteht |
+| 2 | **Node Palette** -- abgeleitet aus Toolbox-Registry, jede Action kann als Node exponiert werden | besteht |
+| 3 | **AI Chat Sidebar** -- Agent mit Toolbox `"workflow"` fuer Graph-Manipulation | neu |
+| 4 | **UDB Integration** -- UnifiedDataBar im Editor | neu |
+| 5 | **Tracing/Debug Log** -- RunStepLog mit Input-Snapshot, Duration, Error pro Node | zu erweitern |
+| 6 | **Test Runner** -- Visual Highlighting, Step-by-Step, AI-assisted Debugging | zu erweitern |
+| 7 | **Version Management** -- Draft/Published Lifecycle | neu |
+
+### Saeule 3: Automation Scheduler (zu konsolidieren)
+
+**Von v1 uebernehmen:**
+- Inkrementeller Sync (nur geaenderte Jobs registrieren/entfernen, nicht full wipe)
+- Persistierter Job-Handle (`eventId`) auf dem Workflow fuer Debugging
+- `automation.changed` Callback-Pattern fuer reaktive Synchronisation
+- Handler laedt Workflow neu und prueft `active` vor Execution
+- Execution-Logs als Audit Trail (capped auf 50 Eintraege)
+- Creator-User Tracking via `sysCreatedBy` fuer Execution-Kontext
+
+**Von v2 beibehalten:**
+- `IntervalTrigger` fuer einfache Wiederholungen
+- Main-Loop-Bridging (`call_soon_threadsafe`) fuer Thread-Safety
+- Delayed Startup Sync (5s) fuer DB-Readiness
+- Striktes Cron-Parsing (5/6 Felder)
+
+### Saeule 4: Unified Action Library mit Toolboxes
+
+**Status:** Infrastruktur besteht (`workflows/methods/` + `methodDiscovery` + `ActionExecutor`). Zu erweitern um Toolbox-Konzept (siehe eigener Abschnitt).
+
+---
+
+## Fokus und kritische Details
+
+- Scheduler-Robustheit: v1 hat bewaehrtes inkrementelles Pattern, v2 macht Full-Wipe-Re-Register
+- Tool-Skalierung: 40+ Core-Tools + dynamische Actions -- flache Tool-Listen skalieren nicht
+- Human-in-the-Loop: Pause/Resume nur in v2 implementiert
+- Keine Migration von v1-Altdaten (nicht produktiv)
+
+---
+
+## Ziel und Nicht-Ziele
+
+- **Ziel:** Einheitliche Plattform mit v1-Scheduler-Robustheit und v2-Graph-Faehigkeiten
+- **Ziel:** Toolbox-Architektur fuer skalierbare Tool-Verwaltung (requestToolbox, availableToolboxes)
+- **Ziel:** Einheitliches Workflow/Version/Run Datenmodell (Draft -> Published, Runs, Tracing)
+- **Explizit NICHT:** Migration von v1-Daten; Abloesung des AI Workspace Chat-Modells
+
+---
+
+## Mandant/Feature/RBAC-Architektur
+
+### Hierarchie
+
+```
+System (PowerOn Platform)
+|
++-- System Template Rollen (isSystemRole=true, mandateId=null, featureCode=null)
+| "admin", "user", "viewer"
+| -> kopiert bei Mandant-Erstellung via copySystemRolesToMandate()
+|
++-- Feature Template Rollen (isSystemRole=false, mandateId=null, featureCode=X)
+| "workspace-admin", "workspace-user", "workspace-viewer"
+| "graphicalEditor-admin", "graphicalEditor-user", ...
+| -> kopiert bei Feature-Instanz-Erstellung via _copyTemplateRoles()
+|
++-- Mandant (Tenant)
+ +-- Mandate-Rollen (kopiert von System Templates)
+ | mandateId=X, featureInstanceId=null, featureCode=null
+ | "admin", "user", "viewer"
+ | -> UserMandateRole <- UserMandate <- User
+ |
+ +-- Feature-Instanz A (z.B. "AI Workspace Produktion")
+ | +-- Feature-Instanz-Rollen (kopiert von Feature Templates)
+ | | mandateId=X, featureInstanceId=Y, featureCode="workspace"
+ | | "workspace-admin", "workspace-user", "workspace-viewer"
+ | | -> FeatureAccessRole <- FeatureAccess <- User
+ | +-- Daten (Workflows, Files, Chats, ...)
+ |
+ +-- Feature-Instanz B (z.B. "Graphical Editor Dev")
+ +-- Feature-Instanz-Rollen
+ +-- Daten (Workflows, Runs, Tasks, ...)
+```
+
+### Zwei getrennte Template-Rollen-Systeme
+
+**System Template Rollen (fuer Mandanten)**
+
+| Feld | Wert |
+|------|------|
+| `isSystemRole` | `true` |
+| `mandateId` | `null` |
+| `featureInstanceId` | `null` |
+| `featureCode` | `null` |
+| `roleLabel` | `"admin"`, `"user"`, `"viewer"` |
+| Kopier-Mechanismus | `copySystemRolesToMandate()` in `interfaceBootstrap.py` |
+| Ausgeloest bei | Mandant-Erstellung |
+
+**Feature Template Rollen (fuer Feature-Instanzen)**
+
+| Feld | Wert |
+|------|------|
+| `isSystemRole` | `false` |
+| `mandateId` | `null` |
+| `featureInstanceId` | `null` |
+| `featureCode` | z.B. `"workspace"`, `"automation2"` |
+| `roleLabel` | z.B. `"workspace-admin"`, `"workspace-user"` |
+| Kopier-Mechanismus | `_copyTemplateRoles()` in `interfaceFeatures.py` |
+| Ausgeloest bei | Feature-Instanz-Erstellung |
+
+**Wichtig:** Templates werden **nur bei Erstellung** kopiert. Spaetere Aenderungen werden **nicht** automatisch propagiert.
+
+### RBAC-Resolution (Priority-System)
+
+| Rollen-Typ | Scope | RBAC Priority |
+|------------|-------|---------------|
+| **Global/Template** | `mandateId=null, featureInstanceId=null` | 1 (niedrigste) |
+| **Mandate-Rolle** | `mandateId=X, featureInstanceId=null` | 2 |
+| **Instanz-Rolle** | `mandateId=X, featureInstanceId=Y` | 3 (hoechste) |
+
+**Resolution:**
+1. Lade Mandate-Rollen (via `UserMandate` -> `UserMandateRole`)
+2. Lade Feature-Instanz-Rollen (via `FeatureAccess` -> `FeatureAccessRole`)
+3. Lade `AccessRules` fuer alle gefundenen Rollen
+4. **Hoechste Prioritaet gewinnt** bei DATA-Permissions
+5. **View wird OR-verknuepft** ueber alle Rollen der hoechsten Prioritaetsstufe
+6. **Item-Spezifitaet** innerhalb einer Stufe: exact > prefix > generic
+
+### RBAC-Datenmodell
+
+```python
+class Role(PowerOnModel):
+ mandateId: Optional[str] # null = Global/Template
+ featureInstanceId: Optional[str] # null = nicht Instanz-spezifisch
+ featureCode: Optional[str] # z.B. "workspace", "graphicalEditor"
+ roleLabel: str # z.B. "workspace-admin"
+ isSystemRole: bool
+
+class AccessRule(PowerOnModel):
+ roleId: str # FK -> Role
+ context: AccessRuleContext # DATA | UI | RESOURCE
+ item: Optional[str] # null=generic, oder spezifisch
+ view: bool
+ read: Optional[AccessLevel] # "n" | "o" | "m" | "a"
+ create: Optional[AccessLevel]
+ update: Optional[AccessLevel]
+ delete: Optional[AccessLevel]
+
+class AccessLevel(str, Enum):
+ NONE = "n"
+ OWN = "o"
+ MANDATE = "m"
+ ALL = "a"
+```
+
+### AccessRule-Kontexte
+
+| Kontext | Item-Beispiel | Prueft |
+|---------|---------------|--------|
+| `UI` | `ui.feature.graphicalEditor.editor` | Seitenleiste, Navigation, Buttons |
+| `RESOURCE` | `resource.feature.graphicalEditor.execute` | Ausfuehrungsberechtigungen |
+| `DATA` | Auto-generiert aus Tabellenname + featureCode | CRUD auf Datenbank-Ebene |
+
+---
+
+## AI-Tool-Architektur: Toolboxes und Sub-Agents
+
+### Problem: Tool-Explosion
+
+Aktuell werden ~50 Tools dem LLM in einem einzigen Prompt exponiert. Bei 100+ Tools:
+- LLM-Context wird ueberladen -> schlechtere Tool-Auswahl
+- Irrelevante Tools fuer den aktuellen Kontext -> Confusion und Halluzinationen
+- Keine Feature-isolierte Tool-Bereitstellung
+
+### Konzept: Toolboxes
+
+Eine **Toolbox** ist eine thematisch gebuendelte Gruppe von Tools mit einem klaren Scope:
+
+```
+Toolbox-Registry
+|
++-- Toolbox "core" (immer verfuegbar)
+| readFile, listFiles, searchInFileContent, writeFile, deleteFile,
+| renameFile, copyFile, listFolders, createFolder, deleteFolder,
+| webSearch, readUrl, detectLanguage, translateText
+|
++-- Toolbox "ai" (AI-Operationen)
+| summarizeContent, describeImage, generateImage, textToSpeech,
+| speechToText, renderDocument, createChart, executeCode, neutralizeData
+|
++-- Toolbox "datasources" (Externe Verbindungen)
+| listConnections, browseDataSource, searchDataSource,
+| downloadFromDataSource, uploadToExternal, browseContainer,
+| readContentObjects, extractContainerItem
+|
++-- Toolbox "email" (Outlook-Integration, requiresConnection="outlook")
+| sendMail, outlook.readEmails, outlook.searchEmails, outlook.draftEmail
+|
++-- Toolbox "sharepoint" (requiresConnection="sharepoint")
+| sharepoint.findDoc, sharepoint.read, sharepoint.upload, ...
+|
++-- Toolbox "clickup" (requiresConnection="clickup")
+| clickup.searchTasks, clickup.createTask, ...
+|
++-- Toolbox "jira" (requiresConnection="jira")
+| jira.connect, jira.exportTickets, ...
+|
++-- Toolbox "workflow" (Graph-Manipulation fuer Editor-Chat)
+| readWorkflowGraph, addNode, removeNode, connectNodes,
+| setNodeParameter, listAvailableNodeTypes, validateGraph,
+| listWorkflowHistory, readWorkflowMessages
+|
++-- Toolbox "trustee" (featureCode="trustee")
+| trustee.extract, trustee.process, trustee.syncAccounting
+|
++-- Toolbox "chatbot" (featureCode="chatbot")
+ chatbot.queryDatabase
+```
+
+### Toolbox-Bereitstellung: Initiales Set + dynamische Eskalation
+
+**Kern-Idee:** Der Agent startet mit einem kompakten Tool-Set. Er kennt den **Katalog aller verfuegbaren Toolboxes**. Wenn er Spezial-Tools braucht, kann er eine Toolbox **anfordern** -- und bekommt sie in der naechsten Runde.
+
+```
+Runde 1:
+ Tools: core (readFile, webSearch, ...) + requestToolbox
+ System-Prompt: "Verfuegbare Toolboxes: email, sharepoint, clickup, ..."
+
+ User: "Lies meine letzten Emails und fasse sie zusammen"
+ LLM: -> requestToolbox("email") [braucht Email-Tools]
+
+Runde 2:
+ Tools: core + email (sendMail, outlook_readEmails, ...) + requestToolbox
+ LLM: -> outlook_readEmails(connectionRef, folder="Inbox", limit=10)
+
+Runde 3:
+ LLM: -> (Text-Antwort mit Zusammenfassung) -> COMPLETED
+```
+
+**`requestToolbox` Meta-Tool:**
+
+```python
+{
+ "name": "requestToolbox",
+ "description": "Request additional specialized tools for the current task.",
+ "parameters": {
+ "toolboxId": {
+ "type": "string",
+ "enum": [...] # Dynamisch: nur verfuegbare Toolboxes
+ },
+ "reason": {"type": "string"}
+ }
+}
+```
+
+### Toolbox-Datenmodell
+
+```python
+class ToolboxDefinition(BaseModel):
+ id: str # z.B. "core", "email", "sharepoint"
+ label: Dict[str, str] # Multilingual: {"en": "Email", "de": "E-Mail"}
+ description: str
+ featureCode: Optional[str] # null = Feature-unabhaengig
+ tools: List[str] # Tool-Namen in dieser Toolbox
+ isDefault: bool = False # Immer aktiv (z.B. "core")
+ requiresConnection: Optional[str] # "outlook" -> auto-aktiviert bei Connection
+
+class ToolboxRegistry:
+ _toolboxes: Dict[str, ToolboxDefinition]
+ _toolRegistry: ToolRegistry
+
+ def registerToolbox(self, toolbox: ToolboxDefinition): ...
+ def getActiveToolboxes(self, featureCode, userConnections, explicitToolboxes): ...
+ def getToolsForToolboxes(self, activeToolboxIds) -> List[ToolDefinition]: ...
+
+class AgentConfig(BaseModel):
+ maxRounds: int = 25
+ maxCostCHF: Optional[float] = None
+ initialToolboxes: List[str] = ["core"]
+ availableToolboxes: List[str] = []
+ temperature: Optional[float] = None
+```
+
+### Toolbox-Zuordnung pro Feature
+
+| Feature | `initialToolboxes` | `availableToolboxes` (anforderbar) |
+|---------|--------------------|------------------------------------|
+| **Workspace** | `["core"]` | `["ai", "datasources", "email", "sharepoint", "clickup", "jira", "workflow"]` -- gefiltert nach User-Connections |
+| **Graphical Editor Chat** | `["core", "workflow"]` | `["ai"]` |
+| **CommCoach** | `["core"]` | `[]` (keine Eskalation erlaubt) |
+| **Chatbot** | `["core"]` | `[]` |
+
+**Automatische Toolbox-Verfuegbarkeit:** Welche Toolboxes in `availableToolboxes` erscheinen, haengt von den aktiven User-Connections ab. Keine Outlook-Verbindung -> `"email"` erscheint nicht.
+
+### Sub-Agents (Feature Data Agents)
+
+```
+User Prompt im Workspace
+ |
+ v
+Main Agent (Toolboxes: core, ai, datasources, ...)
+ |
+ +-- Tool: queryFeatureInstance("trustee", instanceId, question)
+ | |
+ | v
+ | Sub-Agent (Feature Data Agent)
+ | Eigene ToolRegistry: browseTable, queryTable
+ | Eigenes System-Prompt mit Schema-Wissen
+ | Limitiert: maxRounds=5, maxCost=0.10 CHF
+ | |
+ | v
+ | Antwort zurueck an Main Agent
+ |
+ +-- Tool: readFile(fileId) -- Core Tool, direkt
+ +-- Tool: outlook_readEmails(connectionRef) -- Action Tool, direkt
+```
+
+**Faustregel:** Toolbox wenn die Tools generisch sind. Sub-Agent wenn Feature-spezifisches Kontext-/Schema-Wissen noetig ist.
+
+### State Machine: AI Agent Run (mit Toolbox-Eskalation)
+
+```
+ +----------+
+ | IDLE |
+ +----+-----+
+ | runAgent(prompt, initialToolboxes, availableToolboxes)
+ v
+ +----------+
+ +---->| THINKING |<-------------------------------+
+ | +----+-----+ |
+ | | |
+ | +-- LLM Response (Text only) ----------+---> COMPLETED
+ | | |
+ | +-- LLM Response (ToolCalls) |
+ | | |
+ | v |
+ | +--------------------+ |
+ | | EXECUTING_TOOLS | |
+ | +----+---------------+ |
+ | | |
+ | +-- requestToolbox(id) --+ |
+ | | v |
+ | | +---------------------+ |
+ | | | TOOLBOX_ESCALATION | |
+ | | | Toolbox aktiviert | |
+ | | | Tools erweitert | |
+ | | +----------+----------+ |
+ | | | |
+ | +-- Sub-Agent call --+ | |
+ | | v | |
+ | | +-------------+| |
+ | | |SUB_AGENT_CALL|| |
+ | | +------+------+| |
+ | | | | |
+ | +-- Regular tools-+-------+-------------+
+ | (results -> next round)
+ |
+ | maxRounds / maxCost reached
+ v
+ +----------+
+ | COMPLETED | (oder FAILED / CANCELLED)
+ +----------+
+```
+
+---
+
+## Unified Workflow Datenmodell (Ziel)
+
+### Entitaeten
+
+```python
+class WorkflowStatus(str, Enum):
+ DRAFT = "draft"
+ PUBLISHED = "published"
+ ARCHIVED = "archived"
+
+class Workflow(PowerOnModel):
+ id: str
+ mandateId: str
+ featureInstanceId: str
+ label: str
+ description: Optional[str]
+ tags: List[str] = []
+ isTemplate: bool = False
+ templateSourceId: Optional[str] # geklont von diesem Template
+ currentVersionId: Optional[str] # aktive/published Version
+ active: bool = True # Scheduler-enabled
+ eventId: Optional[str] # APScheduler Job-ID (v1-Pattern)
+
+class WorkflowVersion(PowerOnModel):
+ id: str
+ workflowId: str # FK -> Workflow
+ versionNumber: int # auto-increment
+ status: WorkflowStatus # draft | published | archived
+ graph: Dict[str, Any] # { nodes: [...], connections: [...] }
+ invocations: List[Dict[str, Any]] # Entry-Points (manual, schedule, webhook, form)
+ publishedAt: Optional[float]
+ publishedBy: Optional[str]
+```
+
+### State Machine: WorkflowVersion.status
+
+```
+ +-------+
+ create --->| DRAFT |<--- edit (graph mutation via API oder AI Tools)
+ +---+---+
+ | publish
+ v
+ +-----------+
+ unpublish->| PUBLISHED |
+ (->DRAFT) +-----+-----+
+ | archive
+ v
+ +-----------+
+ | ARCHIVED |--> re-publish (-> PUBLISHED)
+ +-----------+
+
+Invariante: Pro Workflow maximal 1 Version mit status=PUBLISHED.
+ Scheduler nutzt immer die PUBLISHED Version.
+```
+
+### Run-Modell
+
+```python
+class RunStatus(str, Enum):
+ PENDING = "pending"
+ RUNNING = "running"
+ PAUSED = "paused"
+ COMPLETED = "completed"
+ FAILED = "failed"
+ CANCELLED = "cancelled"
+
+class WorkflowRun(PowerOnModel):
+ id: str
+ workflowId: str # FK -> Workflow
+ versionId: str # FK -> WorkflowVersion
+ status: RunStatus
+ trigger: Dict[str, Any] # { type: "manual"|"schedule"|"webhook"|..., metadata }
+ startedAt: float
+ completedAt: Optional[float]
+ nodeOutputs: Dict[str, Any] # Outputs pro Node-ID
+ currentNodeId: Optional[str] # Paused bei diesem Node
+ resumeContext: Dict[str, Any] # Kontext fuer Resume
+ error: Optional[str]
+ costTokens: Optional[int] # Aggregierte Token-Kosten
+ costCredits: Optional[float] # Aggregierte Credit-Kosten
+```
+
+### State Machine: WorkflowRun.status
+
+```
+ +---------+
+ executeGraph-->| RUNNING |
+ +----+----+
+ |
+ +----------------+----------------+
+ | | |
+ v v v
++--------+ +----------+ +--------+
+| PAUSED | |COMPLETED | | FAILED |
++---+----+ +----------+ +--------+
+ |
+ | resume(taskResult | emailReceived)
+ v
++---------+
+| RUNNING |---> COMPLETED | FAILED | PAUSED | CANCELLED
++---------+
+
+Pause-Gruende:
+ - input.* Node -> HumanTask erstellt
+ - email.checkEmail -> EmailWait (Background Poller)
+Cancel:
+ - Manuell durch User
+ - Timeout bei HumanTask (expiresAt)
+```
+
+### RunStepLog und HumanTask
+
+```python
+class StepStatus(str, Enum):
+ RUNNING = "running"
+ COMPLETED = "completed"
+ FAILED = "failed"
+ SKIPPED = "skipped"
+
+class RunStepLog(PowerOnModel):
+ id: str
+ runId: str # FK -> WorkflowRun
+ nodeId: str # Node-ID im Graph
+ nodeType: str # z.B. "ai.prompt", "email.checkEmail"
+ status: StepStatus
+ inputSnapshot: Dict[str, Any] # Parameters + Upstream-Daten bei Execution
+ output: Optional[Dict[str, Any]]
+ error: Optional[str]
+ startedAt: float
+ completedAt: Optional[float]
+ durationMs: Optional[int]
+ tokensUsed: Optional[int]
+ retryCount: int = 0
+
+class TaskStatus(str, Enum):
+ PENDING = "pending"
+ COMPLETED = "completed"
+ CANCELLED = "cancelled"
+ EXPIRED = "expired"
+
+class HumanTask(PowerOnModel):
+ id: str
+ runId: str # FK -> WorkflowRun
+ workflowId: str # FK -> Workflow (Convenience-FK)
+ nodeId: str
+ nodeType: str # input.approval, input.form, etc.
+ config: Dict[str, Any] # Node-Parameter (Formular-Felder, Approval-Text)
+ assigneeId: str
+ status: TaskStatus
+ result: Optional[Dict[str, Any]]
+ expiresAt: Optional[float]
+```
+
+### ER-Diagramm
+
+```
++------------------+ +----------------------+
+| Workflow | 1---N | WorkflowVersion |
+|------------------| |----------------------|
+| id | | id |
+| mandateId | | workflowId (FK) |
+| featureInstanceId| | versionNumber |
+| label | | status |
+| description | | graph {} |
+| tags [] | | invocations [] |
+| isTemplate | | publishedAt |
+| currentVersionId +---1-->| publishedBy |
+| active | +----------+-----------+
+| eventId | | 1:N
++------------------+ +----------v-----------+
+ | WorkflowRun |
+ |----------------------|
+ | id |
+ | workflowId (FK) |
+ | versionId (FK) |
+ | status |
+ | trigger {} |
+ | nodeOutputs {} |
+ | currentNodeId |
+ | resumeContext {} |
+ | costTokens |
+ | costCredits |
+ +----------+-----------+
+ 1:N | | 1:N
+ +-------------+ +-----------+
+ v v
+ +------------------+ +------------------+
+ | RunStepLog | | HumanTask |
+ |------------------| |------------------|
+ | runId (FK) | | runId (FK) |
+ | nodeId | | workflowId (FK) |
+ | nodeType | | nodeId |
+ | status | | config {} |
+ | inputSnapshot {} | | assigneeId |
+ | output {} | | status |
+ | durationMs | | result {} |
+ | tokensUsed | | expiresAt |
+ | retryCount | +------------------+
+ +------------------+
+```
+
+---
+
+## Graph-Struktur und Node-Definitionen
+
+### Graph-Schema (innerhalb WorkflowVersion.graph)
+
+```json
+{
+ "nodes": [
+ {
+ "id": "node-uuid",
+ "type": "trigger.schedule",
+ "position": { "x": 100, "y": 200 },
+ "parameters": { "cronExpression": "0 8 * * 1-5" }
+ },
+ {
+ "id": "node-uuid-2",
+ "type": "ai.prompt",
+ "position": { "x": 300, "y": 200 },
+ "parameters": { "prompt": "Analysiere die Emails..." }
+ }
+ ],
+ "connections": [
+ { "source": "node-uuid", "target": "node-uuid-2", "sourceOutput": 0, "targetInput": 0 }
+ ]
+}
+```
+
+### Node-Type zu Method/Action Mapping
+
+| Node Type | `_method` | `_action` | `_paramMap` |
+|-----------|-----------|-----------|-------------|
+| `trigger.manual` | -- | -- | -- (TriggerExecutor) |
+| `trigger.schedule` | -- | -- | -- (TriggerExecutor) |
+| `trigger.form` | -- | -- | -- (TriggerExecutor) |
+| `flow.ifElse` | -- | -- | -- (FlowExecutor) |
+| `flow.switch` | -- | -- | -- (FlowExecutor) |
+| `flow.loop` | -- | -- | -- (FlowExecutor) |
+| `input.*` | -- | -- | -- (InputExecutor -> HumanTask) |
+| `ai.prompt` | `ai` | `process` | `prompt->aiPrompt` |
+| `ai.webResearch` | `ai` | `webResearch` | `query->prompt` |
+| `ai.summarizeDocument` | `ai` | `summarizeDocument` | -- |
+| `ai.translateDocument` | `ai` | `translateDocument` | `targetLanguage->targetLanguage` |
+| `ai.generateDocument` | `ai` | `generateDocument` | `prompt->prompt` |
+| `email.checkEmail` | `outlook` | `readEmails` | `connectionId->connectionReference` |
+| `email.searchEmail` | `outlook` | `searchEmails` | `connectionId->connectionReference` |
+| `email.draftEmail` | `outlook` | `composeAndDraft...` | `connectionId->connectionReference` |
+| `sharepoint.*` | `sharepoint` | entsprechend | `connectionId->connectionReference` |
+| `clickup.*` | `clickup` | entsprechend | `connectionId->connectionReference` |
+| `file.create` | `file` | `create` | `template->template` |
+
+### Execution-Routing
+
+```
+executeGraph(graph, services, ...)
+ |
+ +-- parseGraph() -> nodes, connections, nodeIds
+ +-- validateGraph() -> Konsistenzpruefung
+ +-- topoSort(nodes, connectionMap) -> geordnete Node-Liste
+ |
+ +-- Pro Node:
+ |
+ +-- nodeType.startsWith("trigger.") -> TriggerExecutor
+ +-- nodeType.startsWith("flow.") -> FlowExecutor
+ | ifElse: evaluiert Bedingung, setzt active path
+ | switch: evaluiert Match, setzt active path
+ | loop: iteriert mit _loopState
+ +-- nodeType.startsWith("input.") -> InputExecutor
+ | -> erstellt HumanTask, setzt Run auf PAUSED
+ +-- alles andere -> ActionNodeExecutor
+ +-- _getNodeDefinition(nodeType) -> _method, _action, _paramMap
+ +-- Parameter-Mapping (Node-Params -> Action-Params)
+ +-- Upstream-Daten mergen (documents von vorherigen Nodes)
+ +-- ActionExecutor.executeAction(method, action, params)
+```
+
+---
+
+## Konsolidierter Scheduler (Ziel)
+
+```python
+class WorkflowScheduler:
+ def start(self, eventUser):
+ eventManager.start()
+ self._syncScheduledWorkflows(eventUser)
+ self._registerDelayedSync(eventUser, delaySeconds=5)
+ callbackRegistry.register("workflow.changed",
+ lambda _: self._syncScheduledWorkflows(eventUser))
+
+ def _syncScheduledWorkflows(self, eventUser):
+ """Inkrementeller Sync (v1-Pattern)."""
+ workflows = self._getAllSchedulableWorkflows()
+ for wf in workflows:
+ jobId = f"workflow.{wf.id}"
+ if wf.active and wf.currentVersionId:
+ version = self._getPublishedVersion(wf.currentVersionId)
+ cronKwargs = self._extractSchedule(version)
+ if cronKwargs:
+ handler = self._createHandler(wf, version, eventUser)
+ eventManager.registerCron(
+ jobId=jobId, func=handler,
+ cronKwargs=cronKwargs,
+ replaceExisting=True # v1-Pattern: atomic replace
+ )
+ if wf.eventId != jobId:
+ self._updateEventId(wf.id, jobId)
+ else:
+ self._removeJob(jobId)
+ if wf.eventId:
+ self._updateEventId(wf.id, None)
+
+ def _createHandler(self, wf, version, eventUser):
+ """Handler: Reload + Active-Check + Execute (v1-Pattern)."""
+ async def _handler():
+ current = self._getWorkflow(wf.id)
+ if not current or not current.active:
+ return
+ services = self._buildServices(current, eventUser)
+ result = await executeGraph(graph=version.graph, services=services, ...)
+ self._appendExecutionLog(current.id, result) # capped audit trail
+ return self._wrapAsync(_handler) # Thread-Bridge (v2-Pattern)
+```
+
+---
+
+## Use Cases
+
+### UC-1: Workflow im Workspace erstellen/bearbeiten
+
+User beschreibt im Workspace-Chat einen gewuenschten Workflow -> Agent nutzt Toolbox `"workflow"` -> generiert Graph -> speichert als Draft -> User oeffnet im Graphical Editor.
+
+Voraussetzung: Die `"workflow"` Toolbox muss im Workspace aktivierbar sein. Die Tools validieren jeden Graph-Mutationsschritt:
+- `addNode(type, parameters)` -> prueft: existiert der Node-Typ? Sind die Parameter valide?
+- `connectNodes(source, target)` -> prueft: sind die I/O-Typen kompatibel? Keine Zyklen?
+- `validateGraph()` -> vollstaendige Validierung inkl. Trigger-Pruefung
+
+### UC-2: AI Chat im Graphical Editor
+
+Sidebar mit Chat. Agent nutzt Toolbox `"workflow"` mit System-Prompt, der den aktuellen Graph kennt. Er kann Nodes hinzufuegen, entfernen, umkonfigurieren und den Graph erklaeren. Gleicher `serviceAgent.runAgent()` Pfad wie Workspace, aber mit `toolboxes: ["core", "workflow"]` und Graph als Kontext im System-Prompt.
+
+### UC-3: Workflow testen mit Tracing Log
+
+User klickt "Test Run" -> Graph wird ausgefuehrt -> jeder Node wird visuell hervorgehoben (Status-Farben) -> Tracing Log zeigt pro Node: Input, Output, Dauer, Fehler. Bei Fehlern: User bespricht den Fehler im AI Chat -> Agent liest RunStepLog und schlaegt Korrekturen vor.
+
+**Technisch:** `RunStepLog` pro Node mit Timestamps, Input-Snapshot, Duration, Error-Stack. SSE/WebSocket fuer Live-Updates. Run-Modes: "Full Run" und "Step-by-Step" (Pause nach jedem Node).
+
+### UC-4: Workflow automatisieren (Scheduler)
+
+User konfiguriert Schedule im Editor (via trigger.schedule Node oder Invocation) -> konsolidierter Scheduler registriert Cron-Job -> Run-History wird persistiert -> bei Fehlern Notifications.
+
+---
+
+## Backend Code-Struktur (Ziel)
+
+```
+gateway/modules/
+|
++-- features/
+| +-- graphicalEditor/ <-- NEUES FEATURE (ersetzt automation2)
+| | +-- mainGraphicalEditor.py
+| | | FEATURE_CODE = "graphicalEditor"
+| | | UI_OBJECTS = ["ui.feature.graphicalEditor.editor",
+| | | "ui.feature.graphicalEditor.workflows",
+| | | "ui.feature.graphicalEditor.tasks"]
+| | | RESOURCE_OBJECTS = ["resource.feature.graphicalEditor.execute",
+| | | "resource.feature.graphicalEditor.schedule"]
+| | | TEMPLATE_ROLES = ["graphicalEditor-admin",
+| | | "graphicalEditor-user",
+| | | "graphicalEditor-viewer"]
+| | +-- routeFeatureGraphicalEditor.py (prefix: /api/workflows)
+| | +-- interfaceFeatureGraphicalEditor.py (DB: poweron_workflows)
+| | +-- datamodelFeatureGraphicalEditor.py
+| | +-- nodeDefinitions/
+| | triggers.py, flow.py, input.py, ai.py, email.py, sharepoint.py, ...
+| |
+| +-- workspace/ <-- BLEIBT (AI Chat mit UDB)
+| +-- automation/ <-- BLEIBT bis Abloesung
+| +-- commcoach/ <-- BLEIBT
+| +-- chatbot/ <-- BLEIBT
+| +-- trustee/ <-- BLEIBT
+|
++-- serviceCenter/services/
+| +-- serviceAgent/
+| | +-- mainServiceAgent.py <-- Core Tools + Toolbox-Tagging
+| | +-- agentLoop.py <-- Toolbox-Filtering statt toolSet
+| | +-- toolRegistry.py <-- BLEIBT
+| | +-- toolboxRegistry.py <-- NEU: Toolbox-Verwaltung
+| | +-- actionToolAdapter.py <-- BLEIBT (+ Toolbox-Zuordnung)
+| | +-- featureDataAgent.py <-- BLEIBT (Sub-Agent Pattern)
+| | +-- datamodelAgent.py <-- toolboxes: List[str] statt toolSet
+|
++-- workflows/
+| +-- methods/ <-- BLEIBT (Unified Action Library)
+| +-- processing/ <-- BLEIBT (ActionExecutor, methodDiscovery)
+| +-- automation2/ <-- Graph Engine BLEIBT
+| +-- scheduler/ <-- NEU (konsolidierter Scheduler)
+| | +-- mainScheduler.py
+| +-- automation/ <-- BLEIBT bis Abloesung
+| +-- workflowManager.py <-- BLEIBT (fuer Workspace Dynamic Mode)
+```
+
+---
+
+## Frontend Code-Struktur (Ziel)
+
+```
+frontend_nyla/src/
+|
++-- components/ <-- SHARED COMPONENTS
+| +-- ChatBar/ <-- NEU (extrahiert aus WorkspaceInput)
+| | ChatBar.tsx Props: onSend, onStop, onVoice,
+| | fileAttachments, showProviderSelector, ...
+| +-- ChatStream/ <-- NEU (extrahiert aus workspace/ChatStream)
+| | ChatStream.tsx SSE-driven message stream, wiederverwendbar
+| +-- UnifiedDataBar/ <-- BLEIBT
+| +-- FlowEditor/ <-- RENAMED von Automation2FlowEditor
+| +-- editor/
+| FlowEditor.tsx + AI Chat Panel
+| FlowCanvas.tsx + Visual Run Tracing
+| EditorChatPanel.tsx <-- NEU
+|
++-- pages/views/
+| +-- workspace/
+| | WorkspacePage.tsx Nutzt ChatBar, ChatStream, UDB
+| +-- graphicalEditor/ <-- RENAMED von automation2
+| GraphicalEditorPage.tsx FlowEditor + UDB + ChatPanel
+| WorkflowsListPage.tsx
+| TasksPage.tsx
+|
++-- api/
+ workflowApi.ts <-- Konsolidiert (ersetzt automation + automation2 API)
+```
+
+---
+
+## Empfehlungen und offene Punkte
+
+### Starke Konzepte (umsetzen)
+
+| Konzept | Bewertung |
+|---------|-----------|
+| **Toolbox-Architektur** | Skaliert von 50 auf 100+ Tools ohne LLM-Ueberlastung. Klare Isolierung. |
+| **Sub-Agents pro Feature** | Bewaehrtes Pattern (Trustee), erweiterbar. Haelt Main Agent schlank. |
+| **Validierungs-Layer fuer Workflow-Modellierung** | Graph-Mutation nur ueber validierte Tools. |
+| **v1-Scheduling-Patterns in v2 uebernehmen** | Inkrementeller Sync ist robuster als Full-Wipe. |
+| **State Machines als Grundlage** | Klare Zustaende, klare Uebergaenge. Erweiterbar. |
+
+### Was User brauchen
+
+| User Need | Feature | Prioritaet |
+|-----------|---------|-----------|
+| **Schneller Einstieg** | Workflow-Templates fuer haeufige Use Cases | Hoch |
+| **Vertrauen** | Tracing Log + Test Runner | Hoch |
+| **Effizienz** | AI-gestuetzte Workflow-Erstellung per Chat | Hoch |
+| **Fehlertoleranz** | Retry-Policies, Pause/Resume, klare Fehlermeldungen | Hoch |
+| **Kontext** | UDB im Editor -- Zugriff auf Files/Sources bei Konfiguration | Hoch |
+| **Zusammenarbeit** | Workflows teilen im Mandant, Rollen-basierter Zugriff | Mittel |
+| **Monitoring** | Dashboard: laufende Automationen, Fehlerrate, Kosten | Mittel |
+| **Flexibilitaet** | Custom Script Nodes (Python-Sandbox), AI Decision Nodes | Mittel |
+| **Mobile** | Notifications + Approval-Tasks per Mobile | Phase 2 |
+
+### Offene Architektur-Fragen
+
+| Frage | Empfehlung |
+|-------|------------|
+| **Toolbox-Selektion: statisch oder dynamisch?** | Hybrid: Basis pro Feature statisch, Connection-basierte dynamisch. |
+| **Sub-Agent Tiefe: verschachtelt?** | Maximal 1 Level tief. Kein Sub-Sub-Agent. |
+| **Graph-Execution und WorkflowManager zusammenfuehren?** | Nein, getrennt. `executeGraph` fuer Editor, `WorkflowManager` fuer Workspace Dynamic Mode. |
+| **Feature-Code: `automation2` -> `graphicalEditor`?** | Ja, Rename in Phase 1. |
+
+---
+
+## Phasen-Plan
+
+### Phase 1: Foundation
+- Unified Workflow Datenmodell (Workflow + WorkflowVersion + WorkflowRun + RunStepLog + HumanTask)
+- Toolbox-Registry implementieren (Abloesung `_CORE_ONLY_TOOLS`)
+- ChatBar-Komponente extrahieren
+- Feature Rename: `automation2` -> `graphicalEditor`
+- Scheduler konsolidieren (v1 Patterns in v2 Engine)
+
+### Phase 2: Editor Enhancement
+- AI Chat Sidebar im Editor (Toolbox `"workflow"` + Graph-Manipulation-Tools)
+- UDB Integration im Editor
+- WorkflowVersion Lifecycle (Draft/Published)
+- Enhanced RunStepLog + Visual Tracing
+
+### Phase 3: Productization
+- Workflow Templates / Marketplace
+- Monitoring Dashboard
+- Retry Policies pro Node
+- Notifications bei Scheduler-Fehlern
+- Automation v1 Feature entfernen (wird nicht mehr benoetigt)
+
+### Phase 4: Advanced
+- AI Decision Node (`ai.decide`)
+- Custom Script Node (Python Sandbox)
+- Dynamische Toolbox-Aktivierung basierend auf Connections
+- Sub-Agent Pattern fuer weitere Features
+
+---
+
+## Betroffene Module
+
+- Gateway: `features/automation/`, `features/automation2/`, `workflows/`, `serviceCenter/services/serviceAgent/`
+- Frontend: `components/Automation2FlowEditor/`, `pages/views/automation2/`
+- DB-Migration: ja (neues Workflow/Version/Run Schema)
+- Andere: Scheduler (APScheduler/eventManager), RBAC Template-Rollen
+
+## Entscheidungen
+
+| Datum | Entscheidung | Begruendung |
+|-------|-------------|------------|
+| 2026-04-05 | v1-Scheduler-Pattern in v2 uebernehmen | Robuster (inkrementell, Job-Handle, Reload+active-Check) |
+| 2026-04-05 | Toolbox-Konzept statt flache Tool-Listen | Skalierbarkeit bei 50-100+ Tools |
+| 2026-04-05 | Keine v1-Datenmigration | v1 nicht produktiv |
+| 2026-04-05 | Feature-Code `automation2` -> `graphicalEditor` | Klarer Name fuer User und Entwickler |
+| 2026-04-05 | Graph-Execution und WorkflowManager getrennt lassen | Verschiedene Orchestrierungsmodelle |
+| 2026-04-05 | Sub-Agent maximal 1 Level tief | Komplexitaet kontrollierbar |
+
+## Umsetzungs-Checkliste
+
+- [ ] Vereinheitlichtes Workflow/WorkflowVersion/WorkflowRun Schema
+- [ ] v1-Scheduler-Pattern in v2 Engine
+- [ ] Toolbox Registry + requestToolbox Meta-Tool
+- [ ] Feature-Code Rename `automation2` -> `graphicalEditor`
+- [ ] Frontend: ChatBar + ChatStream extrahieren
+- [ ] Frontend: UDB + Chat im Graph-Editor
+- [ ] RBAC Template-Rollen konsolidieren
+- [ ] RunStepLog + Visual Tracing
+- [ ] Neutralisierung: keine Aenderung (nutzt gleiche Services)
+- [ ] Billing-Impact: pruefen (Automation-Runs zaehlen?)
+
+## Akzeptanzkriterien
+
+| # | Kriterium (Given-When-Then) | Prio |
+|---|---------------------------|------|
+| 1 | Given ein Automation2-Workflow mit Schedule, When der Scheduler neu startet, Then werden nur geaenderte Jobs aktualisiert (inkrementell wie v1) | must |
+| 2 | Given ein Agent mit 50+ Tools, When der Agent startet, Then sind nur core-Toolboxes geladen und Spezial-Toolboxes werden on-demand nachgeladen | should |
+| 3 | Given ein Workflow-Run, When ein Human-Task-Node erreicht wird, Then pausiert der Run und wartet auf User-Input | must |
+| 4 | Given ein Workflow-Graph im Editor, When der User im AI-Chat "Fuege einen Email-Check hinzu" tippt, Then fuegt der Agent einen email.checkEmail Node ein und verbindet ihn korrekt | should |
+| 5 | Given ein Workflow mit Published Version, When der User den Graph editiert, Then wird ein neuer Draft erstellt und die Published Version bleibt aktiv | must |
+
+## Testplan
+
+| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
+|----|----|-----|--------------|-----------|--------|
+| T1 | 1 | integration | ja | gateway/tests/test_automation2_scheduler.py | pending |
+| T2 | 2 | integration | ja | gateway/tests/test_agent_toolbox.py | pending |
+| T3 | 3 | api | ja | gateway/tests/test_workflow_pause_resume.py | pending |
+| T4 | 4 | integration | ja | gateway/tests/test_editor_chat_graph.py | pending |
+| T5 | 5 | unit | ja | gateway/tests/test_workflow_versioning.py | pending |
+
+## Glossar
+
+| Begriff | Definition |
+|---------|-----------|
+| **Toolbox** | Thematisch gebuendelte Gruppe von AI-Tools, kontextabhaengig aktiviert |
+| **Sub-Agent** | Spezialisierter Mini-Agent mit eigener Tool-Registry, aufgerufen vom Main Agent |
+| **Workflow** | Persistiertes Automatisierungsmodell mit Graph-Struktur |
+| **WorkflowVersion** | Immutable Snapshot eines Workflow-Graphen (draft, published, archived) |
+| **WorkflowRun** | Einzelne Ausfuehrung einer WorkflowVersion |
+| **RunStepLog** | Detaillierter Log pro Node-Execution innerhalb eines Runs |
+| **HumanTask** | Aufgabe fuer menschliche Eingabe, erstellt bei Pause eines Runs |
+| **Node** | Ausfuehrungsschritt im Graph (Trigger, Action, Flow-Control, Input/Human) |
+| **Method** | Integrations-Kategorie (z.B. methodOutlook) mit mehreren Actions |
+| **Action** | Spezifische Operation innerhalb einer Method (z.B. outlook.readEmails) |
+| **Invocation** | Entry-Point fuer einen Workflow (Manual, Schedule, Webhook, Form, Event) |
+| **UDB** | Unified Data Bar -- Multi-Tab-Panel fuer Chats, Files und Sources |
+| **ChatBar** | Wiederverwendbare Prompt-Input-Komponente |
+| **Feature Container** | Einheitliches Verzeichnis-Pattern fuer ein Feature |
+
+## Links
+
+- Detail-Spec (Business): z-archive/b-reference/automation-business-spec.md
+- Detail-Spec (Datenmodell): z-archive/b-reference/automation-data-model.md
+- Referenz (Ist-Zusammenfassung): b-reference/gateway/automation.md
+
+## Abschluss
+
+- [ ] b-reference/gateway/automation.md aktualisiert
+- [ ] TOPICS.md aktualisiert
+- [ ] Dieses Dokument -> z-archive/ verschoben
diff --git a/d-guides/coding-conventions.md b/d-guides/coding-conventions.md
index 2782287..585d2f2 100644
--- a/d-guides/coding-conventions.md
+++ b/d-guides/coding-conventions.md
@@ -5,16 +5,61 @@
## Naming
-- Alle internen Funktionen beginnen mit `_` Prefix
-- camelCase für Variablen und Funktionsnamen (kein snake_case)
+- Alle internen Funktionen beginnen mit `_` Prefix (nicht exportierbar)
+- **camelCase** fuer Variablen und Funktionsnamen (kein snake_case)
+- **PascalCase** fuer Klassen und Pydantic-Models
+- Dateien: `camelCase` fuer Module (z.B. `mainServiceAi.py`, `routeBilling.py`)
-## Frontend-Regeln
-
-- Keine Browser-Dialoge (alert/confirm/prompt) -- stattdessen `useConfirm()` und `usePrompt()` Hooks
-- CSS Modules für Komponenten-Styles
-
-## Backend-Regeln
+## Frontend (React/TypeScript)
+- Keine Browser-Dialoge (`alert`, `confirm`, `prompt`) -- stattdessen `useConfirm()` / `usePrompt()` Hooks
+- CSS Modules fuer Styling
+- Hooks-Pattern fuer State und API-Zugriffe (`useApiRequest`, `useBilling`, etc.)
- Fehler propagieren -- keine stillen Fallbacks bei kritischen Pfaden
-- Pydantic-Models als einzige Quelle für UI-Feld-Definitionen
-- `PowerOnModel` als Basis mit `sysCreatedAt`, `sysCreatedBy`, `sysModifiedAt`, `sysModifiedBy`
+
+## Backend (FastAPI/Python)
+
+- **Pydantic-Models** als einzige Quelle fuer UI-Feld-Definitionen
+- **`PowerOnModel`** als Basis mit System-Audit-Feldern (`sysCreatedAt`, `sysCreatedBy`, `sysModifiedAt`, `sysModifiedBy`)
+- Fehler propagieren -- Exceptions explizit werfen, nicht schlucken
+- Config ueber `APP_CONFIG` (aus `modules/shared/configuration.py`)
+
+## Projektstruktur Gateway
+
+```
+gateway/
+ app.py # FastAPI-App, Middleware, Startup
+ config.ini # Statische Konfiguration
+ modules/
+ auth/ # JWT, OAuth, CSRF, Authentication
+ datamodels/ # Pydantic-Models (zentrale Quelle)
+ features/ # Feature-Module (workspace, automation, ...)
+ /
+ main.py # FEATURE_CODE, Registrierung
+ routeFeature.py # HTTP-Endpunkte
+ interfaceFeature.py # DB-Interface
+ datamodelFeature.py # Feature-spezifische Models
+ interfaces/ # DB-Interfaces (CRUD, Queries)
+ routes/ # Core-Routes (billing, admin, GDPR, ...)
+ security/ # RBAC-Engine
+ serviceCenter/
+ core/ # serviceSecurity, serviceUtils, serviceStreaming
+ services/ # serviceAi, serviceChat, serviceAgent, ...
+ registry.py # Service-Registrierung und Dependencies
+ shared/ # configuration.py, Utilities
+ system/ # registry.py (Feature-Discovery)
+ workflows/
+ methods/ # Unified Action Library
+ processing/ # WorkflowProcessor, Modes
+ automation/ # v1 Runtime
+ automation2/ # v2 Engine
+ connectors/ # Externe Systeme (DB, SharePoint, Jira, ...)
+ aicore/ # AI-Provider-Plugins, Model-Selector
+```
+
+## Anti-Patterns
+
+- Keine impliziten Type-Conversions in API-Responses
+- Keine DB-Queries in Route-Handlern (immer ueber Interfaces)
+- Kein direkter `os.environ`-Zugriff -- immer `APP_CONFIG`
+- Keine hartkodierten Secrets -- verschluesselt in Env-Dateien
diff --git a/d-guides/deployment/Instanzenübersicht.drawio b/d-guides/deployment/instanzenuebersicht.drawio
similarity index 100%
rename from d-guides/deployment/Instanzenübersicht.drawio
rename to d-guides/deployment/instanzenuebersicht.drawio
diff --git a/d-guides/deployment/Instanzenübersicht.svg b/d-guides/deployment/instanzenuebersicht.svg
similarity index 100%
rename from d-guides/deployment/Instanzenübersicht.svg
rename to d-guides/deployment/instanzenuebersicht.svg
diff --git a/d-guides/deployment/poweron_sec.kdbx b/d-guides/deployment/poweron-sec.kdbx
similarity index 100%
rename from d-guides/deployment/poweron_sec.kdbx
rename to d-guides/deployment/poweron-sec.kdbx
diff --git a/d-guides/dev-setup.md b/d-guides/dev-setup.md
index 139a1c3..2397294 100644
--- a/d-guides/dev-setup.md
+++ b/d-guides/dev-setup.md
@@ -1,25 +1,85 @@
-
+
# Dev-Setup
## Voraussetzungen
-- Python (Anaconda/Miniconda)
-- Node.js
-- PostgreSQL mit pgvector
+- **Python 3.11** (CI-Standard; Minimum 3.10)
+- **Node.js** (aktuelles LTS empfohlen)
+- **PostgreSQL** mit **pgvector**-Extension
+- **Conda** oder **venv** fuer Python-Umgebung
## Gateway starten
```bash
-conda activate
cd gateway/
+# Python-Umgebung aktivieren (Conda oder venv)
+conda activate
+# oder: python -m venv .venv && .\.venv\Scripts\Activate.ps1
+
+pip install -r requirements.txt
+
+# Config vorbereiten:
+# 1. config.ini muss im gateway/ Verzeichnis liegen (statische Settings)
+# 2. .env Datei aus env_dev.env kopieren/symlinken:
+# copy env_dev.env .env
+# 3. APP_KEY_SYSVAR in config.ini zeigt auf Master-Key (OS-Variable oder Dateipfad)
+
uvicorn app:app --host 0.0.0.0 --port 8000
```
+### Konfigurationsdateien
+
+| Datei | Zweck |
+|-------|-------|
+| `gateway/config.ini` | Statische Settings (Auth-Defaults, Upload-Limits, Operator-Text) |
+| `gateway/.env` | Runtime-Env (DB, API-Keys, Secrets) -- wird aus `env_dev.env` kopiert |
+| `gateway/env_dev.env` | Dev-Umgebung Template (verschluesselte Secrets mit `DEV_ENC:` Prefix) |
+| `gateway/env_int.env` | Integration-Umgebung |
+| `gateway/env_prod.env` | Produktion |
+
+### Wichtige Env-Variablen (Auszug)
+
+| Variable | Beschreibung |
+|----------|-------------|
+| `DB_HOST`, `DB_USER`, `DB_PASSWORD_SECRET` | PostgreSQL-Verbindung |
+| `APP_KEY_SYSVAR` | Master-Key fuer Secrets-Entschluesselung |
+| `APP_API_URL` | API-URL (bestimmt Cookie-Secure-Flag) |
+| `APP_ALLOWED_ORIGINS` | CORS Origins (inkl. `http://localhost:5176`) |
+| `Service_GOOGLE_AUTH_*` | Google OAuth Auth-App |
+| `Service_GOOGLE_DATA_*` | Google OAuth Data-App |
+
## Frontend Nyla starten
```bash
cd frontend_nyla/
-npx vite --port 8080 --mode dev
+npm install
+npm run dev
+# oder: npx vite --port 5176 --mode dev
```
+
+Frontend laeuft auf **http://localhost:5176** und erwartet Gateway auf **http://localhost:8000**.
+
+### Frontend-Konfiguration
+
+| Datei | Zweck |
+|-------|-------|
+| `frontend_nyla/config/.env.dev` | Dev-Mode Env (VITE_API_BASE_URL etc.) |
+| `frontend_nyla/config/.env.int` | Integration |
+| `frontend_nyla/config/.env.prod` | Produktion |
+
+## Secrets-Verwaltung
+
+Env-Dateien enthalten verschluesselte Werte (`DEV_ENC:`, `INT_ENC:`, `PROD_ENC:`).
+Zur Entschluesselung wird der Master-Key ueber `APP_KEY_SYSVAR` geladen.
+
+Details: -> `d-guides/encrypt-env-secrets.md`
+
+## Weiterführende Guides
+
+- Secrets verschluesseln: `d-guides/encrypt-env-secrets.md`
+- Google OAuth einrichten: `d-guides/google-oauth-setup.md`
+- Cookie/JWT-Migration: `d-guides/security-migration-guide.md`
+- Coding-Konventionen: `d-guides/coding-conventions.md`
+- Testing: `d-guides/testing-strategy.md`
diff --git a/d-guides/encrypt-env-secrets.md b/d-guides/encrypt-env-secrets.md
index 5be3eef..ee5ccb2 100644
--- a/d-guides/encrypt-env-secrets.md
+++ b/d-guides/encrypt-env-secrets.md
@@ -1,6 +1,6 @@
### Admin-Leitfaden: *_SECRET-Werte in Env-Dateien verschlüsseln
-Diese Anleitung beschreibt, wie das PowerOn-Gateway-Tool `tool_security_encrypt_all_env_files.py` alle unverschlüsselten `*_SECRET`-Variablen in `env_dev.env`, `env_int.env` und `env_prod.env` verschlüsselt.
+Diese Anleitung beschreibt, wie das PowerOn-Gateway-Tool `scripts/script_security_encrypt_all_env_files.py` alle unverschlüsselten `*_SECRET`-Variablen in `env_dev.env`, `env_int.env` und `env_prod.env` verschlüsselt.
---
@@ -17,7 +17,7 @@ Das Tool kann in jedem Repository eingesetzt werden, sofern die untenstehenden V
- Die zu verarbeitenden Env-Dateien: `env_dev.env`, `env_int.env`, `env_prod.env` (oder eine Teilmenge via `--files`).
- **Rechte**: Schreibrechte auf die Env-Dateien, Leserechte auf die Masterkey-Quelle (siehe Punkt 2).
-Hinweis: Das Tool importiert `encrypt_value` aus `modules/shared/configuration.py`. Stellen Sie sicher, dass dieser Pfad importierbar ist (Start im Gateway-Verzeichnis oder `PYTHONPATH` setzen).
+Hinweis: Das Tool importiert `encryptValue` aus `modules/shared/configuration.py`. Stellen Sie sicher, dass dieser Pfad importierbar ist (Start im Gateway-Verzeichnis oder `PYTHONPATH` setzen). Das Script fuegt `gateway` automatisch zu `sys.path` hinzu.
---
@@ -25,12 +25,12 @@ Hinweis: Das Tool importiert `encrypt_value` aus `modules/shared/configuration.p
1. `requirements.txt` im Projekt (Minimalbeispiel):
```
- cryptography>=42.0.0
+ cryptography>=41.0.0
```
Falls Sie das Tool im bestehenden Gateway verwenden, nutzen Sie stattdessen die dortige Datei `gateway/requirements.txt`.
2. Notwendige Gateway-Komponenten (sofern außerhalb von `gateway` verwendet):
- - `modules/shared/configuration.py` (liefert `APP_CONFIG`, `_get_master_key`, `encrypt_value`, `decrypt_value`)
+ - `modules/shared/configuration.py` (liefert `APP_CONFIG`, `_getMasterKey`, `encryptValue`, `decryptValue`)
- Optional, aber unterstützt: `modules/shared/auditLogger.py` (Audit-Events; Ausfall ist toleriert)
- `config.ini` im gleichen Baum wie `modules`, mit mindestens:
- `APP_ENV_TYPE = dev|int|prod` (kann pro Env-Datei zusätzlich gesetzt werden)
@@ -80,7 +80,7 @@ Tool: `gateway/tool_security_encrypt_all_env_files.py`
- Liest je Datei `APP_ENV_TYPE`.
- Findet alle Schlüssel, deren Name auf `_SECRET` endet, und deren Werte noch kein `*_ENC:`-Präfix haben.
- Unterstützt einzeilige und mehrzeilige JSON-Werte (Klammer-Auf/Zu wird erkannt).
- - Verschlüsselt die Werte mit dem passenden Umgebungs-Key und ersetzt die Originalwerte in der Datei durch `ENV_ENC:`.
+ - Verschlüsselt die Werte mit dem passenden Umgebungs-Key und ersetzt die Originalwerte in der Datei durch den umgebungsspezifischen Prefix, z.B. `DEV_ENC:`, `INT_ENC:`, `PROD_ENC:` (abhaengig von `APP_ENV_TYPE`).
- Legt vor Änderungen eine Backup-Datei mit Zeitstempel neben der Originaldatei an, z. B. `env_prod.env.20251015_101530.backup`.
- Trockenlauf (nur anzeigen, nichts schreiben):
diff --git a/d-guides/google-oauth-setup.md b/d-guides/google-oauth-setup.md
index 85d4500..6f30057 100644
--- a/d-guides/google-oauth-setup.md
+++ b/d-guides/google-oauth-setup.md
@@ -15,11 +15,10 @@ This guide explains how to set up Google OAuth 2.0 authentication for the PowerO
4. Enter a project name (e.g., "PowerOn OAuth")
5. Click "Create"
-## Step 2: Enable Google+ API
+## Step 2: Configure OAuth Consent Screen
-1. In your new project, go to "APIs & Services" > "Library"
-2. Search for "Google+ API" or "Google Identity"
-3. Click on "Google+ API" and click "Enable"
+1. In your new project, go to "APIs & Services" > "OAuth consent screen"
+2. Configure the consent screen (Google+ API is deprecated, use Google Identity Services / OIDC)
## Step 3: Create OAuth 2.0 Credentials
@@ -35,9 +34,10 @@ This guide explains how to set up Google OAuth 2.0 authentication for the PowerO
4. Back to creating OAuth client ID:
- Application type: "Web application"
- Name: "PowerOn Web Client"
- - Authorized redirect URIs: Add your redirect URI
- - For development: `http://localhost:8000/api/google/auth/callback`
- - For production: `https://yourdomain.com/api/google/auth/callback`
+ - Authorized redirect URIs: Add **two** redirect URIs per environment:
+ - Login callback: `http://localhost:8000/api/google/auth/login/callback`
+ - Data connect callback: `http://localhost:8000/api/google/auth/connect/callback`
+ - For production: replace `localhost:8000` with your domain (HTTPS)
5. Click "Create"
6. **Important**: Copy the Client ID and Client Secret - you'll need these for the next step
@@ -48,12 +48,19 @@ This guide explains how to set up Google OAuth 2.0 authentication for the PowerO
2. Replace the placeholder values with your actual Google OAuth credentials:
```env
-# Google OAuth Configuration
-Service_GOOGLE_CLIENT_ID = your-actual-client-id-from-google-console
-Service_GOOGLE_CLIENT_SECRET = your-actual-client-secret-from-google-console
-Service_GOOGLE_REDIRECT_URI = http://localhost:8000/api/google/auth/callback
+# Google OAuth -- Auth App (Login)
+Service_GOOGLE_AUTH_CLIENT_ID = your-auth-client-id
+Service_GOOGLE_AUTH_CLIENT_SECRET = your-auth-client-secret
+Service_GOOGLE_AUTH_REDIRECT_URI = http://localhost:8000/api/google/auth/login/callback
+
+# Google OAuth -- Data App (SharePoint/Drive Connection)
+Service_GOOGLE_DATA_CLIENT_ID = your-data-client-id
+Service_GOOGLE_DATA_CLIENT_SECRET = your-data-client-secret
+Service_GOOGLE_DATA_REDIRECT_URI = http://localhost:8000/api/google/auth/connect/callback
```
+> **Hinweis:** Das Gateway unterscheidet zwei OAuth-Apps: eine fuer Login (Auth) und eine fuer Daten-Connections (Data). Details: `routeSecurityGoogle.py`.
+
3. Save the file
4. Restart your PowerOn gateway server
diff --git a/d-guides/testing-strategy.md b/d-guides/testing-strategy.md
index db2b3ae..bc74902 100644
--- a/d-guides/testing-strategy.md
+++ b/d-guides/testing-strategy.md
@@ -1,26 +1,105 @@
-
+
# Testing-Strategie
## Testpyramide
-- **Unit Tests:** pytest (Gateway), vitest (Frontend)
-- **Integration Tests:** API-Tests gegen laufenden Gateway
-- **E2E Tests:** (zu definieren)
+```
+ / E2E \ <- Manuell / geplant
+ / Functional \ <- Standalone-Scripts (AI, real calls)
+ / Integration \ <- pytest (DB, Workflows, RBAC)
+ / Unit \ <- pytest (Models, Utils, Logic)
+```
-## Akzeptanzkriterien-Format
+## Gateway: `gateway/tests/`
-Given-When-Then Sätze in Arbeits-Dokumenten (`c-work/_TEMPLATE.md`)
+### Test-Kategorien
-## Testplan-Tabelle
+| Kategorie | Pfad | Beschreibung | Ausfuehrung |
+|-----------|------|-------------|-------------|
+| **Unit** | `tests/unit/` | Datamodels, RBAC-Logic, Utils, Workflows | `pytest tests/unit/` |
+| **Integration** | `tests/integration/` | DB-abhaengig (RBAC, Workflow-Execution) | `pytest tests/integration/` |
+| **Validation** | `tests/validation/` | Architektur-Validierung | `pytest tests/validation/` |
+| **Functional** | `tests/functional/` | AI-Modell-Tests, KPI, JSON-Verarbeitung | `python tests/functional/