wiki/concepts/Multi-Mandate-Umsetzungsplan.md
2026-03-24 14:16:36 +01:00

35 KiB
Raw Blame History

Umsetzungsplan: Multi-Mandate Onboarding, Store und Unified Data Layer

Grundlage: Multi-Mandate-Onboarding-und-Store-Konzept.md v4

Struktur: Der Plan folgt den drei Phasen aus dem Konzept. Jede Phase ist in konkrete Arbeitspakete (AP) zerlegt. Jedes AP enthält: betroffene Dateien, Abhängigkeiten und Akzeptanzkriterien.

Legende: [BE] = Backend, [FE] = Frontend, [DB] = Datenbank/Migration, [OPS] = Betrieb/Infrastruktur


Phase 1 — Mandate-per-Registration und Own-Instance-Pattern

Ziel: Saubere Mandanten-Grenze, eigene Instanzen pro Mandant, Root nur noch technisch. FeatureInstance = Datengrenze.


AP 1.1 — [DB] Datenmodell: mandateType Enum auf Mandate

Beschreibung: Neues Feld mandateType auf dem Mandate-Modell. Enum mit Werten system, personal, company. Mutabel und rein informativ — keine Geschäftslogik daran gebunden.

Dateien:

  • gateway/modules/datamodels/datamodelUam.py — Enum MandateType hinzufügen, Feld mandateType auf Mandate

Schritte:

  1. Enum MandateType definieren (system, personal, company)
  2. Feld mandateType: MandateType auf Mandate mit Default company
  3. Bestehende Mandanten erhalten via DB-Update Default company
  4. Root-Mandant explizit auf system setzen (im Bootstrap)

Akzeptanz:

  • Alle bestehenden Mandanten haben mandateType=company
  • Root-Mandant hat mandateType=system
  • Keine Geschäftslogik prüft mandateType für Feature-Gates oder Kapazität

Abhängigkeiten: Keine


AP 1.2 — [BE] Subscription-Timing: PENDINGACTIVE

Beschreibung: MandateSubscription wird bei Registrierung mit Status PENDING erstellt. Aktivierung auf ACTIVE erfolgt bei erstem Login. Trial-Periode beginnt erst ab Aktivierung.

Dateien:

  • gateway/modules/datamodels/datamodelSubscription.py — Status PENDING in die State Machine aufnehmen
  • gateway/modules/routes/routeSecurityLocal.py — Subscription mit PENDING erstellen
  • gateway/modules/routes/routeSecurityGoogle.py — Subscription mit PENDING erstellen
  • Login-Logik (Local + OAuth) — bei erstem Login PENDINGACTIVE Transition auslösen

Schritte:

  1. PENDING als neuen Status in SubscriptionStatus Enum hinzufügen
  2. State-Machine-Transition PENDING → ACTIVE definieren
  3. Bei Registrierung: MandateSubscription mit status=PENDING, trialStartDate=null
  4. Bei erstem Login: Status auf ACTIVE setzen, trialStartDate=now()
  5. Bestehende Subscriptions bleiben unverändert (ACTIVE)

Akzeptanz:

  • Neue Registrierungen erhalten PENDING-Subscription
  • Erster Login setzt auf ACTIVE und startet Trial
  • Kein User verliert Trial-Tage durch Magic-Link-Delay

Abhängigkeiten: AP 1.1


AP 1.3 — [BE] Interne Provisionierungsroutine _provisionMandateForUser

Beschreibung: Zentrale atomare Funktion, die nach createUser ein komplettes Mandate mit Subscription und Feature-Instanzen erstellt. Umgeht RBAC (Root-privilegiert), da der User noch keine Rechte hat.

Dateien:

  • gateway/modules/interfaces/interfaceDbApp.py — neue Funktion _provisionMandateForUser()

Schritte:

  1. Funktion _provisionMandateForUser(userId, mandateType, mandateName, planKey) erstellen
  2. Atomare Transaktion: a. createMandate (mit mandateType, ohne RBAC-Check) b. System-Rollen kopieren (_copySystemRolesToMandate) c. createUserMandate mit Admin-Rolle d. MandateSubscription erstellen (mit PENDING) e. Für Features mit autoCreateInstance: createFeatureInstance + FeatureAccess mit Admin-Instanzrolle
  3. Rollback bei Fehler in einem Schritt
  4. Logging aller Aktionen

Akzeptanz:

  • Ein Aufruf erstellt alles atomar (Mandate + UserMandate + Subscription + Instanzen)
  • Bei Fehler: kein Halbzustand (keine verwaisten Mandate)
  • RBAC wird nicht geprüft (interne Routine)

Abhängigkeiten: AP 1.1, AP 1.2


AP 1.4 — [BE] Registrierung Local: Mandate-Provisionierung

Beschreibung: POST /api/local/register erweitern um registrationType und companyName. Nach createUser wird _provisionMandateForUser aufgerufen.

Dateien:

  • gateway/modules/routes/routeSecurityLocal.py — Register-Endpoint erweitern

Schritte:

  1. Request-Body erweitern: registrationType (personal/company), companyName (optional)
  2. Validierung: company erfordert companyName
  3. Nach createUser: _provisionMandateForUser aufrufen mit:
    • personalmandateType=personal, planKey=TRIAL_7D, mandateName=username
    • companymandateType=company, planKey=STANDARD_MONTHLY, mandateName=companyName
  4. Response erweitern um mandateId

