wiki/concepts/Multi-Mandate-Umsetzungsbericht.md
2026-03-28 16:59:18 +01:00

13 KiB

Multi-Mandate Konzept — Umsetzungsbericht

Datum: 2026-03-28 (aktualisiert) Basis: Multi-Mandate-Onboarding-und-Store-Konzept.md


Legende

Status Bedeutung
OK Vollstaendig umgesetzt gemaess Konzept

1. Datenmodell-Erweiterung

Punkt Status Details
MandateType Enum (system, personal, company) OK Auf Mandate-Model in datamodelUam.py.
isSystem separat von mandateType OK Zwei unabhaengige Felder mit klarer Trennung.
mandateType mutabel/informativ OK Keine Geschaeftslogik an den Typ gebunden.
Default fuer bestehende Mandanten: company OK Migration setzt Default.

2. Onboarding-Flows

Punkt Status Details
Zwei CTAs auf Login-Seite (Personal/Company) OK Login.tsx: "Kostenlos testen" und "Fuer Unternehmen".
Register-Formular mit registrationType + companyName OK Register.tsx liest type aus URL, zeigt Firmenname bei company.
Backend: _provisionMandateForUser mit korrektem Typ OK routeSecurityLocal.py erstellt Mandate mit personal/company.
Subscription startet als PENDING OK MandateSubscription mit status=PENDING bei Erstellung.
_activatePendingSubscriptions bei Login OK Wird sowohl bei Local-Login als auch bei Google-OAuth aufgerufen.
OAuth-Onboarding-Wizard (Post-Login) OK OnboardingWizard.tsx existiert, wird bei isNewUser=true gezeigt.
Invitation-Flow (bestehendes Modell) OK Unveraendert, funktioniert mit Multi-Mandate-Modell.

3. Feature Store: Own Instance Pattern

Punkt Status Details
mandateId immer required (explizit, nie implizit) OK StoreActivateRequest.mandateId: str = Field(...) (required).
Mehrere Instanzen desselben Features erlaubt OK Jede Aktivierung erstellt neue FeatureInstance.
Store fuer alle User sichtbar (Upselling) OK Kein Gate auf Admin-Rolle fuer Store-Ansicht.
Auto-Provisioning Personal-Mandate bei 0 Admin-Mandaten OK Automatische Mandate-Erstellung wenn User keine Admin-Mandate hat.
Orphan Control bei Deaktivierung OK Letzer FeatureAccess entfernt -> FeatureInstance geloescht.
Store.tsx Header: "Own Instance Pattern" OK Kommentar aktualisiert.
Docstring in routeStore.py OK Korrigiert: "mandateId is None" entfernt, da mandateId jetzt required.

4. Root-Mandant: Nur technisch

Punkt Status Details
createUser weist NICHT zum Root-Mandanten zu OK _assignUserToRootMandate wurde geloescht.
Keine Feature-Instanzen fuer Endkunden im Root OK Migration entfernt Root-Instanzen.
sysadmin-User behalten Root-Mitgliedschaft OK Step 2 der Migration entfernt nur Nicht-SysAdmin-User.

5. Migration: Root-Mandant bereinigen

Punkt Status Details
Step 1: Feature-Daten migrieren (alle User) OK migrateRootUsers.py: Erstellt Ziel-Instanzen, migriert 5 Tabellen.
Step 2: Root bereinigen OK Entfernt Root-FeatureInstances, entfernt Nicht-SysAdmin-UserMandates.
Idempotent + DB-Flag OK _isMigrationCompleted / _setMigrationCompleted mit DB-Record.
Bootstrap-Integration OK interfaceBootstrap.py ruft Migration automatisch auf.
Voice/Documents Migration OK migrateVoiceAndDocuments.py migriert VoiceSettings + CoachingDocuments.

6. Unified Data Layer (UDL)

Punkt Status Details
FileItem: scope + neutralize Felder OK scope: str (default "personal"), neutralize: bool (default False).
DataSource: scope + neutralize Felder OK Felder vorhanden in datamodelDataSource.py.
FeatureDataSource: scope + neutralize Felder OK Felder hinzugefuegt in datamodelFeatureDataSource.py.
FileContentIndex: scope, isNeutralized, userId, mandateId OK Alle 4 Felder vorhanden.
scope=global RBAC (nur SysAdmin) OK Auf PATCH und PUT Endpunkten enforced.
Re-Indexing bei Scope/Neutralize-Aenderung OK PATCH-Endpoints triggern _autoIndexFile.
indexFile liest scope aus FileItem OK Setzt scope und isNeutralized auf FileContentIndex.
Alte DB-Records mit scope=None OK _convertFileItems setzt Default "personal" vor Validierung.
PATCH /api/datasources/{id}/scope + /neutralize OK Neue Route routeDataSources.py mit Lookup fuer DataSource + FeatureDataSource.

