From 996f4f055abd1786dc6c7776ee33eaa04cd9b70c Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Tue, 24 Mar 2026 14:16:36 +0100
Subject: [PATCH] unified data - step 1
---
...ate-Onboarding-und-Store-Konzept-REVIEW.md | 225 -----
...ti-Mandate-Onboarding-und-Store-Konzept.md | 70 +-
concepts/Multi-Mandate-Umsetzungsplan.md | 915 ++++++++++++++++++
3 files changed, 983 insertions(+), 227 deletions(-)
delete mode 100644 concepts/Multi-Mandate-Onboarding-und-Store-Konzept-REVIEW.md
create mode 100644 concepts/Multi-Mandate-Umsetzungsplan.md
diff --git a/concepts/Multi-Mandate-Onboarding-und-Store-Konzept-REVIEW.md b/concepts/Multi-Mandate-Onboarding-und-Store-Konzept-REVIEW.md
deleted file mode 100644
index d71bb69..0000000
--- a/concepts/Multi-Mandate-Onboarding-und-Store-Konzept-REVIEW.md
+++ /dev/null
@@ -1,225 +0,0 @@
-# Architektur-Review: Multi-Mandate Onboarding und Store-Konzept
-
-**Gegenstand:** [Multi-Mandate-Onboarding-und-Store-Konzept.md](./Multi-Mandate-Onboarding-und-Store-Konzept.md) v3, 2026-03-23
-
-**Zweck:** Kritischer Review der **Zielarchitektur** — Idee, Konzept, Modelle, Datenflüsse und Konsistenz. Keine Bewertung von Migrations- oder Implementierungsdetails.
-
----
-
-## 1. Gesamtbewertung
-
-Das Konzept definiert eine kohärente Zielarchitektur mit sechs Entscheidungen, die sich gegenseitig stützen: Mandate-per-Registration schafft die Tenant-Grenze, der Unified Data Layer eliminiert Datensilos, die UDB macht den Data Layer navigierbar, die Neutralisierung sichert den Datenfluss ab, und das RAG mit Scope-Tagging bildet den Plattformkern.
-
-**Stärken:**
-
-- Die Architektur löst ein reales, messbares Problem (Shared Root, Datensilos, fehlender Upgrade-Pfad).
-- Mandate-per-Registration mit explizitem Store-Kontext ist sauber durchdacht und vermeidet implizite Logik.
-- Unified Data Layer mit RAG-Scopes ist das richtige Abstraktionsniveau — weder zu granular noch zu grob.
-- Die UDB als featureübergreifende Komponente mit Chat-Baum, Drag-and-Drop-Kontext und Inline-Tagging ist ein klarer Differenzierungsfaktor, den kein Wettbewerber in dieser Form bietet.
-- Neutralisierung mit Fail-Safe-Regel ("kein Fallback auf Originaldaten") ist die einzig vertretbare Design-Entscheidung für regulierte Branchen.
-- Operation Type statt "spezielle LLMs" nutzt das bestehende Modellsystem sauber.
-
----
-
-## 2. Architektur: Mandate-per-Registration
-
-### 2.1 Stimmigkeit des Mandanten-Modells
-
-Die Dreiteilung `system` / `personal` / `company` ist klar und deckt die Kundenprofile ab. Der Upgrade-Pfad Personal → Company (Team einladen, Label ändern) ist elegant, weil er kein neues Benutzerkonto erfordert.
-
-**Offener Punkt:** Ist `mandateType` mutabel (Personal → Company bei Einladung) oder immutabel? Wenn mutabel: Es sollte keine Geschäftslogik hart an `personal` vs. `company` gebunden sein. Wenn immutabel: Der "Upgrade" ist fachlich unklar. Empfehlung: Mutabel, rein informativ — keine Feature-Gates auf Basis von `mandateType`.
-
-### 2.2 Redundanz `isSystem` vs. `mandateType=system`
-
-Beide drücken dasselbe aus. Empfehlung: Eines der beiden Felder eliminieren oder klar trennen — `isSystem` als operativer Delete-Schutz, `mandateType` als fachliche Semantik.
-
-### 2.3 Zwei Registrierungs-Flows: Vollständigkeit
-
-Die zwei Flows (Personal/Trial und Company/Standard) decken die Selbstregistrierung ab. Nicht behandelt:
-
-- **OAuth-Registrierung** (Google, MSAL): Kein Formular mit "Personal vs. Company". Lösung: Onboarding-Wizard nach erstem OAuth-Login.
-- **Invitation-Flow**: User registriert sich via Einladung. Bekommt er ein eigenes Mandate UND Zugang zum Einladungs-Mandate? Das Konzept sagt ja — sinnvoll, da der User auch ausserhalb des einladenden Mandanten arbeiten können soll.
-
-### 2.4 Subscription-Timing
-
-Trial-Start ab Registrierung oder ab erstem Login? Bei Magic-Link-Flow vergehen Stunden. Empfehlung: `PENDING`-Status bei Registrierung, Aktivierung bei erstem Login.
-
----
-
-## 3. Feature Store: Expliziter Kontext und Orphan Control
-
-### 3.1 Expliziter Mandanten-Kontext
-
-Die Entscheidung "nie implizit, immer explizites `mandateId`" ist architektonisch sauber und eliminiert eine ganze Klasse von Mehrdeutigkeits-Bugs. Für Solo-Mandant-User (ein Mandat) ist die UX trivial; für Multi-Mandat-User ist die explizite Auswahl notwendig und richtig.
-
-### 3.2 Orphan Control: Architektonische Bewertung
-
-Das Prinzip "letzter User deaktiviert → Instanz wird gelöscht" ist konsequent und verhindert Kapazitäts-Leaks. Technisch muss die Prüfung atomar sein (Race Condition bei gleichzeitiger Deaktivierung), aber das ist ein Implementierungsdetail, kein Architekturproblem.
-
-### 3.3 Store-Aktivierung bei existierender Instanz
-
-Wenn zwei Admins desselben Mandanten dasselbe Feature aktivieren — was passiert? Das Konzept muss klären: Maximal **eine Instanz pro Feature pro Mandat** via Store (dann: zweiter Admin bekommt nur FeatureAccess, keine neue Instanz) oder mehrere Instanzen erlaubt (dann: andere UX-Logik).
-
-### 3.4 Store-UX für Nicht-Admins
-
-Ein eingeladener User ist kein Admin und kann nichts aktivieren. Sieht er den Store? Empfehlung: Store als read-only Feature-Katalog zeigen oder via Navigation-RBAC ausblenden.
-
----
-
-## 4. Unified Data Layer und RAG
-
-### 4.1 Architektonische Schlüssigkeit
-
-Die Entscheidung, Datensilos aufzulösen (CommCoach-Voice parallel zu Workspace, doppelte Sprachdefinitionen), ist richtig und überfällig. Der Unified Data Layer als mandantenweite Datenschicht mit Features als "Workflow-Oberflächen" ist das korrekte Zielbild.
-
-Die Beibehaltung von `featureInstanceId` und `_createdBy` als Herkunftsreferenzen (Quellenschutz) bei gleichzeitiger mandantenweiter Sichtbarkeit ist eine elegante Lösung: kein Breaking Change auf Datenebene, aber neue Zugriffsmuster via Scope.
-
-### 4.2 RAG-Scopes: Konzeptionelle Bewertung
-
-Die vier Scopes (`personal` / `featureInstance` / `mandate` / `global`) bilden eine vollständige Hierarchie:
-
-```
-global ⊃ mandate ⊃ featureInstance ⊃ personal
-```
-
-Dies ist sauber und erlaubt feingranulare Steuerung. Jeder Scope ist klar abgegrenzt, es gibt keine Überlappung.
-
-**Kritischer Punkt:** Der Scope `global` ist mächtig — eine falsch getaggte Datenquelle wäre plattformweit sichtbar. Das Konzept adressiert dies nicht explizit. Empfehlung: `scope=global` nur durch sysadmin setzbar, RBAC-geschützt.
-
-### 4.3 Datenquellen-Tagging: UX-Bewertung
-
-Das Inline-Tagging in der UDB (Scope-Symbol + Neutralisierungs-Symbol neben jeder Datenquelle) ist elegant gelöst. Kein Dialog, kein Workflow-Bruch. Der Unterschied zwischen "Browse Sources" (Katalog, keine Icons) und "Active Sources" (eingebunden, mit Icons) ist logisch und intuitiv.
-
-**Default `personal` + `neutralize=false`** ist der richtige Default: konservativ für Sichtbarkeit (nur der User), offen für Neutralisierung (User entscheidet bewusst). Der User muss aktiv handeln, um Daten breiter zu teilen — Privacy-by-Default.
-
-### 4.4 Fehlendes konkretes Datenmodell
-
-Das Konzept beschreibt den Unified Data Layer fachlich, aber nicht als Datenmodell. Offene Fragen:
-
-- Neue Entität `DataSource` mit `scope`, `neutralize`, `featureInstanceId`, `createdBy`?
-- Oder Erweiterung bestehender Modelle um `scope` und `neutralize`?
-- Wo lebt der RAG-Index physisch? Eigene DB? pgvector in `poweron_app`?
-- Scope-Metadaten im Vektorspeicher: Wie effizient ist die Union-Query über vier Scopes?
-
-Empfehlung: Separates Konzeptdokument für Phase 2 mit konkretem Datenmodell.
-
-### 4.5 Store vs. Unified Data Layer: Semantische Verschiebung über die Phasen
-
-In Phase 1 erstellt der Store eine `FeatureInstance` (Instanz = Datengrenze). In Phase 3 sind Features reine Workflow-Oberflächen auf dem Unified Layer — was "erstellt" der Store dann? Die Instanz wird zum **UI-Scope** statt zum **Daten-Scope**. Das ist ein fundamentaler Bedeutungswandel von `FeatureInstance`, der im Phasenplan klarer werden sollte.
-
----
-
-## 5. Unified Data Bar (UDB)
-
-### 5.1 Architektonische Bewertung
-
-Die UDB als plattformweite, wiederverwendbare Komponente (extrahiert aus dem Workspace) ist die richtige Entscheidung. Sie löst drei Probleme gleichzeitig:
-
-1. **Datennavigation:** Ein Ort für alle Daten, Chats und Quellen.
-2. **Cross-Feature-Kontext:** Drag-and-Drop von Chats/Files/Sources in Prompts ermöglicht featureübergreifende Analysen.
-3. **Konsistenz:** Alle Features haben dieselbe Datensidebar, keine Duplizierung.
-
-### 5.2 Chat-Baum: Bewertung
-
-Die hierarchische Chat-Struktur (Feature-Instanzen als Top-Level, Chats darunter, feature-spezifische Substrukturen wie CommCoach → Coaching-Modul → Sessions) ist ein starkes Konzept. Es gibt dem User eine Übersicht, die heute nirgends existiert — weder in ChatGPT (flache Ordner), Langdock (flache Projects), noch in Copilot (pro-App-Silos).
-
-**Kritischer Punkt:** Bei vielen Feature-Instanzen und Hunderten von Chats kann der Baum unübersichtlich werden. Empfehlung: Suchfunktion im Chats-Tab und optionaler Flat-Mode (chronologische Liste ohne Hierarchie) als Alternative.
-
-### 5.3 Drag-and-Drop als Kontext-Steuerung
-
-Das Prinzip "jedes UDB-Element kann in den Prompt gezogen werden" ist mächtig und intuitiv. Die Use Cases (Cross-Feature-Analyse, Reporting über Instanzen hinweg, Coaching-Review) demonstrieren den Mehrwert klar.
-
-**Offener Punkt:** Was passiert mit dem Neutralisierungs-Flag, wenn ein neutralisierter Chat in einen Prompt gezogen wird? Wird der neutralisierte Text übergeben oder der Original-Text? Konsistent mit der Fail-Safe-Regel sollte immer die neutralisierte Version übergeben werden, wenn das Flag gesetzt ist.
-
-### 5.4 Wettbewerbsanalyse: Einordnung
-
-Die Wettbewerbstabelle ist präzise. PageSpace ist der nächste Vergleich (einheitlicher Baum), aber ohne Mandanten-Modell, RAG-Scopes und Neutralisierung. Die Kombination aus diesen vier Dimensionen (Hierarchischer Chat-Baum + Scope-Tagging + Neutralisierung + Multi-Tenant) ist tatsächlich ein Alleinstellungsmerkmal.
-
-**Risiko:** PageSpace und ähnliche Startups bewegen sich schnell. Das Fenster für die Differenzierung ist zeitlich begrenzt. Die UDB sollte in Phase 2 Priorität haben, nicht erst in Phase 3.
-
----
-
-## 6. Neutralisierung
-
-### 6.1 Architektonische Schlüssigkeit
-
-Die Zwei-Flag-Steuerung (Datenquelle + AI-Call) mit OR-Verknüpfung ist einfach und korrekt. Die Fail-Safe-Regel ("Neutralisierung fehlgeschlagen = Dokument nicht weitergeben") ist die einzig vertretbare Entscheidung für den Zielmarkt (regulierte Branchen). Kein Kompromiss hier ist richtig.
-
-### 6.2 Operation Type statt spezielle LLMs
-
-Die Nutzung des bestehenden Modellsystems (Operation Type `neutralization`) statt dedizierter "Neutralisierungs-LLMs" ist architektonisch sauber. Es nutzt die vorhandene Modellverwaltung und vermeidet eine parallele Infrastruktur.
-
-### 6.3 ChatWorkflow-Transparenz
-
-Die Entscheidung, neutralisierte Dokumente im ChatWorkflow-Objekt als sichtbare Dokumente mitzugeben, ist ein starker Trust-Mechanismus. Der User sieht, was rausgeht. Das ist nicht nur ein Feature, sondern ein Verkaufsargument für regulierte Branchen.
-
-### 6.4 Latenz-Betrachtung
-
-Die Pipeline hat drei Phasen mit unterschiedlicher Latenz-Charakteristik:
-
-| Phase | Zeitpunkt | Latenz-kritisch? |
-|-------|-----------|-------------------|
-| Datenquellen-Neutralisierung | Beim Einbinden ins RAG | Nein (asynchron, Batch) |
-| Prompt-Neutralisierung | Live, bei jedem AI-Call | Ja — User wartet |
-| Response-Re-Hydrierung | Post-Processing | Nein (String-Replacement aus Mapping-Tabelle) |
-
-Die Datenquellen-Neutralisierung (Phase 1) ist unkritisch, da sie beim Einbinden geschieht und nur die neutralisierte Version im RAG landet. Die Re-Hydrierung ist ein einfaches String-Replacement.
-
-**Kritisch ist die Prompt-Neutralisierung:** Wenn der User im Chat einen Kundennamen tippt und `requireNeutralization=true` gesetzt ist, muss der Prompt live neutralisiert werden. Das erfordert ein schnelles Modell. Empfehlung: Für Prompt-Neutralisierung ein leichtgewichtiges, lokales Modell oder Regex-basierte Vorfilterung evaluieren, um die Latenz unter 500ms zu halten.
-
-### 6.5 Platzhalter-Konsistenz
-
-Die Mapping-Tabelle muss über AI-Calls hinweg konsistent sein. `[PERSON_1]` muss immer "Max Müller" bedeuten, nicht einmal "Max Müller" und einmal "Anna Schmidt". Die Empfehlung: Mapping-Einträge persistent pro Datenquelle, nicht session-scoped. Bei AI-Calls wird das aktive Mapping als Kontext mitgegeben.
-
-### 6.6 Betriebsmodell für Modelle mit Operation Type `neutralization`
-
-Die Neutralisierung sieht **alle** sensiblen Daten im Klartext. Das Modell muss mindestens so vertrauenswürdig sein wie der Mandant selbst. Offene Frage: Self-hosted (GPU-Infrastruktur) oder CH-Provider mit DSG-konformem SLA? Das hat Infrastruktur- und Kostenimplikationen und sollte als eigene Entscheidung dokumentiert werden.
-
----
-
-## 7. Konsistenz und offene Architektur-Fragen
-
-| Thema | Frage | Empfehlung |
-|-------|-------|-----------|
-| `mandateType`-Mutabilität | Personal → Company: Änderung oder neues Mandate? | Mutabel, keine Geschäftslogik daran binden |
-| OAuth-Registrierung | Wo wählt ein OAuth-User den Mandant-Typ? | Onboarding-Wizard nach erstem Login |
-| Store: Existierende Instanz | Zweiter Admin aktiviert dasselbe Feature | Max. eine Store-Instanz pro Feature/Mandat; zweiter Admin bekommt FeatureAccess |
-| Store in Phase 3 | Was "aktiviert" der Store, wenn Features nur UI-Oberflächen sind? | FeatureInstance wird UI-Scope, nicht Daten-Scope — im Phasenplan klären |
-| Scope `global` | Wer darf plattformweite Daten erstellen? | Nur sysadmin, RBAC-geschützt |
-| Drag-and-Drop + Neutralisierung | Was wird übergeben: Original oder neutralisierte Version? | Immer neutralisierte Version, wenn Flag gesetzt |
-| Billing vs. RAG-Volumen | Wachsende Datenmenge = Infrastrukturkosten | Soft-Limit für RAG-Volumen pro Mandant (kein Billing, aber Kapazitätsparameter) |
-| UDB-Skalierung | Hunderte Chats im Baum | Suchfunktion + optionaler Flat-Mode |
-| Company-Onboarding | Was sieht ein Firmen-Admin nach Registrierung? | Definieren: autoCreate wie Personal, oder Feature-Auswahl-Wizard |
-| Mandanten-Löschung | Kaskade: Instanzen → Daten → RAG → Mappings → Stripe | Im Konzept definieren |
-
----
-
-## 8. Fazit
-
-Die Zielarchitektur ist **konzeptionell stark und in sich konsistent**. Die sechs Entscheidungen greifen ineinander:
-
-```
-Mandate-per-Registration
- → saubere Tenant-Grenze
- → Own Instance im Store (expliziter Kontext)
- → Unified Data Layer pro Mandant
- → RAG mit Scope-Tagging als Plattformkern
- → UDB als Navigation + Kontext-Steuerung
- → Neutralisierung als Fail-Safe-Pipeline
-```
-
-Die **UDB mit hierarchischem Chat-Baum, Drag-and-Drop-Kontext, Scope-Tagging und Neutralisierung** ist das architektonische Herzstück und ein belegbares Alleinstellungsmerkmal.
-
-Die **Neutralisierungs-Pipeline** mit Fail-Safe-Regel und ChatWorkflow-Transparenz ist die richtige Antwort auf den Zielmarkt (regulierte Schweizer Branchen).
-
-Die wichtigsten **offenen Architektur-Fragen** (Tabelle oben) betreffen Edge Cases und Phasenübergänge, nicht die Kernentscheidungen. Das Fundament stimmt.
-
-**Empfehlung für nächste Konzeptdokumente:**
-
-1. **Unified Data Layer: Datenmodell** (Phase 2) — Entitäten, Scope-Persistenz, RAG-Index-Architektur
-2. **Neutralisierung: Betriebsmodell** — Trusted-Model-Infrastruktur, Latenz-Budget, Platzhalter-Konsistenz
-3. **UDB: Komponentenarchitektur** — Extraktion aus Workspace, State Management, Drag-and-Drop-API
-
----
-
-*Review-Version: 2026-03-23 v2 — Basierend auf Konzeptdokument v3. Fokus: Zielarchitektur, Idee, Konzept und Modelle.*
diff --git a/concepts/Multi-Mandate-Onboarding-und-Store-Konzept.md b/concepts/Multi-Mandate-Onboarding-und-Store-Konzept.md
index 2b85d41..92e73d2 100644
--- a/concepts/Multi-Mandate-Onboarding-und-Store-Konzept.md
+++ b/concepts/Multi-Mandate-Onboarding-und-Store-Konzept.md
@@ -446,7 +446,7 @@ Dasselbe Prinzip gilt auch für **Files** und **Sources** aus den anderen Tabs
│ │
│ ┌──────────┐ ┌──────────────────────────────────┐ │
│ │ UDB │ │ │ │
-│ │ │ │ Feature-spezifischer Content │ │
+│ │ │ │ Feature-spezifischer Content │ │
│ │ [Chats] │ │ (Workflows, Formulare, etc.) │ │
│ │ [Files] │ │ │ │
│ │ [Sources]│ │ │ │
@@ -515,6 +515,17 @@ Es gibt **keine speziellen LLMs** für Neutralisierung. Die zugelassenen AI-Mode
Die Operation-Type-Konfiguration wird zentral verwaltet und ist nicht vom User änderbar.
+### Bestehende Code-Basis (Ausbau, kein Neubau)
+
+Die Neutralisierung ist in der Plattform bereits implementiert und kann ausgebaut werden:
+
+- **`StringParser`** ([subParseString.py](../../gateway/modules/features/neutralization/serviceNeutralization/subParseString.py)): Regex-basierte Erkennung und Ersetzung von Emails, Telefonnummern, Adressen, IBANs, Daten, Policy-IDs und Namen. Platzhalter im Format `[type.uuid]` (z. B. `[name.a1b2c3d4-...]`). Mapping `originalText → Platzhalter` wird pro Durchlauf aufgebaut und ist persistent nutzbar.
+- **`DataNeutralizerAttributes`** ([datamodelFeatureNeutralizer.py](../../gateway/modules/features/neutralization/datamodelFeatureNeutralizer.py)): Bestehende Datenbanktabelle für Platzhalter-Mappings mit `originalText`, `patternType`, `mandateId`, `featureInstanceId`, `userId`, `fileId`. Entspricht der im Konzept beschriebenen Platzhalter-Mapping-Tabelle.
+- **`neutralizeData`-Action** ([neutralizeData.py](../../gateway/modules/workflows/methods/methodContext/actions/neutralizeData.py)): Bestehende Workflow-Action, die Dokumente (`ContentExtracted` / `ContentPart`) durch die Neutralisierung führt und als `ActionDocument` mit Validierungs-Metadaten zurückgibt.
+- **`DataNeutraliserConfig`**: Pro Feature-Instanz konfigurierbar mit `enabled`-Flag und `namesToParse`-Liste.
+
+Die bestehende Architektur (Config → StringParser → Mapping-Tabelle → neutralisierter Output) entspricht dem Zielbild. Die Erweiterung betrifft: Integration der Scope-Flags, Anbindung an den RAG-Index, Fail-Safe-Logik (Dokument nicht weitergeben bei Fehler), und Re-Hydrierung der AI-Responses.
+
### Neutralisierungs-Pipeline
```mermaid
@@ -573,6 +584,61 @@ Die Neutralisierung läuft **vollautomatisch** in der Pipeline:
---
+## Subscription: Datenvolumen als Parameter
+
+Das RAG und der Unified Data Layer sind kein limitierender Faktor — die Plattform verfügt über ausreichend Datenbank- und Speicherkapazität, und der Fokus liegt darauf, Daten **breit verfügbar** zu machen. Dennoch sollte das **Datenvolumen als Parameter in der Subscription** integriert werden:
+
+- `maxDataVolumeMB` (oder GB) pro Mandant als Subscription-Parameter in `MandateSubscription`.
+- Kein hartes Billing auf Datenvolumen, aber ein Soft-Limit, das dem Mandanten-Admin angezeigt wird.
+- Bei Annäherung ans Limit: Hinweis im UI (z. B. „80% des Datenvolumens genutzt"), kein Schreib-Block.
+- Upgrade-Pfad: Höherer Plan = mehr Volumen.
+
+Dies dient der Kapazitätsplanung und dem Upselling, nicht der Einschränkung.
+
+---
+
+## Onboarding-Assistant
+
+Der **Onboarding-Assistant** ist ein zentrales Element der User Experience. Nach Registrierung (oder nach erstem OAuth-Login) führt ein interaktiver Assistent den neuen User durch die ersten Schritte:
+
+1. **Mandant-Typ bestätigen** (bei OAuth-Flow: Personal oder Company wählen).
+2. **Erste Feature-Instanz aktivieren** — der Assistant empfiehlt basierend auf dem Kundenprofil (z. B. Workspace als Startpunkt).
+3. **Erste Datenquelle einbinden** — Upload oder Konnektor aktivieren, Scope und Neutralisierung erklären.
+4. **Erster AI-Call** — der User erlebt sofort den Mehrwert.
+
+Der Onboarding-Assistant ist kein einmaliger Wizard, sondern ein kontextsensitiver Begleiter, der bei neuen Features, nach Pausen oder bei leeren Zuständen (kein Chat, keine Daten) wieder erscheint. Er reduziert Time-to-Value und ist entscheidend für Trial-Conversion.
+
+---
+
+## Mandanten-Löschung: Kaskade
+
+Die Löschung eines Mandanten erfordert eine vollständige Kaskade über alle abhängigen Entitäten. Diese muss atomar und nachvollziehbar ablaufen:
+
+```
+Mandate löschen
+├── Alle FeatureInstances im Mandanten
+│ ├── Alle FeatureAccess-Records pro Instanz
+│ ├── Alle Daten pro Instanz (Chats, Dokumente, Extraktionen)
+│ └── Alle Neutralisierungs-Mappings (DataNeutralizerAttributes) pro Instanz
+├── Alle DataSources im Mandanten
+│ └── RAG-Index-Einträge mit mandateId entfernen
+├── Alle UserMandate-Zuordnungen zum Mandanten
+│ (User selbst bleiben bestehen — sie haben ggf. andere Mandate)
+├── MandateSubscription
+│ └── Stripe-Subscription kündigen / Stripe-Quantity auf 0
+├── Mandate-spezifische Konfigurationen (Rollen, Settings)
+└── Mandate-Record selbst (soft-delete mit Retention oder hard-delete)
+```
+
+**Schutzmechanismen:**
+
+- `isSystem=true`-Mandate (Root) sind nicht löschbar.
+- Löschung nur durch Mandanten-Admin oder sysadmin.
+- Bestätigung mit expliziter Eingabe des Mandantennamens (wie bei GitHub Repo-Löschung).
+- Soft-Delete mit 30-Tage-Retention als Default; endgültige Löschung per Batch-Job.
+
+---
+
## Verwandte Dokumente
- [Mandanten-Subscription-Konzept.md](./Mandanten-Subscription-Konzept.md) — Lizenz & Kapazität pro Mandant
@@ -597,4 +663,4 @@ Die Neutralisierung läuft **vollautomatisch** in der Pipeline:
---
-*Dokument-Version: 2026-03-23 v3 — Korrekturen: Neutralisierung via Operation Type (keine speziellen LLMs); nur neutralisierte Dokumente im RAG; Platzhalter-Mapping als Datenbanktabelle (kein Vault); ChatWorkflow-Transparenz; explizites Datenquellen-Tagging mit Scope und Neutralisierungs-Flag; Marktbeurteilung in separates Dokument ausgelagert.*
+*Dokument-Version: 2026-03-23 v4 — Review-Integration: mandateType mutabel/informativ, isSystem-Trennung, OAuth-Wizard, Subscription-Timing (PENDING), Store für alle User mit Auto-Mandate, mehrere Instanzen pro Feature erlaubt, scope=global RBAC-geschützt, UDL-Datenmodell definiert (bestehende Infrastruktur), FeatureInstance-Semantikverschiebung über Phasen, Chat-Baum-Skalierung (Suche+Flat), Drag-and-Drop via RAG-Daten, bestehender Neutralisierungs-Code referenziert, Datenvolumen als Subscription-Parameter, Onboarding-Assistant, Mandanten-Löschung-Kaskade.*
diff --git a/concepts/Multi-Mandate-Umsetzungsplan.md b/concepts/Multi-Mandate-Umsetzungsplan.md
new file mode 100644
index 0000000..96b82f6
--- /dev/null
+++ b/concepts/Multi-Mandate-Umsetzungsplan.md
@@ -0,0 +1,915 @@
+# Umsetzungsplan: Multi-Mandate Onboarding, Store und Unified Data Layer
+
+**Grundlage:** [Multi-Mandate-Onboarding-und-Store-Konzept.md](./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: `PENDING` → `ACTIVE`
+
+**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 `PENDING` → `ACTIVE` 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:
+ - `personal` → `mandateType=personal`, `planKey=TRIAL_7D`, `mandateName=username`
+ - `company` → `mandateType=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.py` — `BUILTIN_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.tsx` — `type` Query-Parameter
+- `frontend_nyla/src/api/authApi.ts` — `registerApi` 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.py` — `initRootMandate()` 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.*