Akzeptanz:

  • Registrierung erstellt User + Mandate + Subscription + Instanzen in einem Flow
  • Personal → Trial, Company → Standard
  • Fehler bei Provisionierung → User wird nicht erstellt (oder cleanup)

Abhängigkeiten: AP 1.3


AP 1.5 — [BE] Registrierung OAuth: Onboarding-Wizard

Beschreibung: Bei OAuth-Registrierung (Google, MSAL) gibt es kein Formular. Stattdessen wird beim allerersten Login erkannt, dass kein Mandate existiert, und ein Onboarding-Wizard-Flag gesetzt.

Dateien:

  • gateway/modules/routes/routeSecurityGoogle.py — Erkennung „erster Login ohne Mandate"
  • Analoge Logik für MSAL-Route

Schritte:

  1. Nach OAuth-Login prüfen: Hat der User mindestens ein Mandate?
  2. Falls nein: Response-Flag requiresOnboarding=true setzen
  3. Frontend zeigt Onboarding-Wizard (siehe AP 1.12)
  4. Wizard-Submit ruft neuen Endpoint auf: POST /api/onboarding/provision mit mandateType + companyName
  5. Endpoint nutzt _provisionMandateForUser

Akzeptanz:

  • OAuth-User ohne Mandate wird erkannt
  • Wizard erscheint nur beim allerersten Login
  • Nach Wizard-Abschluss hat der User ein vollständiges Mandate

Abhängigkeiten: AP 1.3


AP 1.6 — [BE] Feature Store: Refactoring auf Own Instance Pattern

Beschreibung: Store erstellt eigene FeatureInstance im Ziel-Mandanten statt Shared Instance im Root. Explizites mandateId in allen Store-APIs. Mehrere Instanzen desselben Features sind erlaubt.

Dateien:

  • gateway/modules/routes/routeStore.py — komplettes Refactoring

Schritte:

  1. POST /api/store/activate:
    • Body: featureCode + mandateId (explizit, nie implizit)
    • Prüfungen: User ist Admin im Ziel-Mandat, Subscription-Kapazität (maxFeatureInstances)
    • Neue FeatureInstance im Ziel-Mandat erstellen (auch wenn bereits eine gleiche existiert)
    • FeatureAccess + Admin-Instanzrolle für den User
    • Stripe-Quantity sync
  2. POST /api/store/deactivate:
    • Body: featureCode + mandateId + instanceId
    • Eigenen FeatureAccess entfernen
    • Orphan-Check: Keine FeatureAccess-Records mehr → Instanz löschen + Stripe-Quantity sync
  3. GET /api/store/features:
    • Zeigt verfügbare Features mit Status pro Mandat des Users
    • Für jeden Mandanten des Users: Anzahl aktiver Instanzen
  4. Alte Shared-Instance-Logik entfernen

Akzeptanz:

  • Aktivierung erstellt immer eine neue Instanz im expliziten Mandat
  • Mehrere Instanzen desselben Features pro Mandat möglich
  • Orphan Control: letzte Deaktivierung löscht Instanz
  • Kein mandateId-Guessing, kein implizites Primary-Mandate

Abhängigkeiten: AP 1.1, AP 1.3


AP 1.7 — [BE] Store: Auto-Mandate für User ohne Admin-Mandate

Beschreibung: User, die nur als Mitglieder (nicht Admin) in fremden Mandanten sind, können über den Store ein eigenes Mandate erstellen lassen.

Dateien:

  • gateway/modules/routes/routeStore.py — Activate-Endpoint erweitern

Schritte:

  1. Bei activate: Prüfen ob User mindestens ein Mandate hat, in dem er Admin ist
  2. Falls kein Admin-Mandate vorhanden und mandateId nicht angegeben:
    • _provisionMandateForUser aufrufen (personal, TRIAL_7D)
    • Feature-Instanz im neuen Mandate erstellen
    • Response enthält neues mandateId
  3. Falls mandateId angegeben aber User kein Admin dort: Fehler (403)

Akzeptanz:

  • User ohne Admin-Mandate kann Feature im Store aktivieren → Auto-Mandate
  • User wird automatisch Admin des neuen Mandanten
  • Bestehende Admins nutzen weiterhin den normalen Flow

Abhängigkeiten: AP 1.6, AP 1.3


AP 1.8 — [BE] Subscription: maxDataVolumeMB Parameter

Beschreibung: Neuer Parameter maxDataVolumeMB in der Subscription für Kapazitätsplanung (Soft-Limit).

Dateien:

  • gateway/modules/datamodels/datamodelSubscription.pyBUILTIN_PLANS erweitern
  • gateway/modules/interfaces/interfaceDbApp.py — Volumen-Berechnung

Schritte:

  1. maxDataVolumeMB als Parameter in SubscriptionPlan hinzufügen
  2. Default-Werte pro Plan definieren (z. B. TRIAL_7D: 500 MB, STANDARD: 10 GB)
  3. API-Endpoint für aktuelle Nutzung: GET /api/mandate/{id}/data-usage
  4. Berechnung: Summe aller Dateigrössen im Mandate

Akzeptanz:

  • Subscription-Pläne enthalten maxDataVolumeMB
  • Aktuelle Nutzung ist abrufbar
  • Kein Schreib-Block bei Überschreitung (Soft-Limit)

