diff --git a/README.md b/README.md new file mode 100644 index 0000000..7bfcf88 --- /dev/null +++ b/README.md @@ -0,0 +1,87 @@ + + + +# PowerOn Portal -- Dokumentation + +## Produkt + +PowerOn Portal ist eine Multi-Tenant SaaS-Plattform mit Feature-Store-Modell, AI-Agent-Workspace und mandantenweiter Datenneutralisierung. + +| Komponente | Repository | Technologie | Beschreibung | +|-----------|-----------|-------------|-------------| +| Frontend Nyla | `frontend_nyla` | React/TypeScript, Vite | Zentrales UI für alle Features | +| Gateway | `gateway` | FastAPI, Python, PostgreSQL | Backend REST-API, Services, AI-Core | +| Private LLM | `private-llm` | Python | Internes LLM für Neutralisierung + sensitive Daten | +| Teams Bot | `service-teams-browser-bot` | Node.js/.NET | Bot für Teams-Meeting-Teilnahme | +| Wiki | `wiki` | Markdown | Dokumentation (dieses Repo) | + +--- + +## Ordnerstruktur + +| Ordner | Zweck | Wann nutzen | +|--------|-------|-------------| +| **a-strategy/** | Produkt-Vision, Strategie, Roadmap, Markt, Investor | Richtung setzen, Business-Kontext | +| **b-reference/** | Wie das System funktioniert (code-verifiziert) | System verstehen, Architektur-Fragen | +| **c-work/** | Laufende Arbeit -- Kanban (plan → build → validate → done) | Feature planen, bauen, testen | +| **d-guides/** | How-to: Dev-Setup, Deployment, Testing, Coding-Regeln | Etwas tun, Prozess nachschlagen | +| **e-compliance/** | Sicherheit, Datenschutz, Audit-Dokumente | Regulatorische Fragen | +| **f-decisions/** | Entscheidungen (ADR-light): Kontext, Entscheidung, Konsequenz | Warum wurde X so entschieden? | +| **z-archive/** | Veraltete Docs mit Forward-Link zum Nachfolger | Historischer Kontext | + +--- + +## Lebenszyklus: Feature oder Refactor + +``` +1. Neues Arbeits-Dokument in c-work/1-plan/ anlegen (Vorlage: c-work/_TEMPLATE.md) +2. Bei Umsetzungsbeginn → nach c-work/2-build/ verschieben +3. Bei Test-Phase → nach c-work/3-validate/ +4. Wenn merged/released → nach c-work/4-done/ +5. Einmalig: betroffene b-reference/ Seite aktualisieren, TOPICS.md prüfen +6. Arbeits-Dokument → z-archive/ verschieben +``` + +**Kernregel:** Während Planung, Umsetzung und Testing pflegst du **nur** das eine Arbeits-Dokument in `c-work/`. Kanon-Seiten in `b-reference/` und `TOPICS.md` werden erst am Ende aktualisiert. + +--- + +## b-reference/ Aufbau + +``` +b-reference/ +├── product.md Komponentenübersicht, Repo-Map, Tech-Stack +├── gateway/ Backend-Komponente +│ ├── architecture.md Module, Services, Interfaces +│ ├── ai-agent.md Agent Core, Tools, Knowledge/RAG +│ ├── workflow.md Workflow-Engine, Methoden, Aktionen +│ ├── automation.md Automation v1 + v2 +│ ├── billing.md Billing, Subscriptions +│ └── features/ trustee.md, commcoach.md, chatbot.md, ... +├── frontend-nyla/ Frontend-Komponente +│ └── architecture.md Seiten, Komponenten, Hooks, Routing +├── private-llm/ Internes LLM +│ └── architecture.md Setup, Modelle, Gateway-Integration +├── teams-bot/ Teams Meeting Bot +│ └── architecture.md Service, WebSocket, Architektur +└── platform/ Cross-Cutting (repo-übergreifend) + ├── neutralization.md Gateway + Private-LLM Zusammenspiel + ├── rbac.md Rollensystem (Gateway + Frontend) + └── navigation.md Navigation API (Gateway → Frontend) +``` + +--- + +## Für AI-Assistenten + +**Immer zuerst laden:** `TOPICS.md` -- dort steht, welche Datei für welches Thema massgeblich ist. + +--- + +## Status-Block (Kopf jeder Kanon-Seite) + +``` + + + +``` diff --git a/TOPICS.md b/TOPICS.md new file mode 100644 index 0000000..6a939d3 --- /dev/null +++ b/TOPICS.md @@ -0,0 +1,45 @@ + + + +# Themen-Index für AI-Kontext + +Lade immer zuerst diese Datei. Dann gezielt die passende(n) Referenz-Datei(en). + +## Produkt & Strategie + +| Thema | Datei | Wann laden | +|-------|-------|------------| +| Produkt-Vision & PMF | a-strategy/product-vision.md | Business-Kontext, Positionierung | +| Produktstrategie | a-strategy/product-strategy.md | Go-to-Market, Preismodell | +| Roadmap | a-strategy/roadmap.md | Priorisierung, Feature-Planung | + +## Architektur & Komponenten + +| Thema | Datei | Wann laden | +|-------|-------|------------| +| Komponentenübersicht | b-reference/product.md | Repo-übergreifende Fragen, Tech-Stack | +| Gateway-Architektur | b-reference/gateway/architecture.md | Backend-Module, Services, Interfaces | +| AI Agent & Tools | b-reference/gateway/ai-agent.md | Agent-Verhalten, Tool-Registrierung, RAG | +| Workflow-Engine | b-reference/gateway/workflow.md | Methoden, Aktionen, WorkflowManager | +| Automation | b-reference/gateway/automation.md | Automation v1+v2, Templates, Flow-Editor | +| Billing & Subscriptions | b-reference/gateway/billing.md | Abrechnung, Prepaid, State Machine | +| Frontend Nyla | b-reference/frontend-nyla/architecture.md | UI-Seiten, Komponenten, Hooks, Routing | +| Private LLM | b-reference/private-llm/architecture.md | Internes LLM, Neutralisierung | +| Teams Bot | b-reference/teams-bot/architecture.md | Meeting-Bot, WebSocket | + +## Cross-Cutting (repo-übergreifend) + +| 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 | +| Navigation | b-reference/platform/navigation.md | Menü-Struktur, Admin-Seiten, API | + +## 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 | diff --git a/appdoc/doc_user_applikation.md b/a-strategy/investor/application-doc.md similarity index 100% rename from appdoc/doc_user_applikation.md rename to a-strategy/investor/application-doc.md diff --git a/appdoc/doc_user_kunden.md b/a-strategy/investor/customer-value.md similarity index 100% rename from appdoc/doc_user_kunden.md rename to a-strategy/investor/customer-value.md diff --git a/userdoc/doc_investor_general.html b/a-strategy/investor/doc_investor_general.html similarity index 100% rename from userdoc/doc_investor_general.html rename to a-strategy/investor/doc_investor_general.html diff --git a/platform_overview/doc_platform_big_picture.css b/a-strategy/investor/doc_platform_big_picture.css similarity index 100% rename from platform_overview/doc_platform_big_picture.css rename to a-strategy/investor/doc_platform_big_picture.css diff --git a/userdoc/doc_referenzen.html b/a-strategy/investor/doc_referenzen.html similarity index 100% rename from userdoc/doc_referenzen.html rename to a-strategy/investor/doc_referenzen.html diff --git a/userdoc/doc_user_main.html b/a-strategy/investor/doc_user_main.html similarity index 100% rename from userdoc/doc_user_main.html rename to a-strategy/investor/doc_user_main.html diff --git a/platform_overview/doc_platform_01_platform_overview.jpg b/a-strategy/investor/images/doc_platform_01_platform_overview.jpg similarity index 100% rename from platform_overview/doc_platform_01_platform_overview.jpg rename to a-strategy/investor/images/doc_platform_01_platform_overview.jpg diff --git a/platform_overview/doc_platform_02_customer_story.jpg b/a-strategy/investor/images/doc_platform_02_customer_story.jpg similarity index 100% rename from platform_overview/doc_platform_02_customer_story.jpg rename to a-strategy/investor/images/doc_platform_02_customer_story.jpg diff --git a/platform_overview/doc_platform_03_workflow_system.jpg b/a-strategy/investor/images/doc_platform_03_workflow_system.jpg similarity index 100% rename from platform_overview/doc_platform_03_workflow_system.jpg rename to a-strategy/investor/images/doc_platform_03_workflow_system.jpg diff --git a/platform_overview/doc_platform_04_microservice_architecture.jpg b/a-strategy/investor/images/doc_platform_04_microservice_architecture.jpg similarity index 100% rename from platform_overview/doc_platform_04_microservice_architecture.jpg rename to a-strategy/investor/images/doc_platform_04_microservice_architecture.jpg diff --git a/platform_overview/doc_platform_05_rbac_system.jpg b/a-strategy/investor/images/doc_platform_05_rbac_system.jpg similarity index 100% rename from platform_overview/doc_platform_05_rbac_system.jpg rename to a-strategy/investor/images/doc_platform_05_rbac_system.jpg diff --git a/platform_overview/doc_platform_06_ui_architecture.jpg b/a-strategy/investor/images/doc_platform_06_ui_architecture.jpg similarity index 100% rename from platform_overview/doc_platform_06_ui_architecture.jpg rename to a-strategy/investor/images/doc_platform_06_ui_architecture.jpg diff --git a/platform_overview/doc_platform_07_big_picture_and_future_vision.jpg b/a-strategy/investor/images/doc_platform_07_big_picture_and_future_vision.jpg similarity index 100% rename from platform_overview/doc_platform_07_big_picture_and_future_vision.jpg rename to a-strategy/investor/images/doc_platform_07_big_picture_and_future_vision.jpg diff --git a/platform_overview/poweron_investor_briefing.html b/a-strategy/investor/investor-briefing.html similarity index 100% rename from platform_overview/poweron_investor_briefing.html rename to a-strategy/investor/investor-briefing.html diff --git a/appdoc/doc_investor_20251014.md b/a-strategy/investor/investor-doc-2025-10.md similarity index 100% rename from appdoc/doc_investor_20251014.md rename to a-strategy/investor/investor-doc-2025-10.md diff --git a/appdoc/doc_user_investoren.md b/a-strategy/investor/investor-summary.md similarity index 100% rename from appdoc/doc_user_investoren.md rename to a-strategy/investor/investor-summary.md diff --git a/platform_overview/logo2.png b/a-strategy/investor/logo2.png similarity index 100% rename from platform_overview/logo2.png rename to a-strategy/investor/logo2.png diff --git a/appdoc/doc_user_partner.pdf b/a-strategy/investor/partner-doc.pdf similarity index 100% rename from appdoc/doc_user_partner.pdf rename to a-strategy/investor/partner-doc.pdf diff --git a/platform_overview/index.html b/a-strategy/investor/platform-overview.html similarity index 100% rename from platform_overview/index.html rename to a-strategy/investor/platform-overview.html diff --git a/appdoc/doc_user_product.md b/a-strategy/investor/product-doc.md similarity index 100% rename from appdoc/doc_user_product.md rename to a-strategy/investor/product-doc.md diff --git a/appdoc/doc_user_summary.md b/a-strategy/investor/product-summary-slides.md similarity index 100% rename from appdoc/doc_user_summary.md rename to a-strategy/investor/product-summary-slides.md diff --git a/strategy/AI-Extraktion und BUHA-Sync.html b/a-strategy/market/AI-Extraktion und BUHA-Sync.html similarity index 100% rename from strategy/AI-Extraktion und BUHA-Sync.html rename to a-strategy/market/AI-Extraktion und BUHA-Sync.html diff --git a/strategy/Dev-Ops-Budget-Pace-VR-Sitzung.html b/a-strategy/market/Dev-Ops-Budget-Pace-VR-Sitzung.html similarity index 100% rename from strategy/Dev-Ops-Budget-Pace-VR-Sitzung.html rename to a-strategy/market/Dev-Ops-Budget-Pace-VR-Sitzung.html diff --git a/strategy/Nyla - Your AI Colleague in Every Meeting.html b/a-strategy/market/Nyla - Your AI Colleague in Every Meeting.html similarity index 100% rename from strategy/Nyla - Your AI Colleague in Every Meeting.html rename to a-strategy/market/Nyla - Your AI Colleague in Every Meeting.html diff --git a/strategy/doc_playground_marketing_pitch.html b/a-strategy/market/doc_playground_marketing_pitch.html similarity index 100% rename from strategy/doc_playground_marketing_pitch.html rename to a-strategy/market/doc_playground_marketing_pitch.html diff --git a/strategy/doc_produktestrategie.html b/a-strategy/market/doc_produktestrategie.html similarity index 100% rename from strategy/doc_produktestrategie.html rename to a-strategy/market/doc_produktestrategie.html diff --git a/strategy/doc_joint_venture_collaboration.md b/a-strategy/market/joint-venture-collaboration.md similarity index 100% rename from strategy/doc_joint_venture_collaboration.md rename to a-strategy/market/joint-venture-collaboration.md diff --git a/market/langdock-markteinschaetzung-poweron.pdf b/a-strategy/market/langdock-markteinschaetzung-poweron.pdf similarity index 100% rename from market/langdock-markteinschaetzung-poweron.pdf rename to a-strategy/market/langdock-markteinschaetzung-poweron.pdf diff --git a/market/langdock-markteinschaetzung-poweron.md b/a-strategy/market/langdock-markteinschaetzung.md similarity index 100% rename from market/langdock-markteinschaetzung-poweron.md rename to a-strategy/market/langdock-markteinschaetzung.md diff --git a/platform_overview/poweron_platform_analysis.md b/a-strategy/market/platform-analysis.md similarity index 100% rename from platform_overview/poweron_platform_analysis.md rename to a-strategy/market/platform-analysis.md diff --git a/strategy/doc_playground_marketing_pitch.md b/a-strategy/market/playground-marketing-pitch.md similarity index 100% rename from strategy/doc_playground_marketing_pitch.md rename to a-strategy/market/playground-marketing-pitch.md diff --git a/strategy/doc_platform_diagrams.md b/a-strategy/platform-diagrams.md similarity index 100% rename from strategy/doc_platform_diagrams.md rename to a-strategy/platform-diagrams.md diff --git a/strategy/doc_produktestrategie.md b/a-strategy/product-strategy.md similarity index 100% rename from strategy/doc_produktestrategie.md rename to a-strategy/product-strategy.md diff --git a/strategy/20260224_Roadmap/20260224_PowerOn_Preismodell.pdf b/a-strategy/roadmap-2026-02/20260224_PowerOn_Preismodell.pdf similarity index 100% rename from strategy/20260224_Roadmap/20260224_PowerOn_Preismodell.pdf rename to a-strategy/roadmap-2026-02/20260224_PowerOn_Preismodell.pdf diff --git a/strategy/20260224_Roadmap/20260224_PowerOn_Roadmap.pdf b/a-strategy/roadmap-2026-02/20260224_PowerOn_Roadmap.pdf similarity index 100% rename from strategy/20260224_Roadmap/20260224_PowerOn_Roadmap.pdf rename to a-strategy/roadmap-2026-02/20260224_PowerOn_Roadmap.pdf diff --git a/strategy/20260224_Roadmap/poweron-logo2.png b/a-strategy/roadmap-2026-02/poweron-logo2.png similarity index 100% rename from strategy/20260224_Roadmap/poweron-logo2.png rename to a-strategy/roadmap-2026-02/poweron-logo2.png diff --git a/strategy/20260224_Roadmap/roadmap_presentation.html b/a-strategy/roadmap-2026-02/roadmap_presentation.html similarity index 100% rename from strategy/20260224_Roadmap/roadmap_presentation.html rename to a-strategy/roadmap-2026-02/roadmap_presentation.html diff --git a/implementation/PLATTFORM_FEATURES_UND_ROADMAP.md b/a-strategy/roadmap.md similarity index 100% rename from implementation/PLATTFORM_FEATURES_UND_ROADMAP.md rename to a-strategy/roadmap.md diff --git a/appdoc/.$doc_architecture_gateway.drawio.bkp b/appdoc/.$doc_architecture_gateway.drawio.bkp deleted file mode 100644 index 96b9b10..0000000 --- a/appdoc/.$doc_architecture_gateway.drawio.bkp +++ /dev/null @@ -1 +0,0 @@ -7V1bd9o6Fv41rJl5SJYt4wuPCUlOO6dpMyed9vS8dBkjwK2xGWNyOb9+JFnyTQJckGyFhKzVgrCNvb+tfdPeWwNrvHz6LfVXi9tkCqMBMKZPA+tqAMDQBkP0Hx55zkfAyAX5yDwNp/mYWQ7ch39DOmjQ0U04hevagVmSRFm4qg8GSRzDIKuN+WmaPNYPmyVR/VdX/hxyA/eBH/GjX8NptqCPYVlO+cU7GM4X7Kcdmz7y0mdH00dZL/xp8lgZsq4H1jhNkix/t3wawwiTjxEmP+9my7fFnaUwztqc8C37PnSe3n15/uvrze/zafY0v52cWflVHvxoQ5/40wNMH0L4SG86e2akSJNNPIX4YsbAunxchBm8X/kB/vYRoY/GFtkyQp9M9NaPwnmM3kdwhm7uchZG0TiJkpRcyprZ+A+Nr7M0+Qkr3zjkhc9I4qwynr/QOLq7LET4XNAfyJIVPfqe3qrJPufMZOKzeFpR8uHLwafKEKXdbzBZwix9RofQb88AsCmSlJktg/LyY4UzTIsetKhyheF5lCcpP86L65eIoTcUNDGANzePPz9+/OH+uP333fez68/X358fz4qbqkD4Ps7QmeEcxgid7TCa+2FsjZt3gf9a4+OnAYXHa6DlVJgnQGhB9AOX89SfhrDGEBPyV0DL4ShAezu0pmXWoTUNx+CwdYYCaIsz5SM7dDlkx0n6hmgrRE2jMVktHlDPEQHqqQPU4wC93KzDGK7Xb6AeMk1dAaidz9IRB+odTGdJuvTfxG87XIHZ1KwCXE0DdDxbAQcsMuFShJ1UTGczEAQiTKfOxLGdAzGVActo1EBlJLB3rJHA3HEdRaCYNm+w3qVJQCSo8eU0zdYjJ1fTbDU9V4Bj13aryeH4mKQ/Z1GyC0Etppcta3oNzTouhclSxYUdVIWlQPQYVH78Z/JlM15b97OfoffxIfvfb+/OkIblYKGedZJKtlHkACPBrzNHTn2C2MxOq+JgiKYHkICD0C13AEdsOJ1D9txJmi2SeRL70XU5eom00wp/WyCGxuoQled9SDAxyeAPmGXPlLf9TZbUYUOETZ//xNLz3HNtNvCNDBQfr56oeM0/PVc/IWMoRETBhgQZjPwJjC794Oec3BsDfgpn/ibKOIYoxzHwN/4yjPDl38HoAWLuaEhNJkX502E8vcABIUygyF+vw2BXXGCdbNIAtpgpmZ/OYbYLSnpFjN9Ofkxh5GfhQz3wJJ2zTFMXznp5jCAmKM8HOxlGFz7gBH2Irf0ZEt8nK+hd0ELQm50KetMY6jIfC0lffGgn5dXO42FX89hpKc/Zkoa8eUxPvUvQDKzah0273WQBQXaR/F7peQ1GLG7kCCOEExEz6Geb9GQFRNMi9yyznUFumhLcpC3yQTvxUJEI32oCoQ/x0Jma99qae31peXEQy9LG3NNTvXgDLmZzQ167OagBr1qW6tVO5JcsEAzZyaoAx22YiKBtLMBRZiJa2k3hl6wC4FOYVZ4BffrGHg+9L58Af2APcPgcN0HLSe71pTd23nZl2g+AQ4g6QW/m+M3FasXG0G8Uw8VxKRu59cMY3+RqFSH0sjDBnyJ/EwcLmOZfnK+epQoUH81RII7U3xjoxUv9GXntwvoIKSJcORFJEVeZEGEWqkZSRCtD4Bf9zEKKVGRIKVFkSxHmc7YzFbSRIuy2qyuoOLlMmxBTuajD4JcbcAJeI19BkFUERAtvQJk1wcLRtaSi5SqJ0XPyqOA0stW6JgqiZDNtgVBrzb1liXVXzsH25VcZqOGFuLoN6PA2oClKRpCRiyAGzeZAC0gmmHGTRFOsRGXOJi+A4tk08eyhvVOS/QqZjUZ6gceyBvaRWd2qG+/sUDLfJtNNJDeZp2cThSf/qHfy85lUqzTJkOGBc26UsPp+xaGE1iOrb1ozQ7NC6+lzjAR2oIbSUx96MyGlncCDE2VcPeqdq11e4ZaUViBXDMM24ExEacMwry7HXcsV0zB7h0CQNJY8wvQTdkTHyRRL+Is0wGQO8PoG+oj9DGT470Dm6GwyZ+g6nisCyjKHlt10SKpAiSKYUi1XLmmsWBbdmzPGXF35KPLeRFU9KJhK0Ao8oog5hC6NkS1S0YZBVbcaYWb3PZM83kJCF14kU00cOvlLghb26mvyrKBudSqIUJCyKihc1tEmZ0CvyO6BgaWBKGayN1CzK6u1ZRJBNzkD52b5Mkb1S8rLIBCSQ5uVC7349OAVCCnLjoJEl+283NfCtWnz2p4liGuia7bokl/KAXcbGh64bOWlolwsYUqarSwz3xZFm/RKApdBe2A08r6BISC+KSonsy0JBtYW4ju6yMzXkPnNCdT9Gp7Njv3y0wOtebIroerqwlwnwguCFJ7dXKMRL/CunG4Z4DKkvOm5Okp5PtRdTi/g+Ev8+IRhP/pLWIywBIvK92PE5vApqx8iO53i6JjisZqai0YJEiqEkRB1EDLj4cXJUpLiWFlhUuaGF4ZAS5tBnlu0X3I7Ak9dfKTrtObXjnJ6WQZ6/5zXUSrPL3NsR1m9x7KW168FIEgFKSwAPovvYrX6NPmBWGetXbLesRZC0w80Qf/aBbyyOd5FWdghekJQ5rtFTwzl64ltUV6rwbAOUFYZtpss2taGlZl9jiQxwYXqRE1qhKE6a6hOTByyEnS0SDh8NrltZxPzTrWxukyWg6eRRH7JZRgd8BATUhrxkH7BXa20upSFtMJJlOwxtuY77TzG4t41reKToZ6HzRAREBnxojCfqaw3oOm8Fd1ounC+f767rd14Nrs0mu+jV8Z3ymOaB5d7qeW89nKyI84TZDvrWN555HpE0xXUIGDEejo2VfzbahJnKQyblgITlz2ip02mnJ6GQmfVuYeIa0Fx7ksJaghy6nWu0JUx/ZET3gzkCfZxcGzR/B8py7lz+Zw7CsSYdOGWLYOPLm04FoSmELZYCLtHIcw3PFvDYJOGmVzaty6wPY7Gtte0UmyBlSLaAkFdvNrlAxEqeqrvJ7C6QARHdkNkHIrIXvR/VkB3Pt+outS720K0L/OFX3T+wEU3YOT7PNlXJ2YYChaC+08zYtzUepE+r4M7/UV6QwNseGe3msXXwOZqcpess3kKTwwaQXZe/+4wy70+5TYnx+4LAZp+sNXSBFO254rpifYfSPtudHKk6GruowJckSGmqo53C6F5x0/jVifSARDsgNI1ALzDp0uzE9nU9kQJ9x1Tm3ft9Gh3Ip3WGnA27+Pp3fBEOgZtLVOFGPDFPX9c339GIxd379/MH9EqgNVWSslozbcFNd5LP/k+NbI3N3OZcdpJoxoxjiPeZ9e9U410GWj1LgNHvHdeD3UFfgbnCf6p7QuiogXTl2cnuK7T6GKDfL2WAKkLBrMJqGszIRmUd5qp+q5dNBTam5hmKFtuGvF+dk76S3+dx6ea0at/ZnC5itCM+dcpCS6nGQNxPVsET7fBqxHvnOfo7JNNJxaQ59DxgHDydIwO77kXEfnxws9OCQE+7A7a6g2FAPDOfAkAC/KeOAptzSuFKPBufoHCRXja5G/tKyok/472HV/h5MTp3zaArpD+O1bUP4fIKT9xCSTa0qRbCIoNVEQQ3K8gDBanDcGwdyUADG1aUehVqCK3E2mLRlStc1B7LlOvNiNtXFFxzTpgWZ71bI1ZOL/1Y38uP8Wy51VPm0uYab3qbCkTF9qkueslLjrtfNS6o4WtQFQcyT+CrAXkcd9F/nOOo9QJ3F9wdgj6Ds4iaSEk9UWULfyN3ABtj3TuPQgODEHS+XMcXMEo818ilbmYnQ68zIcqsEZY+hn8EMY/4RTvT3kKpNaAnd8q3nXokgJYo/+9Wh6wUJZGWp4PrdBaqKsk2CxlB3e7ytWymtO1/yXYYlefCqljuMlSPwr/pjv1vkBK88VlGlBam0jJ6xaMog25d88NfQSjYFduViSK6/ZfqFwcNgvmdJitojoEMgdfqkzktM+QVS/1SGVt9rF65TKx7ZZAhWmmkUzUry3jGw/t1qu6tcsq7p3Xq5ITGboS9mazIrP1aq1CYc8HYR4l5yn0p0v7j3GZfD5IJj8NoTcK24Jmy11TWBCWkJ9l0B+FBYUTHVMY8NGIdzDFZS7hGquWBX4bJMtVhJfC8OMks2J8wiph0AOg+0eA5CKcnsIqvw2SIuIjQz6el8dCH8NoJOhS6focvbvOBwTXYHeDY8YGGkH/zmgBobHwH/LL5uNLnxy0pPUe5POfT09kodnwyb0uYLQip+YH4QuvN5PiIGRjkKvmd0AKgDBrpeQjsiKS6Lxr7msUC8lvtG6Cxo5N3ojnTCDcE1FZMUnxHBXWpCxS6cZRIN1Mnk9mM5gSbDMEu59OEcUw+kW5A+WGJN9ggwGfM3bZkAsxGkbeJ9+vcD2lROiPSG9qsIQUJnDNOhMIxdNIwASuqqIJdA8cD1ygj9hsXzFZRD2KNMmqc3orPyz8dJnEHDdU0PeDIEH8QqRKhdVOF/jmFsZC4L1ugef9Azr5WVkGApLMYhIfKmdqDiHbtxbrmXgeEtVAEN6sIdY1F+QWSvSROsmPpvM/Szes3LOi76g6YGU5xRWKCp6TZZER4PdkH3q8imDJiZ20LgGA928ok9CdUQbYn12lcE0NEZ9YBCkx0dkxhB1qp5S2hl+1NKjdcrSF0avtIIUZLLNuLDgCYwF0ywm8K5ZPcdZzvyYdpiFWBrlh+d/3/0Bf4xZrSTr3mV4o0C8kAbFy/eeSD2ZJgJNyDBycxkbGhHADModXOJ0Sf4OwJGP+ahWFPo1jGz+STRpDwixTf5UR0/cTEVC0eTAVbDDEljERN7mSy7sEVwySkmPJEP0irmst/GSTDT4xhg+FFVu91ASZ4HJNWr1kV7P5qC1gV6F2M0116o13bJnJsl75cQ0K53+bhFZJl++ITfM510o4tunj36y4TqSDaVVMFfYP5pzAz/womTPtxpm75cZSVKIV+8Bjbs1/NsQ+Ic4MoIvWNUVZ3FLx+0So4qlDplbdzD5nz46ImT++I7/u+9eZsti/UIXN1fS43LYe10iZELX4WEAO9VeKPs3axgDj6HWVq2abmAg4RKqs8KLTTYn1HMYwJf1o/HBQM9CoPM389c+S4UqzjlxpQtzwNZHCJI8M5n0dUvzlegWDcIaLyaPn81OWZAIrzLQsgRUmMtXVsQ2fIZyzzbia6l9hmmpkKRcUzBtjwoJgjtwwSI7PSwbOwzgs2CM/O4yxc08EHuMBooIfMEOGueFFLkXYFHNQjI4hP5Vfs/IrEpnmiCoExjRUfktiGy4LdwgEtrtI2ChrvAMs3rN/rIuZE+u/LciF3tKYotsCEYs3nZGhGGevpUSHtS3tD4HhNr17XcGhIj9TOA/XSDzkjmWwgEhq5tGqH8mk6eswU06uXnwBIm7Uu4hj5fr950mozXdwdpjOqrf+BkMKezUJ4lv2feg8vfvy/NfXm9/n0+xpfjs588Qc1NUG8ry6e+sOWJvCVqOfmc0a6PfWHBDY/ArUu/DsA1KP+Nyr0EfUWu6Qq0f3ASxg2U76xsTLX4Nt/bXq3QD5aSwDSK5BIHJ2BfamORR1CLSVNeACrBa3guZ7pILQVEO+qeQFnu3AeRf4rzVA5VqvJ4CrwT07Jy+6dWQkfCBHXpmWrDhGM/H/zHP5QMZQuHSsbO8NYPO5xGPSavsN4kNS20bN+WwKQqiWaPsmlcKZDztcbtZhLNubfz04c1N5JIhJiqeysv18gc0bTncwRR7O0n8T2gdraMDNaEGyny1S0Ka6RTybX/O/pztVGZ9Ymk63wd1D8VbWkch0myFg5PsKqko63WMMsPaAb56u2q5EB3nINg1D7C8TyC233nxkm0/n+FosEzXzufYul2Kczh4p++MEjxjrjGggWki9pjlCtLFrPFnj/+jC1MV7/LTzPIVEi3XKX5VKtmqpNDSbTsCQVydCmWSr0yZ8XHvMJI2mekTtlmFuU+cbbUFSpzjskS6Ko5DUxrnnFuK5nbQmn5BVGuJl6XRwSjVmbBa1UB7tebIjfcJYuX/mOg1ecMy2vKDdrtvFvTeCfyRJ7hVqA9PzNNQGDtBlwupZWDzsaqK37VdYZBV10NrUBM0wpO00luRVtzN19GueUGHJbzWOPOXCd6d14TvjEI0U0VvzhJ08JIigHZRMIJWL9DNt+VDpH7TS4dWZMoKQqBbGjDbZPyehLLps2Ayc1l4vm4gaiQY+7lVET1nA8javYbtYrSoRzYmScGbfG1GLpEOxXNmjdNAv8KWVGfCLrk4hHSqyoZQUkqUDc3peouHA7r26xlpUjY1p1ZgOJkS5esFYoTODwmmuZhT18f3JC5ePX3FSfVzpuSKS6s0lNLyw1Ry7Q1yIkysEHRSu/IxUxOIled7OfI0pq4I8CkOQ/SbcCllh9pvLWwD79rQ+G7ygfa2BwUkEKWByaatFw6a9aavKNrYGrGVo/4aCXu7AgVbLGintjF0uxj2jXkOcFJx75WvUuKbqqCkrsHrjYLHJ2olD25pTbe1ahbKNs/vnHz1dpe4ipqO2W95pGBYRbPD9VoC1p4YSmbMiz6fbIiyHr+W4KdqTKM0KLMsJmu0tXlAWYLd5fyo9ZfQxTTBApXWCqLi4RQ4NPuL/ \ No newline at end of file diff --git a/appdoc/.$doc_gateway_import_map.drawio.bkp b/appdoc/.$doc_gateway_import_map.drawio.bkp deleted file mode 100644 index 781bb2d..0000000 --- a/appdoc/.$doc_gateway_import_map.drawio.bkp +++ /dev/null @@ -1 +0,0 @@ -7ZzZcuI4FIafhnvLC8tldxJ6uipT1dVc9LViH4M7xqKECGGefuRYwrJlHJrxoilxlfjIC/yftv8YaeI9bN+/Ubzb/E0iSCeuE71PvMeJ67oL3+V/8sipiCAXzYrImiaRiJWBVfIPiKAjoockgn3lREZIypJdNRiSLIOQVWKYUnKsnhaTtPrUHV6DFliFONWjv5KIbUTUd5yy4C9I1hv5aEeWbLE8WwT2GxyRoxLynibeAyWEFf9t3x8gzeWTwhTXLS+Unj8ZhYxdcwF/PoWouOoNpweohpfiU7KT/O6UHLII8qvRxPt63CQMVjsc5qVHjpvHNmybiuI4SdMHkhL6ca0HKA7imMf3jJJXUEocFMwWL+cSqaqb34NkbCWej+RxUSWQz4/1byxEeAPK4F0JCQW+AdkCoyd+iiidSjyiQi7k8VGhK4ltFLBTEcOiQq3Pty4l5/8I1ZsJRJjhbd5G9hoFtahbErEHQRw0kfAx8uehKSRmwYAkRHdBqE5CLeqYRMxZOE0kYBrwjmMsEm6NxHTINoGTkFDQKMiwHQTKUWMMBHugb0kIelMoCzoeHOZxAIsmDOglAHc0DLMaBX8+IIUkY0Bj3MRBLeq8QSxCv4lEHMxiPlcbiYRfI+EN2x7CA03YqaE9yIKuKcALQBOFlxkK0WhD9HxWozDkEB0DZgfa0BrKgo4poHje3Ct53nSBYCwK9eEZDUnhSOhrnOY2qo5BKel4dHBiN0aN1sHxI9+cQXpQEFxR1tAYZLjjphCCD2ETgvncAT8eC0HdMwwJAKI1IE1/Tfb8NKkCoWxD1iTD6VMZ/VoFU57zTMhOBH8DYyehHT4wUoWlSw9Z9CVPdvDDl5SEr0VomaTykt+H7U5+KkzDNhp7cqBhgyv9SL1gugZxuppOyL90Kz8KKWbJWzWp8l9puJbRqJtWlUad1DhEvDsRg9qHbxkNNZVgXtsI7jQMaRdTy0hU8zsqC5XROCxmdxZG9VLzOw9xcj0fNw6PxZ2HHDcqWblxaMi30nccBgzjyDY3Xu+RzBrJkW12vA1H3RiOhMQ2P96GxIz5FbLNlLchqb7iGQmIbb68DUh1uB8JiG32vBXI+LMs+xy66jMMHEHss+iXgJhh0ZF9Hv0SkPG7K9c2h16dQ5nXXbm2ufTLQMzorqT+dyBGTHdd2zx6C47xRw/b3PllGLUf/o3EwzZzXlPdrAyva5szb6FhyOTKNnPeQsSIwdw2b97GY/zR3DZjrv5G3LzOyrPNml/CYcJrD882W34Jhhmm3LPNlF/CYcKvfDzbLPllGONPqTzbLPlFGKPPp7z/rRvXlrFFnhu7+TK2CO835w9z6/sQhYxZQ0sKay6ERu1ZCSvsGLyzJqmlbhnJcoDqWkERwmmyzvhhCnF+h3xBXxLi9IsIb5Mo+mDftAqxrA/5ys62RYRuG5DrFxEGn68hdBrWEHodrCEseOhTr2WuAUdPMh5/xiegGpzBN+PpXulrd1PoTml9VvXIrVAvGt+0zU73GiP5e6bhRNZnS9+zmGL+bQ9h7nP6kfuWnVx6kPvaFcjdya3Ph1bFNK2fruOWrVp60Hk+eLXWJzvf5XjeV43+861Yulf6vF3dcErrrxVWZxfYi9A37LbSg9DB4FVaf1uwLFJR/eh8y34qPei8GLxC628Bfok8eT999C0bpnQvtOcOXqH1BP/P3D33U51v2ROlB5Wng1fnhlVvDwkNDynmCjuPsOPnQBaeNLmNMZTCQDr9EFlcWe/d7ohck72/Limi1tYr0yTVVvR5xucP0iqfpkgUjYMGiWXs6kyKeMIPkvBPouwzVCHs18kV2R9xUQlPuw9Cn9yoSBdpN/qoBedv3VQx+GG5c3BxerkDs/f0Lw== \ No newline at end of file diff --git a/b-reference/frontend-nyla/architecture.md b/b-reference/frontend-nyla/architecture.md new file mode 100644 index 0000000..ed791ad --- /dev/null +++ b/b-reference/frontend-nyla/architecture.md @@ -0,0 +1,75 @@ + + + + +# Frontend Nyla -- Architektur + +## Überblick + +Frontend Nyla ist eine React-Single-Page-Application (SPA) mit TypeScript und Vite. Routing über React Router; Schichten: Presentation (Pages, Components), Business Logic (Hooks, `*Logic`-Module), Data Access (`api.ts`, Feature-API-Module), Infrastructure (Contexts, Provider, Konfiguration). **PageManager** lädt Seiten dynamisch (Lazy Loading, State Preservation, Lifecycle-Hooks). Authentifizierung über Azure MSAL; HTTP über Axios mit Interceptors. + +Technologie-Stack (Stand UI-Doku): React 19.x, Vite 5.x, TypeScript 5.8.x, React Router DOM 7.x, Axios, `@azure/msal-browser` / `@azure/msal-react`, Framer Motion, XState, CSS Modules, React Icons. + +## Ordnerstruktur (src/) + +| Ordner | Inhalt | +|--------|--------| +| `pages/` | Seiten: `admin/`, `basedata/`, `billing/`, `settings/`, `views/` (workspace, commcoach, chatbot, trustee, automation) | +| `components/` | Wiederverwendbar: FormGenerator, FolderTree, Navigation, UnifiedDataBar, Automation2FlowEditor, OnboardingAssistant | +| `hooks/` | useApi, useFiles, useNavigation, useConfirm, usePrompt, useResizablePanels, etc. | +| `contexts/` | FileContext, PekContext, ToastContext, WorkflowSelectionContext | +| `api/` | API-Client (`api.ts`) und Feature-spezifische API-Module | +| `core/` | PageManager | +| `layouts/` | Layout-Komponenten | +| `locales/` | i18n | +| `types/` | TypeScript-Typen | +| `utils/` | Utility-Funktionen | + +Ergänzend typische Root-Dateien und Bereiche im Repo: `main.tsx`, `App.tsx`, `api.ts` (Root), `auth/` (MSAL, ProtectedRoute), `assets/` — Feature-Module unter `components/` oft nach Muster: Haupt-`.tsx`, `*.module.css`, `*Logic.tsx`, `*Types.ts`, optional `index.ts`. + +## Wichtige UI-Komponenten + +| Komponente | Zweck | +|------------|-------| +| `UnifiedDataBar (UDB)` | Multi-Tab-Panel: Chats, Files, Sources — wird in Workspace und CommCoach genutzt | +| `FormGenerator` | Dynamische Formulare/Tabellen aus Backend-Attribut-Definitionen | +| `FolderTree` | Rekursiver Ordnerbaum mit Drag&Drop, Multi-Selection, Inline-Editing | +| `MandateNavigation` | Feature-Baum-Navigation mit Mandanten-Kontext | +| `Automation2FlowEditor` | n8n-style Flow-Builder für Automation2 | +| `WorkspacePage` | AI-Workspace mit Chat, UDB, Agent-Streaming | + +## Routing + +- **Einstieg:** `main.tsx` rendert `App.tsx` mit Providern (z. B. Sprache, Auth) und **React Router** (`Routes` / `Route`). +- **Geschützte Bereiche:** Route-Guards (z. B. `ProtectedRoute`) prüfen Authentifizierung; Redirect bei fehlender Session. +- **Haupt-App:** Nach Login typischerweise ein Home-/Shell-Layout mit **Sidebar** und **PageManager**. +- **Seiten-Mapping:** `PageManager` + Konfiguration (z. B. `pageConfigs`) — lazy geladene Page-Komponenten, Sidebar-Metadaten, optional `preserveState` für Navigation ohne State-Verlust. +- **i18n / Theme:** global über Context; API-Requests mit Auth-Header (Interceptor in zentralem API-Client). + +## UI-Regeln + +- **Keine Browser-Dialoge** (`alert` / `confirm` / `prompt`) — stattdessen `useConfirm()` und `usePrompt()` Hooks +- Alle internen Funktionen mit `_` Prefix +- camelCase für Variablen und Funktionen + +## Schlüssel-Dateien + +| Datei / Bereich | Rolle | +|-----------------|--------| +| `main.tsx` | Application Entry Point | +| `App.tsx` | Root-Komponente, Router-Setup, Provider | +| `api.ts` (Root) | Axios-Instanz, Base URL, Token-Interceptor, 401-Handling | +| `core/` / `components/PageManager/` | Dynamisches Laden, Animationen, Lifecycle, Caching | +| `pageConfigs` (o. ä.) | Lazy Imports, Sidebar-Einträge, Page-Metadaten | +| `auth/authConfig`, `authProvider`, `ProtectedRoute` | MSAL, geschützte Routen | +| `contexts/*` | FileContext, PekContext, Toast, Workflow-Auswahl, etc. | +| `locales/*` | Übersetzungen (z. B. de / en / fr) | + +## Regeln / Invarianten + +- **Feature-Organisation:** UI, Logic (`*Logic`), Types und CSS Modules pro Feature-Modul trennen; Exporte über `index.ts` wo üblich. +- **Datenfluss:** Pages → Feature-Komponenten → Hooks → `useApi` / API-Module → Gateway; Fehler nicht verschlucken, konsistente Backend-Fehlerdarstellung. +- **Performance:** Seiten lazy laden; bei konfigurierten Seiten State Preservation nutzen. +- **Styling:** CSS Modules, Theme über CSS-Variablen (Light/Dark) wo vorgesehen. +- **Typisierung:** TypeScript durchgängig; API-Response-Typen an den Grenzen definieren. +- **Naming:** Komponenten PascalCase, Hooks `use*`, interne Hilfsfunktionen `_` + camelCase — kein `snake_case` in neuem Frontend-Code. diff --git a/b-reference/gateway/ai-agent.md b/b-reference/gateway/ai-agent.md new file mode 100644 index 0000000..9bcbb96 --- /dev/null +++ b/b-reference/gateway/ai-agent.md @@ -0,0 +1,237 @@ + + + + +# AI Agent & Knowledge Store + +## Überblick + +Der **AI-Agent** ist der Service `serviceAgent` (`AgentService`) im **ServiceCenter**. Er orchestriert einen **ReAct-Loop** mit nativer Function Calling-Unterstützung: pro Runde ruft das Modell `serviceAi` auf; bei Tool-Calls werden Handler über die **Tool Registry** ausgeführt und Ergebnisse wieder in den Konversationskontext gegeben. Er ist die zentrale Schicht für den **Workspace** (Chat, Streaming, Tools, Dateien, externe Quellen). + +Darunter liegt **`serviceAi`** als Low-Level-Gateway (Billing-Preflight, Provider-/Modellwahl, Neutralisierung vor Modellaufruf). **`serviceKnowledge`** liefert **RAG**: Indexierung extrahierter Inhalte, semantische Suche (pgvector) und **`buildAgentContext`** für kontextuelle Injektion vor jeder Agent-Runde. + +Der **AI-Core** (`gateway/modules/aicore/`) kapselt Provider-Plugins und die Modellwahl; der Agent nutzt ihn indirekt über `serviceAi` (u. a. `OperationTypeEnum.AGENT`, Embeddings für den Knowledge Store). + +--- + +## Agent Core + +### ServiceCenter-Integration + +| Registry-Key | Klasse | `objectKey` | Dependencies (laut `registry.py`) | +|--------------|--------|-------------|-----------------------------------| +| `agent` | `AgentService` | `service.agent` | `ai`, `chat`, `utils`, `extraction`, `billing`, `streaming`, `knowledge` | +| `knowledge` | `KnowledgeService` | `service.knowledge` | `ai` | + +Pro Request propagiert der **ServiceCenterContext** u. a. `userId`, `mandateId`, `featureInstanceId` und optional `requireNeutralization` (siehe Invarianten). + +### Ablauf (Ist-Code) + +- **Einstieg:** `AgentService.runAgent` (`mainServiceAgent.py`) — baut die Tool Registry, optional Anreicherung des Prompts mit Datei-Metadaten/`FileContentIndex`, startet `runAgentLoop` (`agentLoop.py`). +- **Loop:** `runAgentLoop` — `ConversationManager` + Systemprompt; **pro Runde:** optional RAG via `buildRagContextFn`, Budget-Check, **Progressive Summarization** bei Bedarf (`ConversationManager`, Modell-Operation `DATA_ANALYSE`), dann `AiCallRequest` mit `OperationTypeEnum.AGENT`, `messages`, `tools`. +- **Tool Registry:** `_registerCoreTools` in `mainServiceAgent.py` registriert die Kern-Tools; **`ActionToolAdapter`** registriert alle Workflow-Actions mit `dynamicMode=True` als zusätzliche Tools (`method_action` → intern `executeAction`). +- **Parallele Ausführung:** In `_executeToolCalls` werden als **`readOnly=True`** markierte Tool-Calls parallel (`asyncio.gather`), schreibende/übrige sequentiell — vermeidet Race Conditions bei zustandsändernden Tools. +- **Budget:** `AgentConfig.maxCostCHF` — vor jeder Runde Abgleich mit Workflow-Kosten; bei Überschreitung Status `budgetExceeded` und abschliessender Fortschritts-Text (`FINAL`). +- **Rundenlimit:** `AgentConfig.maxRounds` (Default 25); bei Erreichen während `running` → Status `maxRoundsReached` und Fortschritts-Zusammenfassung. +- **Degradation:** Schlägt RAG-Injektion fehl, wird nur geloggt (**non-blocking**); der Agent läuft ohne diesen Kontext weiter. Fehlgeschlagene RoundMemory-Persistenz ebenfalls non-blocking. +- **Streaming:** Optional `aiCallStreamFn` — Chunks als `CHUNK`-Events; Abschluss u. a. `AGENT_SUMMARY` mit Kosten- und Round-Metriken; Trace kann über Knowledge-Entities persistiert werden (`_persistTrace`). + +### Konfiguration (`datamodelAgent.AgentConfig`, Ist) + +| Feld | Bedeutung | +|------|-----------| +| `maxRounds` | Max. Schleifenrunden (Default 25, 1–100) | +| `maxCostCHF` | Optionales Workflow-Budget in CHF | +| `toolSet` | Aktives Tool-Set (Default `"core"`) | +| `temperature` | Optional für den Agent-AI-Call | + +### RBAC (Architekturentscheid) + +Keine separate Tool-Level-RBAC: Zugriff wird über **Datenbank-RBAC** (z. B. File-Queries), **OAuth/Connections** bei externen Quellen und **`serviceAi`** (Billing, Provider-/Modell-RBAC) sowie **`can_access_service`** für `service.agent` durchgesetzt. + +--- + +## Agent Tools + +### Prinzip + +Tools sind registrierte Handler mit JSON-Schema für Argumente, **`readOnly`-Flag** (Parallelisierung) und optional `toolSet`. Tool-Ausgaben sind Rohdaten für das Modell; **Neutralisierung vor dem LLM** erfolgt zentral in `serviceAi`, nicht in den Tools. + +Zusätzlich zu den unten genannten **Kern-Tools** existieren **dynamische Tools** aus dem Workflow-System: `ActionToolAdapter` liest `methodDiscovery.methods` und registriert jede Action mit `dynamicMode=True` unter einem zusammengesetzten Namen (`{methodShort}_{actionName}`); im Adapter sind diese derzeit **alle als nicht-readOnly** registriert. + +### Kern-Tools (registriert in `_registerCoreTools`, 40 Stück) + +**Workspace / Dateien** + +| Tool | Kurzbeschreibung | +|------|------------------| +| `readFile` | Dateiinhalt lesen (optional zeilenweise) | +| `listFiles` | Dateien filtern (Ordner, Tags, Suche) | +| `searchInFileContent` | Suche im Dateiinhalt | +| `writeFile` | Datei anlegen / anhängen / überschreiben | +| `deleteFile` | Datei löschen | +| `renameFile` | Umbenennen | +| `moveFile` | Verschieben (Ordner) | +| `tagFile` | Tags setzen | +| `copyFile` | Unabhängige Kopie | +| `replaceInFile` | Ersetzen im Text | + +**Ordner** + +| Tool | Kurzbeschreibung | +|------|------------------| +| `listFolders` | Ordner auflisten | +| `createFolder` | Ordner anlegen | +| `deleteFolder` | Ordner löschen (optional rekursiv) | +| `renameFolder` | Ordner umbenennen | +| `moveFolder` | Ordner verschieben | + +**Web & Sprache** + +| Tool | Kurzbeschreibung | +|------|------------------| +| `webSearch` | Websuche | +| `readUrl` | Inhalt einer bekannten URL laden | +| `translateText` | Übersetzung (Voice/Translation-Pipeline) | +| `textToSpeech` | TTS | +| `speechToText` | Transkription Audio-Datei | +| `detectLanguage` | Spracherkennung für Text | + +**Externe Datenquellen / Mail** + +| Tool | Kurzbeschreibung | +|------|------------------| +| `listConnections` | User-Connections auflisten | +| `browseDataSource` | Externe Quelle durchsuchen | +| `searchDataSource` | Suche in Datenquelle | +| `downloadFromDataSource` | Download → FileItem (inkl. Vererbung `neutralize` auf Datei, siehe Invarianten) | +| `uploadToExternal` | Upload zu externer Quelle | +| `sendMail` | E-Mail senden | + +**Dokumente / Content-Objekte** + +| Tool | Kurzbeschreibung | +|------|------------------| +| `browseContainer` | Struktur-Index (Seiten, Abschnitte, …) | +| `readContentObjects` | Gezielt Content-Objekte lesen | +| `extractContainerItem` | Element aus Container extrahieren | +| `summarizeContent` | KI-Zusammenfassung | +| `describeImage` | Vision-Analyse | +| `renderDocument` | Dokument rendern | +| `generateImage` | Bildgenerierung | +| `createChart` | Chart erzeugen | + +**Feature / Workflow** + +| Tool | Kurzbeschreibung | +|------|------------------| +| `queryFeatureInstance` | Abfrage anderer Feature-Instanz (setzt bei Bedarf `requireNeutralization` für Sub-Calls) | +| `listWorkflowHistory` | Workflow-Historie | +| `readWorkflowMessages` | Nachrichten eines Workflows lesen | + +**Sicherheit / Ausführung** + +| Tool | Kurzbeschreibung | +|------|------------------| +| `neutralizeData` | Anonymisierter Text (non-destructive) | +| `executeCode` | Sandboxed Code-Ausführung (siehe `sandboxExecutor.py`) | + +--- + +## AI-Core (Provider-Abstraction) + +| Komponente | Datei / Rolle | +|------------|----------------| +| **Model Registry** | `aicoreModelRegistry.py` — registriert Provider-Plugins und Modelle | +| **Model Selector** | `aicoreModelSelector.py` — Auswahl nach Operationstyp, Promptgrösse, Restriktionen, Ranking | + +### Provider-Plugins (Dateien unter `gateway/modules/aicore/`) + +| Plugin-Modul | Typische Rolle | +|--------------|----------------| +| `aicorePluginAnthropic.py` | Claude-Modelle | +| `aicorePluginOpenai.py` | GPT, Embeddings, Bild | +| `aicorePluginMistral.py` | Mistral Chat / Embed | +| `aicorePluginPerplexity.py` | Sonar / Recherche | +| `aicorePluginTavily.py` | Web-Suche | +| `aicorePluginPrivateLlm.py` | Private LLM | +| `aicorePluginInternal.py` | Interne Extraktion/Generierung/Rendering | + +### Operation Types (`datamodelAi.OperationTypeEnum`, Auszug) + +u. a. `plan`, `dataAnalyse`, `dataGenerate`, `dataExtract`, `imageAnalyse`, `imageGenerate`, `neutralizationText`, `neutralizationImage`, `webSearch`, `webCrawl`, **`agent`**, **`embedding`**, `speechTeams`. + +Der Agent-Loop verwendet **`AGENT`** für Hauptrunden und **`DATA_ANALYSE`** für Summarization-Calls; Embeddings laufen über die Knowledge-Service-Pipeline (`callEmbedding`). + +--- + +## Knowledge Store (RAG) + +### Datenmodelle (`datamodelKnowledge.py`) + +| Modell | Zweck | +|--------|--------| +| **FileContentIndex** | Strukturindex pro Datei (ohne LLM): `structure`, `objectSummary`, `status`, Spiegelung von Mandat/Instanz über **`scope`** (`personal`, `featureInstance`, `mandate`, `global`), Neutralisierungs-Felder `isNeutralized`, `neutralizationStatus` | +| **ContentChunk** | Persistente Chunks mit Embedding (`vector(1536)`), `data`, `contextRef`, `contentType` | +| **RoundMemory** | Pro Runde: `file_ref`, Tool-Ergebnisse, Entscheidungen — mit Embedding für semantische Wiederverwendung trotz ConversationManager-Kürzung | +| **WorkflowMemory** | Workflow-scoped Key-Value-Cache (Entities, Fakten, inkl. optional Embedding) | + +Zugriff über **`interfaceDbKnowledge`** (`FileContentIndex`, `ContentChunk`, RoundMemory, WorkflowMemory). + +### Indexierung + +**`KnowledgeService.indexFile`** — nach Extraktion (Content-Objekte): übernimmt Scope aus **FileItem** als Single Source of Truth; bei `FileItem.neutralize=True` werden Inhalte vor dem Speichern neutralisiert; Chunking (u. a. `DEFAULT_CHUNK_TOKENS` / Zeichen-Heuristik), Embedding via AI-Service, Persistenz von Index + Chunks; optional Billing-Reconciliation für Mandats-Speicher. + +### Semantische Suche & Kontext + +**`buildAgentContext`** — priorisierte Schichten (Ist-Code, vereinfacht): + +1. **RoundMemory** `file_ref` („Known Files“) +2. **Instance/personal/mandate/global** — `semanticSearch` mit Query-Embedding (Limit/Score wie im Code) +3. **RoundMemory** semantisch (`semanticSearchRoundMemory`) +4. **Workflow-Entities** (`getWorkflowEntities`) +5. **Mandate-Scope** — geteilte Mandats-Dokumente („Shared Knowledge“) +6. Optional **Cross-Workflow-Hints** (`workflowHintItems`) + +Rückgabe: formatierter String für Injektion in den Agent-Systemkontext. **Wenn Embedding fehlschlägt**, liefert `buildAgentContext` einen **leeren String** (Agent arbeitet ohne diesen RAG-Block). + +Erweiterte Hilfen (z. B. **`readSection`**, Caching) für selektives Lesen sind im selben Service dokumentiert. + +--- + +## Schlüssel-Dateien + +| Datei | Rolle | +|-------|--------| +| `gateway/modules/serviceCenter/registry.py` | Registrierung `agent`, `knowledge`, Dependencies, `objectKey` | +| `gateway/modules/serviceCenter/services/serviceAgent/mainServiceAgent.py` | `AgentService`, Tool-Registrierung, `runAgent`, DataSource/Neutralize-Hooks | +| `gateway/modules/serviceCenter/services/serviceAgent/agentLoop.py` | ReAct-Loop, Budget, RAG-Injektion, Tool-Dispatch, Summaries | +| `gateway/modules/serviceCenter/services/serviceAgent/toolRegistry.py` | Registrierung, Dispatch, `readOnly`, Function-Calling-Format | +| `gateway/modules/serviceCenter/services/serviceAgent/conversationManager.py` | Kontextfenster, Summarization, Systemprompt | +| `gateway/modules/serviceCenter/services/serviceAgent/datamodelAgent.py` | `AgentConfig`, Events, Trace-Modelle | +| `gateway/modules/serviceCenter/services/serviceAgent/actionToolAdapter.py` | Workflow-Actions → Agent-Tools | +| `gateway/modules/serviceCenter/services/serviceAgent/sandboxExecutor.py` | `executeCode`-Sandbox | +| `gateway/modules/serviceCenter/services/serviceKnowledge/mainServiceKnowledge.py` | Index, `buildAgentContext`, Workflow-/Round-Memory-Helfer | +| `gateway/modules/interfaces/interfaceDbKnowledge.py` | DB-Zugriff Knowledge / RAG | +| `gateway/modules/datamodels/datamodelKnowledge.py` | FileContentIndex, ContentChunk, RoundMemory, WorkflowMemory | +| `gateway/modules/serviceCenter/services/serviceAi/mainServiceAi.py` | Zentrales Neutralisierungs-Gate vor LLM, Billing, Provider-Aufruf | +| `gateway/modules/aicore/aicoreModelRegistry.py` | Provider-/Modell-Registry | +| `gateway/modules/aicore/aicoreModelSelector.py` | Modellauswahl | +| `gateway/modules/aicore/aicorePlugin*.py` | Provider-Implementierungen | +| `gateway/modules/datamodels/datamodelAi.py` | `OperationTypeEnum`, `AiCallRequest`, Optionen | + +--- + +## Regeln / Invarianten + +1. **Neutralisierung vor dem Modell:** Alle an ein LLM gehenden Inhalte (Prompt, Kontext, Messages) werden ausschliesslich in **`serviceAi`** entsprechend Policy neutralisiert bzw. blockiert — nicht in den Agent-Tools. +2. **Tools liefern Rohdaten:** Kein zweites Neutralisieren in Tools; Ausnahme ist bewusste **Data-at-rest**-Neutralisierung beim **Indexieren** (`indexFile` bei `FileItem.neutralize=True`). +3. **DataSource → FileItem:** `_downloadFromDataSource` vererbt das **`neutralize`-Flag** der DataSource auf erzeugte Dateien; **`queryFeatureInstance`** kann Sub-Agent-Calls mit **`requireNeutralization=True`** auslösen, wenn die Feature-Datenquelle das vorsieht. +4. **Kein Tool-RBAC:** Autorisierung über Datenbank-, Connection- und Service-Schicht. +5. **Parallele Tools nur bei `readOnly=True`:** Schreibende Tools nicht parallel zueinander aus demselben Batch. +6. **RAG optional:** Embedding- oder DB-Fehler im Kontextpfad führen nicht zwingend zum Abbruch des Agent-Runs (RAG wird übersprungen/entfällt). +7. **Billing:** AI-Calls und eingebettete Pfade (Embeddings, Summaries) laufen über bestehende Billing-/Subscription-Checks in `serviceAi` bzw. aufrufenden Schichten. + +Detaillierte Neutralisierungs-Kette und Compliance: **`wiki/compliance/Neutralisierung.md`**. + +Architektur-Roadmap (Unified Workspace, ProviderConnector 1:n, Phasenplan): **`wiki/concepts/AI-Agent-Architecture-Konzept.md`** — als Zielbild lesen, nicht als Ist-Abbild aller Codepfade. diff --git a/b-reference/gateway/architecture.md b/b-reference/gateway/architecture.md new file mode 100644 index 0000000..dfb8b4b --- /dev/null +++ b/b-reference/gateway/architecture.md @@ -0,0 +1,106 @@ + + + + +# Gateway -- Architektur + +## Überblick + +Das Gateway ist das Python-Backend der PowerOn-Plattform (FastAPI, PostgreSQL). Es kapselt Mandanten- und Feature-Logik hinter einer REST-API und folgt einer klaren Schichtenfolge: **Connectors** sprechen externe Systeme und Datenbanken an, **Interfaces** normalisieren Zugriffe und DTOs, **Services** bündeln fachliche Operationen darauf, und das **ServiceCenter** löst diese Services pro Request mit einheitlichem Kontext auf. Routen in `modules/routes/` sind der HTTP-Einstieg; Security-Middleware und gemeinsame Utilities liegen in `modules/security/` bzw. `modules/shared/`. Feature-spezifische Domänen leben in `modules/features/` als weitgehend autonome Module. + +## Modulstruktur + +Unter `gateway/modules/` (Kontext-Audit): + +| Modul | Zweck | +|-------|-------| +| `aicore/` | Model-Registry, Model-Selector, Provider-Plugins (Anthropic, OpenAI, Mistral, Perplexity, Tavily, PrivateLLM) | +| `auth/` | Authentifizierung | +| `connectors/` | DB-Connector (PostgreSQL), externe Konnektoren | +| `datamodels/` | Pydantic-Datenmodelle (u. a. Ai, Billing, Chat, Content, Files, Knowledge, Rbac, Subscription, Workflow) | +| `features/` | Feature-Module (autonome Domänen): workspace, automation, automation2, chatbot, commcoach, neutralization, realEstate, trustee, teamsbot | +| `interfaces/` | DB-Interfaces (App, Billing, Chat, Knowledge, Management, Subscription), AI-Objects, RBAC, Features, Messaging | +| `migration/` | Daten-Migrationen | +| `routes/` | REST-API-Routen (u. a. Admin, Billing, DataFiles, DataSources, Security, Store, System) | +| `security/` | Sicherheits-Middleware | +| `serviceCenter/` | Zentrale Service-Orchestrierung (Registry, Resolver, Kontext, Haupt-Services) | +| `serviceHub/` | Service-Registry und Dependency Injection (u. a. `PublicService`-Wrapper) | +| `shared/` | Gemeinsame Utilities (attributeUtils, Konfiguration, Logging, …) | +| `system/` | System-Konfiguration | +| `workflows/` | Workflow-Engine mit Methoden und Aktionen | + +## ServiceCenter (Kern-Orchestrierung) + +Das ServiceCenter ist die zentrale Schicht, die Kern- und importierbare Services verbindet. Pro Request/Session wird ein **`ServiceCenterContext`** (`serviceCenter/context.py`) mitgeführt und propagiert u. a.: + +- `userId`, `mandateId`, `featureInstanceId` +- `requireNeutralization` (optional) — Neutralisierungsflag auf Chat-Ebene +- Provider-Restrictions, Billing-Context + +Die öffentliche API umfasst u. a. `getService(key, context)` zur Auflösung einer Service-Instanz; registrierte Services sind in `registry.py` als **CORE_SERVICES** und **IMPORTABLE_SERVICES** hinterlegt, mit feature-spezifischer Auflösung und optionaler Vorabladung (`preWarm`). + +### Services (`serviceCenter/services/`) + +| Service | Hauptmodul (Auszug) | Zweck | +|---------|---------------------|-------| +| `serviceAgent` | `mainServiceAgent.py` | AI-Agent mit vielen Tools (u. a. Dateien, Suche, Container, Web, Mail) | +| `serviceAi` | `mainServiceAi.py` | AI-Call-Gateway: Neutralisierung, Billing-Preflight, Provider-Auswahl, Streaming, Extraktion, Generierung | +| `serviceKnowledge` | `mainServiceKnowledge.py` | Knowledge Store: Indexierung, semantische Suche, RAG-Kontext (`buildAgentContext`) | +| `serviceBilling` | `mainServiceBilling.py` | Billing-Checks, Transaktionen | +| `serviceChat` | `mainServiceChat.py` | Chat-Persistenz | +| `serviceExtraction` | `mainServiceExtraction.py` | Dokument-Extraktion (PDF, DOCX, XLSX, …) | +| `serviceGeneration` | `mainServiceGeneration.py` | Dokument-Generierung | +| `serviceMessaging` | `mainServiceMessaging.py` | E-Mail, Notifications | +| `serviceSubscription` | `mainServiceSubscription.py` | Subscription-Verwaltung | +| `serviceWeb` | `mainServiceWeb.py` | Web-Scraping | + +**Hinweis (Agent):** Agent-Tools liefern Rohdaten; Neutralisierung vor dem Versand an ein Sprachmodell erfolgt zentral im **serviceAi** (`mainServiceAi.py`), nicht in den Tools selbst. + +### Einordnung (Framework) + +Daten- und Steuerfluss: **Client oder Workflow → Service Center → Service → Interface → Connector → externes System**. Das Service Center bündelt dabei Erkennbarkeit (Registry), Konfiguration und querschnittliche Aspekte wie Logging, RBAC-Objekt-Registrierung (`registerServiceObjects`) und konsistente Service-Lebenszyklen; **`serviceHub`** ergänzt dies mit **`PublicService`**, sodass nur bewusst exponierte Methoden nach außen sichtbar sind. + +## Interfaces (DB-Schicht) + +Die genannten Module kapseln die Datenbankzugriffe bzw. die zugehörigen Fachverträge (Audit-Liste): + +| Interface | Verantwortlich für | +|-----------|-------------------| +| `interfaceDbApp.py` | User, Mandate, FeatureAccess, UserConnections, Preferences | +| `interfaceDbBilling.py` | BillingAccount, BillingTransaction, Subscriptions | +| `interfaceDbChat.py` | ChatWorkflow, ChatMessage, ChatDocument | +| `interfaceDbKnowledge.py` | FileContentIndex, ContentChunk, RoundMemory (RAG/Knowledge Store) | +| `interfaceDbManagement.py` | FileItem, Folder, Prompt, DataSource (mandantenweite Stammdaten) | +| `interfaceDbSubscription.py` | Subscription-Verwaltung | +| `interfaceAiObjects.py` | AI-Call-Abstraktion (Text, Embedding, Vision, Streaming) | +| `interfaceFeatures.py` | Feature-Instanz-Lifecycle, Template-Rollen-Kopie | +| `interfaceRbac.py` | RBAC-Regelauswertung | + +Weitere Interface-Dateien im Ordner (z. B. Voice, Tickets, Messaging, Bootstrap) erfüllen dieselbe Normalisierungsrolle gegenüber Connectors bzw. externen APIs; die Tabelle oben entspricht der expliziten DB-/Kern-Zuordnung aus dem Kontext-Audit. + +## Schlüssel-Dateien + +| Datei / Pfad | Rolle | +|--------------|-------| +| `gateway/app.py` | FastAPI-Anwendung, Einbindung von Routen und Middleware | +| `gateway/modules/serviceCenter/__init__.py` | Service Center: `getService`, `preWarm`, RBAC-Registrierung für Service-Objekte | +| `gateway/modules/serviceCenter/context.py` | `ServiceCenterContext` pro Request | +| `gateway/modules/serviceCenter/registry.py` | Service-Registry (CORE / IMPORTABLE) | +| `gateway/modules/serviceCenter/resolver.py` | Auflösung von Service-Instanzen inkl. Cache | +| `gateway/modules/serviceHub/__init__.py` | Hub / DI, `PublicService`-Wrapper für kontrollierte Oberflächen | +| `gateway/modules/routes/*.py` | HTTP-Endpunkte, Aufruf in Richtung Service Center / Features | +| `gateway/modules/interfaces/*.py` | Stabile Verträge und DB-Zugriffe (keine direkte Vendor-Logik in Services) | +| `gateway/modules/connectors/*.py` | Vendor-spezifische Adapter (Auth, Transport, Mapping) | +| `gateway/modules/security/*` | CSRF, Token-Refresh-Middleware, JWT/Auth-Utilities | +| `gateway/modules/shared/*` | Querschnitt: Konfiguration, Audit-Logging, Events, Utilities | +| `gateway/modules/features/init.py` | Initiale Trigger beim App-Start | +| `gateway/modules/workflows/workflowManager.py` | Zentrale Workflow-Steuerung | + +## Regeln / Invarianten + +- **Schichten:** Connectors sind anbieterspezifisch und ersetzbar; **Services hängen von Interfaces ab, nicht direkt von Connectors**. Geschäftslogik und Guardrails liegen in den Services. +- **Datenbank:** Persistenz und die genannten Domänen-Reads/Writes laufen über die **Interface**-Schicht, nicht ad hoc aus Routen heraus. +- **Service Center:** Aufrufe laufen über die zentrale Auflösung (`getService` + Kontext); Workflows und Routen konsumieren dieselbe Landschaft. +- **Sicherheit & Governance:** RBAC und Geheimnisse werden zentral geführt; Service-Aufrufe und Workflow-Schritte sollen nachvollziehbar sein (Audit); Kontingente und Limits pro Mandant/Service sind vorgesehen. +- **HTTP-Einstieg:** Globale Middleware u. a. CSRF und Token-Refresh; zusätzliche AuthN/AuthZ-Utilities unter `modules/security/`. +- **Code-Konventionen (Projekt):** Interne Hilfsfunktionen mit Präfix **`_`**; Bezeichner in **camelCase** für Variablen und Funktionen. diff --git a/concepts/Automation Business Spec.md b/b-reference/gateway/automation-business-spec.md similarity index 100% rename from concepts/Automation Business Spec.md rename to b-reference/gateway/automation-business-spec.md diff --git a/concepts/Automation Data Model.md b/b-reference/gateway/automation-data-model.md similarity index 100% rename from concepts/Automation Data Model.md rename to b-reference/gateway/automation-data-model.md diff --git a/b-reference/gateway/automation.md b/b-reference/gateway/automation.md new file mode 100644 index 0000000..df03c12 --- /dev/null +++ b/b-reference/gateway/automation.md @@ -0,0 +1,97 @@ + + + + +# Automation + +## Überblick + +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). + +**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. + +--- + +## Business Spec (Zusammenfassung) + +**Ist-Systeme:** + +| System | Kurzbeschreibung | +|--------|------------------| +| **Automation v1** | Template + Cron + Placeholders; robuster inkrementeller Scheduler-Sync; keine visuelle Branching-Logik. | +| **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`. + +**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 + +| Aspekt | Automation v1 | Automation2 (v2) | +|--------|----------------|------------------| +| Modell | Template/Cron/Placeholders | Graph + Node-Typen (`nodeDefinitions/`) | +| DB / Schema | `poweron_automation` | `poweron_automation2` | +| Scheduler | Inkrementell, Callback `automation.changed`, `eventId` auf Workflow | u.a. 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 | + +**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. + +--- + +## Schlüssel-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`) | +| Feature-Discovery | `system/registry.py`, `serviceHub/__init__.py` | +| RBAC | `interfaces/interfaceRbac.py`, `security/`, Rollen/AccessRules in Datamodels | + +--- + +## 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. +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 new file mode 100644 index 0000000..e946f66 --- /dev/null +++ b/b-reference/gateway/billing.md @@ -0,0 +1,186 @@ + + + + +# Billing & Subscriptions + +## Überblick + +Die Plattform trennt zwei Ebenen: + +1. **Usage-Billing (LLM-Verbrauch):** Prepaid-Guthaben in CHF, Buchung pro AI-Operation (`priceCHF`), Transaktionen mit Mandanten- und Provider-Kontext. Zentrale Erfassung über Billing-Interfaces und `serviceBilling`; Integration im AI-Pfad (`mainServiceAi`). +2. **Mandanten-Subscription (SaaS-Lizenz):** Wiederkehrende Pläne, Kapazitäten (User-Seats, Feature-Instanzen), Stripe für Plattformgebühr und Zahlungsstatus. Vorgesehen als eigener Domänen-Service `serviceSubscription`, gekoppelt an Billing-Checks. + +**Gateway-Audit (2026-03-29):** Produktseitig liegt der Schwerpunkt auf **PREPAY_MANDATE** (gemeinsames Mandantenkonto); Billing-Checks und Datenvolumen-Assertions laufen vor AI-Calls. Ergänzend beschreiben die Konzeptdokumente Subscription-Pflicht, Stripe und eine explizite Zustandsmaschine. + +Ohne gültige, zahlungswirksame Subscription (soweit implementiert) sollen **nur AI-Calls** blockiert werden; Lesen, Navigation und Datenhaltung bleiben möglich. `Mandate.enabled` bleibt für technische Sperren; Subscription steuert die geschäftliche Nutzbarkeit von KI-Funktionen. + +--- + +## Billing-Modell + +### Abrechnungseinheit und Hierarchie + +- **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`) + +| 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. + +### Kernentitäten + +- **`BillingAccount`:** Guthaben (`balance` CHF), optional `userId` bei `PREPAY_USER`, `accountType` MANDATE | USER, `warningThreshold`, `enabled`. +- **`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). +- **`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. + +### Provider-Steuerung (RBAC) + +- Ressourcen: `resource.aicore.{connectorType}` mit Aktion `USE`. +- Keine parallele Provider-Whitelist in den Chat-Tabellen; Filterung bei Modellauswahl über erlaubte Provider / RBAC. + +--- + +## Subscription-System + +### Abgrenzung zu Usage-Billing + +- **Billing:** Verbrauch, Guthaben, Transaktionen. +- **Subscription:** Vertrag, Laufzeit, Stripe-Subscription, Kapazitätsregeln, Status für „darf der Mandant KI nutzen“. + +Empfohlene Platzierung: **`serviceSubscription`** parallel zu `serviceBilling` im Service Center; Persistenz im gemeinsamen Billing-Kontext (z. B. DB `poweron_billing`). **`BillingService.checkBalance`** soll intern **`SubscriptionService.assertActive(mandateId)`** aufrufen, damit Call-Sites (z. B. `mainServiceAi`) eine zusammengefasste Prüfung behalten. + +### Pläne und Kapazität + +- **Katalog `SubscriptionPlan`:** u. a. `planKey`, mehrsprachige Texte, `billingPeriod` (`monthly` | `yearly` | `none`), `pricePerUserCHF` / `pricePerFeatureInstanceCHF`, optional `maxUsers` / `maxFeatureInstances` (`None` = unbegrenzt), `trialDays`, `successorPlanKey`, Stripe-Product/Price-IDs für User- und Instance-Items. +- **Instanz `MandateSubscription`:** `mandateId`, `planKey`, Snapshot-Preise, Status, Laufzeit (`startedAt`, `endedAt`, `currentPeriodStart` / `currentPeriodEnd`, `trialEndsAt`), Stripe-IDs (`stripeSubscriptionId`, Item-IDs für User/Instanzen). + +### Nutzungsbasierte Mengen (Stripe) + +- Zwei Subscription-Items mit dynamischer **Quantity:** aktive `UserMandate` (`enabled = true`) und aktive `FeatureInstance` (`enabled = true`). Änderungen an User/Instanz → DB-Update → **Stripe `subscription_items.update`** mit Proration (Standard: `create_prorations`). +- **Trial:** harte Caps (Konzept: z. B. `maxUsers: 1`, `maxFeatureInstances: 3`). **Standard/Enterprise:** ohne harte Plan-Caps, rein nutzungsbasiert. **Root:** Plan `ROOT`, `billingPeriod: none`, keine Stripe-Subscription, unbegrenzt; Usage-Billing kann **PREPAY_USER** mit Startguthaben bleiben. + +### Source of Truth + +- **App** führt Plan-Definitionen und Entitlements; Anlage/Änderung von Products/Prices über Stripe-API aus der App, nicht ad hoc im Dashboard. +- **Stripe** liefert Source of Truth für **Zahlungsstatus**; Webhooks (`invoice.paid`, `invoice.payment_failed`, `customer.subscription.updated`, …) synchronisieren in die lokale DB. + +### Integration (Konzept) + +- **AI-Hot-Path:** Subscription-Status (gecacht, TTL z. B. 60 s) + bestehende Balance-Prüfung; erweiterte `BillingCheckResult`-Gründe (`SUBSCRIPTION_INACTIVE`, …) und UI-Pfade (`subscriptionUiPath`, `userAction`). +- **Mutationen:** Cap-Check nur bei Plänen mit Limits; danach Stripe-Quantity-Sync. Periodischer Job: Abgleich Stripe-Quantity vs. DB-Counts. +- **Downgrade:** nur wenn `aktive User/Instanzen ≤ neue Plan-Caps`. + +Referenz **Gateway-Audit** zu Prepaid-Beispielen: Trial **5 CHF**, Standard **10 CHF/Monat** — als kompakte Audit-Angabe; detaillierte Plan-Beispiele (z. B. CHF pro Seat/Instanz und Periode) stehen in den Subscription-Konzepttabellen. + +--- + +## Subscription State Machine + +### Grundregeln + +- Pro Mandant ist höchstens **eine** Subscription **operativ** im Sinne von **`ACTIVE` oder `TRIALING`** (für volle KI-Nutzung laut Konzept; siehe unten zu `PAST_DUE`). +- Zusätzlich höchstens eine in **`PENDING`** oder **`SCHEDULED`** (Wechsel while Vorgänger läuft). +- Wechsel bei laufendem Abo: Vorgänger **`recurring = false`** (Stripe `cancel_at_period_end`), neues Abo startet nach Periodenende des Vorgängers bzw. laut Scheduler/Webhook. +- **`CANCELLED` als Status entfällt:** gekündigt = **`ACTIVE`** mit **`recurring = false`** bis Periodenende, danach **`EXPIRED`**. + +### Felder (Ergänzung zum Instanzmodell) + +- **`recurring: bool`** — automatische Verlängerung vs. Auslauf am Periodenende. +- **`effectiveFrom: Optional[datetime]`** — bei `SCHEDULED`: Wirksamkeit ab Periodenende des Vorgängers; `None` = sofort. + +### Zustände + +| State | Bedeutung | +|-------|-----------| +| **PENDING** | Checkout gestartet, Zahlung noch nicht bestätigt | +| **SCHEDULED** | Bestätigt, wartet auf Ende des Vorgänger-Abos | +| **TRIALING** | Testphase | +| **ACTIVE** | Bezahlt / laufend (ggf. `recurring` false bei Kündigung zum Laufzeitende) | +| **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). + +### Erlaubte Statusübergänge (Kernmenge) + +Alle Writes mit expliziter **`subscriptionId`**; Validierung zentral (z. B. `transitionStatus(from, to)`). + +- `PENDING` → `ACTIVE` | `SCHEDULED` | `EXPIRED` +- `SCHEDULED` → `ACTIVE` | `EXPIRED` +- `TRIALING` → `EXPIRED` +- `ACTIVE` → `PAST_DUE` | `EXPIRED` +- `PAST_DUE` → `ACTIVE` | `EXPIRED` + +Typische Trigger: Stripe-Webhooks (`checkout.session.completed`, `invoice.payment_failed`, `customer.subscription.updated` / `deleted`), Admin-Aktionen (Kündigung = `recurring` false, Force-Cancel = sofort `EXPIRED`), Trial-Ende (Cron/Webhook). + +--- + +## Billing-Checks + +### AI-Call (Hot Path) + +- **`mainServiceAi`:** `_preflightBillingCheck` und **`_checkBillingBeforeAiCall`** vor Provider-Auswahl bzw. Call. +- Reihenfolge (Zielbild nach Konzept): zuerst **Subscription aktiv** (`assertActive` / eingebettet in `checkBalance`), dann **Guthaben** (`checkBalance` / Prepaid), um unnötige DB-Runden zu vermeiden. +- **Datenvolumen:** **`assertCapacity("dataVolumeMB")`** prüft die RAG-Index-Grösse (Gateway-Kontext). + +### Mutationen (kein Hot Path) + +- Kapazitäts-Caps (**`assertCapacity`**) bei User-Zuordnung und Feature-Instanz-Erstellung, nicht bei jedem AI-Request. +- Nach Änderungen: Stripe-Quantity-Sync. + +### Konsistenz-Job + +- Vergleich Stripe-Quantities mit DB-Counts; bei Drift Korrektur Richtung DB und Benachrichtigung. + +--- + +## Schlüssel-Dateien + +| Datei / Bereich | Rolle | +|-----------------|--------| +| `serviceCenter/services/serviceBilling/` | Balance, Usage-Recording, Orchestrierung mit Subscription-Assert (Zielbild) | +| `serviceCenter/services/serviceAi/mainServiceAi.py` | `_preflightBillingCheck`, `_checkBillingBeforeAiCall`, zentrales AI-Gate | +| `serviceCenter/services/serviceSubscription/` | Subscription-Domäne, Cache, Stripe-Sync, Trial (vorgesehen) | +| `serviceCenter/registry.py` | Registrierung `billing`, `subscription` | +| `interfaces/interfaceDbBilling.py` | `BillingAccount`, `BillingTransaction`, `checkBalance` | +| `interfaces/interfaceDbSubscription.py` | Subscription-CRUD, `assertActive`, `assertCapacity` (vorgesehen) | +| `interfaces/interfaceDbApp.py` | `createUserMandate` / Root-Zuordnung — Hooks für Cap + Stripe-Quantity | +| `routes/routeBilling.py` | Billing-APIs, Stripe Checkout Top-Up / Webhooks | +| `routes/routeAdminFeatures.py` | `create_feature_instance` — Cap + Quantity-Sync (vorgesehen) | +| `routes/routeSubscription.py` | Plan-Aktivierung, Status, Wechsel (vorgesehen) | +| `datamodels/datamodelBilling.py` | `BillingSettings`, Transaktionen, `stripeCustomerId` | +| `datamodels/datamodelSubscription.py` | `SubscriptionPlan`, `MandateSubscription` (vorgesehen) | +| `features/workspace/routeFeatureWorkspace.py` | Pattern für Billing-/Fehlerantworten an UI | +| `aicore/aicoreModelSelector.py` | Filter nach erlaubten Providern | +| `aicore/*Plugin*.py` | `connectorType`, Preislogik CHF | +| `frontend_nyla/src/pages/billing/*` | Dashboard, Admin, Stripe-Flow, Subscription-UI | +| `frontend_nyla/src/hooks/useBilling.ts` | Billing-Settings / Subscription-Daten | +| `frontend_nyla/src/pages/views/workspace/useWorkspace.ts` | `billingUiPath` / User-Actions — gleiches Muster für Subscription-Pfade | + +--- + +## Regeln / Invarianten + +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. +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`. +7. **Aktive Zählung:** nur `UserMandate.enabled` und `FeatureInstance.enabled`; Einladungen und Deaktivierte zählen nicht für Quantity/Caps. +8. **`BillingService.checkBalance`** soll **`SubscriptionService.assertActive`** kapseln, damit der AI-Pfad nicht doppelt verteilt ist. +9. **Kapazität** (User/Instanz-Limits) an **Mutations-Endpunkten** enforce’n, **nicht** auf jedem AI-Call. +10. **Root-Mandant:** systemische Subscription ohne Stripe-Abrechnung; unbegrenzte Seats/Instanzen; Usage-Billing kann **PREPAY_USER** mit Bootstrap-Guthaben bleiben. diff --git a/b-reference/gateway/workflow.md b/b-reference/gateway/workflow.md new file mode 100644 index 0000000..2680131 --- /dev/null +++ b/b-reference/gateway/workflow.md @@ -0,0 +1,94 @@ + + + + +# Workflow-Engine + +## Überblick + +Die Workflow-Engine im Gateway orchestriert KI-gestützte Aufgabenpläne und die Ausführung einzelner **Aktionen** über eine gemeinsame **Method/Action-Bibliothek**. Sie verbindet die Schichten *Workflow* → *Methods* → *Services* → *Interfaces* → *Connectors*; Workflows importieren bewusst **nicht** direkt Interfaces, Connectors oder `aicore` (Zugriff über Services). + +**Einsatzorte (Konsumenten der Action Library):** + +- **Workspace (Dynamic Mode):** `WorkflowProcessor` / `modeDynamic` → Planung (Stage 1/2) → `ActionExecutor` +- **Automation v1:** `WorkflowProcessor` / `modeAutomation` → `ActionExecutor` +- **Automation2:** Graph-Engine mappt Nodes (`_method` / `_action`) auf dieselbe Library +- **Workspace-Agent:** `ActionToolAdapter` exponiert `dynamicMode=True`-Aktionen als Tools → `ActionExecutor` + +**Ausführungsmodell:** Pro Workflow-Instanz sequentielle Ausführung (kein paralleles Multi-Task-Modell auf einer Instanz). Ausführungszähler (`currentRound`, `currentTask`, `currentAction`) liegen am **`ChatWorkflow`** (Single Source of Truth). + +--- + +## WorkflowManager + +Zentrale Steuerung in `gateway/modules/workflows/workflowManager.py` (grosse Datei; Einstieg für Start/Stopp und Hauptloop). + +**Öffentliche / zentrale Verantwortlichkeiten (Konzept):** + +| Bereich | Inhalt | +|--------|--------| +| Lebenszyklus | Start eines Workflow-Laufs, Verarbeitungsschleife, Beendigung | +| Planung | Aufgaben- und Aktionsplanung (modusabhängig; KI-Planning über Services) | +| Ausführung | Abarbeitung von Tasks/Actions in definierter Reihenfolge | +| Zustand | Anbindung an persistierten `ChatWorkflow` / Chat-DB über Service- und Interface-Schicht | + +**Workflow-Zustände (konzeptionell):** `running`, `stopped`, `completed`, `failed`. + +**Modi (Dokumentation):** Klassische Beschreibung nennt u.a. **React** (iterativ, begrenzte Schritte) und **Actionplan** (Plan upfront, ein Pfad). Die erweiterte Planungsarchitektur (`ai_plan_architecture.md`) beschreibt zusätzlich **dynamischen Modus** mit zweistufiger Aktionsplanung (Stage 1: Aktionswahl + Ressourcen; optional Stage 2: Parametergenerierung). + +--- + +## Methoden + +Methoden sind Python-Klassen unter `gateway/modules/workflows/methods/`; der **Methodenname** (`self.name`) ist der Registry-Schlüssel (z. B. `ai`, `context`). Aktionen sind über `WorkflowActionDefinition` registriert; viele tragen `actionId` im Muster `.` und `dynamicMode=True` für den Agent/Graph. + +| Method (`self.name`) | Actions (Registry-Keys) | +|---------------------|-------------------------| +| `context` | `getDocumentIndex`, `extractContent`, `neutralizeData`, `triggerPreprocessingServer` | +| `ai` | `process`, `webResearch`, `summarizeDocument`, `translateDocument`, `convertDocument`, `generateDocument`, `generateCode` | +| `outlook` | `readEmails`, `searchEmails`, `composeAndDraftEmailWithContext`, `sendDraftEmail` | +| `sharepoint` | `findDocumentPath`, `readDocuments`, `uploadDocument`, `listDocuments`, `analyzeFolderUsage`, `findSiteByUrl`, `downloadFileByPath`, `copyFile`, `uploadFile` | +| `clickup` | `listTasks`, `searchTasks`, `getTask`, `createTask`, `updateTask`, `uploadAttachment` | +| `jira` | `connectJira`, `exportTicketsAsJson`, `importTicketsFromJson`, `mergeTicketData`, `parseCsvContent`, `parseExcelContent`, `createCsvContent`, `createExcelContent` | +| `trustee` | `extractFromFiles`, `processDocuments`, `syncToAccounting` | +| `chatbot` | `queryDatabase` | +| `file` | `create` | + +*Hinweis:* Ältere Kontext-Dokumente nennen für `context` u. a. `saveContent` / `transformContent`; der aktuelle Gateway-Stand listet die obigen Aktionen (Stand Abgleich Code / Review 2026-04-05). + +--- + +## Aktionen + +- **Registrierung:** Jede Aktion ist eine `WorkflowActionDefinition` mit Metadaten, Parametern (`WorkflowActionParameter`, u. a. `FrontendType`) und `execute`-Callable. +- **Ausführung:** `ActionExecutor` löst `methodName` + `actionName` auf, validiert Parameter (Action Registry / Pydantic je nach Implementierung) und liefert ein **`ActionResult`** (Erfolg, Dokumente, Fehler). +- **Dokumente:** Ergebnisse werden typischerweise als strukturierte **`ActionDocument`** / Extraktionsartefakte (`ContentExtracted` / `ContentPart`) weitergereicht. +- **Extraktion vs. KI:** Zielarchitektur (siehe `ai_plan_architecture.md`): **reine Extraktion** (`context.extractContent` bzw. dokumentbezogene Pipeline) ist von **KI-Aufrufen** (`serviceAi`) zu trennen; KI-Methoden arbeiten bevorzugt mit bereits extrahierten `ContentPart`-Strukturen. +- **Planung:** Stage 1 liefert u. a. `action` (`method.action`), Zieltext, optional `documentList` / `connectionReference`; Stage 2 ergänzt bei Bedarf das Parameter-JSON ohne die Stage-1-Ressourcen zu überschreiben. + +--- + +## Schlüssel-Dateien + +| Pfad (unter `gateway/modules/`) | Rolle | +|--------------------------------|--------| +| `workflows/workflowManager.py` | Workflow-Orchestrierung, Einstieg | +| `workflows/processing/` | Processor, Modi (`modeReact`, `modeActionplan`, `modeDynamic`, …), `ActionExecutor` | +| `workflows/methods/methodBase.py` | Basis für Methoden, Aktions-Validierung | +| `workflows/methods/method*/` | Konkrete Methoden und Aktionen | +| `datamodels/datamodelChat.py` | `ChatWorkflow`, `TaskContext`, Task-/Plan-Modelle | +| `datamodels/datamodelWorkflowActions.py` | Aktionsdefinitionen | +| `services/serviceWorkflow/` | Fortschritt, Logs, Nachrichten/Dokumente am Workflow | +| `services/serviceAi/` | Planning- und Content-KI (kein direkter Workflow-Import aus Methods zurück) | +| `interfaces/interfaceDbChat*` | Persistenz Workflow/Nachrichten/Dokumente | + +--- + +## Regeln / Invarianten + +1. **Schichten-Imports:** Workflows importieren nur `datamodels`, `services`, interne `workflows/*`. Methods importieren `datamodels`, `services`, `workflows.methods.*` — **keine** direkten Interface-/Connector-/aicore-Imports in Methods. +2. **Zustand am Workflow:** Rund-/Task-/Action-Indices und Kontext gehören zum **`ChatWorkflow`** / `TaskContext`, nicht als lose Parameter durch alle Ebenen. +3. **Typisierung:** Bevorzugt Pydantic-Modelle für Planungs- und Aktionskontext (`ActionDefinition`, `TaskResult`, …); JSON aus KI-Calls über zentrale Parse-/Repair-Hilfen. +4. **Sequenz:** Ein Workflow läuft in einer Instanz sequentiell ab; parallele Ausführung ist kein Designziel der beschriebenen Engine. +5. **Neutralisierung:** Sensible Daten an **KI-Modelle** laufen über das zentrale Gate in `serviceAi` (`mainServiceAi.py`); die Workflow-Aktion `context.neutralizeData` ist eine **explizite** Neutralisierung extrahierter Inhalte und ersetzt nicht das globale KI-Gate (siehe Compliance-Doku). +6. **Gemeinsame Library:** Dieselben Actions werden von Chat-Workflow, Automation v1/v2 und Agent-Tools genutzt — Änderungen an `actionId` / Parametern wirken quer über alle Konsumenten. diff --git a/b-reference/platform/navigation.md b/b-reference/platform/navigation.md new file mode 100644 index 0000000..deef305 --- /dev/null +++ b/b-reference/platform/navigation.md @@ -0,0 +1,85 @@ + + + + +# Navigation API + +## Überblick + +Die Navigation-API ist die **Single Source of Truth** für die Navigationsstruktur: Das **Gateway** entscheidet, welche Einträge ein Benutzer sieht; das **UI** rendert nur die gelieferte Struktur — **keine** parallele Berechtigungslogik im Frontend für die Navigation. Die API liefert **keine** Darstellungsassets (Icons, CSS); stattdessen **UI-Komponenten-Codes** (`uiComponent`), die im Client (z. B. `PAGE_REGISTRY`) auf Komponenten gemappt werden. Einträge ohne Berechtigung erscheinen **nicht** im Baum (kein `hasAccess: false`). Unbekannte `uiComponent`-Codes sollen im UI **sichtbar als Fehler** gemeldet werden, damit Gateway/UI-Drift auffällt. + +**Ziel-Endpoint (Konzept):** `GET /api/navigation` mit Antwort u. a. `language`, `blocks[]`. +**Ist-Stand (Audit):** Statische Navigation u. a. über `GET /api/system/navigation` mit `sections` — Migration auf kombinierten Endpoint und `blocks`-Schema ist im Konzept dokumentiert. + +**Personalisierung:** Sortierung über numerisches `order`; User-Overrides in Settings (`navOrder`), Merge im Gateway: `EffektiveOrder = User-Override ?? Default ?? 50`. Update-Konzept: `PUT /api/user/settings/navOrder`. + +Aktuelle UI-Bezüge im Kontext: `MandateNavigation`, Hook `useNavigation` (`frontend_nyla`). + +## Block-Struktur + +Die Antwort besteht aus einer geordneten Liste von **Blocks**: + +- **`type`:** `static` oder `dynamic` +- **`id`:** z. B. `system`, `workflows`, `basedata`, `admin`, `features` +- **`title`:** Anzeige-Gruppentitel +- **`order`:** Reihenfolge der Blöcke + +**Static Block:** enthält `items[]` mit Navigationsknoten auf System-/Admin-/Basisdaten-Seiten. + +**Dynamic Block:** enthält `mandates[]` → je Mandat `features[]` → `instances[]` → `views[]`. Der dynamische Block fehlt, wenn der User keine zugängliche Feature-Instanz hat. + +**Item-Felder (Static / Views):** + +| Feld | Bedeutung | +|------|-----------| +| `uiComponent` | Eindeutiger Code für das UI-Mapping | +| `uiLabel` | Text in der gewählten Sprache | +| `uiPath` | URL-Pfad | +| `order` | Sortierung innerhalb der Ebene | +| `objectKey` | Vollqualifizierter RBAC-Bezug (UI-Kontext), z. B. `ui.system.home` | + +## Static Blocks (System, Basedata, Admin) + +Typische **static** Blöcke im Konzept: + +- **`system`:** mandatsübergreifende Systemseiten (z. B. Home, Einstellungen) — `page.system.*`, ObjectKeys `ui.system.*`. +- **`workflows`:** Workflow-bezogene Systemseiten (z. B. Playground, Chat-Liste) — ebenfalls `page.system.*` / `ui.system.*` im Beispiel. +- **`basedata`:** Stammdaten (z. B. Prompts, Dateien) — weiterhin `page.system.*` mit Pfaden unter `/basedata/...`. +- **`admin`:** Administration — `page.admin.*`, ObjectKeys `ui.admin.*` (Benutzer, Mandanten, …). + +Die exakte Liste und Default-`order` stammen aus der Gateway-Konfiguration (`NAVIGATION_SECTIONS` in `mainSystem.py` laut Analyse — Felder teilweise noch `label`/`path`/`icon`; Zielmapping: `uiLabel`/`uiPath`, ohne `icon` in der API). + +## Dynamic Block (Features) + +- **`id`:** typischerweise `features` +- Hierarchie: **Mandat** → **Feature-Typ** (`uiComponent` z. B. `feature.trustee`) → **Instanz** → **Views** (`page.feature..`) +- Pfade enthalten Mandats- und Instanz-IDs (siehe Konzeptbeispiele) +- Sortierung auf allen Ebenen über jeweiliges `order` (Mandat, Feature, Instanz, View) + +## RBAC-Integration + +- **`objectKey`** in Navigationsitems entspricht dem **`item`**-String im **UI-Kontext** der Access Rules (vollqualifiziert), z. B. `ui.feature.trustee.dashboard`. +- Navigation-Endpoint wendet **Permission-Filter** an, bevor die Response gebaut wird — nur erlaubte Knoten sind enthalten. +- Konventionen (Kontext UI): `ui.system.`, `ui.admin.`, `ui.feature..`. Für DATA/RESOURCE siehe übergreifendes RBAC-Dokument (`data.*`, `resource.*`). +- **Inkonsistenz-Hinweis (Audit):** Template-Rollen dürfen keine Kurz-`item`-Namen (`dashboard`) nutzen, wenn `objectKey` vollqualifiziert ist — `item` und Navigation müssen übereinstimmen. + +## Schlüssel-Dateien + +| Schicht | Pfad / Artefakt | +|---------|------------------| +| Statische Sektionen (Gateway) | `mainSystem.py` — `NAVIGATION_SECTIONS` | +| Navigation-Route | `routeSystem.py` — Endpoint-Evolution `/api/system/navigation` → `/api/navigation` | +| Feature-Views / Template-Rollen | z. B. `mainTrustee.py`, `mainRealEstate.py` — `UI_OBJECTS`, `TEMPLATE_ROLES` | +| Admin-Feature-Permission (Ist teils feature-spezifisch) | `routeAdminFeatures.py` — z. B. `_deriveViewPermissions` | +| Frontend: Navigation | `MandateNavigation.tsx`, `useNavigation` | +| Frontend: Registry (Ziel) | `frontend_nyla/src/config/pageRegistry.ts` — `PAGE_REGISTRY`, `FEATURE_REGISTRY` | +| Legacy-Duplikate (Audit) | `mandate.ts` — `FEATURE_REGISTRY` / View-Definitionen parallel zum Backend | + +## Regeln / Invarianten + +- **Backend autoritativ:** Keine eigenständige Zusammenstellung der Navigationsstruktur im UI aus mehreren Quellen ohne Gateway-Abgleich (Zielzustand: ein Endpoint, ein Baum). +- **Nur sichtbare Knoten:** Keine negativen Sichtbarkeitsflags in der Response. +- **Sortierung:** ausschließlich vom Gateway; das UI sortiert empfangene Listen nicht erneut. +- **`uiComponent`-Konventionen:** `page.system.`, `page.admin.`, `page.feature..`, Feature-Gruppe `feature.`. +- **Drift sichtbar machen:** Unbekannte Codes im UI als Fehler anzeigen, nicht still ignorieren. +- Vollständiges API-Konzept und Migrationsphasen: `wiki/concepts/Navigation-API-Konzept.md`. diff --git a/b-reference/platform/neutralization.md b/b-reference/platform/neutralization.md new file mode 100644 index 0000000..0af4c5d --- /dev/null +++ b/b-reference/platform/neutralization.md @@ -0,0 +1,81 @@ + + + + +# Neutralisierungs-System + +## Überblick + +Neutralisierung ersetzt mandantensensible Inhalte durch stabile Platzhalter, bevor Text an externe KI-Modelle geht oder dauerhaft im RAG landet. Rohdaten aus Tools werden nicht separat „nachgefiltert“: der Schutz liegt am **Content-Einstieg** (Indexierung, Extraktion, zentrales AI-Gate) und an vererbten Flags auf `FileItem` / Session / Feature-Konfiguration. + +## Architektur: Einzige zentrale Stelle + +**Für jeden AI-Modell-Call** gilt: Prompt, RAG-Kontext und Chat-Nachrichten werden **ausschließlich** in `mainServiceAi.py` geprüft und neutralisiert (`_shouldNeutralize`, `_neutralizeRequest`). Kein anderes Modul entscheidet parallel „stattdessen“ für dieselbe Modell-Schnittstelle. + +Orthogonal dazu (kein Ersatz des Gates, sondern Data-at-rest bzw. Workflow): + +- **RAG:** `mainServiceKnowledge.indexFile()` neutralisiert Chunks bei `FileItem.neutralize=True`. +- **Agent:** DataSource- und FeatureDataSource-Flags setzen bzw. vererben Neutralisierungspflicht; Sub-Agent-Calls können `requireNeutralization=True` tragen. +- **Workflows:** Aktion `neutralizeData` neutralisiert explizit extrahierte ContentParts (prüft u. a. `NeutralizationConfig.enabled`, nicht das Session-Flag). + +## Neutralisierungs-Trigger (Prioritätsreihenfolge) + +**Am AI-Gate (`_shouldNeutralize`)** (Auswertung in der dokumentierten Reihenfolge): + +1. **Pro Request:** `AiCallRequest.requireNeutralization` — expliziter Override auf dem Call. +2. **Chat-/Session-Level:** `ServiceCenterContext.requireNeutralization` (z. B. Workspace, Automation). +3. **Mandanten-/Feature-Konfiguration:** `NeutralizationConfig.enabled` (DataNeutraliser / Feature-Instanz). + +**Quellen gesamt (OR-Logik):** Ist irgendwo Neutralisierung erforderlich (Feature-Instanz, Workflow/Session, konkretes Objekt mit `FileItem.neutralize` / `DataSource.neutralize` / `FeatureDataSource.neutralize`), wird entsprechend verarbeitet. Dokumentierte Produktregel: **Kein `False` von einer Quelle hebt ein `True` einer anderen auf.** + +## Was neutralisiert wird + +Im zentralen AI-Gate (`_neutralizeRequest`): + +- `request.prompt` +- `request.context` (RAG-Kontext) +- `request.messages` (OpenAI-artige Nachrichten) + +**Engine** (`NeutralizationService`): `processText`, `processFile`, `processBinaryBytes` (synchron/asynchron); Rückübersetzung über `resolveText` / Mappings. Modell-Familien u. a. `NEUTRALIZATION_TEXT` / `NEUTRALIZATION_IMAGE` (Private-LLM-Plugin; externe Provider ohne diese Ratings werden für Neutralisierung nicht gewählt). + +**Nicht erneut neutralisieren:** Bereits neutral indexierte RAG-Chunks; Web-Suchergebnisse ohne Mandantendaten (laut Spezifikation). + +**Bekannter Ist-Stand Medien:** Bild-Binary wird in der Engine derzeit weitgehend durchgereicht bzw. übersprungen — dedizierter Bild-Neutralisierungspfad ist in der Fachdoku als Lücke / Soll beschrieben, nicht als abgeschlossene Implementierung ausgewiesen. + +## Failsafe-Kette + +1. **Toggle `FileItem.neutralize`:** Index und Chunks werden synchron gelöscht; Re-Index im Hintergrund verhindert Leaks bei Fehlern in der Nachindexierung. +2. **Indexierung:** `indexFile()` neutralisiert Text-Chunks bei `FileItem.neutralize=True` → Data-at-rest abgesichert. +3. **DataSource-Download:** `neutralize`-Flag wird auf erzeugte `FileItem`s vererbt. +4. **FeatureDataSource:** `_queryFeatureInstance()` setzt bei `neutralize=True` u. a. `requireNeutralization=True` für Sub-Agent-AI-Calls. +5. **AI-Call:** Bei erzwungener Neutralisierung (`requireNeutralization=True`) schlägt fehlgeschlagene Neutralisierung hart fehl (`RuntimeError` / Blockierung bzw. Entfernen betroffener Message-Teile — kein Durchleiten im Rohzustand). +6. **`_rehydrateResponse()`:** Als Hilfsmethode vorhanden; automatische Rückübersetzung der Modellantwort ist nicht mehr der Standardpfad. + +**Engine-Failsafe (Spezifikation):** Neutralisierung verlangt, Engine nicht verfügbar → nicht weiterverarbeiten; Teilfehler → Teil entfernen, nicht roh weitergeben; fehlendes internes Medienmodell → Medien-Part entfernen. + +## NeutralizationPanel (Frontend) + +`frontend_nyla/src/pages/views/workspace/NeutralizationPanel.tsx` — Übersicht zu Dateien mit `neutralize`-Flag, Status und Platzhalter-Mappings. Datenbasis u. a. `GET /api/workspace/{instanceId}/files` → `{ files: [...] }`. + +## Schlüssel-Dateien + +| Bereich | Pfad | +|--------|------| +| **Zentrales AI-Gate** | `serviceCenter/services/serviceAi/mainServiceAi.py` | +| **Neutralisierungs-Engine** | `features/neutralization/serviceNeutralization/mainServiceNeutralization.py` (+ `subProcess*.py`) | +| **Feature-Config / DB** | `features/neutralization/datamodelFeatureNeutralizer.py`, `interfaceFeatureNeutralizer.py` | +| **RAG-Index** | `serviceCenter/services/serviceKnowledge/mainServiceKnowledge.py` | +| **Agent / Quellen** | `serviceCenter/services/serviceAgent/mainServiceAgent.py` (`_resolveDataSource`, `_downloadFromDataSource`, `_queryFeatureInstance`) | +| **Datei-Toggle / Index** | `routes/routeDataFiles.py` — `PATCH /{fileId}/neutralize` | +| **Workflow-Aktion** | `workflows/methods/methodContext/actions/neutralizeData.py` | +| **Kontext** | `serviceCenter/context.py` — `requireNeutralization` | +| **Flags (Modelle)** | `datamodels/datamodelFiles.py` (`FileItem.neutralize`), `datamodelDataSource.py`, `datamodelFeatureDataSource.py` | +| **AI-Operationen / Enums** | `datamodels/datamodelAi.py`, `aicore/aicorePluginPrivateLlm.py` | + +## Regeln / Invarianten + +- **Ein Gate pro Modell-Call:** Sämtlicher Text in Richtung externes LLM für diesen Call läuft über `mainServiceAi` — keine parallele „zweite“ Neutralisierungstelle für dieselbe Schnittstelle. +- **Hard-Mode:** `requireNeutralization=True` und Neutralisierung scheitert → Call blockieren bzw. Inhalt nicht im Klartext an das Modell geben. +- **Kein stilles Weiterreichen** sensibler Inhalte bei Pflicht zur Neutralisierung. +- **Platzhalter:** Mapping `[typ.uuid]` in der DB; `resolveText` für kontrollierte Rückübersetzung. +- Detaillierte Compliance- und Prozessbeschreibung: `wiki/compliance/Neutralisierung.md`. diff --git a/b-reference/platform/rbac.md b/b-reference/platform/rbac.md new file mode 100644 index 0000000..30d7e22 --- /dev/null +++ b/b-reference/platform/rbac.md @@ -0,0 +1,69 @@ + + + + +# RBAC-System + +## Überblick + +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. + +## 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` | + +**Invariante:** Mandantenrollen und Feature-Instanz-Rollen **nicht vermischen** — kein Zuweisen eines Mandanten-Labels zu `FeatureAccessRole` oder umgekehrt. + +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. + +## Access Rules (DATA / UI / RESOURCE) + +### 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`). + +### Spezifität (pro Rolle) + +Innerhalb **einer** Rolle gewinnt die **spezifischste** passende Regel (längster passender Präfix/exakter `item`) gegenüber generischen Regeln (`item = null`). + +### Mehrere Rollen + +Ü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. + +### DATA: Öffnungsrechte (CUD vs. Read) + +- 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. + +### Systemfelder (DATA) + +Felder `id` und Namen mit führendem `_` sind für Anwendungs-CUD geschützt; Connector erzwingt das unabhängig von Access Rules. + +### Frontend-Optionen für Rollen + +`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/frontendOptionsTypes.py`. + +## Schlüssel-Dateien + +| Rolle | 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/appdoc/doc_security_role_based_access.md` | + +## 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. diff --git a/b-reference/private-llm/architecture.md b/b-reference/private-llm/architecture.md new file mode 100644 index 0000000..b38b0f0 --- /dev/null +++ b/b-reference/private-llm/architecture.md @@ -0,0 +1,66 @@ + + + + +# Private LLM -- Architektur + +## Überblick + +Eigenständiger Service für die Verarbeitung sensitiver Daten mit lokalen AI-Modellen (Ollama). Läuft auf einem dedizierten GPU-Server (Infomaniak Swiss Cloud) und wird vom Gateway als Provider-Plugin (`aicorePluginPrivateLlm.py`) angesprochen. Kein Datenabfluss an externe Cloud-APIs. + +## Technologie-Stack + +| Layer | Technologie | +|-------|------------| +| Framework | FastAPI (Python) | +| AI Runtime | Ollama (lokale Vision/Text-Modelle) | +| PDF-Support | PyMuPDF (fitz) | +| Hosting | Infomaniak Swiss Cloud (GPU) | +| Deployment | GitHub Actions → `main` Branch | + +## Modelle + +| Externer Name | Internes Ollama-Modell | Typ | +|--------------|----------------------|-----| +| `poweron-text-general` | `qwen2.5:7b` | Text | +| `poweron-vision-general` | `qwen2.5vl:7b` | Vision | +| `poweron-vision-deep` | `granite3.2-vision` | Vision | + +## API-Routen + +| Modul | Zweck | +|-------|-------| +| `routeApi.py` | Analyse-API: Bild-/PDF-Analyse mit Prompt, Modellauswahl | +| `routeOpenAi.py` | OpenAI-kompatibles Chat-Completion-API (für Cursor-Integration) | +| `routeWeb.py` | Web-UI für manuelle Tests | + +## Integration mit Gateway + +Der Gateway nutzt das Private LLM über `aicorePluginPrivateLlm.py` als Provider für: +- **Neutralisierung:** Text-Analyse mit `poweron-text-general` +- **Sensitive Datenverarbeitung:** Vision-Analyse von Dokumenten (Rechnungen, Belege, Handschrift) +- **Keine Billing-Kosten** für mandanteninterne LLM-Calls (eigene Infrastruktur) + +## Sicherheit + +- API-Key-Authentifizierung (`X-API-Key` Header) +- Separater Cursor-API-Key für OpenAI-kompatible Endpoints (Bearer Token) +- Rate-Limiting per API-Key (Token Bucket, konfigurierbar) +- Konfiguration über `config.ini` + Environment-Variablen (Secrets nie im Code) + +## Schlüssel-Dateien + +| Datei | Rolle | +|-------|-------| +| `app.py` | FastAPI-Einstieg, Router-Mount | +| `config.py` | Konfiguration, Model-Mapping, Auth, Rate-Limiting, Request/Response-Modelle | +| `routeApi.py` | Analyse-Endpunkte (Bild, PDF) | +| `routeOpenAi.py` | OpenAI-kompatibles Chat-API | +| `routeWeb.py` | Test-UI | + +## Regeln / Invarianten + +- Alle Daten werden **lokal** verarbeitet -- kein Weiterleiten an externe APIs +- Model-Mapping ist die einzige Stelle für Namensauflösung (`MODEL_MAPPING` in `config.py`) +- API-Keys werden aus `config.ini` oder Environment gelesen, nie hardcoded +- PDF-Verarbeitung rendert Seiten als Bilder für Vision-Modelle (max 5 Seiten) diff --git a/b-reference/product.md b/b-reference/product.md new file mode 100644 index 0000000..e978913 --- /dev/null +++ b/b-reference/product.md @@ -0,0 +1,56 @@ + + + +# PowerOn Portal -- Komponentenübersicht + +## Produkt + +PowerOn Portal ist eine Multi-Tenant SaaS-Plattform mit Feature-Store-Modell, AI-Agent-Workspace und mandantenweiter Datenneutralisierung. + +## Komponenten + +| Komponente | Repository | Technologie | Beschreibung | +|-----------|-----------|-------------|-------------| +| Frontend Nyla | frontend_nyla | React/TypeScript, Vite | Zentrales UI für alle Features | +| Gateway | gateway | FastAPI, Python, PostgreSQL | Backend REST-API, Services, AI-Core | +| Private LLM | private-llm | Python | Internes LLM für Neutralisierung + sensitive Daten | +| Teams Bot | service-teams-browser-bot | Node.js/.NET | Bot für Teams-Meeting-Teilnahme | +| Wiki | wiki | Markdown | Dokumentation (dieses Repo) | + +## Technologie-Stack + +| Layer | Technologie | Pfad | +|-------|------------|------| +| Backend (Gateway) | FastAPI (Python), PostgreSQL | `@poweron/gateway` | +| Frontend | React/TypeScript (Vite) | `@poweron/frontend_nyla` | +| AI Core | Multi-Provider (Anthropic, OpenAI, Mistral, Perplexity, Tavily, PrivateLLM) | `@poweron/gateway/modules/aicore` | +| DB-Connector | PostgreSQL mit pgvector (Embeddings) | `@poweron/gateway/modules/connectors/connectorDbPostgre.py` | + +## Feature-Module + +| Feature | Beschreibung | +|---------|-------------| +| `workspace` | AI-Agent-Workspace mit Chat, Tools, RAG, Streaming | +| `automation` | Workflow-Automatisierung (v1) | +| `automation2` | Flow-Editor n8n-Style (v2) | +| `chatbot` | Chatbot-Feature | +| `commcoach` | Kommunikations-Coach mit Voice, Dossier, UDB | +| `neutralization` | Datenneutralisierungs-Service und Config | +| `trustee` | Trustee/Treuhand-Feature (Buchhaltung, Positionen) | +| `realEstate` | Immobilien-Feature | +| `teamsbot` | MS Teams Bot | + +## Coding-Konventionen + +- Alle internen Funktionen beginnen mit `_` Prefix +- camelCase für Variablen und Funktionsnamen (kein snake_case) +- Keine Browser-Dialoge — `useConfirm()` / `usePrompt()` Hooks +- 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` + +## Cross-Cutting Concerns + +- Neutralisierung: Gateway ↔ Private LLM (→ platform/neutralization.md) +- RBAC: Gateway ↔ Frontend (→ platform/rbac.md) +- Navigation: Gateway → Frontend (→ platform/navigation.md) diff --git a/b-reference/teams-bot/architecture.md b/b-reference/teams-bot/architecture.md new file mode 100644 index 0000000..3dd6540 --- /dev/null +++ b/b-reference/teams-bot/architecture.md @@ -0,0 +1,64 @@ + + + + +# Teams Meeting Bot -- Architektur + +## Überblick + +AI-gesteuerter Meeting-Bot für Microsoft Teams. Tritt Meetings als regulärer Teilnehmer bei (Browser-Automation via Playwright/Chromium), erfasst Live-Transkripte, reagiert per Sprache (TTS) und/oder Chat. Kein Teams-Graph-SDK nötig -- funktioniert mandantenübergreifend ohne Admin-Approval. + +## System-Architektur + +``` +┌────────────┐ SSE ┌──────────────┐ WebSocket ┌─────────────┐ +│ Frontend │◄──────────────│ Gateway │◄───────────────│ Bot Service │ +│ (Nyla UI) │ │ (AI, TTS, │ HTTP (join/ │ (Playwright │ +│ │ │ Sessions) │ leave) │ Chromium) │ +└────────────┘ └──────────────┘ └─────────────┘ +``` + +| Verbindung | Protokoll | Zweck | +|------------|----------|-------| +| Gateway ↔ Bot | WebSocket | Echtzeit: Transkripte, Chat, Audio, Status | +| Gateway → Bot | HTTP | Session-Steuerung (join, leave, status) | +| Frontend ← Gateway | SSE | Live-Transkript-Stream für UI | + +## Kernfähigkeiten + +- **Live Transcription:** Erfasst Untertitel mit Sprecher-Zuordnung, streamt via SSE +- **AI-Analyse:** Transkript-Segmente werden durch AI-Modell (GPT-4o-mini / Claude) analysiert +- **Voice Response:** TTS-Audio wird über den Mikrofon-Kanal ins Meeting gespielt +- **Chat Response:** Bot kann Chat-Nachrichten ins Meeting schreiben +- **Multi-Session:** Mehrere Bot-Instanzen parallel in verschiedenen Meetings + +## Use Cases + +| UC | Beschreibung | +|----|-------------| +| AI Meeting Assistant | Bot nimmt teil, hört zu, antwortet auf Ansprache ("Hey Nyla, ...") | +| Live Transcription | Echtzeit-Transkript-Stream für Teilnehmer ausserhalb des Meetings | +| Meeting Summary | AI-generierte Zusammenfassung nach Meeting-Ende | +| Multi-Bot | Mehrere parallele Sessions in verschiedenen Meetings | + +## Integration mit Gateway + +Der Gateway (Feature `teamsbot`) verwaltet Sessions und stellt die AI-Pipeline bereit: +- Session-Lifecycle: erstellen, starten, stoppen +- WebSocket-Verbindung pro Session +- AI-Analyse der Transkript-Segmente via `serviceAi` +- TTS-Generierung für Voice-Responses + +## Schlüssel-Dateien + +| Datei / Bereich | Rolle | +|-----------------|-------| +| `gateway/modules/features/teamsbot/` | Gateway-seitiges Feature-Modul | +| `service-teams-browser-bot/` | Eigenständiger Bot-Service (separates Repository) | + +## Regeln / Invarianten + +- Bot tritt als **regulärer Web-Teilnehmer** bei (Browser-Automation), nicht via Graph Communications SDK +- Jede Session läuft in einer **eigenen Browser-Instanz** (Isolation) +- Authentifizierter Join (mit Microsoft-Account) oder Anonymous Guest -- je nach Konfiguration +- Gateway ist die **einzige** Schnittstelle für AI-Aufrufe und TTS -- der Bot-Service selbst hat keine AI-Logik diff --git a/c-work/1-plan/2026-03-codeeditor-phase1.md b/c-work/1-plan/2026-03-codeeditor-phase1.md new file mode 100644 index 0000000..4a30ad2 --- /dev/null +++ b/c-work/1-plan/2026-03-codeeditor-phase1.md @@ -0,0 +1,85 @@ +# PR: CodeEditor Feature - Phase 1 (MVP) + +## Summary + +Neues Feature "CodeEditor" -- Cursor-artiger AI-gestuetzter Text-Editor als eigenstaendiges Feature im Gateway mit Frontend-Integration in Nyla UI. Komplett unabhaengig vom bestehenden Workflow-System (Option B). + +- Eigenstaendiger Verarbeitungspfad in `features/codeeditor/` ohne Eingriff in `workflowManager.py` +- AI-Aufrufe direkt ueber `interfaceAiObjects.callWithTextContext()` mit voller Model Selection, Failover und Billing +- SSE-Streaming via bestehender `EventManager`-Infrastruktur aus dem Chatbot-Feature +- Frontend: Drei-Panel-Layout (FileList, Chat, DiffPreview) mit Accept/Reject fuer Datei-Aenderungen +- Phase 1 = Single-Shot Mode (1 AI Call pro Prompt). Phase 2 (Agent Loop mit Tool Calling) ist geplant. + +## Neue Dateien + +### Backend (Gateway) + +| Datei | Beschreibung | +|---|---| +| `gateway/modules/features/codeeditor/__init__.py` | Package init | +| `gateway/modules/features/codeeditor/datamodelCodeeditor.py` | Pydantic Models: FileContext, ResponseSegment, FileEditProposal, FileVersion, MIME-Type Validierung | +| `gateway/modules/features/codeeditor/mainCodeeditor.py` | Feature-Registration: RBAC UI/Resource Objects, Template Roles (Plug&Play) | +| `gateway/modules/features/codeeditor/fileContextManager.py` | Text-Dateien aus DB laden, MIME-Type filtern | +| `gateway/modules/features/codeeditor/promptAssembly.py` | System Prompt Builder mit Datei-Kontext und Format-Instruktionen | +| `gateway/modules/features/codeeditor/responseParser.py` | AI-Antwort in typisierte Segmente parsen (text, code_block, file_edit) | +| `gateway/modules/features/codeeditor/codeEditorProcessor.py` | Orchestrator: Files laden -> Prompt bauen -> AI call -> Parse -> SSE emit | +| `gateway/modules/features/codeeditor/routeFeatureCodeeditor.py` | 8 FastAPI Endpoints inkl. SSE Stream | + +### Frontend (Nyla UI) + +| Datei | Beschreibung | +|---|---| +| `frontend_nyla/src/pages/views/codeeditor/CodeEditorPage.tsx` | Drei-Panel-Layout mit resizable Panels | +| `frontend_nyla/src/pages/views/codeeditor/FileListPanel.tsx` | Datei-Auswahl mit Checkboxen | +| `frontend_nyla/src/pages/views/codeeditor/DiffPreviewPanel.tsx` | Diff-Anzeige mit Accept/Reject | +| `frontend_nyla/src/pages/views/codeeditor/useCodeEditor.ts` | SSE Hook mit Auth/CSRF, File-Selection, Edit-State | +| `frontend_nyla/src/pages/views/codeeditor/CodeEditor.module.css` | Styling | +| `frontend_nyla/src/pages/views/codeeditor/index.ts` | Export | + +## Geaenderte Dateien + +| Datei | Aenderung | +|---|---| +| `gateway/modules/datamodels/datamodelChat.py` | `WORKFLOW_CODEEDITOR = "CodeEditor"` zu `WorkflowModeEnum` hinzugefuegt | +| `gateway/modules/routes/routeSystem.py` | `codeeditor` in `_getFeatureUiObjects()` fuer Navigation API | +| `gateway/modules/system/mainSystem.py` | Store-Resource `resource.store.codeeditor` | +| `gateway/modules/interfaces/interfaceBootstrap.py` | `resource.store.codeeditor` in `storeResources` | +| `frontend_nyla/src/pages/FeatureView.tsx` | Import + `codeeditor` in `VIEW_COMPONENTS` Registry | +| `frontend_nyla/src/config/pageRegistry.tsx` | `feature.codeeditor` Icon (FaFileAlt) | +| `frontend_nyla/src/types/mandate.ts` | `codeeditor` in `FEATURE_REGISTRY` mit Views | +| `frontend_nyla/src/pages/Store.tsx` | Icon + Beschreibung fuer Feature Store | +| `frontend_nyla/src/App.tsx` | Route `editor` fuer CodeEditorPage | + +## API Endpoints + +| Endpoint | Methode | Beschreibung | +|---|---|---| +| `/api/codeeditor/{instanceId}/start/stream` | POST | Workflow starten + SSE-Stream | +| `/api/codeeditor/{instanceId}/{workflowId}/stop` | POST | Workflow stoppen | +| `/api/codeeditor/{instanceId}/{workflowId}/chatData` | GET | Polling-Fallback | +| `/api/codeeditor/{instanceId}/workflows` | GET | Workflows auflisten | +| `/api/codeeditor/{instanceId}/files` | GET | Text-Dateien auflisten | +| `/api/codeeditor/{instanceId}/files/{fileId}/content` | GET | Datei-Inhalt laden | +| `/api/codeeditor/{instanceId}/{workflowId}/apply` | POST | Aenderung akzeptieren | + +## Architektur-Entscheide + +- **Option B**: Eigenstaendiger Pfad, kein Eingriff in WorkflowManager/WorkflowProcessor +- **AI-Zugriff**: Direkt ueber `interfaceAiObjects.callWithTextContext()` -- nutzt bestehende Model Selection, Failover, Provider-Filtering, Billing +- **SSE**: Segment-weise Emission (nicht token-weise), da aicore aktuell kein Token-Streaming hat +- **Feature-Discovery**: Plug&Play via `mainCodeeditor.py` + `routeFeatureCodeeditor.py` (automatisch entdeckt durch `registry.py`) + +## Test Plan + +- [ ] Gateway startet ohne Fehler mit neuem Feature +- [ ] Feature erscheint im Feature Store und kann aktiviert werden +- [ ] Navigation zeigt CodeEditor-Instanz mit Icon und Views (Editor, Workflows) +- [ ] Editor-View laedt: FileList links, Chat mitte, DiffPreview rechts +- [ ] Panel-Divider sind verschiebbar +- [ ] Text-Dateien werden in FileList angezeigt (nur text-basierte MIME-Types) +- [ ] Chat-Prompt mit ausgewaehlten Dateien sendet SSE-Request +- [ ] AI-Antwort wird als Chat-Nachrichten gerendert +- [ ] file_edit Vorschlaege erscheinen im DiffPreview Panel +- [ ] Accept/Reject Buttons funktionieren (Accept ueberschreibt Datei in DB) +- [ ] Follow-Up Prompts nutzen bestehenden Workflow (kein neuer Workflow pro Message) +- [ ] Keine Auswirkungen auf bestehende Features (Chatplayground, Automation, Chatbot, Teamsbot) diff --git a/c-work/1-plan/2026-03-cursor-style-chat.md b/c-work/1-plan/2026-03-cursor-style-chat.md new file mode 100644 index 0000000..15843c1 --- /dev/null +++ b/c-work/1-plan/2026-03-cursor-style-chat.md @@ -0,0 +1,263 @@ +--- +name: Cursor-Style Chat Feature MVP +overview: Integration eines Cursor-artigen File-Editing-Chat-Features als neues Feature "codeeditor" im Gateway und der Nyla UI. Nutzt aicore-Modelle direkt, Chat-Datenmodelle vom Chatplayground, SSE-Streaming vom Chatbot-Feature. Nur Text-Dokumente (Markdown, JSON, YAML, Code). Dateien werden hochgeladen (kein SharePoint), spaeter mit virtuellen Folder-Tags strukturiert. Apply erzeugt neue lokale Dokument-Versionen. +todos: + - id: extend-workflow-mode + content: WorkflowModeEnum um WORKFLOW_CODEEDITOR erweitern in datamodelChat.py + FileContext/FileEditProposal Models + status: pending + - id: backend-feature-scaffold + content: "Feature-Scaffold: mainCodeeditor.py (Registrierung) + routeFeatureCodeeditor.py (Endpoints, Vorlage: chatplayground)" + status: pending + - id: file-context-manager + content: "fileContextManager.py: Hochgeladene Text-Dateien laden, Workspace-Snapshot erstellen (kein SharePoint)" + status: pending + - id: prompt-assembly + content: "promptAssembly.py: Cursor-artiger System Prompt Builder mit Datei-Kontext und Format-Instruktionen" + status: pending + - id: response-parser + content: "responseParser.py: AI-Antwort in Document-Segmente parsen (text, code_block, file_edit, etc.)" + status: pending + - id: frontend-feature-register + content: "FeatureView.tsx: codeeditor Views registrieren, CodeEditorPage + FileBrowserPanel + DiffPreviewPanel erstellen" + status: pending + - id: frontend-hooks + content: "useCodeEditor.ts Hook: Erweitert Playground-Pattern um File-Selection und Edit-Management" + status: pending +isProject: false +--- + +# MVP: Cursor-Style File-Editing Chat Feature ("CodeEditor") + +## Professionelle Einschaetzung + +### Kernfrage: aicore-Modelle direkt oder ueber Chat-Komponente? + +**Empfehlung: Die bestehenden aicore-Modelle direkt nutzen** (nicht ueber eine externe Cursor-Chat-Komponente). + +Begruendung: + +- Die aicore-Infrastruktur (`aicoreModelRegistry`, `aicoreModelSelector`, Plugin-System) ist bereits produktionsreif mit Failover, Billing, RBAC und Multi-Provider-Support +- Eine externe Cursor-Komponente wuerde eine Abhaengigkeit schaffen, die schwer zu kontrollieren ist +- Der Mehrwert liegt nicht im LLM-Aufruf (den beherrscht aicore), sondern in der **Prompt-Orchestrierung** (System Prompt + Context + Tool Definitions) und dem **Response Parsing** (Antwort in Dokument-Segmente zerlegen) +- Der neue "Cursor-Style" Layer wird **auf aicore aufgebaut**, nicht neben oder statt aicore + +### Was vom Chatplayground uebernommen werden kann + +Sehr viel -- die Grundarchitektur ist ideal: + +- **ChatWorkflow** Datenmodell: 1:1 wiederverwendbar (neuer `workflowMode: "CodeEditor"`) +- **ChatMessage** + **ChatDocument**: Vollstaendig wiederverwendbar fuer Chat-Verlauf und Datei-Referenzen +- **Polling-Mechanismus** (`getUnifiedChatData` mit `afterTimestamp`): Sofort nutzbar +- **SSE-Infrastruktur** (aus Chatbot-Feature): Kann fuer Echtzeit-Streaming aktiviert werden +- **PlaygroundPage UI-Pattern**: Resizable Two-Column Layout, Messages-Komponente, File-Upload, Input-Footer +- **Route-Pattern** (`routeFeatureChatplayground.py`): Als Vorlage fuer neue Feature-Route +- **Feature-Registrierung**: `VIEW_COMPONENTS` Registry in `FeatureView.tsx`, Backend `mainChatplayground.py` + +### Was NEU gebaut werden muss + +1. **File-Context-Manager** (Backend): Hochgeladene Text-Dateien als "Workspace" laden und als Kontext bereitstellen (kein SharePoint, spaeter virtuelle Folder-Tags) +2. **Prompt Assembly Service** (Backend): System Prompt mit File-Kontext und Cursor-artigen Instruktionen zusammenbauen +3. **Response Document Parser** (Backend): AI-Antwort in typisierte Dokument-Segmente zerlegen (text, code_block, file_edit, etc.) +4. **Diff-Preview UI** (Frontend): Text-Aenderungen als Diff anzeigen mit Accept/Reject +5. **File-List Panel** (Frontend): Hochgeladene Dateien auflisten und als Kontext auswaehlen (spaeter: virtuelle Folder-Tags) +6. **SSE-Integration** (Backend+Frontend): Echtzeit-Streaming ueber bestehende EventManager-Infrastruktur + +--- + +## Architektur + +```mermaid +flowchart TB + subgraph ui [Nyla UI - Frontend] + CodeEditorPage["CodeEditorPage\n(neue View)"] + FileList["FileListPanel\n(hochgeladene Dateien)"] + ChatPanel["ChatPanel\n(Messages + SSE)"] + DiffPreview["DiffPreviewPanel\n(Text-Diffs)"] + CodeEditorPage --> FileList + CodeEditorPage --> ChatPanel + CodeEditorPage --> DiffPreview + end + + subgraph gw [Gateway - Backend] + Route["routeFeatureCodeeditor.py\n(FastAPI Endpoints)"] + SSE["SSE Stream Endpoint\n(EventManager)"] + FileCtx["fileContextManager.py\n(Text-Dateien laden)"] + PromptAsm["promptAssembly.py\n(System Prompt Builder)"] + RespParse["responseParser.py\n(Document Segmentation)"] + Route --> FileCtx + Route --> PromptAsm + PromptAsm --> AiService["serviceAi\n(bestehend)"] + AiService --> AiCore["aicore\n(ModelRegistry + Plugins)"] + RespParse --> Route + RespParse --> SSE + end + + subgraph data [Datenspeicher] + DB["Gateway DB\n(interfaceDbComponent)\nHochgeladene Dateien"] + end + + ChatPanel -->|"POST /api/codeeditor/.../start"| Route + ChatPanel -->|"GET .../stream (SSE)"| SSE + FileList -->|"GET .../files"| Route + DiffPreview -->|"POST .../apply"| Route + FileCtx --> DB +``` + + + +--- + +## MVP Scope: Konkrete Implementierung + +### Backend: Gateway + +**1. Neues Feature `codeeditor`** + +- Datei: `gateway/modules/features/codeeditor/mainCodeeditor.py` +- Registrierung analog zu `mainChatplayground.py` (RBAC, Feature-Config) + +**2. Routes** + +- Datei: `gateway/modules/features/codeeditor/routeFeatureCodeeditor.py` +- Kopie von `routeFeatureChatplayground.py` als Basis, erweitert um: + + +| Endpoint | Methode | Beschreibung | +| -------------------------------------- | ------- | ---------------------------------------------------------- | +| `/{instanceId}/start` | POST | Workflow starten (nutzt `chatStart` mit mode `CodeEditor`) | +| `/{instanceId}/{workflowId}/stop` | POST | Workflow stoppen | +| `/{instanceId}/{workflowId}/stream` | GET | SSE-Stream fuer Echtzeit-Updates (Messages, Logs, Edits) | +| `/{instanceId}/{workflowId}/chatData` | GET | Fallback-Polling fuer Chat-Daten | +| `/{instanceId}/workflows` | GET | Workflows auflisten | +| `/{instanceId}/files` | GET | Hochgeladene Text-Dateien auflisten | +| `/{instanceId}/files/{fileId}/content` | GET | Text-Datei-Inhalt laden | +| `/{instanceId}/{workflowId}/apply` | POST | Aenderung als neue Dokument-Version speichern | + + +**3. WorkflowMode Erweiterung** + +- Datei: `gateway/modules/datamodels/datamodelChat.py` +- Neuer Enum-Wert: `WORKFLOW_CODEEDITOR = "CodeEditor"` in `WorkflowModeEnum` + +**4. File Context Manager** + +- Datei: `gateway/modules/features/codeeditor/fileContextManager.py` +- Laedt hochgeladene Text-Dateien aus Gateway DB (`interfaceDbComponent`) +- Unterstuetzte Formate: `.md`, `.txt`, `.json`, `.yaml`, `.yml`, `.xml`, `.csv`, `.py`, `.js`, `.ts`, `.html`, `.css`, `.sql` +- Baut einen "Workspace-Snapshot": Dateiliste + Inhalte der vom User ausgewaehlten Dateien +- Validiert MIME-Types (nur text-basierte Dateien akzeptieren) +- Spaeter erweiterbar: virtuelle Folder-Tags pro Datei fuer Strukturierung + +**5. Prompt Assembly** + +- Datei: `gateway/modules/features/codeeditor/promptAssembly.py` +- Baut System Prompt nach Cursor-Muster (dokumentiert in `wiki/cursor-doc/doc_cursor_ai_agent_architecture.md`) +- Injiziert: Datei-Kontexte, Benutzer-Instruktionen, Antwort-Format-Vorgaben +- Nutzt `aiService.callAiContent()` oder `interfaceAiObjects.callWithTextContext()` als LLM-Aufruf + +**6. Response Document Parser** + +- Datei: `gateway/modules/features/codeeditor/responseParser.py` +- Parst AI-Antwort in typisierte Segmente: `text`, `code_block`, `code_reference`, `file_edit` +- Speichert Segmente als erweiterte `ChatMessage` Eintraege (mit `actionMethod: "codeeditor"`) +- Spezifikation: `wiki/cursor-doc/doc_cursor_response_json_structure.md` + +### Frontend: Nyla UI + +**7. Feature-Registrierung** + +- Datei: `frontend_nyla/src/pages/FeatureView.tsx` +- Neuer Eintrag in `VIEW_COMPONENTS`: + +```typescript +codeeditor: { + editor: CodeEditorPage, + workflows: WorkflowsPage, // wiederverwendet +} +``` + +**8. CodeEditorPage** + +- Datei: `frontend_nyla/src/pages/views/codeeditor/CodeEditorPage.tsx` +- Drei-Panel-Layout (File-Browser links, Chat mitte, Diff-Preview rechts) +- Nutzt bestehende `Messages` Komponente, `useResizablePanels`, `usePlayground`-Pattern + +**9. File List Panel** + +- Datei: `frontend_nyla/src/components/CodeEditor/FileListPanel.tsx` +- Flache Liste der hochgeladenen Text-Dateien mit Checkbox-Auswahl +- Upload-Button fuer neue Dateien (Drag & Drop wiederverwendet aus Playground) +- Ausgewaehlte Dateien werden als Kontext an den Chat gesendet (analog `listFileId`) +- Spaeter erweiterbar: virtuelle Folder-Tags als Gruppierung + +**10. Diff Preview Panel** + +- Datei: `frontend_nyla/src/components/CodeEditor/DiffPreviewPanel.tsx` +- Zeigt `file_edit` Segmente aus der AI-Antwort als Text-Diff an +- Accept/Reject Buttons pro Aenderung +- Accept erzeugt neue Dokument-Version (POST `/{instanceId}/{workflowId}/apply`) +- MVP: einfacher Side-by-Side Text-Diff (kein vollstaendiger Code-Editor noetig) + +**11. Hooks** + +- Datei: `frontend_nyla/src/hooks/useCodeEditor.ts` +- Erweitert `useDashboardInputForm` Pattern um: + - `selectedFiles: string[]` (ausgewaehlte Kontext-Dateien) + - `pendingEdits: FileEdit[]` (vorgeschlagene Aenderungen) + - `applyEdit(editId)` / `rejectEdit(editId)` Aktionen + +### Datenmodell-Erweiterungen + +**12. Neue Pydantic Models** (in bestehendem `datamodelChat.py` oder eigenem File) + +```python +class FileContext(BaseModel): + fileId: str + fileName: str + content: Optional[str] = None + mimeType: str + tags: List[str] = Field(default_factory=list) # virtuelle Folder-Tags (spaeter) + +class FileEditProposal(BaseModel): + id: str = Field(default_factory=lambda: str(uuid.uuid4())) + fileId: str # Referenz auf bestehende Datei + fileName: str + operation: str # "edit" | "create" + oldContent: Optional[str] = None + newContent: str + diffSummary: Optional[str] = None # Kurzbeschreibung der Aenderung + status: str = "pending" # "pending" | "accepted" | "rejected" + +class FileVersion(BaseModel): + id: str = Field(default_factory=lambda: str(uuid.uuid4())) + sourceFileId: str # Original-Datei + editProposalId: str # Referenz auf akzeptiertes FileEditProposal + newFileId: str # Neue Datei-Version in DB + createdAt: float = Field(default_factory=getUtcTimestamp) +``` + +--- + +## Entschiedene Design-Entscheide + +1. **Datenquelle**: Hochgeladene Dateien im System (kein SharePoint). Spaeter: virtuelle Folder-Tags pro Datei fuer Strukturierung +2. **Dateitypen**: Nur Text-basierte Dokumente (Markdown, JSON, YAML, Code, etc.) +3. **Apply-Mechanismus**: Erzeugt neue lokale Dokument-Version in der DB (keine externe Synchronisation) +4. **Streaming**: SSE ueber bestehende `EventManager`-Infrastruktur aus dem Chatbot-Feature + +--- + +## SSE-Integration (Details) + +Nutzt die bestehende Infrastruktur aus `gateway/modules/features/chatbot/streaming/events.py`: + +- **EventManager** Singleton: `get_event_manager()` - verwaltet async Queues pro Workflow +- **Event-Emission**: In `interfaceDbChat.createMessage()` und `createLog()` bereits eingebaut +- **Neuer SSE-Endpoint**: `GET /api/codeeditor/{instanceId}/{workflowId}/stream` +- **Event-Typen fuer CodeEditor**: + - `chatdata` (bestehend): Messages, Logs, Stats + - `file_edit` (neu): FileEditProposal Events fuer Echtzeit-Diff-Updates + - `file_version` (neu): Neue Datei-Version erstellt (nach Apply) +- **Frontend**: `useCodeEditor` Hook oeffnet `EventSource` statt Polling +- **Fallback**: `chatData` Polling-Endpoint bleibt als Fallback verfuegbar + diff --git a/c-work/1-plan/2026-03-web-image-search.md b/c-work/1-plan/2026-03-web-image-search.md new file mode 100644 index 0000000..240fd65 --- /dev/null +++ b/c-work/1-plan/2026-03-web-image-search.md @@ -0,0 +1,361 @@ +# Refactoring Concept: Add WEB_SEARCH_MEDIA Operation Type + +## Executive Summary + +**Refactoring Goal**: Add image search capability by introducing `WEB_SEARCH_MEDIA` operation type and Google Custom Search connector. + +**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 + +**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` + +**Estimated Complexity**: Medium (1-2 days development) + +**Integration Impact**: Low - additive changes, no breaking changes + +--- + +## 1. Current Architecture + +### 1.1 Operation Types + +**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 +``` + +**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 +``` + +### 1.2 Model Capabilities + +**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 + +**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 + +--- + +## 2. Refactoring Plan + +### 2.1 Add WEB_SEARCH_MEDIA Operation Type + +**File**: `gateway/modules/datamodels/datamodelAi.py` + +**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 +``` + +### 2.2 Create AiCallPromptWebSearchMedia Model + +**File**: `gateway/modules/datamodels/datamodelAi.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)") +``` + +### 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 diff --git a/c-work/1-plan/2026-03-workflow-editor.md b/c-work/1-plan/2026-03-workflow-editor.md new file mode 100644 index 0000000..66c0df4 --- /dev/null +++ b/c-work/1-plan/2026-03-workflow-editor.md @@ -0,0 +1,1219 @@ +# Graphischer Workflow-Editor Konzept + +## Übersicht + +Dieses Dokument beschreibt das Konzept für einen graphischen Workflow-Editor, der es ermöglicht, Workflow-Templates visuell zu modellieren. Der Editor wird für die Erstellung und Bearbeitung von Automation-Templates verwendet, die in `formAutomations.js` verwaltet werden. + +## Wichtige Terminologie: Workflow vs. WorkflowTemplate + +**WICHTIG**: Es gibt eine klare Trennung zwischen ausführbaren Workflows und Templates: + +### ChatWorkflow (ausführbares Objekt) +- **Klasse**: `ChatWorkflow` (in `datamodelChat.py`) +- **Zweck**: Ausführbare Workflow-Instanz +- **Eigenschaften**: + - Hat `id`, `status` (running/completed/stopped/error) + - Enthält `tasks` (Liste von TaskItem-Objekten) + - Enthält `messages`, `logs`, `stats` + - Hat `workflowMode` (automatic oder dynamic) +- **Ausführung**: + - Kann über Route mit `start` oder `stop` ausgeführt werden + - Wird automatisch (scheduled) oder dynamisch (on-demand) gestartet +- **Lebenszyklus**: Wird zur Laufzeit erstellt und ausgeführt + +### AutomationDefinition (Template-Objekt) +- **Klasse**: `AutomationDefinition` (in `datamodelChat.py`) +- **Zweck**: Vorlage für ChatWorkflows +- **Eigenschaften**: + - Hat `id`, `label`, `schedule` (Cron-Pattern) + - Enthält `template` (JSON-String mit Workflow-Struktur) + - Enthält `placeholders` (Dict mit Platzhalter-Werten) + - Hat `active` (ob Automation aktiviert ist) +- **Verwendung**: + - Wird im Workflow-Editor bearbeitet + - Wird verwendet, um ChatWorkflows zu erstellen + - Template wird mit Placeholders gefüllt → ChatWorkflow wird erstellt +- **Lebenszyklus**: Wird einmal erstellt und mehrfach verwendet + +### WorkflowTemplateModel (Editor-Modell) +- **Klasse**: `WorkflowTemplateModel` (nur für Editor, nicht in Datenbank) +- **Zweck**: Strukturiertes Modell für graphischen Editor +- **Verwendung**: + - Wird aus `AutomationDefinition.template` (JSON-String) geparst + - Wird im Editor bearbeitet + - Wird zurück zu `AutomationDefinition.template` konvertiert +- **Lebenszyklus**: Nur während Editor-Session vorhanden + +### Beziehung zwischen Objekten + +``` +AutomationDefinition (Template) + ↓ (wird verwendet, um zu erstellen) +ChatWorkflow (ausführbare Instanz) + ↓ (wird ausgeführt) +TaskItem → ActionItem → Ergebnisse +``` + +**Beispiel**: +1. `AutomationDefinition` mit `template: '{"tasks": [...]}'` und `placeholders: {"connectionName": "MyConn"}` +2. Template wird mit Placeholders gefüllt → `ChatWorkflow` wird erstellt +3. `ChatWorkflow` wird gestartet → Tasks werden ausgeführt → Actions werden ausgeführt + +## Zielsetzung + +1. **Visuelle Modellierung**: Workflows mit Tasks und Actions graphisch erstellen +2. **Parameter-Konfiguration**: Action-Parameter direkt im Editor setzen +3. **Dependency-Management**: Document-Dependencies zwischen Actions visuell darstellen +4. **Template-Generierung**: Automatische Generierung von JSON-Templates aus graphischem Modell + +## Datenstruktur-Analyse + +### Bestehende Datenmodelle + +#### ChatWorkflow (datamodelChat.py) - AUSFÜHRBARES OBJEKT +```python +class ChatWorkflow(BaseModel): + """Ausführbare Workflow-Instanz""" + id: str + mandateId: str + status: str # "running", "completed", "stopped", "error" + workflowMode: WorkflowModeEnum # "automatic" oder "dynamic" + tasks: list # Liste von TaskItem-Objekten (zur Laufzeit erstellt) + messages: List[ChatMessage] + logs: List[ChatLog] + stats: List[ChatStat] + # ... weitere Felder +``` + +**WICHTIG**: `ChatWorkflow` ist das **ausführbare Objekt**, das über Route mit `start`/`stop` gesteuert werden kann. + +#### TaskItem (datamodelChat.py) - Teil von ChatWorkflow +```python +class TaskItem(BaseModel): + """Task innerhalb eines ausführbaren ChatWorkflows""" + id: str + workflowId: str # Foreign Key zu ChatWorkflow + userInput: str + status: TaskStatus + actionList: List[ActionItem] # Liste von Actions + dependencies: List[str] # Task IDs, von denen dieser Task abhängt + # ... weitere Felder +``` + +**WICHTIG**: `TaskItem` existiert nur in ausführbaren `ChatWorkflow`-Instanzen, nicht in Templates. + +#### ActionItem (datamodelChat.py) - Teil von TaskItem +```python +class ActionItem(BaseModel): + """Action innerhalb eines TaskItems""" + id: str + execMethod: str # z.B. "outlook", "sharepoint", "ai" + execAction: str # z.B. "readEmails", "uploadDocument" + execParameters: Dict[str, Any] # Action-Parameter (mit konkreten Werten) + execResultLabel: Optional[str] # Label für resultierende Documents + # ... weitere Felder +``` + +**WICHTIG**: `ActionItem` existiert nur in ausführbaren `ChatWorkflow`-Instanzen, nicht in Templates. + +#### AutomationDefinition (datamodelChat.py) - TEMPLATE-OBJEKT +```python +class AutomationDefinition(BaseModel): + """Template/Vorlage für ChatWorkflows""" + id: str + mandateId: str + label: str # User-friendly name + template: str # JSON-String mit Workflow-Struktur (enthält Tasks und Actions als Template) + placeholders: Dict[str, str] # Platzhalter-Werte (z.B. {"connectionName": "MyConn"}) + schedule: str # Cron-Schedule für automatische Ausführung + active: bool # Ob Automation aktiviert ist + eventId: Optional[str] # Event ID für Event-Management + executionLogs: List[Dict[str, Any]] # Logs von Workflow-Ausführungen + # ... weitere Felder +``` + +**WICHTIG**: +- `AutomationDefinition` ist das **Template-Objekt**, das im Workflow-Editor bearbeitet wird +- `template` Feld enthält JSON-String mit Workflow-Struktur (Tasks und Actions als Vorlage) +- `placeholders` enthält Werte für Platzhalter im Template +- Wird verwendet, um `ChatWorkflow`-Instanzen zu erstellen + +### Document Dependencies + +Actions können `documentList` Parameter haben, die auf Ergebnisse von anderen Actions verweisen: + +**Formate**: +- `docList:label` - Referenz zu einem Document-Label aus einer vorherigen Action +- `docList:messageId:label` - Cross-Round Referenz mit Message-ID + +**Beispiel**: +```json +{ + "execMethod": "sharepoint", + "execAction": "readDocuments", + "execParameters": { + "connectionReference": "{{connectionName}}", + "documentList": ["docList:emails_found"] // Verweist auf execResultLabel "emails_found" + } +} +``` + +## Workflow-Editor UI-Konzept + +### Layout-Struktur + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Workflow Editor - [Template Name] │ +├─────────────────────────────────────────────────────────────┤ +│ [Toolbar] [Save] [Validate] [Preview] [Help] │ +├─────────────────────────────────────────────────────────────┤ +│ ┌──────────────────┐ ┌─────────────────────────────────┐ │ +│ │ Toolbox │ │ Canvas (Graph Editor) │ │ +│ │ │ │ │ │ +│ │ 📋 Tasks │ │ ┌─────────┐ │ │ +│ │ ┌─────────────┐ │ │ │ Task 1 │ │ │ +│ │ │ + Task │ │ │ └────┬───┘ │ │ +│ │ └─────────────┘ │ │ │ │ │ +│ │ │ │ ┌────▼───┐ │ │ +│ │ ⚙️ Actions │ │ │Action 1 │ │ │ +│ │ ┌─────────────┐ │ │ └────┬───┘ │ │ +│ │ │ outlook │ │ │ │ │ │ +│ │ │ sharepoint │ │ │ ┌────▼───┐ │ │ +│ │ │ ai │ │ │ │Action 2│ │ │ +│ │ │ ... │ │ │ └────────┘ │ │ +│ │ └─────────────┘ │ │ │ │ +│ │ │ │ ┌─────────┐ │ │ +│ │ 🔗 Connections │ │ │ Task 2 │ │ │ +│ │ (Drag to link) │ │ └─────────┘ │ │ +│ └──────────────────┘ └─────────────────────────────────┘ │ +├─────────────────────────────────────────────────────────────┤ +│ [Properties Panel] - Selected: Task 1 │ +│ ┌───────────────────────────────────────────────────────┐ │ +│ │ Task Properties: │ │ +│ │ ID: task_1 │ │ +│ │ User Input: {{userPrompt}} │ │ +│ │ Dependencies: [task_0] │ │ +│ │ │ │ +│ │ Actions: │ │ +│ │ [Action 1] [Action 2] [+ Add Action] │ │ +│ └───────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +### Komponenten + +#### 1. Toolbox (Links) +- **Tasks**: Drag & Drop für neue Tasks +- **Actions**: Gruppiert nach Methoden (outlook, sharepoint, ai, etc.) +- **Connections**: Visueller Hinweis für Dependency-Verbindungen + +#### 2. Canvas (Mitte) +- **Graph-Editor**: Visualisierung des Workflows +- **Nodes**: Tasks (große Boxen) und Actions (kleinere Boxen innerhalb von Tasks) +- **Edges**: Verbindungen zwischen Tasks (Dependencies) und Actions (Document-Flows) + +#### 3. Properties Panel (Unten) +- **Task Properties**: Wenn Task selektiert +- **Action Properties**: Wenn Action selektiert +- **Parameter Editor**: Dynamisches Formular basierend auf `WorkflowActionParameter` Definitionen + +## Graphische Darstellung + +### Task-Node +``` +┌─────────────────────────────────────┐ +│ 📋 Task 1 │ +│ ───────────────────────────────── │ +│ User Input: {{userPrompt}} │ +│ │ +│ ┌─────────────┐ ┌─────────────┐ │ +│ │ Action 1.1 │ │ Action 1.2 │ │ +│ │ outlook. │ │ sharepoint. │ │ +│ │ readEmails │ │ uploadDoc │ │ +│ └─────────────┘ └─────────────┘ │ +│ │ +│ Dependencies: [Task 0] │ +└─────────────────────────────────────┘ +``` + +### Action-Node +``` +┌─────────────────────────┐ +│ ⚙️ outlook.readEmails │ +│ ─────────────────────── │ +│ connectionRef: {{...}} │ +│ query: "unread" │ +│ limit: 50 │ +│ │ +│ Result Label: emails │ +│ ─────────────────────── │ +│ [Edit] [Delete] │ +└─────────────────────────┘ +``` + +### Dependency-Verbindungen + +**Task Dependencies** (gestrichelte Linie): +``` +Task 0 ──┐ + │ (depends on) + ▼ + Task 1 +``` + +**Document Flow** (durchgezogene Linie mit Label): +``` +Action 1.1 (emails) ──[docList:emails]──► Action 2.1 +``` + +## Datenmodell für Editor + +### WorkflowTemplateModel (neues Datenmodell) + +```python +class WorkflowTemplateModel(BaseModel): + """Template-Modell für graphischen Editor""" + + # Metadaten + name: str = Field(description="Template name") + description: Optional[str] = Field(None, description="Template description") + version: str = Field(default="1.0", description="Template version") + + # Graph-Struktur + tasks: List[TaskTemplateModel] = Field( + default_factory=list, + description="List of task templates" + ) + + # Placeholders (werden aus Template extrahiert) + placeholders: Dict[str, str] = Field( + default_factory=dict, + description="Placeholder definitions with default values" + ) + + # UI-Metadaten (für Editor) + uiMetadata: Optional[Dict[str, Any]] = Field( + None, + description="UI metadata (node positions, zoom level, etc.)" + ) + +class TaskTemplateModel(BaseModel): + """Task-Template für Editor""" + + id: str = Field(description="Task ID (unique within template)") + label: str = Field(description="Task label/name") + userInput: str = Field( + description="User input template (can contain placeholders like {{userPrompt}})" + ) + dependencies: List[str] = Field( + default_factory=list, + description="List of task IDs this task depends on" + ) + actions: List[ActionTemplateModel] = Field( + default_factory=list, + description="List of actions in this task" + ) + + # UI-Metadaten + position: Optional[Dict[str, float]] = Field( + None, + description="Node position in editor: {x: number, y: number}" + ) + +class ActionTemplateModel(BaseModel): + """Action-Template für Editor""" + + id: str = Field(description="Action ID (unique within task)") + method: str = Field(description="Method name (e.g., 'outlook', 'sharepoint')") + action: str = Field(description="Action name (e.g., 'readEmails', 'uploadDocument')") + parameters: Dict[str, Any] = Field( + default_factory=dict, + description="Action parameters (can contain placeholders and document references)" + ) + resultLabel: Optional[str] = Field( + None, + description="Result label for document output (used in documentList references)" + ) + + # Document Dependencies (automatisch aus parameters extrahiert) + documentDependencies: List[str] = Field( + default_factory=list, + description="List of result labels this action depends on (from documentList parameter)" + ) + + # UI-Metadaten + position: Optional[Dict[str, float]] = Field( + None, + description="Node position within task: {x: number, y: number}" + ) +``` + +## Konvertierung: Template ↔ Editor-Modell + +### AutomationDefinition.template → Editor-Modell + +```python +def parseTemplateToEditorModel(templateJson: str) -> WorkflowTemplateModel: + """ + Parse AutomationDefinition.template (JSON string) to WorkflowTemplateModel + + INPUT: AutomationDefinition.template (JSON-String) + OUTPUT: WorkflowTemplateModel (Editor-Modell) + + Template-Format (aktuell in AutomationDefinition.template): + { + "tasks": [ + { + "id": "task_1", + "userInput": "{{userPrompt}}", + "dependencies": [], + "actions": [ + { + "method": "outlook", + "action": "readEmails", + "parameters": { + "connectionReference": "{{connectionName}}", + "query": "unread", + "limit": 50 + }, + "resultLabel": "emails" + } + ] + } + ] + } + """ + templateData = json.loads(templateJson) + + tasks = [] + for taskData in templateData.get("tasks", []): + actions = [] + for actionData in taskData.get("actions", []): + # Extract document dependencies from documentList parameter + documentDeps = [] + if "documentList" in actionData.get("parameters", {}): + docList = actionData["parameters"]["documentList"] + if isinstance(docList, list): + for ref in docList: + if isinstance(ref, str) and ref.startswith("docList:"): + # Extract label: docList:label or docList:messageId:label + parts = ref.split(":") + if len(parts) >= 2: + label = parts[-1] # Last part is always the label + documentDeps.append(label) + + actions.append(ActionTemplateModel( + id=actionData.get("id", f"action_{len(actions)}"), + method=actionData["method"], + action=actionData["action"], + parameters=actionData.get("parameters", {}), + resultLabel=actionData.get("resultLabel"), + documentDependencies=documentDeps + )) + + tasks.append(TaskTemplateModel( + id=taskData["id"], + label=taskData.get("label", taskData["id"]), + userInput=taskData.get("userInput", ""), + dependencies=taskData.get("dependencies", []), + actions=actions + )) + + # Extract placeholders from template + placeholders = extractPlaceholders(templateJson) + + return WorkflowTemplateModel( + name="Template", + tasks=tasks, + placeholders=placeholders + ) +``` + +### Editor-Modell → AutomationDefinition.template + +```python +def convertEditorModelToTemplate( + editorModel: WorkflowTemplateModel, + placeholders: Dict[str, str] +) -> str: + """ + Convert WorkflowTemplateModel to AutomationDefinition.template JSON string + + INPUT: WorkflowTemplateModel (Editor-Modell) + placeholders Dict + OUTPUT: JSON-String für AutomationDefinition.template Feld + """ + templateData = { + "tasks": [] + } + + for task in editorModel.tasks: + taskData = { + "id": task.id, + "userInput": task.userInput, + "dependencies": task.dependencies, + "actions": [] + } + + for action in task.actions: + # Build documentList from documentDependencies + parameters = action.parameters.copy() + if action.documentDependencies: + documentList = [f"docList:{label}" for label in action.documentDependencies] + parameters["documentList"] = documentList + + actionData = { + "method": action.method, + "action": action.action, + "parameters": parameters + } + + if action.resultLabel: + actionData["resultLabel"] = action.resultLabel + + taskData["actions"].append(actionData) + + templateData["tasks"].append(taskData) + + return json.dumps(templateData, indent=2) +``` + +## UI-Implementierung + +### Technologie-Stack + +**Empfehlung**: +- **Graph-Library**: [Cytoscape.js](https://js.cytoscape.org/) oder [React Flow](https://reactflow.dev/) oder [JointJS](https://www.jointjs.com/) +- **Framework**: Vanilla JavaScript (konsistent mit bestehendem Frontend) oder React (falls Migration geplant) +- **Styling**: CSS mit bestehenden Styles aus `formGeneric.js` + +### HTML-Struktur + +```html + + + + Workflow Editor + + + +
+ +
+ + + +
+ + +
+ +
+
+