7. Daten-Neutralisierung

Punkt Status Details
Flag auf Datenquelle (neutralize) OK Auf FileItem, DataSource und FeatureDataSource.
Fail-Safe: Dokument NICHT weitergeben bei Fehler OK _neutralizeRequest returned excludedDocs, Call laeuft weiter ohne fehlgeschlagene Docs.
_neutralizeRequest neutralisiert prompt UND messages OK Beide werden verarbeitet.
Graceful Degradation statt RuntimeError OK Einzelne Dokumente werden ausgeschlossen, nicht der gesamte Call.
Neutralisierte Docs im Chat-UI sichtbar OK ChatStream.tsx: <details> Block mit "Gesendete Daten", neutralisiert/uebersprungen Badges, und "Nicht gesendet (Neutralisierung fehlgeschlagen)" Bereich fuer excludedDocs.
User kann Platzhalter-Mappings einsehen/loeschen OK Settings-Tab "Datenneutralisierung" mit Tabelle aller DataNeutralizerAttributes pro User. GET/DELETE API unter /api/local/neutralization-mappings.
requireNeutralization Flag pro AI-Call OK Feld auf AiCallRequest (Optional[bool]). _shouldNeutralize respektiert per-Request Override. UI-Toggle (Lock-Button) in WorkspaceInput.tsx neben Send-Button.

8. UI-Komponente: Unified Data Bar (UDB)

Punkt Status Details
UDB als wiederverwendbare Plattform-Komponente OK components/UnifiedDataBar/ mit UnifiedDataBar, ChatsTab, FilesTab, SourcesTab.
Keine Render-Props, direkte Tab-Komposition OK Tabs direkt gerendert, hideTabs-Prop verfuegbar.
hideTabs fuer Feature-spezifische Konfiguration OK CommCoach nutzt hideTabs={['chats']}.
Alte Komponenten geloescht (FileBrowser, DataSourcePanel, ConversationList) OK Alle drei Dateien geloescht.

8.1 Files-Tab

Punkt Status Details
FolderTree mit Ordnerstruktur OK Nutzt FolderTree-Komponente.
Upload (Drag-Drop + Dateidialog) OK Implementiert.
Suche OK Volltextsuche ueber Dateinamen und Tags.
Scope-Icons inline (cycling) OK Klick wechselt personal -> featureInstance -> mandate. Icons auf 14px vergroessert fuer bessere Sichtbarkeit.
Neutralisierungs-Toggle inline OK Lock-Emoji mit opacity 0.4/1.0 Toggle. 14px fuer Sichtbarkeit.
Legende OK Am unteren Rand der Komponente.

8.2 Sources-Tab

Punkt Status Details
Connection Browsing (Services, Ordner, Dateien) OK Volle Browsing-Logik transferiert.
Feature Data Browsing (Mandate -> Instanzen -> Tabellen) OK Volle Logik transferiert.
Active Sources mit Scope/Neutralize-Icons OK Scope-Cycling und Neutralisierungs-Toggle auf Active-Elementen.
Icons NUR auf Active Sources (nicht auf Browse/Feature Data) OK Konzeptkonform.
PATCH-Endpoints fuer DataSource/FeatureDataSource OK routeDataSources.py registriert unter /api/datasources.

8.3 Chats-Tab

Punkt Status Details
Baumstruktur nach Feature-Instanzen OK Gruppiert nach featureInstanceId mit aufgeloestem featureLabel.
Feature-Label (nicht UUID) als Gruppenname OK Backend listWorkspaceWorkflows reichert featureLabel und featureCode aus FeatureInstance-Lookup an.
Suchfunktion OK Volltextsuche ueber Chat-Labels.
Flat Mode (chronologische Liste) OK Toggle im Tab-Header.
Drag-and-Drop in Prompt OK draggable + onDragStart mit application/chat-id.
Create New Button OK "+" Button wenn onCreateNew gesetzt.
Aktiv/Archiv Filter-Tabs OK Sub-Tabs "Aktiv (N)" und "Archiv (N)" unter der Toolbar. Nutzt includeArchived=true im API-Call.
Inline Action Icons (Umbenennen, Archivieren, Loeschen) OK Drei Icons pro Chat-Eintrag auf Hover: Stift, Box/Pfeil, Muelleimer. Archivierung/Wiederherstellung per PATCH workflow status.
Active Workflow Highlighting OK CSS-Klasse auf aktiven Chat.
API-Response korrekt gelesen (workflows key) OK response.data?.workflows (Bugfix angewendet).

8.4 FolderTree