Abhängigkeiten: AP 1.2


AP 1.9 — [DB] Migrations-Script: Root-Mandant bereinigen

Beschreibung: Separates Script, das alle Endkunden-Daten aus dem Root-Mandate in eigene Mandate migriert. Einmalig im Bootstrap aufgerufen.

Dateien:

  • gateway/scripts/script_migrate_root_users.py (oder gateway/modules/migration/migrateRootUsers.py) — NEU
  • gateway/modules/interfaces/interfaceBootstrap.py — Aufruf einhängen

Schritte:

  1. Script erstellen mit Dry-Run-Modus
  2. Schritt 1 — Feature-Daten migrieren:
    • Für jeden User mit FeatureAccess auf Root-Instanzen:
      • Hat User eigenes Mandate? → Ziel-Mandate setzen
      • Kein Mandate? → _provisionMandateForUser (personal)
      • Pro FeatureAccess: Neue Instanz im Ziel-Mandat erstellen, Daten umschreiben (featureInstanceId), FeatureAccess transferieren
  3. Schritt 2 — Root bereinigen:
    • Alle Feature-Instanzen im Root entfernen
    • UserMandate zum Root entfernen (ausser isSysAdmin=true)
  4. Root-Mandate: mandateType=system setzen
  5. Flag in DB setzen: Migration abgeschlossen (verhindert Doppelausführung)
  6. Im Bootstrap einhängen nach initRootMandateFeatures

Akzeptanz:

  • Dry-Run zeigt alle Aktionen ohne Änderungen
  • Alle User haben eigene Mandate mit migrierten Daten
  • Root enthält nur sysadmin-User, keine Feature-Instanzen
  • Script läuft nur einmal (Flag-Check)

Abhängigkeiten: AP 1.1, AP 1.3


AP 1.10 — [BE] Mandanten-Löschung: Kaskade

Beschreibung: Vollständige Lösch-Kaskade für Mandanten mit Soft-Delete und Schutzmechanismen.

Dateien:

  • gateway/modules/interfaces/interfaceDbApp.py — neue Funktion _deleteMandate()
  • gateway/modules/shared/gdprDeletion.py — erweitern
  • API-Endpoint: DELETE /api/mandates/{mandateId}

Schritte:

  1. Schutzmechanismen:
    • isSystem=true → Löschung verweigern
    • Nur Mandanten-Admin oder sysadmin darf löschen
    • Bestätigung via confirmMandateName im Request-Body
  2. Soft-Delete:
    • deletedAt Timestamp auf Mandate setzen
    • Alle Zugriffe sofort sperren (RBAC-Check auf deletedAt)
    • 30-Tage Retention
  3. Kaskade (bei endgültiger Löschung):
    • FeatureInstances → FeatureAccess → Instanz-Daten (Chats, Dokumente, Extraktionen)
    • DataNeutralizerAttributes (Mapping-Tabelle)
    • RAG-Index-Einträge mit mandateId
    • UserMandate-Zuordnungen (User bleiben bestehen)
    • MandateSubscription → Stripe-Subscription kündigen
    • Mandate-Konfigurationen (Rollen, Settings)
    • Mandate-Record
  4. Batch-Job für endgültige Löschung nach Retention

Akzeptanz:

  • Root-Mandate nicht löschbar
  • Soft-Delete mit sofortiger Zugriffssperre
  • Vollständige Kaskade ohne verwaiste Daten
  • Stripe-Subscription wird gekündigt

Abhängigkeiten: AP 1.1


AP 1.11 — [FE] Register-Seite: Zwei Flows

Beschreibung: Register-Formular unterstützt type=personal und type=company via Query-Parameter.

Dateien:

  • frontend_nyla/src/pages/Register.tsxtype Query-Parameter
  • frontend_nyla/src/api/authApi.tsregisterApi erweitern

Schritte:

  1. Query-Parameter type auslesen (personal / company)
  2. Bei company: Zusatzfeld „Firmenname" anzeigen
  3. API-Call erweitern: registrationType + companyName im Body
  4. Erfolgsseite anpassen: „Dein Mandant wurde erstellt"
  5. Redirect nach Login auf Dashboard (nicht Store, da Instanzen via autoCreate existieren)

Akzeptanz:

  • /register?type=personal zeigt Personal-Flow
  • /register?type=company zeigt Company-Flow mit Firmenname
  • API-Body enthält neue Felder

Abhängigkeiten: AP 1.4


AP 1.12 — [FE] Login-Seite: Zwei CTAs + OAuth Onboarding-Wizard

Beschreibung: Login/Landing-Seite mit zwei prominenten Call-to-Actions und Onboarding-Wizard für OAuth-Erstregistrierungen.

Dateien:

  • frontend_nyla/src/pages/Login.tsx — CTAs hinzufügen
  • frontend_nyla/src/components/OnboardingWizard.tsx — NEU

Schritte:

  1. Login-Seite: Zwei CTAs
    • „Kostenlos testen" → /register?type=personal
    • „Für Unternehmen" → /register?type=company
  2. Onboarding-Wizard Komponente:
    • Schritt 1: „Wie möchtest du PowerON nutzen?" (Personal / Unternehmen)
    • Schritt 2: Bei Company → Firmenname eingeben
    • Submit → POST /api/onboarding/provision
  3. Nach OAuth-Login: Prüfen ob requiresOnboarding=true in Response → Wizard anzeigen

