From 70649218f1a0436fb00fce4eec87bc500ba5d0fc Mon Sep 17 00:00:00 2001 From: ValueOn AG
`, `featureInstanceId=`, `mandateId=`
-- Templates: `isSystemRole=False`, `mandateId=NULL`, `featureInstanceId=NULL`, `featureCode=` (globale Vorlagen)
-- Verknüpfung: `FeatureAccessRole` Junction Table
-- Logik: Zuordnung User → Feature-Instanz erfolgt via `createFeatureAccess()` in `interfaceDbApp.py`, welche IMMER mindestens eine Instanz-Rolle verlangt (ValueError wenn leer)
-- Jedes Feature-Modul definiert seine `TEMPLATE_ROLES` in `mainXxx.py`
-
-### Strikte Regeln:
-1. NIE eine Mandantenrolle (`admin`) einer `FeatureAccessRole` zuweisen
-2. NIE eine Feature-Rolle (`workspace-admin`) einer `UserMandateRole` zuweisen
-3. Admin-Lookup für Feature-Instanzen: `roleLabel.endswith("-admin")`, NICHT `"admin" in roleLabel`
-4. `_copyTemplateRoles` sucht: `featureCode=X, mandateId=NULL, featureInstanceId=NULL` — nie `isSystemRole=True`
-5. Alle Pfade, die `FeatureAccess` erstellen, MÜSSEN mindestens eine instanz-scoped roleId mitgeben
-
-### Datenmodelle:
-- `Role`: `@poweron/gateway/modules/datamodels/datamodelRbac.py` — Felder: id, roleLabel, description, mandateId, featureInstanceId, featureCode, isSystemRole
-- `UserMandate`: `@poweron/gateway/modules/datamodels/datamodelMembership.py` — User-Mitgliedschaft in Mandant
-- `FeatureAccess`: `@poweron/gateway/modules/datamodels/datamodelMembership.py` — User-Zugriff auf Feature-Instanz
-- `FeatureInstance`: `@poweron/gateway/modules/datamodels/datamodelFeatures.py` — Instanz eines Features in einem Mandanten
-- `Mandate`: `@poweron/gateway/modules/datamodels/datamodelUam.py` — Mandantenmodell mit isSystem (Root-Schutz), deletedAt. `mandateType` wurde entfernt (keine Geschäftslogik).
-
----
-
-## Feature-Store-Konzept ("Own Instance Pattern")
-
-- **UI:** `@poweron/frontend_nyla/src/pages/Store.tsx` — Pro Mandant ein "Aktivieren für [Mandant]" Button
-- **Backend:** `@poweron/gateway/modules/routes/routeStore.py` — `POST /api/store/activate`
-- **Flow:** User wählt Feature → wählt Mandant → Backend erstellt `FeatureInstance` mit `copyTemplateRoles=True` → findet Admin-Rolle (`endswith("-admin")`) → weist User via `createFeatureAccess(userId, instanceId, roleIds=[adminRoleId])` zu
-- **Auto-Provisioning:** `GET /api/store/mandates` erstellt automatisch "Home {username}"-Mandate, wenn User keine Admin-Mandate hat
-- **Home-Mandant:** Jeder User hat ab erstem Login ein Home-Mandat ("Home {username}"). Wird in Login, Register, OAuth-Onboarding und Store einheitlich sichergestellt.
-- **Template-Rollen-Kopie:** `@poweron/gateway/modules/interfaces/interfaceFeatures.py` — `_copyTemplateRoles()` und `syncRolesFromTemplate()`
-- **Orphan Control:** Letzer FeatureAccess entfernt → FeatureInstance wird gelöscht
-
----
-
-## Schlüssel-Backend-Dateien
-
-| Datei | Zweck |
-|-------|-------|
-| `@poweron/gateway/modules/interfaces/interfaceDbApp.py` | Kern-DB-Interface: createUserMandate, createFeatureAccess, _provisionMandateForUser; Domain-Models nutzen `PowerOnModel` / `sys*`-Metadaten |
-| `@poweron/gateway/modules/interfaces/interfaceFeatures.py` | Feature-Instanz-Verwaltung: _copyTemplateRoles, syncRolesFromTemplate |
-| `@poweron/gateway/modules/routes/routeStore.py` | Store-API: activate, mandates-list |
-| `@poweron/gateway/modules/routes/routeAdminFeatures.py` | Admin-API: add_user_to_feature_instance (Rollen-Validierung: nur Instanz-Rollen!), rename instance |
-| `@poweron/gateway/modules/routes/routeSystem.py` | `/api/navigation` — liefert isAdmin pro FeatureInstance |
-| `@poweron/gateway/modules/routes/routeSecurityLocal.py` | Login, Register, _provisionMandateForUser |
-| `@poweron/gateway/modules/shared/attributeUtils.py` | Generiert Attribute aus Pydantic-Models für FormGenerator |
-| `@poweron/gateway/modules/connectors/connectorDbPostgre.py` | DB-Connector: `sysCreatedAt` / `sysCreatedBy` / `sysModifiedAt` / `sysModifiedBy`; Migration alter `_createdAt`-Spalten via `migrateLegacyUnderscoreSysColumns` (Bootstrap) |
-| `@poweron/gateway/modules/migration/migrateRootUsers.py` | Root→Personal-Mandate-Migration |
-
----
-
-## Schlüssel-Frontend-Dateien
-
-| Datei | Zweck |
-|-------|-------|
-| `@poweron/frontend_nyla/src/pages/Store.tsx` | Feature-Store mit Mandate-Kontext |
-| `@poweron/frontend_nyla/src/components/UnifiedDataBar/UnifiedDataBar.tsx` | UDB: Chats, Files, Sources Tabs |
-| `@poweron/frontend_nyla/src/components/UnifiedDataBar/ChatsTab.tsx` | Chats: Volltext-Suche, Feature-Code-Gruppierung, Flat-Mode nach lastMessageAt |
-| `@poweron/frontend_nyla/src/components/UnifiedDataBar/FilesTab.tsx` | Files: Scope/Neutralize Icons |
-| `@poweron/frontend_nyla/src/components/UnifiedDataBar/SourcesTab.tsx` | Sources: Scope/Neutralize auf Active Sources |
-| `@poweron/frontend_nyla/src/components/Navigation/MandateNavigation.tsx` | Nav-Tree mit Rename-Icon für Instanz-Admins |
-| `@poweron/frontend_nyla/src/components/Navigation/TreeNavigation/TreeNavigation.tsx` | Generischer Tree mit actions-Slot |
-| `@poweron/frontend_nyla/src/components/OnboardingAssistant.tsx` | Globaler Onboarding-Assistent (Dashboard, dismissible, reaktivierbar via UserSection) |
-| `@poweron/frontend_nyla/src/components/Navigation/UserSection.tsx` | User-Kontextmenü: Guthaben, Einstellungen, Onboarding |
-| `@poweron/frontend_nyla/src/pages/Settings.tsx` | User-Settings: profile, appearance, voice, neutralization, privacy |
-| `@poweron/frontend_nyla/src/components/FormGenerator/` | Dynamische Formulare aus Backend-Attribut-Definitionen |
-| `@poweron/frontend_nyla/src/hooks/useNavigation.ts` | Navigation-Hook mit FeatureInstance.isAdmin |
-| `@poweron/frontend_nyla/src/pages/views/workspace/WorkspacePage.tsx` | Workspace-Feature-Seite mit Chat-Drag&Drop + RAG-Resolve |
-| `@poweron/frontend_nyla/src/pages/views/commcoach/CommcoachDossierView.tsx` | CommCoach mit UDB (`hideTabs: chats`), gleicher `instanceId`/`mandateId`-Kontext wie Workspace |
-| `@poweron/gateway/modules/datamodels/datamodelBase.py` | `PowerOnModel`: `sysCreatedAt`, `sysCreatedBy`, `sysModifiedAt`, `sysModifiedBy` (camelCase, UI-readonly vorbereitet) |
-
----
-
-## System-Felder (DB-Metadaten)
-
-- **Spalten / Modelle:** `sysCreatedAt`, `sysCreatedBy`, `sysModifiedAt`, `sysModifiedBy` — gepflegt durch den Connector (`connectorDbPostgre.py`); viele Domain-Models erben von `PowerOnModel` in `datamodelBase.py`.
-- **Legacy:** Frühere `_createdAt`-Spalten werden bei Bootstrap durch `migrateLegacyUnderscoreSysColumns` / `migrateLegacyUnderscoreSysColumnsAllPoweronDatabases` in die `sys*`-Felder übernommen.
-- **UI:** FormGenerator unterstützt `readonly`-Attribute; wo Metadaten in Listen/Forms explizit gezeigt werden sollen, Felder als readonly markieren (schrittweise je Screen).
-
----
-
-## Produkt-Themen (Stand 2026-03-28)
-
-1. **CommCoach UDB + Voice:** UDB in `CommcoachDossierView`. Voice-Controller bezieht STT-Sprache dynamisch aus zentralen Preferences.
-2. **Neutralisierung End-to-End:** `requireNeutralization` vom UI-Toggle bis `AiCallRequest` durchgereicht via ServiceCenterContext. Mandanten-RAG in CommCoach via `searchSessionsByTopicRag`.
-3. **Settings (5 Tabs):** Profil, Darstellung, Stimme, Datenneutralisierung, Datenschutz.
-4. **Billing: nur PREPAY_MANDATE:** `PREPAY_USER` komplett entfernt. `budgetAiCHF` in Subscriptions (Trial: 5 CHF, Standard: 10 CHF/Monat). Auto-Recharge-Felder in BillingSettings.
-5. **mandateType entfernt:** Enum, Feld, Validator in 13+ Dateien gelöscht. `isSystem` als einziger Root-Schutz.
-6. **Home-Mandant:** "Home {username}" bei erstem Login (Register/OAuth/Invitation) via `_ensureHomeMandate()`.
-7. **UDB ChatsTab:** Server-seitige Volltext-Suche (`searchWorkflowsByContent`), Flat-Mode nach `lastMessageAt`, zweistufige Baumansicht (Feature-Code-Sektionen > Feature-Instanzen).
-8. **Chat Drag & Drop + RAG:** Chat-Items aus ChatsTab auf Workspace droppbar. Backend `/resolve-rag` liefert Zusammenfassung.
-9. **Datenvolumen:** `assertCapacity("dataVolumeMB")` prüft RAG-Index-Grösse (`FileContentIndex.totalSize`). API `/api/subscription/data-volume/{mandateId}` liefert `ragIndexMB`, `filesMB`, `percentUsed`, `warning` (>=80%).
-10. **Mandate-Cascade:** `deleteMandate(force=True)` löscht alle abhängigen Tabellen: ContentChunk, FileContentIndex, DataNeutralizerAttributes, DataSource, FeatureDataSource, FileItem, ChatMessage/Log/Workflow, FeatureAccessRole, FeatureAccess, FeatureInstance, UserMandateRole, UserMandate, Stripe-Subscriptions, BillingTransaction/Account/Settings, AccessRule, Role, Mandate. Frontend: Namensbestätigungs-Dialog.
-
----
-
-## Coding-Konventionen
-
-- Alle internen Funktionen beginnen mit `_` Prefix (z.B. `_copyTemplateRoles`)
-- camelCase für alle Variablen und Funktionsnamen (kein snake_case)
-- Keine unnötigen Fallbacks — Fehler müssen propagiert werden
-- Keine Deprecations — alte Logik löschen statt deprecaten
-- Keine Backwards-Compatibility-Workarounds
-- Pydantic-Models sind die einzige Quelle für UI-Feld-Definitionen (via `attributeUtils.py`)
diff --git a/concepts/Kontext-20260329.md b/concepts/Kontext-20260329.md
new file mode 100644
index 0000000..1c7b7b4
--- /dev/null
+++ b/concepts/Kontext-20260329.md
@@ -0,0 +1,288 @@
+# PowerOn Applikations-Kontext (Stand 2026-03-29)
+
+Multi-Tenant SaaS-Applikation mit Feature-Store-Modell, AI-Agent-Workspace und mandantenweiter Datenneutralisierung.
+
+---
+
+## 1. 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` |
+
+---
+
+## 2. Gateway-Architektur (Backend)
+
+### Modulstruktur (`gateway/modules/`)
+
+| 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 (30+ Dateien: 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 (30+ Dateien: Admin, Billing, DataFiles, DataSources, Security, Store, System...) |
+| `security/` | Sicherheits-Middleware |
+| `serviceCenter/` | Zentrale Service-Orchestrierung (siehe Abschnitt 3) |
+| `serviceHub/` | Service-Registry und Dependency Injection |
+| `shared/` | Gemeinsame Utilities (attributeUtils, etc.) |
+| `system/` | System-Konfiguration |
+| `workflows/` | Workflow-Engine mit Methoden und Aktionen (siehe Abschnitt 4) |
+
+### Interfaces (DB-Schicht)
+
+Die Interfaces kapseln alle Datenbankzugriffe:
+
+| 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-Abstraction (Text, Embedding, Vision, Streaming) |
+| `interfaceFeatures.py` | Feature-Instanz-Lifecycle, Template-Rollen-Kopie |
+| `interfaceRbac.py` | RBAC-Regelauswertung |
+
+---
+
+## 3. ServiceCenter (Kern-Orchestrierung)
+
+Das ServiceCenter ist die zentrale Schicht, die alle Services verbindet. Es wird pro Request/Session erstellt und propagiert einen **ServiceCenterContext** (`context.py`).
+
+### Services (`serviceCenter/services/`)
+
+| Service | Pfad | Zweck |
+|---------|------|-------|
+| `serviceAgent` | `mainServiceAgent.py` (3400+ Zeilen) | AI-Agent mit 30+ Tools (readFile, writeFile, searchInFileContent, browseContainer, summarizeContent, readContentObjects, webSearch, sendMail, etc.) |
+| `serviceAi` | `mainServiceAi.py` (1700+ Zeilen) | AI-Call-Gateway: Neutralisierung, Billing-Preflight, Provider-Selection, Streaming, Extraction, Generation |
+| `serviceKnowledge` | `mainServiceKnowledge.py` | Knowledge Store: Indexierung, Semantic Search, RAG-Kontext-Aufbau (`buildAgentContext`) |
+| `serviceBilling` | | Billing-Checks, Transaktionen |
+| `serviceChat` | | Chat-Persistence |
+| `serviceExtraction` | | Dokument-Extraktion (PDF, DOCX, XLSX...) |
+| `serviceGeneration` | | Dokument-Generierung |
+| `serviceMessaging` | | E-Mail, Notifications |
+| `serviceSubscription` | | Subscription-Verwaltung |
+| `serviceWeb` | | Web-Scraping |
+
+### ServiceCenterContext (`context.py`)
+
+Propagiert pro Request:
+- `userId`, `mandateId`, `featureInstanceId`
+- `requireNeutralization: Optional[bool]` — Chat-Level Neutralisierungsflag
+- Provider-Restrictions, Billing-Context
+
+### Agent-Tools (in `mainServiceAgent.py`)
+
+Der Agent hat 30+ registrierte Tools. Tools liefern direkt Rohdaten — Neutralisierung erfolgt zentral im AI-Service (`mainServiceAi.py`) bevor Daten an ein AI-Modell gesendet werden.
+
+Datenschutz-relevante DataSource-Tools:
+- `_resolveDataSource()` — liest `neutralize`-Flag der DataSource als 4. Tuple-Element
+- `_downloadFromDataSource()` — vererbt `neutralize`-Flag auf erstellte FileItems
+- `_queryFeatureInstance()` — setzt `requireNeutralization=True` auf Sub-Agent AI-Calls wenn FeatureDataSource `neutralize=True`
+
+---
+
+## 4. Workflow-Engine
+
+### WorkflowManager (`workflows/workflowManager.py`, 1400+ Zeilen)
+
+Zentrale Workflow-Steuerung für Automation und dynamische Workflows.
+
+### Methoden (`workflows/methods/`)
+
+| Methode | Aktionen |
+|---------|----------|
+| `methodContext` | `extractContent`, `neutralizeData`, `saveContent`, `transformContent` |
+| `methodAi` | AI-Analyse, Summarization, Prompt-Processing |
+| `methodChatbot` | Chatbot-spezifische Aktionen |
+| `methodSharepoint` | SharePoint-Integration |
+| `methodOutlook` | Outlook/E-Mail-Integration |
+| `methodJira` | Jira-Integration |
+| `methodTrustee` | Trustee-Feature-Aktionen |
+
+---
+
+## 5. Neutralisierungs-System (KRITISCH)
+
+**Architektur, Prozess und Code-Karte (ein Dokument):** [wiki/compliance/Neutralisierung.md](../compliance/Neutralisierung.md)
+
+### Prinzip: Zentrales Gate — ALLE Daten, die an ein AI-Modell gehen, werden AUSSCHLIESSLICH in `mainServiceAi.py` neutralisiert.
+
+### Architektur: Einzige zentrale Stelle
+
+Neutralisierung findet nur an **einer einzigen Stelle** statt: `_shouldNeutralize()` und `_neutralizeRequest()` in `mainServiceAi.py`. Kein anderer Service, kein Tool und kein Workflow prüft oder neutralisiert eigenständig. Failsafe: Wenn Neutralisierung erforderlich ist (`requireNeutralization=True`) und fehlschlägt, wird der AI-Call blockiert (`RuntimeError`).
+
+### Neutralisierungs-Trigger (Prioritätsreihenfolge)
+
+1. **Per-Request:** `AiCallRequest.requireNeutralization = True/False` — expliziter Override
+2. **Chat-Level:** `ServiceCenterContext.requireNeutralization = True` — Session-Level-Flag
+3. **Mandate-Config:** `NeutralizationConfig.enabled` — mandantenweite Konfiguration
+
+### Was neutralisiert wird (in `_neutralizeRequest`)
+
+- `request.prompt` — Benutzer-Prompt
+- `request.context` — RAG-Kontext (externe Dokumente)
+- `request.messages` — Chat-Nachrichten (OpenAI-Style)
+
+### Schlüssel-Dateien
+
+| Datei | Rolle |
+|-------|-------|
+| `features/neutralization/serviceNeutralization/mainServiceNeutralization.py` | `processText(text)` → `{neutralized_text, mappings}`, `resolveText(text)` → Rehydrierung |
+| `routes/routeDataFiles.py` | `PATCH /{fileId}/neutralize` — Toggle löscht Index synchron, re-indexiert im Background |
+| `serviceAi/mainServiceAi.py` | **Zentrales Gate:** `_shouldNeutralize()` prüft Request → Context → Config; `_neutralizeRequest()` neutralisiert prompt, context, messages. Hard-Mode bei `requireNeutralization=True` |
+| `serviceKnowledge/mainServiceKnowledge.py` | `indexFile()` neutralisiert bei `FileItem.neutralize=True` (Data-at-rest-Schutz). RAG-Chunks werden neutral gespeichert |
+| `serviceAgent/mainServiceAgent.py` | `_resolveDataSource()` liest `neutralize`-Flag der DataSource. `_downloadFromDataSource()` vererbt Flag auf erstellte FileItems. `_queryFeatureInstance()` setzt `requireNeutralization=True` wenn FeatureDataSource neutralize-Flag gesetzt |
+| `workflows/methods/methodContext/actions/neutralizeData.py` | Explizite Neutralisierungs-Aktion in Workflows (prüft nur Config, nicht Context-Flag) |
+
+### Failsafe-Kette
+
+1. **Toggle ON:** Index + Chunks werden synchron gelöscht → kein Leak bei Background-Re-Index-Fehler
+2. **Indexierung:** `indexFile()` neutralisiert Chunks bei `FileItem.neutralize=True` → Data-at-rest ist sicher
+3. **DataSource-Download:** neutralize-Flag wird auf erstellte FileItems vererbt
+4. **FeatureDataSource:** `_queryFeatureInstance()` setzt `requireNeutralization=True` auf Sub-Agent AI-Calls
+5. **AI-Calls (Zentrales Gate):** Hard-Mode (`requireNeutralization=True`) → Prompt-/Context-Fehler = `RuntimeError` (AI-Call blockiert), Message-Fehler = Message entfernt
+6. **`_rehydrateResponse()`** bleibt als Utility-Methode verfügbar, wird aber nicht mehr automatisch aufgerufen
+
+### NeutralizationPanel (Frontend)
+
+`frontend_nyla/src/pages/views/workspace/NeutralizationPanel.tsx` — zeigt alle Files mit `neutralize`-Flag, deren Status und Platzhalter-Mappings. API: `GET /api/workspace/{instanceId}/files` → `{files: [...]}`.
+
+---
+
+## 6. Frontend-Architektur
+
+### Struktur (`frontend_nyla/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 |
+
+### 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 |
+
+### UI-Regeln
+
+- **Keine Browser-Dialoge** (alert/confirm/prompt) — stattdessen `useConfirm()` und `usePrompt()` Hooks
+- Alle internen Funktionen mit `_` Prefix
+- camelCase für Variablen und Funktionen
+
+---
+
+## 7. RBAC-System (Zwei getrennte Rollensysteme!)
+
+### Mandantenrollen
+- Labels: `admin`, `user`, `viewer`
+- Scope: `mandateId`, kein `featureCode`/`featureInstanceId`
+- Junction: `UserMandateRole`
+
+### Feature-Instanz-Rollen
+- Labels: `workspace-admin`, `workspace-user`, `workspace-viewer`, etc.
+- Scope: `mandateId` + `featureCode` + `featureInstanceId`
+- Junction: `FeatureAccessRole`
+
+**Strikte Regel:** NIE eine Mandantenrolle einer FeatureAccessRole zuweisen oder umgekehrt.
+
+---
+
+## 8. Billing & Subscriptions
+
+- **Modell:** PREPAY_MANDATE (kein PREPAY_USER)
+- **Billing-Check:** Vor jedem AI-Call via `_preflightBillingCheck` und `_checkBillingBeforeAiCall`
+- **Datenvolumen:** `assertCapacity("dataVolumeMB")` prüft RAG-Index-Grösse
+- **Trial:** 5 CHF, Standard: 10 CHF/Monat
+
+---
+
+## 9. AI-Core (Provider-Abstraction)
+
+### Model-Registry (`aicoreModelRegistry.py`)
+Registriert alle Provider-Plugins und deren Modelle dynamisch.
+
+### Model-Selector (`aicoreModelSelector.py`)
+Wählt optimal basierend auf: Operation Type, Prompt-Grösse, Provider-Restrictions, Score-Ranking.
+
+### Provider-Plugins
+- `aicorePluginAnthropic.py` — Claude Sonnet/Haiku/Opus
+- `aicorePluginOpenai.py` — GPT-4o, Embeddings (text-embedding-3-small/large), DALL-E
+- `aicorePluginMistral.py` — Mistral Large/Small, Mistral Embed
+- `aicorePluginPerplexity.py` — Sonar/Sonar-Pro
+- `aicorePluginTavily.py` — Web-Search
+- `aicorePluginPrivateLlm.py` — Private LLM
+- `aicorePluginInternal.py` — Interne Extraktoren/Generatoren/Renderer
+
+### Operation Types
+`dataExtract`, `dataAnalyse`, `agent`, `embedding`, `imageGeneration`, `vision`, `webSearch`
+
+---
+
+## 10. Knowledge Store (RAG)
+
+### Datenmodelle (`datamodelKnowledge.py`)
+- `FileContentIndex` — Pro File: Struktur, Metadaten, `isNeutralized`, `neutralizationStatus`, `totalObjects`, `totalSize`
+- `ContentChunk` — Semantische Chunks mit Embedding-Vektor, `fileId`, `data`, `metadata`
+- `RoundMemory` — Kontext aus früheren Runden (file_ref, etc.)
+
+### Indexierung (`serviceKnowledge.indexFile()`)
+1. Extraktion via `serviceExtraction`
+2. Optional: Neutralisierung via `serviceNeutralization.processText()`
+3. Chunking + Embedding
+4. Speicherung in `FileContentIndex` + `ContentChunk`
+
+### RAG-Kontext (`serviceKnowledge.buildAgentContext()`)
+1. Semantic Search via pgvector
+2. Context-Budget: Priorisierte Layer (File-Refs, Instance Docs, Mandate Docs)
+3. Neutralisierung erfolgt zentral im AI-Service wenn der RAG-Kontext als `request.context` an ein AI-Modell geht
+
+---
+
+## 11. 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 |
+
+---
+
+## 12. 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`