diff --git a/concepts/Kontext-20260328.md b/concepts/Kontext-20260328.md index 9e519dd..986b60a 100644 --- a/concepts/Kontext-20260328.md +++ b/concepts/Kontext-20260328.md @@ -42,7 +42,7 @@ Es gibt ZWEI vollständig getrennte Rollensysteme. Siehe auch: `@poweron/.cursor - `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 mandateType (system/personal/company), isSystem, deletedAt +- `Mandate`: `@poweron/gateway/modules/datamodels/datamodelUam.py` — Mandantenmodell mit isSystem (Root-Schutz), deletedAt. `mandateType` wurde entfernt (keine Geschäftslogik). --- @@ -51,7 +51,8 @@ Es gibt ZWEI vollständig getrennte Rollensysteme. Siehe auch: `@poweron/.cursor - **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 Personal-Mandate, wenn User keine Admin-Mandate hat +- **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 @@ -79,7 +80,7 @@ Es gibt ZWEI vollständig getrennte Rollensysteme. Siehe auch: `@poweron/.cursor |-------|-------| | `@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: Aktiv/Archiv, Rename/Delete/Archive Icons | +| `@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 | @@ -89,7 +90,7 @@ Es gibt ZWEI vollständig getrennte Rollensysteme. Siehe auch: `@poweron/.cursor | `@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 | +| `@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) | @@ -98,16 +99,23 @@ Es gibt ZWEI vollständig getrennte Rollensysteme. Siehe auch: `@poweron/.cursor ## 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`-ähnliche Spalten werden bei Bootstrap durch `migrateLegacyUnderscoreSysColumns` / `migrateLegacyUnderscoreSysColumnsAllPoweronDatabases` in die `sys*`-Felder übernommen. +- **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 laut Umsetzung) +## Produkt-Themen (Stand 2026-03-28) -1. **CommCoach UDB:** `CommcoachDossierView` nutzt `UnifiedDataBar` mit `hideTabs={['chats']}` (Dateien + Quellen). Coaching bleibt bei der bestehenden SSE-Pipeline. **KI:** `CommcoachService._callAi` nutzt `getService("ai", ServiceCenterContext)` — dieselbe ServiceCenter-AI-Schicht wie der Workspace inkl. Neutralisierung in `mainServiceAi.callAi`. Nach `documentCreated` im Stream feuert die View `fileUploaded`, die UDB-`FilesTab` lädt die Liste neu. -2. **Zentrale Neutralisierung & RAG:** Prompt-Neutralisierung und Rehydration laufen in `mainServiceAi` (stream + non-stream). Tool `neutralizeData` im Agent und die Indizierung in `mainServiceKnowledge` nutzen denselben Neutralization-Service. **Mandanten-RAG in CommCoach:** Bei Retrieval-Intent „Thema erinnern“ (`RECALL_TOPIC`) werden nach Keyword-Suche zusätzlich Embedding + `searchSessionsByTopicRag` (Knowledge-Interface, mandate-scoped) eingespeist; die Prompt-Zeile „Relevante Sessions und Mandantenwissen …“ fasst Sessions und RAG-Snippets zusammen. -3. **Settings (5 Tabs):** Profil (Modal + Konto + About), Darstellung (Theme + UI-Sprache), Stimme (STT/TTS API), Datenneutralisierung (Erklärung + Platzhalter-Mappings-Liste), Datenschutz (Kurztext Mandant/Features + Link GDPR). Für tiefergehende Neutralizer-Konfiguration (Feature-Instanz) bleiben die Feature-spezifischen Admin-UIs zuständig. +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. --- @@ -118,4 +126,4 @@ Es gibt ZWEI vollständig getrennte Rollensysteme. Siehe auch: `@poweron/.cursor - 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`) \ No newline at end of file +- Pydantic-Models sind die einzige Quelle für UI-Feld-Definitionen (via `attributeUtils.py`) diff --git a/concepts/Multi-Mandate-Onboarding-und-Store-Konzept.md b/concepts/Multi-Mandate-Onboarding-und-Store-Konzept.md index 92e73d2..9a9cbd4 100644 --- a/concepts/Multi-Mandate-Onboarding-und-Store-Konzept.md +++ b/concepts/Multi-Mandate-Onboarding-und-Store-Konzept.md @@ -60,22 +60,11 @@ Dieses Dokument beschreibt die **Ziel-Architektur** für Marktzugang und Mandant ## Datenmodell-Erweiterung -Auf `Mandate` ([datamodelUam.py](../../gateway/modules/datamodels/datamodelUam.py)) ein fachlicher Typ: +**`mandateType` wurde entfernt** (2026-03-28). Das Feld hatte keine Geschäftslogik — kein RBAC, kein Billing, kein Feature-Gate brancht darauf. Der Root-Mandant wird durch `isSystem=true` geschützt. -| Wert | Bedeutung | -|------|-----------| -| `system` | Root / nicht löschbar, nur Betrieb (sysadmin-User) | -| `personal` | Solo-Mandat (ein primärer „Owner"-Admin) | -| `company` | Organisations-Mandat (Team, Einladungen) | +**Aktuelles Modell:** `Mandate` hat `name`, `label`, `enabled`, `isSystem`, `deletedAt`. Kein `mandateType` mehr. -**Trennung `isSystem` vs. `mandateType`:** Beide Felder haben unterschiedliche Aufgaben und bleiben bestehen: - -- **`isSystem`** = operativer Schutz (Delete-Schutz, Bootstrap-Erkennung). Nur der Root-Mandant hat `isSystem=true`. -- **`mandateType`** = fachliche Semantik (Markt, Onboarding, UI, Reporting). Steuert keine Geschäftslogik oder Feature-Gates. - -**`mandateType` ist mutabel und rein informativ.** Ein Personal-Mandat kann zu `company` geändert werden, wenn der User sein Team erweitert (Einladungen, Name ändern). Es darf **keine Geschäftslogik** hart an `personal` vs. `company` gebunden sein — keine Feature-Gates, keine unterschiedliche Kapazitätsbehandlung auf Basis von `mandateType`. Der Typ dient der UI-Darstellung, dem Reporting und der Onboarding-Steuerung. - -**Default für bestehende Mandanten (Migration):** `company`, Root explizit `system`. +**Home-Mandant:** Jeder Benutzer hat ab erstem Login ein Home-Mandat mit dem Namen **"Home {username}"** (unique, da `username` unique). Dies dient als persönliche Basis für Features, Billing und Daten. Wird einheitlich bei Register, OAuth-Onboarding, Invite-Login und Store-Zugriff sichergestellt. ---