Akzeptanz:

  • Zwei CTAs sichtbar auf Login-Seite
  • OAuth-User ohne Mandate sieht Wizard
  • Wizard erstellt Mandate und leitet zum Dashboard

Abhängigkeiten: AP 1.5


AP 1.13 — [FE] Store-Seite: Mandanten-Auswahl

Beschreibung: Store zeigt explizite Mandanten-Auswahl bei Aktivierung. Alle User sehen den Store.

Dateien:

  • frontend_nyla/src/pages/Store.tsx — Refactoring

Schritte:

  1. Store für alle User zugänglich machen (kein Admin-Gate)
  2. Pro Feature: Mandanten-Auswahl anzeigen (Dropdown bei Multi-Mandate, auto-select bei Solo)
  3. „Aktivieren für [Mandantenname]" statt nur „Aktivieren"
  4. Bei User ohne Admin-Mandate: „Eigenen Mandanten erstellen und Feature aktivieren" als Option
  5. Deaktivierung: Pro Instanz mit Orphan-Warnung („Du bist der letzte User — Instanz wird gelöscht")
  6. Anzeige aktiver Instanzen pro Mandate mit Instanz-Anzahl

Akzeptanz:

  • Mandanten-Auswahl bei jeder Aktivierung
  • Auto-Mandate-Option für User ohne eigenes Mandate
  • Orphan-Warnung bei letzter Deaktivierung

Abhängigkeiten: AP 1.6, AP 1.7


AP 1.14 — [FE] Subscription-Datenvolumen: UI-Hinweis

Beschreibung: Anzeige der Datenvolumen-Nutzung im Billing-Bereich.

Dateien:

  • frontend_nyla/src/pages/billing/BillingDataView.tsx — Datenvolumen-Anzeige

Schritte:

  1. API-Aufruf: GET /api/mandate/{id}/data-usage
  2. Fortschrittsbalken: genutzt / maximal (z. B. „3.2 GB / 10 GB")
  3. Warnung bei > 80%: „Du näherst dich dem Datenvolumen-Limit"
  4. Upgrade-Link bei hoher Nutzung

Akzeptanz:

  • Datenvolumen sichtbar im Billing-Bereich
  • Warnung bei > 80%
  • Kein Block, nur Hinweis

Abhängigkeiten: AP 1.8


AP 1.15 — [BE] Bootstrap: Root-Mandant mandateType=system setzen

Beschreibung: Im Bootstrap den Root-Mandanten explizit auf mandateType=system setzen.

Dateien:

  • gateway/modules/interfaces/interfaceBootstrap.pyinitRootMandate() erweitern

Schritte:

  1. In initRootMandate(): mandateType=system setzen
  2. initRootMandateFeatures() bleibt für System-Instanzen (aber keine Endkunden-Instanzen mehr nach Migration)

Akzeptanz:

  • Root-Mandant hat mandateType=system nach Bootstrap
  • Keine Endkunden-Feature-Instanzen im Root (nach Migration)

Abhängigkeiten: AP 1.1, AP 1.9


Phase 2 — UDB + Shared Data Scope

Ziel: UDB als plattformweite Komponente, mandantenweiter Datenzugriff via Scopes. FeatureInstance = Datengrenze + mandantenweiter Zugriff.

Voraussetzung: Phase 1 vollständig abgeschlossen.


AP 2.1 — [BE] Datenmodell: Scope- und Neutralisierungs-Felder auf DataSources

Beschreibung: Bestehende Datenquellen-Modelle um scope und neutralize Felder erweitern. RAG-Index um Scope-Metadaten erweitern.

Dateien:

  • Bestehende Datenmodelle (Dokumente, Extraktionen, Konnektoren) — scope + neutralize Felder
  • RAG-Index-Konfiguration — Filterbare Metadaten

Schritte:

  1. Enum DataScope definieren: personal, featureInstance, mandate, global
  2. Felder hinzufügen: scope: DataScope (default personal), neutralize: bool (default false), neutralizationStatus: str
  3. Bestehende Daten: Default scope=featureInstance (bestehendes Verhalten)
  4. RAG-Index-Metadaten erweitern: mandateId, scope, featureInstanceId, userId, isNeutralized
  5. Bestehende RAG-Einträge: Backfill mit Scope-Metadaten

Akzeptanz:

  • Alle DataSources haben scope und neutralize
  • RAG-Index filtert korrekt nach Scope
  • Bestehende Daten haben konsistente Defaults

Abhängigkeiten: Phase 1 abgeschlossen


AP 2.2 — [BE] RAG-Query: Scope-basierte Filterung

Beschreibung: RAG-Queries filtern Ergebnisse basierend auf dem effektiven Scope des anfragenden Users.

Dateien:

  • RAG-Query-Logik — Scope-Filter aufbauen

Schritte:

  1. Scope-Kontext aufbauen pro Query:
    personal(userId)  featureInstance(instanceId)  mandate(mandateId)  global()
    
  2. Union-Query über vier Scopes implementieren
  3. scope=global nur sysadmin-setzbar (RBAC-Check beim Tagging)
  4. Performance-Tests mit grossen Datenmengen

Akzeptanz:

  • User sieht nur Daten seiner Scopes
  • Global-Scope RBAC-geschützt
  • Query-Performance akzeptabel (< 500ms)

Abhängigkeiten: AP 2.1


AP 2.3 — [BE] Datenquellen-Tagging API

Beschreibung: API-Endpoints für Scope- und Neutralisierungs-Tagging auf Datenquellen.

Dateien:

  • Neue oder erweiterte Routes — Tagging-Endpoints

Schritte:

  1. PATCH /api/datasources/{id}/scope — Scope ändern (personal → featureInstance → mandate; global nur sysadmin)
  2. PATCH /api/datasources/{id}/neutralize — Neutralisierungs-Flag togglen
  3. Bei Scope-Änderung: RAG-Index re-indizieren (async)
  4. Bei Neutralisierungs-Änderung: Re-Neutralisierung oder De-Neutralisierung triggern (async)
  5. Defaults bei Upload: scope=personal, neutralize=false

Akzeptanz:

  • Scope-Änderung löst Re-Indizierung aus
  • Neutralisierungs-Änderung löst Re-Verarbeitung aus
  • RBAC: global nur für sysadmin

Abhängigkeiten: AP 2.1, AP 2.2


AP 2.4 — [FE] UDB: Extraktion aus Workspace

Beschreibung: Die bestehende Sidebar im AI Workspace (Chats, Files, Sources) wird als wiederverwendbare Plattformkomponente extrahiert.

Dateien:

  • frontend_nyla/src/pages/workspace/ — Sidebar-Logik identifizieren und extrahieren
  • frontend_nyla/src/components/UnifiedDataBar/ — NEU: UDB-Komponente

Schritte:

  1. Bestehende Sidebar-Komponenten im Workspace identifizieren (Chats-Liste, Files-Liste, Sources-Liste)
  2. Gemeinsame UDB-Komponente erstellen mit drei Tabs: Chats, Files, Sources
  3. Props: mandateId, featureInstanceId, userId für Kontext
  4. Workspace refactoren: UDB einbinden statt eigener Sidebar
  5. Verifizieren: Workspace funktioniert identisch mit UDB-Komponente

Akzeptanz:

  • UDB ist eine eigenständige Komponente in src/components/
  • Workspace nutzt UDB und funktioniert wie zuvor
  • Keine Duplizierung von Sidebar-Logik

Abhängigkeiten: Phase 1 abgeschlossen


AP 2.5 — [FE] UDB: Chats-Tab mit Baumstruktur

Beschreibung: Chat-Verläufe als hierarchischer Baum, gruppiert nach Feature-Instanzen mit Suchfunktion und Flat Mode.

Dateien:

  • frontend_nyla/src/components/UnifiedDataBar/ChatsTab.tsx — NEU

Schritte:

  1. API: Chats über alle Feature-Instanzen des Users laden (gruppiert)
  2. Baumstruktur: Feature-Instanzen als Top-Level-Knoten, Chats darunter
  3. Feature-spezifische Substrukturen (z. B. CommCoach → Coaching-Modul → Sessions)
  4. Aktuelle Feature-Instanz: hervorgehoben und expandiert
  5. Klick auf Chat: Navigation in den Chat (ggf. Feature-Kontext wechseln)
  6. Suchfunktion: Volltextsuche über Chat-Titel, filtert Baum auf Treffer
  7. Flat Mode: Toggle im Tab-Header, chronologische Liste sortiert nach letzter Aktivität

Akzeptanz:

  • Alle Chats über alle Feature-Instanzen sichtbar in einem Baum
  • Suche filtert korrekt
  • Flat Mode zeigt chronologische Liste
  • Klick navigiert zum Chat

Abhängigkeiten: AP 2.4


AP 2.6 — [FE] UDB: Files-Tab mit Scope- und Neutralisierungs-Symbolen

Beschreibung: Dateien mit Inline-Scope-Symbolen und Neutralisierungs-Icons.

Dateien:

  • frontend_nyla/src/components/UnifiedDataBar/FilesTab.tsx — NEU

Schritte:

  1. Dateien pro Mandat laden (alle Scopes, die der User sehen darf)
  2. Pro Datei: Scope-Symbol (👤 personal, 👥 instanz, 🏢 mandant) + Neutralisierungs-Symbol (🔒)
  3. Klick auf Scope-Symbol: Zyklisch wechseln oder Popover
  4. Klick auf Neutralisierungs-Symbol: Toggle on/off
  5. Default bei Upload: personal + kein 🔒
  6. Legende am Tab-Footer

Akzeptanz:

  • Alle Dateien mit korrekten Scope-Symbolen
  • Scope- und Neutralisierungs-Toggle funktionieren mit API-Calls
  • Visuell klar und unkompliziert

Abhängigkeiten: AP 2.3, AP 2.4


AP 2.7 — [FE] UDB: Sources-Tab mit Active/Browse

Beschreibung: Datenquellen-Tab mit Trennung zwischen Active Sources (mit Icons) und Browse Sources (Katalog ohne Icons).

Dateien:

  • frontend_nyla/src/components/UnifiedDataBar/SourcesTab.tsx — NEU

Schritte:

  1. Active Sources: Eingebundene Quellen mit Scope- und Neutralisierungs-Symbolen
  2. Browse Sources: Verfügbare Quellen als Katalog (keine Symbole)
  3. Feature Data: Daten pro Feature-Instanz (Tabellen-Übersicht)
  4. Aktivierung: Drag aus Browse in Active oder Klick → Default-Scope setzen
  5. Deaktivierung: x-Button bei Active Sources

Akzeptanz:

  • Klare Trennung Active vs. Browse
  • Symbole nur bei Active Sources
  • Aktivierung setzt Defaults korrekt

Abhängigkeiten: AP 2.3, AP 2.4


AP 2.8 — [FE] UDB: Drag-and-Drop in Prompt

Beschreibung: Alle UDB-Elemente (Chats, Files, Sources) können per Drag-and-Drop in den Prompt gezogen werden. Bei Chats werden die RAG-Daten des Chats abgefragt, nicht der Chat-Inhalt.

Dateien:

  • frontend_nyla/src/components/UnifiedDataBar/ — DnD-Logik
  • Prompt-Eingabe-Komponente — Drop-Zone

Schritte:

  1. Drag-Source auf allen UDB-Elementen (Chats, Files, Sources)
  2. Drop-Zone im Prompt-Bereich
  3. Chats: Bei Drop → RAG-Query nach Daten, die dem Chat zugeordnet sind (nicht Chat-Inhalt selbst)
  4. Files: Bei Drop → Datei als Kontext-Dokument anhängen
  5. Sources: Bei Drop → Datenquelle als aktiven Kontext setzen
  6. Visuelles Feedback: Drag-Preview, Drop-Highlight, Kontext-Badge im Prompt

Akzeptanz:

  • Drag-and-Drop funktioniert für alle drei Tabs
  • Chats liefern RAG-Daten, nicht Chat-Inhalt
  • Visuelles Feedback bei Drag und Drop

Abhängigkeiten: AP 2.5, AP 2.6, AP 2.7


AP 2.9 — [FE] UDB: Integration in alle Feature-Instanzen

Beschreibung: UDB in alle bestehenden Features einbinden (Workspace, CommCoach, Trustee, Automation).

Dateien:

  • Feature-Seiten: Workspace, CommCoach, Trustee, Automation — UDB einbinden

Schritte:

  1. Workspace: UDB ersetzt bestehende Sidebar (bereits in AP 2.4)
  2. CommCoach: UDB als Sidebar einbinden
  3. Trustee: UDB als Sidebar einbinden
  4. Automation: UDB als Sidebar einbinden
  5. Pro Feature: Korrekter Kontext (featureInstanceId) an UDB übergeben
  6. Layout-Anpassungen pro Feature

Akzeptanz:

  • Alle Features haben die UDB
  • Kontext stimmt pro Feature-Instanz
  • Keine Feature-eigenen Sidebar-Duplikate mehr

Abhängigkeiten: AP 2.4 — AP 2.8


AP 2.10 — [BE] Doppelte Strukturen konsolidieren

Beschreibung: Datensilos auflösen: Voice-Definitionen, Dokumentenkontext und Wissensbasis mandantenweit verfügbar machen.

Dateien:

  • CommCoach Voice-Datenmodell — Scope-Feld hinzufügen
  • Workspace Dokument-Logik — Scope-basierte Queries

Schritte:

  1. Voice-Definitionen: Von instanz-zentriert auf mandantenweit umstellen (scope=mandate)
  2. Wissensbasis: Von instanz-zentriert auf scope-basiert (User wählt Scope)
  3. Dokumenten-Kontext: Mandantenweite Suche mit Scope-Filter
  4. Feature-spezifische Daten-Tabellen: scope-Feld wo nötig
  5. Migration bestehender Daten: Default-Scope setzen

Akzeptanz:

  • Voice-Definitionen mandantenweit nutzbar
  • Keine doppelten Definitionen mehr nötig
  • Cross-Feature-Zugriff auf Wissensbasis funktioniert

Abhängigkeiten: AP 2.1, AP 2.2


Phase 3 — Unified Data Layer + Neutralisierung als Kerndisziplin

Ziel: Features sind reine Workflow-Oberflächen. UDL mit Neutralisierung ist der Plattformkern. FeatureInstance = UI-Scope.

Voraussetzung: Phase 2 vollständig abgeschlossen.


AP 3.1 — [BE] Neutralisierung: Fail-Safe-Logik

Beschreibung: Wenn Neutralisierung fehlschlägt, wird das Dokument nicht weitergegeben. Kein Fallback auf Originaldaten.

Dateien:

  • gateway/modules/workflows/methods/methodContext/actions/neutralizeData.py — Fail-Safe einbauen
  • gateway/modules/features/neutralization/serviceNeutralization/ — Error Handling

Schritte:

  1. Bestehende Error-Handling-Logik ändern: Bei Fehler nicht das Original-Part verwenden
  2. Stattdessen: Part überspringen + Warning-Flag setzen
  3. ChatWorkflow: Hinweis „Dokument X konnte aus Datenschutzgründen nicht einbezogen werden"
  4. AI-Call läuft ohne das fehlgeschlagene Dokument weiter
  5. Logging: Fehlergrund (Timeout, Modell nicht erreichbar, etc.)
  6. Beim RAG-Indexing: Neutralisierung fehlgeschlagen → Dokument nicht indizieren, neutralizationStatus=failed

Akzeptanz:

  • Kein Originaldokument geht an externe AI wenn Neutralisierung fehlschlägt
  • User sieht Hinweis, welches Dokument fehlt und warum
  • AI-Call funktioniert ohne das fehlende Dokument

Abhängigkeiten: Phase 2 abgeschlossen


AP 3.2 — [BE] Neutralisierung: RAG-Integration

Beschreibung: Datenquellen mit neutralize=true werden nur in neutralisierter Form im RAG indiziert.

Dateien:

  • RAG-Indexing-Pipeline — Neutralisierungs-Gate
  • gateway/modules/features/neutralization/ — Pipeline-Integration

Schritte:

  1. Beim Einbinden einer Datenquelle mit neutralize=true:
    • Container auflösen (bestehende Extraction-Pipeline)
    • Media droppen
    • Bilder → neutraler Text via Modell mit opType=neutralization
    • Text → neutralisieren via StringParser + Modell mit opType=neutralization
    • Platzhalter-Mapping in DataNeutralizerAttributes persistieren
    • Nur neutralisierte Version im RAG indizieren
  2. Bei neutralize=false: Direkt indizieren (wie bisher)
  3. Re-Neutralisierung bei Flag-Änderung (async Batch-Job)

Akzeptanz:

  • Neutralisierte Datenquellen: nur neutralisierte Version im RAG
  • Mapping-Tabelle wird korrekt befüllt
  • Re-Neutralisierung bei Flag-Änderung funktioniert

Abhängigkeiten: AP 3.1, AP 2.1


AP 3.3 — [BE] Neutralisierung: AI-Call-Integration + Re-Hydrierung

Beschreibung: Bei AI-Calls mit requireNeutralization=true: Prompt live neutralisieren und Response re-hydrieren.

Dateien:

  • Workflow-Manager / Chat-Pipeline — Pre-/Post-Processing
  • gateway/modules/workflows/workflowManager.py

Schritte:

  1. Pre-Processing: Wenn requireNeutralization=true:
    • User-Prompt durch Neutralisierungs-Pipeline
    • RAG-Kontext-Dokumente: bereits neutralisiert (aus RAG-Index)
    • Prompt-Mapping in temporärer Tabelle
  2. AI-Call mit neutralisiertem Prompt + neutralisierten Dokumenten
  3. Post-Processing: AI-Response re-hydrieren
    • Platzhalter via Mapping-Tabelle durch Originale ersetzen
    • Konsistenz: [PERSON_1] = immer derselbe Originalwert (persistent pro Datenquelle)
  4. Re-hydrierte Response an User ausliefern

Akzeptanz:

  • Live-Neutralisierung von User-Prompts funktioniert
  • Re-Hydrierung ersetzt Platzhalter korrekt
  • Platzhalter-Konsistenz über Calls hinweg

Abhängigkeiten: AP 3.1, AP 3.2


AP 3.4 — [FE] ChatWorkflow-Transparenz: „Gesendete Daten"

Beschreibung: Im Chat-UI: aufklappbarer Bereich, der die neutralisierten Dokumente zeigt, die an das AI-Modell gesendet werden.

Dateien:

  • Chat-UI-Komponente — Neue Sektion „Gesendete Daten (neutralisiert)"

Schritte:

  1. API liefert ActionDocument-Liste mit neutralized=true Metadaten im ChatWorkflow
  2. UI: Aufklappbarer Bereich unter jedem AI-Call
  3. Anzeige: Dokumentname, Neutralisierungs-Status, Vorschau des neutralisierten Texts
  4. Hinweis wenn Dokument übersprungen wurde (Fail-Safe)
  5. Link zur Neutralisierungs-Konfiguration der Datenquelle

Akzeptanz:

  • User sieht bei jedem AI-Call, was rausgegangen ist
  • Übersprungene Dokumente sind sichtbar mit Grund
  • Aufklappbar (nicht standardmässig offen)

Abhängigkeiten: AP 3.3


AP 3.5 — [FE] Neutralisierung: User-Kontrolle

Beschreibung: UI für Einsicht und Verwaltung der neutralisierten Daten und Platzhalter-Mappings.

Dateien:

  • Neue Seite oder Sektion im Settings-Bereich

Schritte:

  1. Übersicht: Alle Datenquellen mit Neutralisierungs-Status
  2. Pro Datenquelle: Detailansicht der Platzhalter-Mappings (Original ↔ Platzhalter)
  3. Löschen: Einzelne Mappings oder alle Mappings einer Datenquelle
  4. Status: pending, completed, failed, not_required
  5. Re-Trigger: Neutralisierung manuell neu anstossen

Akzeptanz:

  • User kann alle Mappings einsehen
  • Löschen funktioniert
  • Status ist korrekt und aktuell

Abhängigkeiten: AP 3.2


AP 3.6 — [BE] RAG-Scopes: Vollständige Implementierung

Beschreibung: Alle vier Scopes (personal, featureInstance, mandate, global) vollständig implementiert mit korrekter Union-Query und RBAC.

Dateien:

  • RAG-Query-Engine — vollständige Scope-Logik
  • RBAC-Layer — Scope-Berechtigungen

Schritte:

  1. personal: Nur Daten des anfragenden Users
  2. featureInstance: Alle Daten der aktuellen Instanz (alle User mit FeatureAccess)
  3. mandate: Alle Daten aller Instanzen im Mandat
  4. global: Alle plattformweiten Daten (read-only, nur sysadmin setzbar)
  5. Union-Query: Effiziente Kombination aller anwendbaren Scopes
  6. Caching: Scope-Metadaten cachen für Performance

Akzeptanz:

  • Alle Scope-Kombinationen funktionieren korrekt
  • User sieht nie Daten ausserhalb seiner Berechtigung
  • Performance: Union-Query < 500ms

Abhängigkeiten: AP 2.2, AP 3.2


AP 3.7 — [FE] Onboarding-Assistant

Beschreibung: Kontextsensitiver Onboarding-Begleiter für neue User und leere Zustände.

Dateien:

  • frontend_nyla/src/components/OnboardingAssistant.tsx — NEU

Schritte:

  1. Trigger-Bedingungen: Kein Mandate, keine Instanzen, keine Chats, nach Pause
  2. Schritt 1: Mandant-Typ bestätigen (bei OAuth)
  3. Schritt 2: Erste Feature-Instanz aktivieren (Empfehlung: Workspace)
  4. Schritt 3: Erste Datenquelle einbinden (Upload oder Konnektor)
  5. Schritt 4: Erster AI-Call (geführter Prompt)
  6. Kontextsensitiv: Erscheint bei neuen Features, nach Pausen, bei leeren Zuständen
  7. Dismissable: User kann jederzeit überspringen, aber Assistant kommt bei relevantem Trigger zurück

Akzeptanz:

  • Neue User durchlaufen den 4-Schritt-Flow
  • Assistant erscheint kontextsensitiv
  • Kein Nerv-Faktor (smart triggers, nicht bei jedem Login)

Abhängigkeiten: AP 2.9


AP 3.8 — [BE/FE] FeatureInstance als UI-Scope (Semantische Verschiebung)

Beschreibung: Features werden zu reinen Workflow-Oberflächen. Die FeatureInstance definiert den UI-Kontext, nicht mehr die Datengrenze. Der Unified Data Layer ist die Datengrenze.

Dateien:

  • Feature-Logik in allen Features — Daten-Queries auf UDL umstellen
  • Instanz-Referenzen — von Daten-Ownership auf UI-Scope

Schritte:

  1. Daten-Queries: Von WHERE featureInstanceId = X auf Scope-basierte RAG-Queries umstellen
  2. featureInstanceId bleibt als Herkunftsreferenz (Quellenschutz), steuert aber nicht mehr den Zugriff
  3. Zugriff wird über Scope + RBAC gesteuert
  4. Feature-Instanz liefert: Workflow-Oberfläche, Feature-spezifische Substrukturen, Default-Scope-Kontext
  5. Alle Features verifizieren: Datenfluss via UDL statt Instanz-Silo

Akzeptanz:

  • Features zeigen Daten aus dem UDL (nicht nur eigene Instanz)
  • Cross-Feature-Datennutzung funktioniert
  • featureInstanceId dient nur noch als Herkunftsinfo

Abhängigkeiten: AP 3.6, AP 2.9, AP 2.10


Zusammenfassung

Phase Arbeitspakete Schwerpunkt
Phase 1 AP 1.1 — 1.15 (15 APs) Mandanten-Grenze, Registrierung, Store, Migration, Löschung
Phase 2 AP 2.1 — 2.10 (10 APs) UDB, Scope-Tagging, RAG-Filter, Cross-Feature-Zugriff
Phase 3 AP 3.1 — 3.8 (8 APs) Neutralisierung, RAG-Scopes, Onboarding-Assistant, UI-Scope-Shift
Total 33 Arbeitspakete

Abhängigkeitsgraph (kritischer Pfad)

Phase 1:
  AP 1.1 (mandateType) ──┬── AP 1.2 (Subscription PENDING) ── AP 1.3 (_provision)
                          │                                          │
                          │   ┌──────────────────────────────────────┘
                          │   │
                          ├── AP 1.4 (Register Local) ── AP 1.11 (FE Register)
                          │   │
                          ├── AP 1.5 (Register OAuth) ── AP 1.12 (FE Login + Wizard)
                          │   │
                          ├── AP 1.6 (Store Refactoring) ── AP 1.7 (Auto-Mandate) ── AP 1.13 (FE Store)
                          │
                          ├── AP 1.8 (Subscription Volume) ── AP 1.14 (FE Volume)
                          │
                          ├── AP 1.9 (Migration Script) ── AP 1.15 (Bootstrap)
                          │
                          └── AP 1.10 (Mandanten-Löschung)

Phase 2: (nach Phase 1)
  AP 2.1 (Scope-Felder) ── AP 2.2 (RAG Scope-Filter) ── AP 2.3 (Tagging API)
                                                              │
  AP 2.4 (UDB Extraktion) ── AP 2.5 (Chats) ─┐              │
                              AP 2.6 (Files) ──┤── AP 2.8 (DnD) ── AP 2.9 (Integration)
                              AP 2.7 (Sources)─┘
                                                                     │
  AP 2.10 (Konsolidierung) ─────────────────────────────────────────┘

Phase 3: (nach Phase 2)
  AP 3.1 (Fail-Safe) ── AP 3.2 (RAG-Integration) ── AP 3.3 (AI-Call + Rehydrate) ── AP 3.4 (FE Transparenz)
                              │
                              └── AP 3.5 (FE User-Kontrolle)
                              
  AP 3.6 (RAG-Scopes komplett) ── AP 3.8 (UI-Scope-Shift)
  
  AP 3.7 (Onboarding-Assistant)

Umsetzungsplan-Version: 2026-03-23 v1 — Basierend auf Konzeptdokument v4. 33 Arbeitspakete in 3 Phasen.