Tasks

+
+ Task +
+
+ +
+

Actions

+
+
Outlook
+
+ readEmails +
+
+ sendEmail +
+
+
+
SharePoint
+
+ readDocuments +
+ +
+
+
+ + +
+ +
+ + +
+
+

Properties

+
+
+

Select a node to edit properties

+
+
+
+ + +
+

Placeholders

+
+
+
+ + + + +``` + +### JavaScript-Architektur + +```javascript +// workflow-editor.js + +class WorkflowEditor { + constructor(containerId, initialTemplate = null) { + this.container = document.getElementById(containerId); + this.graph = null; // Graph-Library Instanz + this.model = null; // WorkflowTemplateModel + this.selectedNode = null; + + this.init(); + if (initialTemplate) { + this.loadTemplate(initialTemplate); + } + } + + init() { + this.initGraph(); + this.initToolbox(); + this.initPropertiesPanel(); + this.initEventHandlers(); + } + + initGraph() { + // Initialize graph library (z.B. Cytoscape.js) + this.graph = cytoscape({ + container: document.getElementById('editor-canvas'), + elements: [], + style: [ + { + selector: 'node[type="task"]', + style: { + 'shape': 'roundrectangle', + 'width': 200, + 'height': 150, + 'background-color': '#e8f4f8', + 'label': 'data(label)', + 'text-valign': 'top', + 'text-margin-y': 10 + } + }, + { + selector: 'node[type="action"]', + style: { + 'shape': 'roundrectangle', + 'width': 150, + 'height': 80, + 'background-color': '#fff4e6', + 'label': 'data(label)', + 'text-valign': 'center' + } + }, + { + selector: 'edge[type="task-dependency"]', + style: { + 'line-style': 'dashed', + 'target-arrow-shape': 'triangle', + 'curve-style': 'bezier' + } + }, + { + selector: 'edge[type="document-flow"]', + style: { + 'line-style': 'solid', + 'target-arrow-shape': 'triangle', + 'label': 'data(label)', + 'curve-style': 'bezier', + 'line-color': '#4a90e2' + } + } + ], + layout: { + name: 'dagre', + rankDir: 'TB', + spacingFactor: 1.5 + } + }); + + // Event handlers + this.graph.on('tap', 'node', (evt) => { + this.selectNode(evt.target); + }); + + this.graph.on('tap', (evt) => { + if (evt.target === this.graph) { + this.deselectNode(); + } + }); + } + + loadTemplate(templateJson) { + // Parse template to editor model + this.model = parseTemplateToEditorModel(templateJson); + + // Render graph + this.renderGraph(); + + // Update placeholders panel + this.updatePlaceholdersPanel(); + } + + renderGraph() { + const elements = []; + + // Add task nodes + this.model.tasks.forEach((task, taskIndex) => { + // Task node + elements.push({ + data: { + id: `task_${task.id}`, + type: 'task', + label: task.label || task.id, + taskId: task.id, + nodeType: 'task' + }, + position: task.position || { x: 100, y: taskIndex * 200 + 100 } + }); + + // Action nodes within task + task.actions.forEach((action, actionIndex) => { + const actionNodeId = `action_${task.id}_${action.id}`; + elements.push({ + data: { + id: actionNodeId, + type: 'action', + label: `${action.method}.${action.action}`, + taskId: task.id, + actionId: action.id, + nodeType: 'action' + }, + position: action.position || { + x: 100 + actionIndex * 180, + y: taskIndex * 200 + 150 + } + }); + + // Parent-child relationship (action belongs to task) + elements.push({ + data: { + id: `edge_${task.id}_${action.id}`, + source: `task_${task.id}`, + target: actionNodeId, + type: 'contains' + } + }); + }); + }); + + // Add task dependencies + this.model.tasks.forEach(task => { + task.dependencies.forEach(depId => { + elements.push({ + data: { + id: `dep_${depId}_${task.id}`, + source: `task_${depId}`, + target: `task_${task.id}`, + type: 'task-dependency' + } + }); + }); + }); + + // Add document flow edges + this.model.tasks.forEach(task => { + task.actions.forEach(action => { + action.documentDependencies.forEach(depLabel => { + // Find source action with matching resultLabel + const sourceAction = this.findActionByResultLabel(depLabel); + if (sourceAction) { + elements.push({ + data: { + id: `doc_${sourceAction.id}_${action.id}`, + source: `action_${sourceAction.taskId}_${sourceAction.id}`, + target: `action_${task.id}_${action.id}`, + type: 'document-flow', + label: depLabel + } + }); + } + }); + }); + }); + + this.graph.elements().remove(); + this.graph.add(elements); + this.graph.layout({ name: 'dagre' }).run(); + } + + selectNode(node) { + this.selectedNode = node; + const nodeData = node.data(); + + if (nodeData.nodeType === 'task') { + this.showTaskProperties(nodeData.taskId); + } else if (nodeData.nodeType === 'action') { + this.showActionProperties(nodeData.taskId, nodeData.actionId); + } + + // Highlight selected node + this.graph.elements().removeClass('selected'); + node.addClass('selected'); + } + + showActionProperties(taskId, actionId) { + const task = this.model.tasks.find(t => t.id === taskId); + const action = task?.actions.find(a => a.id === actionId); + + if (!action) return; + + // Load action schema from API + this.loadActionSchema(action.method, action.action).then(schema => { + const propertiesHtml = this.renderActionPropertiesForm(action, schema); + document.getElementById('properties-content').innerHTML = propertiesHtml; + + // Bind form handlers + this.bindActionFormHandlers(taskId, actionId, schema); + }); + } + + async loadActionSchema(method, actionName) { + // Fetch from /api/workflows/actions/{method}/{actionName} + const response = await fetch(`/api/workflows/actions/${method}/${actionName}`); + return await response.json(); + } + + renderActionPropertiesForm(action, schema) { + let html = ` +
+
${action.method}.${action.action}
+
+ + + Label for document output (used in documentList references) +
+
+ + `; + + // Render parameter fields based on schema + Object.entries(schema.parameters || {}).forEach(([paramName, paramDef]) => { + html += this.renderParameterField(paramName, paramDef, action.parameters[paramName]); + }); + + html += ` +
+
+ + +
+
+ `; + + return html; + } + + renderParameterField(paramName, paramDef, currentValue) { + const value = currentValue !== undefined ? currentValue : (paramDef.default || ''); + const valueStr = typeof value === 'object' ? JSON.stringify(value) : String(value); + + let html = `
`; + html += ``; + + switch (paramDef.frontendType) { + case 'text': + case 'textarea': + html += ``; + break; + case 'number': + html += ``; + break; + case 'select': + case 'userConnection': + case 'documentReference': + html += ``; + break; + case 'checkbox': + html += ``; + break; + default: + html += ``; + } + + html += `${paramDef.description || ''}`; + html += `
`; + + return html; + } + + saveActionProperties(actionId) { + const task = this.model.tasks.find(t => + t.actions.some(a => a.id === actionId) + ); + const action = task?.actions.find(a => a.id === actionId); + + if (!action) return; + + // Collect parameter values from form + const parameters = {}; + // ... collect from form fields ... + + // Update action + action.parameters = parameters; + action.resultLabel = document.getElementById('action-result-label').value; + + // Update document dependencies + action.documentDependencies = this.extractDocumentDependencies(parameters); + + // Re-render graph to show updated connections + this.renderGraph(); + } + + extractDocumentDependencies(parameters) { + const deps = []; + if (parameters.documentList && Array.isArray(parameters.documentList)) { + parameters.documentList.forEach(ref => { + if (typeof ref === 'string' && ref.startsWith('docList:')) { + const parts = ref.split(':'); + if (parts.length >= 2) { + deps.push(parts[parts.length - 1]); // Last part is label + } + } + }); + } + return deps; + } + + saveTemplate() { + // Convert editor model to template JSON + const templateJson = convertEditorModelToTemplate( + this.model, + this.getPlaceholders() + ); + + // Save via API to AutomationDefinition (Template-Objekt) + // WICHTIG: Dies speichert das Template, nicht das ausführbare ChatWorkflow + return this.saveToAutomationDefinition(templateJson); + } + + validateTemplate() { + const errors = []; + + // Check: All tasks have at least one action + this.model.tasks.forEach(task => { + if (task.actions.length === 0) { + errors.push(`Task "${task.id}" has no actions`); + } + }); + + // Check: All document dependencies resolve to valid result labels + this.model.tasks.forEach(task => { + task.actions.forEach(action => { + action.documentDependencies.forEach(depLabel => { + const sourceAction = this.findActionByResultLabel(depLabel); + if (!sourceAction) { + errors.push(`Action "${action.method}.${action.action}" depends on unknown result label "${depLabel}"`); + } + }); + }); + }); + + // Check: Circular dependencies + const circularDeps = this.detectCircularDependencies(); + if (circularDeps.length > 0) { + errors.push(`Circular dependencies detected: ${circularDeps.join(', ')}`); + } + + // Check: Required parameters are set + // ... weitere Validierungen ... + + return { + valid: errors.length === 0, + errors: errors + }; + } + + findActionByResultLabel(resultLabel) { + for (const task of this.model.tasks) { + for (const action of task.actions) { + if (action.resultLabel === resultLabel) { + return { ...action, taskId: task.id }; + } + } + } + return null; + } + + detectCircularDependencies() { + // Graph-based cycle detection + // ... Implementation ... + return []; + } +} + +// Initialize editor +let editor; +document.addEventListener('DOMContentLoaded', () => { + const templateJson = getInitialTemplate(); // From formAutomations.js + editor = new WorkflowEditor('workflow-editor', templateJson); +}); +``` + +## Integration mit formAutomations.js + +### Erweiterte Automation-Form + +```javascript +// In formAutomations.js + +// Add "Edit Template" button to automation form +function initAutomationForm() { + // ... existing code ... + + // Add workflow editor button + const templateField = form.querySelector('#entity-template'); + if (templateField) { + const editorButton = document.createElement('button'); + editorButton.type = 'button'; + editorButton.className = 'btn btn-secondary'; + editorButton.innerHTML = ' Open Workflow Editor'; + editorButton.addEventListener('click', () => { + openWorkflowEditor(templateField.value); + }); + templateField.parentNode.appendChild(editorButton); + } +} + +function openWorkflowEditor(templateJson) { + // Open workflow editor in modal or new tab + const modal = document.createElement('div'); + modal.className = 'workflow-editor-modal'; + modal.innerHTML = ` +
+
+