Punkt Status Details
FileNode mit scope + neutralize OK Optionale Felder auf dem Interface.
Scope/Neutralize Icons in Datei-Zeilen OK Zwischen Dateiname und Aktions-Buttons. 14px Emoji-Groesse.
Callbacks onScopeChange/onNeutralizeToggle OK Durch SelectionCtx durchgereicht.

9. RAG als zentrales Repository

Punkt Status Details
Scope-basiertes Filtering bei RAG-Queries OK semanticSearch filtert nach Scope.
Union-Query (personal + featureInstance + mandate + global) OK Implementiert im Knowledge-Service.
scope aus FileItem in RAG-Index uebernommen OK indexFile liest und setzt Scope.
isNeutralized im RAG-Index OK Wird bei Neutralisierung gesetzt.

10. Onboarding-Assistant

Punkt Status Details
Global (nicht Feature-gebunden) OK Keine instanceId/mandateId Props.
Auf Dashboard-Seite OK In Dashboard.tsx eingebunden.
4 globale Schritte (Mandant, Feature, Datenquelle, Chat) OK API-basierte Pruefung.
"Nicht wieder anzeigen" Checkbox OK localStorage-basiert mit Checkbox.
Reaktivierbar ueber User-Kontextmenu OK "Onboarding-Assistent" in UserSection.tsx.
Kontextsensitive Callouts OK Pro Schritt ein Tipp-Text (Callout) mit farbiger Hervorhebung fuer den naechsten offenen Schritt. Texte fuer alle 4 Schritte definiert.

11. Mandanten-Loeschung: Kaskade

Punkt Status Details
FeatureAccess loeschen OK Pro Instanz.
FeatureInstances loeschen OK Alle im Mandanten.
Instanz-Daten: ChatWorkflow, ChatMessage, ChatLog OK Geloescht pro Instanz.
Instanz-Daten: FileItem OK Geloescht pro Instanz.
Instanz-Daten: DataSource OK Geloescht pro Instanz.
Instanz-Daten: DataNeutralizerAttributes OK Geloescht pro Instanz.
Instanz-Daten: FileContentIndex (RAG) OK Geloescht pro Instanz.
UserMandate-Zuordnungen OK Entfernt.
MandateSubscription OK Entfernt.
Stripe-Subscription kuendigen OK stripe.Subscription.cancel(stripeSubId) wird pro aktiver Subscription vor dem Loeschen aufgerufen.
isSystem=true Schutz OK Systemmandate nicht loeschbar.
Soft-Delete mit 30-Tage Retention OK deletedAt Feld auf Mandate-Model. Soft-Delete setzt enabled=False + deletedAt=now(). purgeExpiredMandates(retentionDays=30) im Bootstrap. restoreMandate() fuer Wiederherstellung.

12. Subscription: Datenvolumen als Parameter

Punkt Status Details
maxDataVolumeMB in SubscriptionPlan OK Feld existiert auf SubscriptionPlan (Optional[int]).
API fuer Datenvolumen-Nutzung OK GET /api/subscription/data-volume/{mandateId} berechnet Nutzung (FileItem.fileSize Summe), liefert usedMB, maxDataVolumeMB, percentUsed, warning.

13. Voice-Settings Zentralisierung

Punkt Status Details
UserVoicePreferences Model (User-Level) OK In datamodelUam.py.
Settings-Seite mit Tabs inkl. "Stimme & Sprache" OK Settings.tsx mit 5 Tabs (inkl. Datenneutralisierung).
CommCoach nutzt zentrale Voice-Preferences OK Kein eigenes Voice-Silo mehr.
Workspace nutzt zentrale Voice-Preferences OK WorkspaceInput.tsx liest von /api/local/voice-preferences.

14. Code-Hygiene

Punkt Status Details
_assignUserToRootMandate geloescht OK Methode entfernt.
Store.tsx: "Own Instance Pattern" im Kommentar OK Aktualisiert.
interfaceFeatureWorkspace.py: Kein "VoiceSettings" in Docstring OK Bereinigt.
routeFeatureCommcoach.py: Kein "voice endpoints" in Docstring OK Bereinigt.
CommCoach: Eigene Dokument-/Voice-Endpoints geloescht OK Entfernt.
Alte FileBrowser/DataSourcePanel/ConversationList geloescht OK Alle drei entfernt.

Zusammenfassung

Kategorie OK
Datenmodell 4
Onboarding-Flows 7
Feature Store 7
Root-Mandant 3
Migration 5
Unified Data Layer 9
Neutralisierung 7
UDB (UI) 27
RAG 4
Onboarding-Assistant 6
Mandanten-Loeschung 12
Subscription/Datenvolumen 2
Voice-Zentralisierung 4
Code-Hygiene 6
Gesamt 103

Alle Punkte sind vollstaendig umgesetzt. Keine offenen oder teilweisen Punkte verbleibend.