Workflow Editor

+ +
+
+
+
+ +
+ `; + + document.body.appendChild(modal); + + // Initialize editor + const editor = new WorkflowEditor('workflow-editor-container', templateJson); + + // Save handler + document.getElementById('workflow-editor-save').addEventListener('click', () => { + const updatedTemplate = editor.saveTemplate(); + // Update template field in form + document.querySelector('#entity-template').value = updatedTemplate; + modal.remove(); + }); + + // Cancel handler + document.getElementById('workflow-editor-cancel').addEventListener('click', () => { + modal.remove(); + }); +} +``` + +## API-Endpunkte + +### GET /api/workflows/actions +Liefert alle verfügbaren Actions (bereits im RBAC-Konzept definiert). + +### GET /api/workflows/actions/{method}/{action} +Liefert Action-Schema mit Parameter-Definitionen: + +```json +{ + "method": "outlook", + "action": "readEmails", + "actionId": "outlook.readEmails", + "description": "Read emails from Outlook mailbox", + "parameters": { + "connectionReference": { + "name": "connectionReference", + "type": "str", + "frontendType": "userConnection", + "frontendOptions": "user.connection", + "required": true, + "description": "Microsoft connection label" + }, + "query": { + "name": "query", + "type": "str", + "frontendType": "text", + "required": false, + "description": "Search query for emails" + } + } +} +``` + +### GET /api/automations/{automationId} +Liefert AutomationDefinition für Editor. + +**Zweck**: Lädt AutomationDefinition (Template) für Bearbeitung im Editor +**Rückgabe**: `AutomationDefinition` Objekt mit `template` (JSON-String) und `placeholders` + +### POST /api/automations/{automationId} +Speichert AutomationDefinition (Template). + +**Zweck**: Speichert bearbeitetes Template zurück in AutomationDefinition +**Input**: `AutomationDefinition` Objekt mit aktualisiertem `template` (JSON-String) und `placeholders` +**Hinweis**: Dies ist das Template-Objekt, nicht das ausführbare ChatWorkflow-Objekt + +## Validierung + +### Template-Validierung + +1. **Struktur-Validierung**: + - Alle Tasks haben mindestens eine Action + - Alle Task-Dependencies verweisen auf existierende Tasks + - Keine zirkulären Dependencies + +2. **Action-Validierung**: + - Alle Actions haben gültige method/action Kombinationen + - Alle required Parameters sind gesetzt + - Alle documentList Referenzen verweisen auf existierende resultLabels + +3. **Placeholder-Validierung**: + - Alle Placeholders im Template sind in placeholders-Dict definiert + - Placeholder-Format: `{{PLACEHOLDER_NAME}}` + +## Beispiel-Workflow + +### Visuelle Darstellung + +``` +┌─────────────────────────────────────┐ +│ 📋 Task 1: Read Emails │ +│ ───────────────────────────────── │ +│ User Input: {{userPrompt}} │ +│ │ +│ ┌───────────────────────────────┐ │ +│ │ ⚙️ outlook.readEmails │ │ +│ │ connectionRef: {{conn}} │ │ +│ │ query: "unread" │ │ +│ │ Result: emails │ │ +│ └───────────────┬───────────────┘ │ +└──────────────────┼─────────────────┘ + │ docList:emails + ▼ +┌─────────────────────────────────────┐ +│ 📋 Task 2: Process Documents │ +│ ───────────────────────────────── │ +│ Dependencies: [Task 1] │ +│ │ +│ ┌───────────────────────────────┐ │ +│ │ ⚙️ ai.process │ │ +│ │ documentList: [docList:emails]│ │ +│ │ aiPrompt: {{processPrompt}} │ │ +│ │ Result: processed │ │ +│ └───────────────────────────────┘ │ +└─────────────────────────────────────┘ +``` + +### Generiertes Template JSON + +```json +{ + "tasks": [ + { + "id": "task_1", + "userInput": "{{userPrompt}}", + "dependencies": [], + "actions": [ + { + "method": "outlook", + "action": "readEmails", + "parameters": { + "connectionReference": "{{conn}}", + "query": "unread", + "limit": 50 + }, + "resultLabel": "emails" + } + ] + }, + { + "id": "task_2", + "userInput": "Process emails", + "dependencies": ["task_1"], + "actions": [ + { + "method": "ai", + "action": "process", + "parameters": { + "documentList": ["docList:emails"], + "aiPrompt": "{{processPrompt}}", + "resultType": "json" + }, + "resultLabel": "processed" + } + ] + } + ] +} +``` + +## Nächste Schritte + +1. **Graph-Library auswählen**: Cytoscape.js vs. React Flow vs. JointJS +2. **Editor-Komponenten implementieren**: Toolbox, Canvas, Properties Panel +3. **API-Integration**: Action-Schemas laden, Templates speichern +4. **Validierung implementieren**: Dependency-Checking, Parameter-Validierung +5. **Placeholder-Management**: UI für Placeholder-Definition +6. **Testing**: Unit-Tests für Konvertierungs-Logik + +## Offene Fragen + +1. **Graph-Library**: Welche Library bevorzugt? (Cytoscape.js ist gut für komplexe Graphen, React Flow ist moderner) +2. **Positionierung**: Sollen Node-Positionen gespeichert werden oder automatisch layouted? +3. **Placeholder-UI**: Separate UI für Placeholder-Management oder integriert in Editor? +4. **Versionierung**: Sollen Templates versioniert werden? + diff --git a/c-work/_TEMPLATE.md b/c-work/_TEMPLATE.md new file mode 100644 index 0000000..1828412 --- /dev/null +++ b/c-work/_TEMPLATE.md @@ -0,0 +1,66 @@ + + + + +# + +## Beschreibung und Kontext + +Was ist das Thema? Warum jetzt? Was ist der Business-Treiber? +Welche Abhängigkeiten bestehen? Was ist das Risiko wenn wir es NICHT machen? + +## Fokus und kritische Details + +- Worauf muss besonders geachtet werden? +- Welche Stellen im Code sind fragil / komplex? +- Bekannte Fallstricke oder Edge Cases + +## Ziel und Nicht-Ziele + +- Ziel: ... +- Explizit NICHT: ... + +## Betroffene Module + +- Gateway: ... +- Frontend: ... +- DB-Migration: ja/nein +- Andere Komponenten: ... + +## Entscheidungen + +| Datum | Entscheidung | Begründung | +|-------|-------------|------------| + +## Umsetzungs-Checkliste + +- [ ] API-Endpunkte +- [ ] DB-Schema / Migration +- [ ] Frontend-Komponenten +- [ ] RBAC / Permissions +- [ ] Neutralisierung betroffen? +- [ ] Navigation / Routing +- [ ] Billing-Impact? + +## Akzeptanzkriterien + +| # | Kriterium (Given-When-Then) | Prio | +|---|---------------------------|------| +| 1 | Given ... When ... Then ... | must | + +## Testplan + +| ID | AC | Art | Automatisiert | Repo-Pfad | Status | +|----|----|-----|--------------|-----------|--------| +| T1 | 1 | api | ja | gateway/tests/... | pending | + +## Links + +- PR: ... +- Issue: ... + +## Abschluss + +- [ ] b-reference/ aktualisiert (welche Seite?) +- [ ] TOPICS.md aktualisiert (falls neues Thema) +- [ ] Dieses Dokument → z-archive/ verschoben diff --git a/d-guides/coding-conventions.md b/d-guides/coding-conventions.md new file mode 100644 index 0000000..2782287 --- /dev/null +++ b/d-guides/coding-conventions.md @@ -0,0 +1,20 @@ + + + +# Coding-Konventionen + +## Naming + +- Alle internen Funktionen beginnen mit `_` Prefix +- camelCase für Variablen und Funktionsnamen (kein snake_case) + +## Frontend-Regeln + +- Keine Browser-Dialoge (alert/confirm/prompt) -- stattdessen `useConfirm()` und `usePrompt()` Hooks +- CSS Modules für Komponenten-Styles + +## Backend-Regeln + +- 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` diff --git a/deployment/Instanzenübersicht.drawio b/d-guides/deployment/Instanzenübersicht.drawio similarity index 100% rename from deployment/Instanzenübersicht.drawio rename to d-guides/deployment/Instanzenübersicht.drawio diff --git a/deployment/Instanzenübersicht.svg b/d-guides/deployment/Instanzenübersicht.svg similarity index 100% rename from deployment/Instanzenübersicht.svg rename to d-guides/deployment/Instanzenübersicht.svg diff --git a/deployment/README.txt b/d-guides/deployment/README.txt similarity index 100% rename from deployment/README.txt rename to d-guides/deployment/README.txt diff --git a/deployment/poweron_sec.kdbx b/d-guides/deployment/poweron_sec.kdbx similarity index 100% rename from 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 new file mode 100644 index 0000000..139a1c3 --- /dev/null +++ b/d-guides/dev-setup.md @@ -0,0 +1,25 @@ + + + +# Dev-Setup + +## Voraussetzungen + +- Python (Anaconda/Miniconda) +- Node.js +- PostgreSQL mit pgvector + +## Gateway starten + +```bash +conda activate +cd gateway/ +uvicorn app:app --host 0.0.0.0 --port 8000 +``` + +## Frontend Nyla starten + +```bash +cd frontend_nyla/ +npx vite --port 8080 --mode dev +``` diff --git a/appdoc/doc_admin_encrypt_env_secret.md b/d-guides/encrypt-env-secrets.md similarity index 100% rename from appdoc/doc_admin_encrypt_env_secret.md rename to d-guides/encrypt-env-secrets.md diff --git a/appdoc/doc_system_google_oauth_setup.md b/d-guides/google-oauth-setup.md similarity index 100% rename from appdoc/doc_system_google_oauth_setup.md rename to d-guides/google-oauth-setup.md diff --git a/implementation/security-migration-guide.md b/d-guides/security-migration-guide.md similarity index 100% rename from implementation/security-migration-guide.md rename to d-guides/security-migration-guide.md diff --git a/d-guides/testing-strategy.md b/d-guides/testing-strategy.md new file mode 100644 index 0000000..db2b3ae --- /dev/null +++ b/d-guides/testing-strategy.md @@ -0,0 +1,26 @@ + + + +# Testing-Strategie + +## Testpyramide + +- **Unit Tests:** pytest (Gateway), vitest (Frontend) +- **Integration Tests:** API-Tests gegen laufenden Gateway +- **E2E Tests:** (zu definieren) + +## Akzeptanzkriterien-Format + +Given-When-Then Sätze in Arbeits-Dokumenten (`c-work/_TEMPLATE.md`) + +## Testplan-Tabelle + +Jedes Arbeits-Dokument enthält eine Testplan-Tabelle: + +| ID | AC | Art | Automatisiert | Repo-Pfad | Status | +|----|----|-----|--------------|-----------|--------| + +## Test-Pfade im Repo + +- Gateway: `gateway/tests/` +- Frontend: `frontend_nyla/src/**/*.test.ts` diff --git a/compliance/2026-03-11-ai-skills-timeline-poweron-vs-claude.pdf b/e-compliance/2026-03-11-ai-skills-timeline-poweron-vs-claude.pdf similarity index 100% rename from compliance/2026-03-11-ai-skills-timeline-poweron-vs-claude.pdf rename to e-compliance/2026-03-11-ai-skills-timeline-poweron-vs-claude.pdf diff --git a/compliance/2026-03-11-ai-skills-timeline-poweron-vs-claude.md b/e-compliance/ai-skills-timeline-comparison.md similarity index 100% rename from compliance/2026-03-11-ai-skills-timeline-poweron-vs-claude.md rename to e-compliance/ai-skills-timeline-comparison.md diff --git a/compliance/Neutralisierung.md b/e-compliance/neutralisierung-detail.md similarity index 100% rename from compliance/Neutralisierung.md rename to e-compliance/neutralisierung-detail.md diff --git a/compliance/poweron_sicherheit_und_compliance.md b/e-compliance/security-overview.md similarity index 100% rename from compliance/poweron_sicherheit_und_compliance.md rename to e-compliance/security-overview.md diff --git a/appdoc/README_LangDoc.md b/z-archive/appdoc/README_LangDoc.md similarity index 100% rename from appdoc/README_LangDoc.md rename to z-archive/appdoc/README_LangDoc.md diff --git a/appdoc/ai_call_flow_analysis.md b/z-archive/appdoc/ai_call_flow_analysis.md similarity index 100% rename from appdoc/ai_call_flow_analysis.md rename to z-archive/appdoc/ai_call_flow_analysis.md diff --git a/appdoc/ai_plan_architecture.md b/z-archive/appdoc/ai_plan_architecture.md similarity index 100% rename from appdoc/ai_plan_architecture.md rename to z-archive/appdoc/ai_plan_architecture.md diff --git a/appdoc/ai_plan_implementation.md b/z-archive/appdoc/ai_plan_implementation.md similarity index 100% rename from appdoc/ai_plan_implementation.md rename to z-archive/appdoc/ai_plan_implementation.md diff --git a/appdoc/analysis_ai_workflow.md b/z-archive/appdoc/analysis_ai_workflow.md similarity index 100% rename from appdoc/analysis_ai_workflow.md rename to z-archive/appdoc/analysis_ai_workflow.md diff --git a/appdoc/doc_ai_system_validator.md b/z-archive/appdoc/doc_ai_system_validator.md similarity index 100% rename from appdoc/doc_ai_system_validator.md rename to z-archive/appdoc/doc_ai_system_validator.md diff --git a/appdoc/doc_architecture_ai_service.html b/z-archive/appdoc/doc_architecture_ai_service.html similarity index 100% rename from appdoc/doc_architecture_ai_service.html rename to z-archive/appdoc/doc_architecture_ai_service.html diff --git a/appdoc/doc_architecture_gateway.drawio b/z-archive/appdoc/doc_architecture_gateway.drawio similarity index 100% rename from appdoc/doc_architecture_gateway.drawio rename to z-archive/appdoc/doc_architecture_gateway.drawio diff --git a/appdoc/doc_architecture_gateway.pdf b/z-archive/appdoc/doc_architecture_gateway.pdf similarity index 100% rename from appdoc/doc_architecture_gateway.pdf rename to z-archive/appdoc/doc_architecture_gateway.pdf diff --git a/appdoc/doc_architecture_workflow.html b/z-archive/appdoc/doc_architecture_workflow.html similarity index 100% rename from appdoc/doc_architecture_workflow.html rename to z-archive/appdoc/doc_architecture_workflow.html diff --git a/appdoc/doc_concept_callAiContent_flow.md b/z-archive/appdoc/doc_concept_callAiContent_flow.md similarity index 100% rename from appdoc/doc_concept_callAiContent_flow.md rename to z-archive/appdoc/doc_concept_callAiContent_flow.md diff --git a/appdoc/doc_dev_workflow.md b/z-archive/appdoc/doc_dev_workflow.md similarity index 100% rename from appdoc/doc_dev_workflow.md rename to z-archive/appdoc/doc_dev_workflow.md diff --git a/appdoc/doc_diagram_components.md b/z-archive/appdoc/doc_diagram_components.md similarity index 100% rename from appdoc/doc_diagram_components.md rename to z-archive/appdoc/doc_diagram_components.md diff --git a/appdoc/doc_gateway_architecture_overview.md b/z-archive/appdoc/doc_gateway_architecture_overview.md similarity index 100% rename from appdoc/doc_gateway_architecture_overview.md rename to z-archive/appdoc/doc_gateway_architecture_overview.md diff --git a/appdoc/doc_gateway_development_framework.md b/z-archive/appdoc/doc_gateway_development_framework.md similarity index 100% rename from appdoc/doc_gateway_development_framework.md rename to z-archive/appdoc/doc_gateway_development_framework.md diff --git a/appdoc/doc_gateway_schematics.html b/z-archive/appdoc/doc_gateway_schematics.html similarity index 100% rename from appdoc/doc_gateway_schematics.html rename to z-archive/appdoc/doc_gateway_schematics.html diff --git a/appdoc/doc_progress_reporting_generation_proposal.md b/z-archive/appdoc/doc_progress_reporting_generation_proposal.md similarity index 100% rename from appdoc/doc_progress_reporting_generation_proposal.md rename to z-archive/appdoc/doc_progress_reporting_generation_proposal.md diff --git a/appdoc/doc_security_key_management.md b/z-archive/appdoc/doc_security_key_management.md similarity index 100% rename from appdoc/doc_security_key_management.md rename to z-archive/appdoc/doc_security_key_management.md diff --git a/appdoc/doc_security_role_based_access.md b/z-archive/appdoc/doc_security_role_based_access.md similarity index 100% rename from appdoc/doc_security_role_based_access.md rename to z-archive/appdoc/doc_security_role_based_access.md diff --git a/appdoc/doc_security_role_based_access_admin_api.md b/z-archive/appdoc/doc_security_role_based_access_admin_api.md similarity index 100% rename from appdoc/doc_security_role_based_access_admin_api.md rename to z-archive/appdoc/doc_security_role_based_access_admin_api.md diff --git a/appdoc/doc_security_role_based_access_implementation_plan.md b/z-archive/appdoc/doc_security_role_based_access_implementation_plan.md similarity index 100% rename from appdoc/doc_security_role_based_access_implementation_plan.md rename to z-archive/appdoc/doc_security_role_based_access_implementation_plan.md diff --git a/appdoc/doc_spec_progress_logging.md b/z-archive/appdoc/doc_spec_progress_logging.md similarity index 100% rename from appdoc/doc_spec_progress_logging.md rename to z-archive/appdoc/doc_spec_progress_logging.md diff --git a/appdoc/doc_spec_ui.md b/z-archive/appdoc/doc_spec_ui.md similarity index 100% rename from appdoc/doc_spec_ui.md rename to z-archive/appdoc/doc_spec_ui.md diff --git a/appdoc/doc_statemachine_frontend.md b/z-archive/appdoc/doc_statemachine_frontend.md similarity index 100% rename from appdoc/doc_statemachine_frontend.md rename to z-archive/appdoc/doc_statemachine_frontend.md diff --git a/appdoc/doc_system_call_sites_callAiDocuments.md b/z-archive/appdoc/doc_system_call_sites_callAiDocuments.md similarity index 100% rename from appdoc/doc_system_call_sites_callAiDocuments.md rename to z-archive/appdoc/doc_system_call_sites_callAiDocuments.md diff --git a/appdoc/doc_system_function_relationship_ai.mermaid b/z-archive/appdoc/doc_system_function_relationship_ai.mermaid similarity index 100% rename from appdoc/doc_system_function_relationship_ai.mermaid rename to z-archive/appdoc/doc_system_function_relationship_ai.mermaid diff --git a/appdoc/doc_system_polling_logic.md b/z-archive/appdoc/doc_system_polling_logic.md similarity index 100% rename from appdoc/doc_system_polling_logic.md rename to z-archive/appdoc/doc_system_polling_logic.md diff --git a/appdoc/doc_system_prompt_flow.md b/z-archive/appdoc/doc_system_prompt_flow.md similarity index 100% rename from appdoc/doc_system_prompt_flow.md rename to z-archive/appdoc/doc_system_prompt_flow.md diff --git a/appdoc/doc_system_statemachine_backend.md b/z-archive/appdoc/doc_system_statemachine_backend.md similarity index 100% rename from appdoc/doc_system_statemachine_backend.md rename to z-archive/appdoc/doc_system_statemachine_backend.md diff --git a/appdoc/doc_user_partner.html b/z-archive/appdoc/doc_user_partner.html similarity index 100% rename from appdoc/doc_user_partner.html rename to z-archive/appdoc/doc_user_partner.html diff --git a/appdoc/doc_userauth_process_concept_review.md b/z-archive/appdoc/doc_userauth_process_concept_review.md similarity index 100% rename from appdoc/doc_userauth_process_concept_review.md rename to z-archive/appdoc/doc_userauth_process_concept_review.md diff --git a/appdoc/doc_workflow_actions_rbac_concept.md b/z-archive/appdoc/doc_workflow_actions_rbac_concept.md similarity index 100% rename from appdoc/doc_workflow_actions_rbac_concept.md rename to z-archive/appdoc/doc_workflow_actions_rbac_concept.md diff --git a/appdoc/doc_workflow_actions_rbac_concept_done.md b/z-archive/appdoc/doc_workflow_actions_rbac_concept_done.md similarity index 100% rename from appdoc/doc_workflow_actions_rbac_concept_done.md rename to z-archive/appdoc/doc_workflow_actions_rbac_concept_done.md diff --git a/appdoc/doc_workflow_method_refactoring_concept_done.md b/z-archive/appdoc/doc_workflow_method_refactoring_concept_done.md similarity index 100% rename from appdoc/doc_workflow_method_refactoring_concept_done.md rename to z-archive/appdoc/doc_workflow_method_refactoring_concept_done.md diff --git a/appdoc/implementation_concept_ai_workflow_rev4.md b/z-archive/appdoc/implementation_concept_ai_workflow_rev4.md similarity index 100% rename from appdoc/implementation_concept_ai_workflow_rev4.md rename to z-archive/appdoc/implementation_concept_ai_workflow_rev4.md diff --git a/appdoc/implementation_concept_generation_structure_rev4.md b/z-archive/appdoc/implementation_concept_generation_structure_rev4.md similarity index 100% rename from appdoc/implementation_concept_generation_structure_rev4.md rename to z-archive/appdoc/implementation_concept_generation_structure_rev4.md diff --git a/appdoc/json_string_accumulation_concept.md b/z-archive/appdoc/json_string_accumulation_concept.md similarity index 100% rename from appdoc/json_string_accumulation_concept.md rename to z-archive/appdoc/json_string_accumulation_concept.md diff --git a/appdoc/json_string_accumulation_implementation_plan.md b/z-archive/appdoc/json_string_accumulation_implementation_plan.md similarity index 100% rename from appdoc/json_string_accumulation_implementation_plan.md rename to z-archive/appdoc/json_string_accumulation_implementation_plan.md diff --git a/appdoc/json_string_accumulation_kpi_adaptation.md b/z-archive/appdoc/json_string_accumulation_kpi_adaptation.md similarity index 100% rename from appdoc/json_string_accumulation_kpi_adaptation.md rename to z-archive/appdoc/json_string_accumulation_kpi_adaptation.md diff --git a/appdoc/loop_plan.md b/z-archive/appdoc/loop_plan.md similarity index 100% rename from appdoc/loop_plan.md rename to z-archive/appdoc/loop_plan.md diff --git a/appdoc/loop_plan_critical_analysis.md b/z-archive/appdoc/loop_plan_critical_analysis.md similarity index 100% rename from appdoc/loop_plan_critical_analysis.md rename to z-archive/appdoc/loop_plan_critical_analysis.md diff --git a/appdoc/mcp_architecture_analysis.md b/z-archive/appdoc/mcp_architecture_analysis.md similarity index 100% rename from appdoc/mcp_architecture_analysis.md rename to z-archive/appdoc/mcp_architecture_analysis.md diff --git a/appdoc/mcp_integration_proposal.md b/z-archive/appdoc/mcp_integration_proposal.md similarity index 100% rename from appdoc/mcp_integration_proposal.md rename to z-archive/appdoc/mcp_integration_proposal.md diff --git a/appdoc/mcp_outlook_sharepoint_analysis.md b/z-archive/appdoc/mcp_outlook_sharepoint_analysis.md similarity index 100% rename from appdoc/mcp_outlook_sharepoint_analysis.md rename to z-archive/appdoc/mcp_outlook_sharepoint_analysis.md diff --git a/appdoc/mcp_value_analysis.md b/z-archive/appdoc/mcp_value_analysis.md similarity index 100% rename from appdoc/mcp_value_analysis.md rename to z-archive/appdoc/mcp_value_analysis.md diff --git a/appdoc/prompt_produce_diagrams.md b/z-archive/appdoc/prompt_produce_diagrams.md similarity index 100% rename from appdoc/prompt_produce_diagrams.md rename to z-archive/appdoc/prompt_produce_diagrams.md diff --git a/archiv/2025-07_WorkflowDesigner.html b/z-archive/archiv/2025-07_WorkflowDesigner.html similarity index 100% rename from archiv/2025-07_WorkflowDesigner.html rename to z-archive/archiv/2025-07_WorkflowDesigner.html diff --git a/archiv/2025-07_chat_process_visualization.md b/z-archive/archiv/2025-07_chat_process_visualization.md similarity index 100% rename from archiv/2025-07_chat_process_visualization.md rename to z-archive/archiv/2025-07_chat_process_visualization.md diff --git a/archiv/ComponentDiagram.drawio b/z-archive/archiv/ComponentDiagram.drawio similarity index 100% rename from archiv/ComponentDiagram.drawio rename to z-archive/archiv/ComponentDiagram.drawio diff --git a/archiv/ComponentDiagram.pdf b/z-archive/archiv/ComponentDiagram.pdf similarity index 100% rename from archiv/ComponentDiagram.pdf rename to z-archive/archiv/ComponentDiagram.pdf diff --git a/archiv/ERD.drawio b/z-archive/archiv/ERD.drawio similarity index 100% rename from archiv/ERD.drawio rename to z-archive/archiv/ERD.drawio diff --git a/archiv/ERD.pdf b/z-archive/archiv/ERD.pdf similarity index 100% rename from archiv/ERD.pdf rename to z-archive/archiv/ERD.pdf diff --git a/archiv/Konzept AI Calls with document content extraction.txt b/z-archive/archiv/Konzept AI Calls with document content extraction.txt similarity index 100% rename from archiv/Konzept AI Calls with document content extraction.txt rename to z-archive/archiv/Konzept AI Calls with document content extraction.txt diff --git a/archiv/PRISM_Präsentation.html b/z-archive/archiv/PRISM_Präsentation.html similarity index 100% rename from archiv/PRISM_Präsentation.html rename to z-archive/archiv/PRISM_Präsentation.html diff --git a/archiv/PowerOn_Functional_Overview.html b/z-archive/archiv/PowerOn_Functional_Overview.html similarity index 100% rename from archiv/PowerOn_Functional_Overview.html rename to z-archive/archiv/PowerOn_Functional_Overview.html diff --git a/archiv/PowerOn_Technical_Overview_202507.html b/z-archive/archiv/PowerOn_Technical_Overview_202507.html similarity index 100% rename from archiv/PowerOn_Technical_Overview_202507.html rename to z-archive/archiv/PowerOn_Technical_Overview_202507.html diff --git a/archiv/README_AzureSpeechPermissions.md b/z-archive/archiv/README_AzureSpeechPermissions.md similarity index 100% rename from archiv/README_AzureSpeechPermissions.md rename to z-archive/archiv/README_AzureSpeechPermissions.md diff --git a/archiv/README_AzureVoiceSetup.md b/z-archive/archiv/README_AzureVoiceSetup.md similarity index 100% rename from archiv/README_AzureVoiceSetup.md rename to z-archive/archiv/README_AzureVoiceSetup.md diff --git a/archiv/Strategie_Themen_Präsentation.html b/z-archive/archiv/Strategie_Themen_Präsentation.html similarity index 100% rename from archiv/Strategie_Themen_Präsentation.html rename to z-archive/archiv/Strategie_Themen_Präsentation.html diff --git a/archiv/User_Editable_Fields_Overview.md b/z-archive/archiv/User_Editable_Fields_Overview.md similarity index 100% rename from archiv/User_Editable_Fields_Overview.md rename to z-archive/archiv/User_Editable_Fields_Overview.md diff --git a/archiv/app_keymanagement.html b/z-archive/archiv/app_keymanagement.html similarity index 100% rename from archiv/app_keymanagement.html rename to z-archive/archiv/app_keymanagement.html diff --git a/archiv/diagramm_datenfluss.mermaid b/z-archive/archiv/diagramm_datenfluss.mermaid similarity index 100% rename from archiv/diagramm_datenfluss.mermaid rename to z-archive/archiv/diagramm_datenfluss.mermaid diff --git a/archiv/diagramm_datenfluss.png b/z-archive/archiv/diagramm_datenfluss.png similarity index 100% rename from archiv/diagramm_datenfluss.png rename to z-archive/archiv/diagramm_datenfluss.png diff --git a/archiv/diagramm_hld.mermaid b/z-archive/archiv/diagramm_hld.mermaid similarity index 100% rename from archiv/diagramm_hld.mermaid rename to z-archive/archiv/diagramm_hld.mermaid diff --git a/archiv/diagramm_hld.png b/z-archive/archiv/diagramm_hld.png similarity index 100% rename from archiv/diagramm_hld.png rename to z-archive/archiv/diagramm_hld.png diff --git a/archiv/diagramm_komponenten.mermaid b/z-archive/archiv/diagramm_komponenten.mermaid similarity index 100% rename from archiv/diagramm_komponenten.mermaid rename to z-archive/archiv/diagramm_komponenten.mermaid diff --git a/archiv/diagramm_komponenten.png b/z-archive/archiv/diagramm_komponenten.png similarity index 100% rename from archiv/diagramm_komponenten.png rename to z-archive/archiv/diagramm_komponenten.png diff --git a/archiv/doc_system.html b/z-archive/archiv/doc_system.html similarity index 100% rename from archiv/doc_system.html rename to z-archive/archiv/doc_system.html diff --git a/archiv/implementation_content_handling_with_dynamic_ai.md b/z-archive/archiv/implementation_content_handling_with_dynamic_ai.md similarity index 100% rename from archiv/implementation_content_handling_with_dynamic_ai.md rename to z-archive/archiv/implementation_content_handling_with_dynamic_ai.md diff --git a/archiv/komponenten_fortschritt_chart.html b/z-archive/archiv/komponenten_fortschritt_chart.html similarity index 100% rename from archiv/komponenten_fortschritt_chart.html rename to z-archive/archiv/komponenten_fortschritt_chart.html diff --git a/archiv/poweron_summary_202404.md b/z-archive/archiv/poweron_summary_202404.md similarity index 100% rename from archiv/poweron_summary_202404.md rename to z-archive/archiv/poweron_summary_202404.md diff --git a/archiv/poweron_user_capabilities.html b/z-archive/archiv/poweron_user_capabilities.html similarity index 100% rename from archiv/poweron_user_capabilities.html rename to z-archive/archiv/poweron_user_capabilities.html diff --git a/archiv/pricing.html b/z-archive/archiv/pricing.html similarity index 100% rename from archiv/pricing.html rename to z-archive/archiv/pricing.html diff --git a/archiv/release_status_chart.html b/z-archive/archiv/release_status_chart.html similarity index 100% rename from archiv/release_status_chart.html rename to z-archive/archiv/release_status_chart.html diff --git a/archiv/release_status_report.md b/z-archive/archiv/release_status_report.md similarity index 100% rename from archiv/release_status_report.md rename to z-archive/archiv/release_status_report.md diff --git a/archiv/spec.md b/z-archive/archiv/spec.md similarity index 100% rename from archiv/spec.md rename to z-archive/archiv/spec.md diff --git a/archiv/status.html b/z-archive/archiv/status.html similarity index 100% rename from archiv/status.html rename to z-archive/archiv/status.html diff --git a/concepts/AI-Agent-Architecture-Konzept.md b/z-archive/concepts/AI-Agent-Architecture-Konzept.md similarity index 100% rename from concepts/AI-Agent-Architecture-Konzept.md rename to z-archive/concepts/AI-Agent-Architecture-Konzept.md diff --git a/concepts/AI-Agent-Architecture-Review.md b/z-archive/concepts/AI-Agent-Architecture-Review.md similarity index 100% rename from concepts/AI-Agent-Architecture-Review.md rename to z-archive/concepts/AI-Agent-Architecture-Review.md diff --git a/concepts/Agent-Toolbox-Dateisystem-Konzept.md b/z-archive/concepts/Agent-Toolbox-Dateisystem-Konzept.md similarity index 100% rename from concepts/Agent-Toolbox-Dateisystem-Konzept.md rename to z-archive/concepts/Agent-Toolbox-Dateisystem-Konzept.md diff --git a/concepts/Billing-Konzept.md b/z-archive/concepts/Billing-Konzept.md similarity index 100% rename from concepts/Billing-Konzept.md rename to z-archive/concepts/Billing-Konzept.md diff --git a/concepts/Commcoach-Voice-Recording-Streaming-Konzept.md b/z-archive/concepts/Commcoach-Voice-Recording-Streaming-Konzept.md similarity index 100% rename from concepts/Commcoach-Voice-Recording-Streaming-Konzept.md rename to z-archive/concepts/Commcoach-Voice-Recording-Streaming-Konzept.md diff --git a/concepts/Kontext-20260329.md b/z-archive/concepts/Kontext-20260329.md similarity index 100% rename from concepts/Kontext-20260329.md rename to z-archive/concepts/Kontext-20260329.md diff --git a/concepts/Mandanten-Subscription-Konzept.md b/z-archive/concepts/Mandanten-Subscription-Konzept.md similarity index 100% rename from concepts/Mandanten-Subscription-Konzept.md rename to z-archive/concepts/Mandanten-Subscription-Konzept.md diff --git a/concepts/Multi-Mandate-Onboarding-und-Store-Konzept.md b/z-archive/concepts/Multi-Mandate-Onboarding-und-Store-Konzept.md similarity index 100% rename from concepts/Multi-Mandate-Onboarding-und-Store-Konzept.md rename to z-archive/concepts/Multi-Mandate-Onboarding-und-Store-Konzept.md diff --git a/concepts/Multi-Mandate-Umsetzungsbericht.md b/z-archive/concepts/Multi-Mandate-Umsetzungsbericht.md similarity index 100% rename from concepts/Multi-Mandate-Umsetzungsbericht.md rename to z-archive/concepts/Multi-Mandate-Umsetzungsbericht.md diff --git a/concepts/Multi-Mandate-Umsetzungsplan.md b/z-archive/concepts/Multi-Mandate-Umsetzungsplan.md similarity index 100% rename from concepts/Multi-Mandate-Umsetzungsplan.md rename to z-archive/concepts/Multi-Mandate-Umsetzungsplan.md diff --git a/concepts/Navigation-API-Konzept.md b/z-archive/concepts/Navigation-API-Konzept.md similarity index 100% rename from concepts/Navigation-API-Konzept.md rename to z-archive/concepts/Navigation-API-Konzept.md diff --git a/concepts/OAuth-Auth-vs-Data-Connection-Konzept.md b/z-archive/concepts/OAuth-Auth-vs-Data-Connection-Konzept.md similarity index 100% rename from concepts/OAuth-Auth-vs-Data-Connection-Konzept.md rename to z-archive/concepts/OAuth-Auth-vs-Data-Connection-Konzept.md diff --git a/concepts/Plan-SystemFields-Architecture.md b/z-archive/concepts/Plan-SystemFields-Architecture.md similarity index 100% rename from concepts/Plan-SystemFields-Architecture.md rename to z-archive/concepts/Plan-SystemFields-Architecture.md diff --git a/concepts/Subscription-State-Machine.md b/z-archive/concepts/Subscription-State-Machine.md similarity index 100% rename from concepts/Subscription-State-Machine.md rename to z-archive/concepts/Subscription-State-Machine.md diff --git a/cursor-doc/doc_cursor_ai_agent_architecture.md b/z-archive/cursor-doc/doc_cursor_ai_agent_architecture.md similarity index 100% rename from cursor-doc/doc_cursor_ai_agent_architecture.md rename to z-archive/cursor-doc/doc_cursor_ai_agent_architecture.md diff --git a/cursor-doc/doc_cursor_chat_api_integration_concept.md b/z-archive/cursor-doc/doc_cursor_chat_api_integration_concept.md similarity index 100% rename from cursor-doc/doc_cursor_chat_api_integration_concept.md rename to z-archive/cursor-doc/doc_cursor_chat_api_integration_concept.md diff --git a/cursor-doc/doc_cursor_response_json_structure.md b/z-archive/cursor-doc/doc_cursor_response_json_structure.md similarity index 100% rename from cursor-doc/doc_cursor_response_json_structure.md rename to z-archive/cursor-doc/doc_cursor_response_json_structure.md diff --git a/z-archive/db-structure-model-comparison.md b/z-archive/db-structure-model-comparison.md new file mode 100644 index 0000000..189b9d8 --- /dev/null +++ b/z-archive/db-structure-model-comparison.md @@ -0,0 +1,200 @@ +# Detaillierte Analyse: Datenbankstruktur vs. Pydantic-Modelle + +**Export-Datum:** 2026-01-19T20:12:28.176720Z +**Export-Quelle:** Production Instance + +## Zusammenfassung + +Von 19 Tabellen haben alle ein entsprechendes Pydantic-Modell, aber es wurden Unterschiede gefunden. Die meisten Unterschiede sind erwartbar (z.B. ID-Felder mit `default_factory` sind im Modell optional, aber in der DB NOT NULL), aber es gibt einige wichtige Inkonsistenzen, die behoben werden sollten. + +--- + +## Kritische Unterschiede (müssen behoben werden) + +### 1. **UserInDB** (`datamodelUam.py`) + +#### Felder nur in DB (fehlen im Modell): +- **`privilege`** (text, nullable) + - **Problem:** Feld existiert in der Datenbank, aber nicht im Pydantic-Modell + - **Empfehlung:** Entweder Feld zum Modell hinzufügen oder aus der DB entfernen + +#### Typ-Mismatches: + +1. **`roleLabels`** + - **DB:** `jsonb` (dict) - nullable + - **Modell:** `List[str]` - optional + - **Problem:** Datenbank speichert JSONB (wird als dict interpretiert), Modell erwartet Liste von Strings + - **Empfehlung:** Prüfen, wie die Daten tatsächlich gespeichert werden. Wenn es eine Liste ist, sollte der Typ in der DB korrekt sein. Wenn es ein dict ist, sollte das Modell angepasst werden. + +2. **`resetTokenExpires`** + - **DB:** `text` - nullable + - **Modell:** `float` (UTC timestamp in seconds) - optional + - **Problem:** Datenbank speichert als Text, Modell erwartet Float (Unix-Timestamp) + - **Empfehlung:** DB-Typ sollte `double precision` (float8) sein, nicht `text` + +--- + +### 2. **ChatLog** (`datamodelChat.py`) + +#### Felder nur im Modell (fehlen in DB): +- **`actionNumber`** (Optional[int]) +- **`roundNumber`** (Optional[int]) +- **`taskNumber`** (Optional[int]) +- **Problem:** Diese Felder sind im Modell definiert, aber nicht in der Datenbank vorhanden +- **Empfehlung:** Entweder Migration erstellen, um diese Spalten hinzuzufügen, oder aus dem Modell entfernen + +#### Typ-Mismatches: + +1. **`progress`** + - **DB:** `text` - nullable + - **Modell:** `float` (0.0 to 1.0) - optional + - **Problem:** Datenbank speichert als Text, Modell erwartet Float + - **Empfehlung:** DB-Typ sollte `double precision` (float8) sein + +2. **`performance`** + - **DB:** `text` - nullable + - **Modell:** `Dict[str, Any]` - optional + - **Problem:** Datenbank speichert als Text, Modell erwartet Dictionary (JSON) + - **Empfehlung:** DB-Typ sollte `jsonb` sein + +--- + +### 3. **Token** (`datamodelSecurity.py`) + +#### Typ-Mismatches: + +1. **`userId`** + - **DB:** `text` - nullable + - **Modell:** `str` - required (nicht optional) + - **Problem:** Datenbank erlaubt NULL, Modell erwartet zwingend einen Wert + - **Empfehlung:** DB sollte `NOT NULL` sein, da es ein required Feld ist + +2. **`authority`** + - **DB:** `text` - nullable + - **Modell:** `AuthAuthority` (Enum) - required + - **Problem:** Datenbank erlaubt NULL, Modell erwartet zwingend einen Wert + - **Empfehlung:** DB sollte `NOT NULL` sein + +3. **`tokenAccess`** + - **DB:** `text` - nullable + - **Modell:** `str` - required + - **Problem:** Datenbank erlaubt NULL, Modell erwartet zwingend einen Wert + - **Empfehlung:** DB sollte `NOT NULL` sein + +4. **`createdAt`** + - **DB:** `text` - nullable + - **Modell:** `float` (UTC timestamp) - optional + - **Problem:** Datenbank speichert als Text, Modell erwartet Float + - **Empfehlung:** DB-Typ sollte `double precision` (float8) sein + +5. **`revokedAt`** + - **DB:** `text` - nullable + - **Modell:** `float` (UTC timestamp) - optional + - **Problem:** Datenbank speichert als Text, Modell erwartet Float + - **Empfehlung:** DB-Typ sollte `double precision` (float8) sein + +--- + +### 4. **UserConnection** (`datamodelUam.py`) + +#### Typ-Mismatches: + +1. **`expiresAt`** + - **DB:** `text` - nullable + - **Modell:** `float` (UTC timestamp) - optional + - **Problem:** Datenbank speichert als Text, Modell erwartet Float + - **Empfehlung:** DB-Typ sollte `double precision` (float8) sein + +2. **`tokenExpiresAt`** + - **DB:** `text` - nullable + - **Modell:** `float` (UTC timestamp) - optional + - **Problem:** Datenbank speichert als Text, Modell erwartet Float + - **Empfehlung:** DB-Typ sollte `double precision` (float8) sein + +--- + +### 5. **ChatWorkflow** (`datamodelChat.py`) + +#### Typ-Mismatches (JSONB vs. List): + +Mehrere Felder haben das Problem, dass die DB `jsonb` (als dict interpretiert) speichert, aber das Modell `List[...]` erwartet: + +- **`logs`**: DB=`jsonb` (dict), Modell=`List[ChatLog]` +- **`messages`**: DB=`jsonb` (dict), Modell=`List[ChatMessage]` +- **`stats`**: DB=`jsonb` (dict), Modell=`List[ChatStat]` +- **`tasks`**: DB=`jsonb` (dict), Modell=`List[...]` +- **`expectedFormats`**: DB=`text`, Modell=`List[...]` + +**Problem:** JSONB-Felder werden als Dictionary interpretiert, aber das Modell erwartet Listen. Dies deutet darauf hin, dass die Daten möglicherweise als Arrays im JSONB gespeichert werden sollten, oder dass die Serialisierung/Deserialisierung angepasst werden muss. + +**Empfehlung:** Prüfen, wie diese Daten tatsächlich gespeichert und geladen werden. Möglicherweise benötigt die Anwendung eine Custom Serialisierung für JSONB-Arrays. + +--- + +## Erwartbare Unterschiede (keine Aktion erforderlich) + +### ID-Felder mit `default_factory` + +Viele Tabellen haben ID-Felder, die im Modell als `optional=True` markiert sind (wegen `default_factory=lambda: str(uuid.uuid4())`), aber in der DB als `NOT NULL` definiert sind. Dies ist **erwartbar und korrekt**, da: +- Pydantic-Felder mit `default_factory` sind technisch optional (können beim Erstellen weggelassen werden) +- Die Datenbank erwartet jedoch immer einen Wert (NOT NULL) + +**Betroffene Tabellen:** AccessRule, AuthEvent, DataNeutraliserConfig, DataNeutralizerAttributes, Mandate, Role, ChatDocument, FileData, FileItem, Prompt + +--- + +## Weitere Typ-Mismatches (möglicherweise erwartbar) + +### Role.description +- **DB:** `jsonb` (dict) - nullable +- **Modell:** `str` - optional +- **Hinweis:** Möglicherweise wird hier ein mehrsprachiges Dictionary gespeichert, während das Modell einen String erwartet. Prüfen, ob eine Custom Serialisierung verwendet wird. + +### ActionItem.expectedDocumentFormats +- **DB:** `jsonb` (dict) - nullable +- **Modell:** `List[...]` - optional +- **Hinweis:** Ähnlich wie bei ChatWorkflow - JSONB vs. List + +### AutomationDefinition.executionLogs +- **DB:** `jsonb` (dict) - nullable +- **Modell:** `List[...]` - optional +- **Hinweis:** Ähnlich wie bei ChatWorkflow - JSONB vs. List + +### ChatMessage.documents +- **DB:** `jsonb` (dict) - nullable +- **Modell:** `List[...]` - optional +- **Hinweis:** Ähnlich wie bei ChatWorkflow - JSONB vs. List + +--- + +## Empfohlene Maßnahmen + +### Priorität 1 (Kritisch - Datenintegrität): +1. **UserInDB.privilege**: Feld hinzufügen oder entfernen +2. **ChatLog**: `actionNumber`, `roundNumber`, `taskNumber` hinzufügen oder aus Modell entfernen +3. **Token**: Required-Felder (`userId`, `authority`, `tokenAccess`) sollten `NOT NULL` in DB sein +4. **Timestamp-Felder**: Alle Timestamp-Felder sollten `double precision` sein, nicht `text` + +### Priorität 2 (Wichtig - Typ-Konsistenz): +1. **JSONB vs. List**: Prüfen und korrigieren der Serialisierung für alle JSONB-Felder, die Listen enthalten sollen +2. **UserInDB.roleLabels**: Prüfen, ob es wirklich eine Liste oder ein Dictionary ist + +### Priorität 3 (Optional - Code-Qualität): +1. **ID-Felder**: Optional können die Modelle angepasst werden, um explizit `NOT NULL` zu reflektieren (aber nicht notwendig) + +--- + +## Technische Details + +### Typ-Mapping-Probleme + +Das Vergleichstool mappt PostgreSQL-Typen wie folgt: +- `character varying` / `varchar` / `text` → `str` +- `boolean` / `bool` → `bool` +- `integer` / `int` / `bigint` → `int` +- `double precision` / `float8` → `float` +- `jsonb` / `json` → `dict` + +**Problem:** JSONB kann sowohl Dictionaries als auch Arrays enthalten. Das Tool interpretiert JSONB immer als `dict`, auch wenn es tatsächlich ein Array ist. Dies führt zu falschen Mismatch-Meldungen bei Listen-Feldern. + +**Lösung:** Für eine genauere Analyse müsste das Tool die tatsächlichen JSONB-Werte prüfen oder die Datenbank-Schema-Definitionen genauer analysieren. diff --git a/z-archive/feat-file-tree-release-notes.md b/z-archive/feat-file-tree-release-notes.md new file mode 100644 index 0000000..81705f5 --- /dev/null +++ b/z-archive/feat-file-tree-release-notes.md @@ -0,0 +1,116 @@ +# Feature Branch Notes - `feat/file-tree-system` + +Date: 2026-03-17 +Repos: `gateway`, `frontend_nyla` + +## Release Notes (Kurzfassung) + +- Filesystem-Funktionen wurden deutlich erweitert: Batch-Delete und Batch-Move fuer Files/Folders laufen effizient ueber Backend-Endpunkte und DB-Operationen. +- Folder/File-Tree-Verhalten wurde zwischen `Dateien` und `AI Workspace` vereinheitlicht, inklusive Multi-Select und Drag&Drop-Workflows. +- `Dateien`-Ansicht ist wieder strikt backend-getrieben fuer Sortierung, Filter und Pagination (kein Client-Side-Fallback mehr). +- Chat-UX wurde gestrafft: kompaktere CHATS-Liste und optimierter Umgang mit Prompt-Inhalten. +- Langer Paste-Text im Workspace-Input wird als Datei behandelt statt den Prompt zu ueberfrachten. +- Agent-/Workspace-Dokumentfluss wurde stabilisiert (sauberere Ablage und Metadatenkette im Backend-Kontext). +- Mehrere Stabilitaets- und Integrationsanpassungen in Voice/Commcoach/Billing-nahen Bereichen runden das Branch-Inkrement ab. + +--- + +## PR Text - `gateway` + +### Title +`feat: file system + agent/voice revisions (batch ops, workspace docs, stt/tts)` + +### Body +```md +## Summary + +This PR consolidates backend changes for file system handling, workspace-agent document persistence, and voice/service revisions. + +- adds/updates file-system APIs for efficient folder/file operations (including batch-oriented endpoints/DB handling) +- improves workspace agent file persistence flow so downloaded/generated artifacts are stored with proper metadata and structured placement +- extends/adjusts route and interface layers for file, voice, billing, and service-center integrations +- includes commcoach/service-agent updates to stabilize chat/voice-related backend behavior + +## Main areas touched + +- File management: + - `modules/routes/routeDataFiles.py` + - `modules/interfaces/interfaceDbManagement.py` + - `modules/datamodels/datamodelFiles.py` +- Agent/service runtime: + - `modules/serviceCenter/services/serviceAgent/mainServiceAgent.py` + - `modules/serviceCenter/services/serviceAgent/sandboxExecutor.py` + - `modules/serviceCenter/services/serviceChat/mainServiceChat.py` +- Voice/Commcoach: + - `modules/routes/routeVoiceGoogle.py` + - `modules/connectors/connectorVoiceGoogle.py` + - `modules/interfaces/interfaceVoiceObjects.py` + - `modules/features/commcoach/*` +- Billing/other integrations: + - `modules/routes/routeBilling.py` + - `modules/interfaces/interfaceDbBilling.py` + - `modules/serviceCenter/services/serviceBilling/stripeCheckout.py` + +## Test plan + +- [ ] verify batch delete/move endpoints (`/api/files/batch-delete`, `/api/files/batch-move`) with mixed file/folder payloads +- [ ] verify folder recursive delete behavior and conflict/circular checks on folder moves +- [ ] verify agent-generated/downloaded documents are stored with correct filename/extension and expected metadata +- [ ] run relevant backend smoke tests for workspace chat + commcoach voice flows +- [ ] regression-check billing route changes +``` + +--- + +## PR Text - `frontend_nyla` + +### Title +`feat: unified folder/file tree + workspace/files UX and backend-driven table behavior` + +### Body +```md +## Summary + +This PR delivers the frontend part of the file-tree/workspace enhancement with consistent state handling and backend-driven table interactions. + +- unifies folder/file tree behavior across Files page and AI Workspace +- improves tree interactions (multi-select, drag/drop, action handling, visual behavior) +- adds batch-aware file/folder operations via new API usage +- updates workspace prompt behavior (long paste as file attachment) +- compacts CHATS list presentation and adjusts metadata layout +- keeps table sort/filter/pagination aligned with backend refetch mechanism + +## Main areas touched + +- Tree + file context: + - `src/components/FolderTree/FolderTree.tsx` + - `src/components/FolderTree/FolderTree.module.css` + - `src/contexts/FileContext.tsx` + - `src/api/fileApi.ts` +- Files page/table integration: + - `src/pages/basedata/FilesPage.tsx` + - `src/components/FormGenerator/FormGeneratorTable/FormGeneratorTable.tsx` + - `src/hooks/useFiles.ts` +- Workspace UX: + - `src/pages/views/workspace/FileBrowser.tsx` + - `src/pages/views/workspace/WorkspaceInput.tsx` + - `src/pages/views/workspace/WorkspacePage.tsx` + - `src/pages/views/workspace/ConversationList.tsx` +- Additional related adjustments: + - `src/hooks/useCommcoach.ts` + - `src/hooks/useSpeechAudioCapture.ts` + - `src/hooks/useTtsPlayback.ts` + - `src/api/billingApi.ts` + - `src/pages/billing/BillingDataView.tsx` + - `src/pages/views/commcoach/*` + +## Test plan + +- [ ] Files page: select folder in tree -> table shows correct folder scope +- [ ] Files page: sorting/filtering/pagination trigger backend refetch correctly +- [ ] Tree: multi-select with CTRL/SHIFT, drag selected items, delete files/folders via separate batch actions +- [ ] Workspace: drag file/folder refs into prompt and validate attachment behavior +- [ ] Workspace input: paste long text (>=1000 chars) creates file attachment instead of inline prompt text +- [ ] CHATS list: no redundant second status line; last activity shown on left +- [ ] run production build (`npm run build`) and smoke-test key views +``` diff --git a/implementation/Chatbot/FUNCTIONAL_DIFFERENCES_ANALYSIS.md b/z-archive/implementation/Chatbot/FUNCTIONAL_DIFFERENCES_ANALYSIS.md similarity index 100% rename from implementation/Chatbot/FUNCTIONAL_DIFFERENCES_ANALYSIS.md rename to z-archive/implementation/Chatbot/FUNCTIONAL_DIFFERENCES_ANALYSIS.md diff --git a/implementation/Chatbot/legacy/chatbot.py b/z-archive/implementation/Chatbot/legacy/chatbot.py similarity index 100% rename from implementation/Chatbot/legacy/chatbot.py rename to z-archive/implementation/Chatbot/legacy/chatbot.py diff --git a/implementation/Chatbot/legacy/constants.py b/z-archive/implementation/Chatbot/legacy/constants.py similarity index 100% rename from implementation/Chatbot/legacy/constants.py rename to z-archive/implementation/Chatbot/legacy/constants.py diff --git a/implementation/Chatbot/legacy/router.py b/z-archive/implementation/Chatbot/legacy/router.py similarity index 100% rename from implementation/Chatbot/legacy/router.py rename to z-archive/implementation/Chatbot/legacy/router.py diff --git a/implementation/Chatbot/legacy/schemas.py b/z-archive/implementation/Chatbot/legacy/schemas.py similarity index 100% rename from implementation/Chatbot/legacy/schemas.py rename to z-archive/implementation/Chatbot/legacy/schemas.py diff --git a/implementation/Chatbot/legacy/service.py b/z-archive/implementation/Chatbot/legacy/service.py similarity index 100% rename from implementation/Chatbot/legacy/service.py rename to z-archive/implementation/Chatbot/legacy/service.py diff --git a/implementation/Chatbot/legacy/sqlitetool.py b/z-archive/implementation/Chatbot/legacy/sqlitetool.py similarity index 100% rename from implementation/Chatbot/legacy/sqlitetool.py rename to z-archive/implementation/Chatbot/legacy/sqlitetool.py diff --git a/implementation/Chatbot/legacy/streaming_helper.py b/z-archive/implementation/Chatbot/legacy/streaming_helper.py similarity index 100% rename from implementation/Chatbot/legacy/streaming_helper.py rename to z-archive/implementation/Chatbot/legacy/streaming_helper.py diff --git a/implementation/RBAC-AccessRules-Refactoring.md b/z-archive/implementation/RBAC-AccessRules-Refactoring.md similarity index 100% rename from implementation/RBAC-AccessRules-Refactoring.md rename to z-archive/implementation/RBAC-AccessRules-Refactoring.md diff --git a/implementation/README-react-mode.md b/z-archive/implementation/README-react-mode.md similarity index 100% rename from implementation/README-react-mode.md rename to z-archive/implementation/README-react-mode.md diff --git a/implementation/Refactor Nyla UI basic components with new mandate SaaS model/analysis_and_implementation_plan.md b/z-archive/implementation/Refactor Nyla UI basic components with new mandate SaaS model/analysis_and_implementation_plan.md similarity index 100% rename from implementation/Refactor Nyla UI basic components with new mandate SaaS model/analysis_and_implementation_plan.md rename to z-archive/implementation/Refactor Nyla UI basic components with new mandate SaaS model/analysis_and_implementation_plan.md diff --git a/implementation/Saas Multi Tenant Mandate/admin_ui_concept.md b/z-archive/implementation/Saas Multi Tenant Mandate/admin_ui_concept.md similarity index 100% rename from implementation/Saas Multi Tenant Mandate/admin_ui_concept.md rename to z-archive/implementation/Saas Multi Tenant Mandate/admin_ui_concept.md diff --git a/implementation/Saas Multi Tenant Mandate/mandate_concept.md b/z-archive/implementation/Saas Multi Tenant Mandate/mandate_concept.md similarity index 100% rename from implementation/Saas Multi Tenant Mandate/mandate_concept.md rename to z-archive/implementation/Saas Multi Tenant Mandate/mandate_concept.md diff --git a/implementation/Saas Multi Tenant Mandate/mandate_implementation_analysis.md b/z-archive/implementation/Saas Multi Tenant Mandate/mandate_implementation_analysis.md similarity index 100% rename from implementation/Saas Multi Tenant Mandate/mandate_implementation_analysis.md rename to z-archive/implementation/Saas Multi Tenant Mandate/mandate_implementation_analysis.md diff --git a/implementation/Saas Multi Tenant Mandate/mandate_implementation_gateway.md b/z-archive/implementation/Saas Multi Tenant Mandate/mandate_implementation_gateway.md similarity index 100% rename from implementation/Saas Multi Tenant Mandate/mandate_implementation_gateway.md rename to z-archive/implementation/Saas Multi Tenant Mandate/mandate_implementation_gateway.md diff --git a/implementation/Saas Multi Tenant Mandate/mandate_implementation_ui_myla.md b/z-archive/implementation/Saas Multi Tenant Mandate/mandate_implementation_ui_myla.md similarity index 100% rename from implementation/Saas Multi Tenant Mandate/mandate_implementation_ui_myla.md rename to z-archive/implementation/Saas Multi Tenant Mandate/mandate_implementation_ui_myla.md diff --git a/implementation/SharePoint/concept_sharepoint_feature.md b/z-archive/implementation/SharePoint/concept_sharepoint_feature.md similarity index 100% rename from implementation/SharePoint/concept_sharepoint_feature.md rename to z-archive/implementation/SharePoint/concept_sharepoint_feature.md diff --git a/implementation/Use Case Expenses Workflow/expenses_workflow_definition.md b/z-archive/implementation/Use Case Expenses Workflow/expenses_workflow_definition.md similarity index 100% rename from implementation/Use Case Expenses Workflow/expenses_workflow_definition.md rename to z-archive/implementation/Use Case Expenses Workflow/expenses_workflow_definition.md diff --git a/implementation/doc_automation_templates_db_and_editor_concept.md b/z-archive/implementation/doc_automation_templates_db_and_editor_concept.md similarity index 100% rename from implementation/doc_automation_templates_db_and_editor_concept.md rename to z-archive/implementation/doc_automation_templates_db_and_editor_concept.md diff --git a/implementation/doc_automation_templates_impl_frontend.md b/z-archive/implementation/doc_automation_templates_impl_frontend.md similarity index 100% rename from implementation/doc_automation_templates_impl_frontend.md rename to z-archive/implementation/doc_automation_templates_impl_frontend.md diff --git a/implementation/doc_automation_templates_impl_gateway.md b/z-archive/implementation/doc_automation_templates_impl_gateway.md similarity index 100% rename from implementation/doc_automation_templates_impl_gateway.md rename to z-archive/implementation/doc_automation_templates_impl_gateway.md diff --git a/implementation/implementation_action_validation_generic.md b/z-archive/implementation/implementation_action_validation_generic.md similarity index 100% rename from implementation/implementation_action_validation_generic.md rename to z-archive/implementation/implementation_action_validation_generic.md diff --git a/implementation/implementation_adaptive_react_mode.md b/z-archive/implementation/implementation_adaptive_react_mode.md similarity index 100% rename from implementation/implementation_adaptive_react_mode.md rename to z-archive/implementation/implementation_adaptive_react_mode.md diff --git a/implementation/implementation_adaptive_react_mode_technical.md b/z-archive/implementation/implementation_adaptive_react_mode_technical.md similarity index 100% rename from implementation/implementation_adaptive_react_mode_technical.md rename to z-archive/implementation/implementation_adaptive_react_mode_technical.md diff --git a/implementation/implementation_ai-call-looping-architecture_done.md b/z-archive/implementation/implementation_ai-call-looping-architecture_done.md similarity index 100% rename from implementation/implementation_ai-call-looping-architecture_done.md rename to z-archive/implementation/implementation_ai-call-looping-architecture_done.md diff --git a/implementation/implementation_ai_processing_flows.md b/z-archive/implementation/implementation_ai_processing_flows.md similarity index 100% rename from implementation/implementation_ai_processing_flows.md rename to z-archive/implementation/implementation_ai_processing_flows.md diff --git a/implementation/implementation_centralized_ai_calls.md b/z-archive/implementation/implementation_centralized_ai_calls.md similarity index 100% rename from implementation/implementation_centralized_ai_calls.md rename to z-archive/implementation/implementation_centralized_ai_calls.md diff --git a/implementation/implementation_chat_validation_workflow_task_action.md b/z-archive/implementation/implementation_chat_validation_workflow_task_action.md similarity index 100% rename from implementation/implementation_chat_validation_workflow_task_action.md rename to z-archive/implementation/implementation_chat_validation_workflow_task_action.md diff --git a/implementation/implementation_content_handling_done.md b/z-archive/implementation/implementation_content_handling_done.md similarity index 100% rename from implementation/implementation_content_handling_done.md rename to z-archive/implementation/implementation_content_handling_done.md diff --git a/implementation/implementation_content_handling_with_dynamic_ai_v2.md b/z-archive/implementation/implementation_content_handling_with_dynamic_ai_v2.md similarity index 100% rename from implementation/implementation_content_handling_with_dynamic_ai_v2.md rename to z-archive/implementation/implementation_content_handling_with_dynamic_ai_v2.md diff --git a/implementation/implementation_core_ai_engine.md b/z-archive/implementation/implementation_core_ai_engine.md similarity index 100% rename from implementation/implementation_core_ai_engine.md rename to z-archive/implementation/implementation_core_ai_engine.md diff --git a/implementation/implementation_doc_userauth_process_concept.md b/z-archive/implementation/implementation_doc_userauth_process_concept.md similarity index 100% rename from implementation/implementation_doc_userauth_process_concept.md rename to z-archive/implementation/implementation_doc_userauth_process_concept.md diff --git a/implementation/implementation_doc_userauth_ui_adaptations.md b/z-archive/implementation/implementation_doc_userauth_ui_adaptations.md similarity index 100% rename from implementation/implementation_doc_userauth_ui_adaptations.md rename to z-archive/implementation/implementation_doc_userauth_ui_adaptations.md diff --git a/implementation/implementation_document_generation_one-path.md b/z-archive/implementation/implementation_document_generation_one-path.md similarity index 100% rename from implementation/implementation_document_generation_one-path.md rename to z-archive/implementation/implementation_document_generation_one-path.md diff --git a/implementation/implementation_dynamic_generic_ai_calls.md b/z-archive/implementation/implementation_dynamic_generic_ai_calls.md similarity index 100% rename from implementation/implementation_dynamic_generic_ai_calls.md rename to z-archive/implementation/implementation_dynamic_generic_ai_calls.md diff --git a/implementation/implementation_extraction.md b/z-archive/implementation/implementation_extraction.md similarity index 100% rename from implementation/implementation_extraction.md rename to z-archive/implementation/implementation_extraction.md diff --git a/implementation/implementation_key_management.md b/z-archive/implementation/implementation_key_management.md similarity index 100% rename from implementation/implementation_key_management.md rename to z-archive/implementation/implementation_key_management.md diff --git a/implementation/implementation_multifile_output_refactoring.md b/z-archive/implementation/implementation_multifile_output_refactoring.md similarity index 100% rename from implementation/implementation_multifile_output_refactoring.md rename to z-archive/implementation/implementation_multifile_output_refactoring.md diff --git a/implementation/implementation_normalization_service.md b/z-archive/implementation/implementation_normalization_service.md similarity index 100% rename from implementation/implementation_normalization_service.md rename to z-archive/implementation/implementation_normalization_service.md diff --git a/implementation/implementation_react_two_stage_prompting_spec.md b/z-archive/implementation/implementation_react_two_stage_prompting_spec.md similarity index 100% rename from implementation/implementation_react_two_stage_prompting_spec.md rename to z-archive/implementation/implementation_react_two_stage_prompting_spec.md diff --git a/implementation/implementation_refactor_db-consistency.md b/z-archive/implementation/implementation_refactor_db-consistency.md similarity index 100% rename from implementation/implementation_refactor_db-consistency.md rename to z-archive/implementation/implementation_refactor_db-consistency.md diff --git a/implementation/implementation_refactor_stats-unified.md b/z-archive/implementation/implementation_refactor_stats-unified.md similarity index 100% rename from implementation/implementation_refactor_stats-unified.md rename to z-archive/implementation/implementation_refactor_stats-unified.md diff --git a/implementation/implementation_taskintentions_done.md b/z-archive/implementation/implementation_taskintentions_done.md similarity index 100% rename from implementation/implementation_taskintentions_done.md rename to z-archive/implementation/implementation_taskintentions_done.md diff --git a/implementation/implementation_ui_table_pagination.md b/z-archive/implementation/implementation_ui_table_pagination.md similarity index 100% rename from implementation/implementation_ui_table_pagination.md rename to z-archive/implementation/implementation_ui_table_pagination.md diff --git a/implementation/implementation_user_prompt_analysis.md b/z-archive/implementation/implementation_user_prompt_analysis.md similarity index 100% rename from implementation/implementation_user_prompt_analysis.md rename to z-archive/implementation/implementation_user_prompt_analysis.md diff --git a/implementation/implementation_workflow_automation_architecture.md b/z-archive/implementation/implementation_workflow_automation_architecture.md similarity index 100% rename from implementation/implementation_workflow_automation_architecture.md rename to z-archive/implementation/implementation_workflow_automation_architecture.md diff --git a/implementation/implementation_workflow_processing_refactoring.md b/z-archive/implementation/implementation_workflow_processing_refactoring.md similarity index 100% rename from implementation/implementation_workflow_processing_refactoring.md rename to z-archive/implementation/implementation_workflow_processing_refactoring.md diff --git a/implementation/rbac_access_concept_done.md b/z-archive/implementation/rbac_access_concept_done.md similarity index 100% rename from implementation/rbac_access_concept_done.md rename to z-archive/implementation/rbac_access_concept_done.md diff --git a/implementation/rbac_access_umsetzungskonzept done.md b/z-archive/implementation/rbac_access_umsetzungskonzept done.md similarity index 100% rename from implementation/rbac_access_umsetzungskonzept done.md rename to z-archive/implementation/rbac_access_umsetzungskonzept done.md diff --git a/implementation/security_check.html b/z-archive/implementation/security_check.html similarity index 100% rename from implementation/security_check.html rename to z-archive/implementation/security_check.html diff --git a/implementation/spec-workflow-architecture.md b/z-archive/implementation/spec-workflow-architecture.md similarity index 100% rename from implementation/spec-workflow-architecture.md rename to z-archive/implementation/spec-workflow-architecture.md diff --git a/implementation/spec-workflow-implementation.md b/z-archive/implementation/spec-workflow-implementation.md similarity index 100% rename from implementation/spec-workflow-implementation.md rename to z-archive/implementation/spec-workflow-implementation.md diff --git a/implementation/trustee_feature_rbac_architecture.md b/z-archive/implementation/trustee_feature_rbac_architecture.md similarity index 100% rename from implementation/trustee_feature_rbac_architecture.md rename to z-archive/implementation/trustee_feature_rbac_architecture.md diff --git a/reviews/20260111 doc_session_handling_analysis.md b/z-archive/reviews/20260111 doc_session_handling_analysis.md similarity index 100% rename from reviews/20260111 doc_session_handling_analysis.md rename to z-archive/reviews/20260111 doc_session_handling_analysis.md diff --git a/reviews/20260111 doc_session_handling_summary_operations.md b/z-archive/reviews/20260111 doc_session_handling_summary_operations.md similarity index 100% rename from reviews/20260111 doc_session_handling_summary_operations.md rename to z-archive/reviews/20260111 doc_session_handling_summary_operations.md diff --git a/reviews/connector_generic_refactoring_analysis.md b/z-archive/reviews/connector_generic_refactoring_analysis.md similarity index 100% rename from reviews/connector_generic_refactoring_analysis.md rename to z-archive/reviews/connector_generic_refactoring_analysis.md diff --git a/reviews/context_checker_analysis.md b/z-archive/reviews/context_checker_analysis.md similarity index 100% rename from reviews/context_checker_analysis.md rename to z-archive/reviews/context_checker_analysis.md diff --git a/reviews/report_20251020_unused_functions_analysis.md b/z-archive/reviews/report_20251020_unused_functions_analysis.md similarity index 100% rename from reviews/report_20251020_unused_functions_analysis.md rename to z-archive/reviews/report_20251020_unused_functions_analysis.md diff --git a/reviews/report_20251020_workflow_step_by_step_analysis.md b/z-archive/reviews/report_20251020_workflow_step_by_step_analysis.md similarity index 100% rename from reviews/report_20251020_workflow_step_by_step_analysis.md rename to z-archive/reviews/report_20251020_workflow_step_by_step_analysis.md diff --git a/test-local-llm/analysis/buy-spec.md b/z-archive/test-local-llm/analysis/buy-spec.md similarity index 100% rename from test-local-llm/analysis/buy-spec.md rename to z-archive/test-local-llm/analysis/buy-spec.md diff --git a/test-local-llm/app.py b/z-archive/test-local-llm/app.py similarity index 100% rename from test-local-llm/app.py rename to z-archive/test-local-llm/app.py diff --git a/test-local-llm/requirements.txt b/z-archive/test-local-llm/requirements.txt similarity index 100% rename from test-local-llm/requirements.txt rename to z-archive/test-local-llm/requirements.txt diff --git a/test-local-llm/start-python.bat b/z-archive/test-local-llm/start-python.bat similarity index 100% rename from test-local-llm/start-python.bat rename to z-archive/test-local-llm/start-python.bat diff --git a/test-local-llm/start-python.ps1 b/z-archive/test-local-llm/start-python.ps1 similarity index 100% rename from test-local-llm/start-python.ps1 rename to z-archive/test-local-llm/start-python.ps1 diff --git a/test-local-llm/static/favicon.png b/z-archive/test-local-llm/static/favicon.png similarity index 100% rename from test-local-llm/static/favicon.png rename to z-archive/test-local-llm/static/favicon.png diff --git a/test-local-llm/static/poweron-logo.png b/z-archive/test-local-llm/static/poweron-logo.png similarity index 100% rename from test-local-llm/static/poweron-logo.png rename to z-archive/test-local-llm/static/poweron-logo.png diff --git a/test-local-llm/t1.png b/z-archive/test-local-llm/t1.png similarity index 100% rename from test-local-llm/t1.png rename to z-archive/test-local-llm/t1.png diff --git a/test-local-llm/templates/index.html b/z-archive/test-local-llm/templates/index.html similarity index 100% rename from test-local-llm/templates/index.html rename to z-archive/test-local-llm/templates/index.html diff --git a/training/handover_agenda_sync.md b/z-archive/training/handover_agenda_sync.md similarity index 100% rename from training/handover_agenda_sync.md rename to z-archive/training/handover_agenda_sync.md diff --git a/training/handover_einarbeitungsplan.md b/z-archive/training/handover_einarbeitungsplan.md similarity index 100% rename from training/handover_einarbeitungsplan.md rename to z-archive/training/handover_einarbeitungsplan.md diff --git a/training/handover_naming_convention.md b/z-archive/training/handover_naming_convention.md similarity index 100% rename from training/handover_naming_convention.md rename to z-archive/training/handover_naming_convention.md diff --git a/ui_nyla/ARCHITECTURE_DIAGRAMS.md b/z-archive/ui_nyla/ARCHITECTURE_DIAGRAMS.md similarity index 100% rename from ui_nyla/ARCHITECTURE_DIAGRAMS.md rename to z-archive/ui_nyla/ARCHITECTURE_DIAGRAMS.md diff --git a/ui_nyla/DEPENDENCY_MAP.md b/z-archive/ui_nyla/DEPENDENCY_MAP.md similarity index 100% rename from ui_nyla/DEPENDENCY_MAP.md rename to z-archive/ui_nyla/DEPENDENCY_MAP.md diff --git a/ui_nyla/README.md b/z-archive/ui_nyla/README.md similarity index 100% rename from ui_nyla/README.md rename to z-archive/ui_nyla/README.md diff --git a/ui_nyla/feature-trustee/doc_trustee_feature_architecture.md b/z-archive/ui_nyla/feature-trustee/doc_trustee_feature_architecture.md similarity index 100% rename from ui_nyla/feature-trustee/doc_trustee_feature_architecture.md rename to z-archive/ui_nyla/feature-trustee/doc_trustee_feature_architecture.md diff --git a/ui_nyla/feature-trustee/doc_trustee_feature_ui_demo.html b/z-archive/ui_nyla/feature-trustee/doc_trustee_feature_ui_demo.html similarity index 100% rename from ui_nyla/feature-trustee/doc_trustee_feature_ui_demo.html rename to z-archive/ui_nyla/feature-trustee/doc_trustee_feature_ui_demo.html diff --git a/ui_nyla/feature-trustee/doc_trustee_feature_ui_specification.md b/z-archive/ui_nyla/feature-trustee/doc_trustee_feature_ui_specification.md similarity index 100% rename from ui_nyla/feature-trustee/doc_trustee_feature_ui_specification.md rename to z-archive/ui_nyla/feature-trustee/doc_trustee_feature_ui_specification.md diff --git a/ui_nyla/feature-userregistration/doc_userregistration_ui_adaptations.md b/z-archive/ui_nyla/feature-userregistration/doc_userregistration_ui_adaptations.md similarity index 100% rename from ui_nyla/feature-userregistration/doc_userregistration_ui_adaptations.md rename to z-archive/ui_nyla/feature-userregistration/doc_userregistration_ui_adaptations.md diff --git a/ui_playground/doc_frontend_options_usage.md b/z-archive/ui_playground/doc_frontend_options_usage.md similarity index 100% rename from ui_playground/doc_frontend_options_usage.md rename to z-archive/ui_playground/doc_frontend_options_usage.md diff --git a/ui_playground/doc_styles_architecture.md b/z-archive/ui_playground/doc_styles_architecture.md similarity index 100% rename from ui_playground/doc_styles_architecture.md rename to z-archive/ui_playground/doc_styles_architecture.md