Files
leocrm/PLATFORM_ROADMAP.md
T

1315 lines
97 KiB
Markdown
Raw Normal View History

# LeoCRM → LeoPlatform: Entwicklungs-Roadmap
> **Erstellt:** 2026-08-11
> **Aktualisiert:** 2026-08-12 — Phase 0.5 (Universal Undo & Restore) hinzugefügt
> **Status:** Draft — zur Diskussion
> **Prämisse:** LeoCRM wird zu einer KI-gesteuerten Business-Plattform erweitert
---
## Ausgangslage
LeoCRM ist bereits keine reine CRM-Anwendung mehr. Die bestehende Architektur bietet:
- **26 Built-in-Plugins** inkl. AI Assistant, AI Proactive, AI UI Control, Automation, Agent Memory, GraphRAG, Unified Search, MCP Client/Server, Workflow Engine
- **Plugin-Manifest** mit Agent-Definitionen, Automation-Templates, Cron-Jobs, Heartbeats, Frontend-Komponenten, Custom Fields, Dashboard-Widgets
- **Event Bus + Transactional Outbox** für zuverlässige asynchrone Workflows
- **Hooks-System** (WordPress-style Actions + Filters)
- **Tool Registry** mit OpenAI Function-Calling Schema
- **CRM API Tool** — KI bekommt alle API-Endpunkte via OpenAPI-Spec-Injection
- **Agent Runner** mit Safety-Checks (Rate-Limit, Budget, Infinite-Loop-Detection)
- **Agent Coordinator** für Multi-Agent-Subtask-Delegation
- **10 Search Provider** (contact, company, mail, file, event, task, contactperson, tag, conversation, user)
- **pgvector** Embeddings (768-dim, HNSW Index)
- **ARQ Worker** für Background-Jobs
- **Multi-Tenant + RBAC + ABAC + Field-Permissions + Audit-Log**
**Sicherheit:** Phase 1-5 Security Fix Plan komplett abgeschlossen.
**Offen:** 14 Frontend-Features in 4 Phasen (IMPLEMENTATION_PLAN.md, nicht begonnen).
---
## Roadmap-Übersicht
```
Phase 0 — Foundation Cleanup & Frontend Completion [Woche 1-4]
Phase 0.5 — Universal Undo & Restore System [Woche 5-9]
Phase 0.7 — System-Konsolidierung (Attachments, LLM, [Woche 10-19]
WebSocket, Redis, Events, File Upload,
Import/Export, Error/Custom Fields,
Plugin-Specification & Contract,
Plugin Public Web Content)
Phase 0.8 — Frontend-Konsolidierung & UI-System [Woche 20-24]
Phase 1 — Unified Search Platform [Woche 25-28]
Phase 2 — Autonomous Agent Engine (ReAct-Loop) [Woche 29-34]
Phase 3 — Workflow Platform (n8n-Ersatz) [Woche 35-40]
Phase 4 — Knowledge Management & RAG [Woche 41-46]
Phase 5 — Platform Integration & Polish [Woche 47-50]
```
```
┌──────────────────────────────────────────────────────────┐
│ LeoPlatform │
│ │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ │
│ │ Search │ │ Agents │ │ Workflows │ │ Knowledge │ │
│ │ (Phase 1)│ │ (Phase 2)│ │ (Phase 3)│ │ (Phase 4) │ │
│ └────┬────┘ └────┬─────┘ └────┬─────┘ └─────┬─────┘ │
│ │ │ │ │ │
│ ┌────┴────────────┴──────────────┴──────────────┴────┐ │
│ │ Plugin System + Event Bus │ │
│ │ ┌────────┐ ┌─────────┐ ┌───────┐ ┌───────────────┐ │ │
│ │ │ Tools │ │ Memory │ │ MCP │ │ Contracts │ │ │
│ │ │Registry│ │ +GraphRAG│ │ C/S │ │ (Cross-Plugin)│ │ │
│ │ └────────┘ └─────────┘ └───────┘ └───────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Undo & Restore (Phase 0.5) — durchdringt alle Layer │ │
│ └─────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ PostgreSQL 16 + pgvector + Redis + ARQ Worker │ │
│ └─────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
```
---
## Phase 0 — Foundation Cleanup & Frontend Completion
**Dauer:** 4 Wochen
**Ziel:** Offene Frontend-Features abschließen, Tests ergänzen, technische Schulden abbauen
**Begründung:** Bevor Platform-Features gebaut werden, muss das Fundament stabil sein.
### 0.1 Frontend-Features (aus IMPLEMENTATION_PLAN.md)
| Task | Beschreibung | Priorität | Aufwand |
|------|-------------|-----------|---------|
| F-WF-UI | Workflows UI — Liste, Editor, Instanz-Detail | Hoch | 3-4 Tage |
| F-DEDUP | Dedup/Merge UI für Kontakte | Mittel | 2-3 Tage |
| F-IMPORT | Import/Export UI (CSV, vCard) | Hoch | 2-3 Tage |
| F-PRINT | Print/PDF für Contact/Company | Niedrig | 1 Tag |
| F-TAGS | Tags UI — Tag-Manager, Tag-Filter | Mittel | 2 Tage |
| F-CF | Custom Fields UI — Editor, Anzeige in Detail | Mittel | 2-3 Tage |
| F-NOTIF | Notifications Dropdown in TopBar | Hoch | 1-2 Tage |
| F-FILTER | Saved Filters — speichern, laden, teilen | Mittel | 2 Tage |
| F-HISTORY | Entity History (Audit-Log UI) | Mittel | 2 Tage |
| F-TIMELINE | Activity Timeline (Kontakt-Historie) | Niedrig | 2 Tage |
| F-DOCS | API Docs UI (Swagger-UI Embed) | Niedrig | 0.5 Tage |
| F-WEBHOOK | Webhooks UI — CRUD, Test-Send | Niedrig | 1-2 Tage |
| F-BACKUP | Backup/Restore UI | Niedrig | 1 Tag |
| F-ONBOARD | Onboarding-Wizard für neue Nutzer | Niedrig | 1-2 Tage |
### 0.4 Navigation & Workspace-UI
Konkrete UI-Verbesserungen an der Navigation, Workspace-Verwaltung, und Seiten-Struktur.
| Task | Beschreibung | Priorität | Aufwand |
|------|-------------|-----------|---------|
| F-NAV-WS-UI | **Workspace-Editor UI** — UI um Workspaces zusammenzustellen: Module auswählen, Unterpunkte/Reihenfolge konfigurieren, Vorschau. Drag-and-Drop für Menü-Reihenfolge | Hoch | 2-3 Tage |
| F-NAV-WS-DEFAULT | **Standard-Workspace konfigurierbar** — Standard-Workspace zeigt aktuell nichts. Soll stattdessen alles anzeigen was für den User freigeschaltet ist (basierend auf Permissions). Standard-Workspace muss konfigurierbar sein (Admin kann definieren was im Standard angezeigt wird) | Hoch | 1-2 Tage |
| F-NAV-WS-BACK | **Workspace Zurück-Button** — jeder Workspace braucht einen Zurück-Button um zum Startbildschirm zu kommen | Hoch | 0.5 Tage |
| F-NAV-AGENT | **Agentenverwaltung als eigene Seite** — eigener Menüpunkt im Startseiten-Menü (links der Workspace-Auswahl). Eigene Seite mit Menü links. NICHT innerhalb eines Workspaces — nur Topbar sichtbar mit Zurück-Button | Hoch | 1-2 Tage |
| F-NAV-SETTINGS | **Einstellungen als eigene Seite** — eigener Menüpunkt im Startseiten-Menü (links der Workspace-Auswahl). Einstellungen hat schon vertikale Reiter — komplett auf eigene Seite mit nur Topbar + Zurück-Button. NICHT innerhalb eines Workspaces | Hoch | 1-2 Tage |
| F-NAV-LAYOUT | **Seiten-Layout-Typen** — zwei Layout-Typen: (1) Workspace-Layout (mit Sidebar + Workspace-Menü), (2) Standalone-Layout (nur Topbar + eigenes Menü links + Zurück-Button). Agentenverwaltung und Einstellungen nutzen Standalone-Layout | Hoch | 1 Tag |
### 0.2 Test-Ergänzungen
| Task | Beschreibung |
|------|-------------|
| T-AM | Tests für agent_memory Plugin |
| T-GR | Tests für graph_rag Plugin |
| T-MP | Tests für marketplace Plugin |
| T-AUTO | Tests für automation Plugin (agent_runner, coordinator, scheduler) |
| T-E2E | E2E-Tests für kritische User-Flows (Login, Contact CRUD, Mail, Search) |
### 0.3 Cleanup
- Test-Instanzen CRM2/CRM3 löschen
- `dump.rdb` entfernen (in .gitignore prüfen)
- Veraltete ENV-Variablen bereinigen
**Deliverables:** Stabile Frontend-UI für alle Core-Features, Test-Coverage > 80% für neue Plugins.
---
## Phase 0.5 — Universal Undo & Restore System
**Dauer:** 5 Wochen
**Ziel:** Ein einziges universelles Undo/Restore-System für ALLE Entitäten — alle bestehenden fragmentierten History-Systeme werden konsolidiert und rückgebaut. Zukünftige Plugins bekommen eine klare Bauanleitung.
**Begründung:** Das bestehende EntityHistory-System ist nur halb implementiert. `restore_from_history()` unterstützt hardcoded nur `entity_type == "contact"`. `record_history()` wird nur in `contact_service.py` (3x) und `companies.py` (1x) aufgerufen — keine Plugins nutzen es. Gleichzeitig existieren 7+ separate History/Version-Systeme parallel (EntityHistory, AuditLog, CommMessageEdit, AgentVersion, AutomationVersion, ContactMergeHistory, WorkflowStepHistory, Backup) die alle etwas Ähnliches machen, aber völlig unabhängig voneinander. Das muss vereinheitlicht werden — ein System, eine Logik, eine API.
### Aktueller State
| Komponente | Status |
|---|---|
| EntityHistory Model | ✅ Vorhanden (snapshot_before, snapshot_after, changes) |
| entity_history_service | 🟡 Vorhanden, aber restore nur für Contact hardcoded |
| record_history() Aufrufe | 🟡 Nur Contact (3x) + Company (1x), keine Plugins |
| Soft-Delete (deleted_at) | ✅ Contact, Company, Mail, MailAccount, MailFolder, DMS, Tasks, Calendar |
| Backup/Restore (DB-Level) | ✅ pg_dump-basiert, scripts/backup.py + restore.py |
| Undo UI | ❌ Nicht vorhanden |
| Plugin-History-Integration | ❌ Nicht vorhanden |
| Mail-Undo (IMAP) | ❌ Nicht vorhanden |
| AI Chat History/Undo | ❌ Nicht vorhanden — AIChatSession, AIChatMessage, AIConversation, AIMessage haben kein deleted_at, keine History, kein Undo |
| Kommunikation Chat Undo | 🟡 CommMessage hat deleted_at + CommMessageEdit, aber kein Restore-Mechanismus |
### 0.5.0 Konsolidierung & Rückbau bestehender Systeme
Bevor das neue universelle System gebaut wird, müssen alle bestehenden fragmentierten History/Version-Systeme konsolidiert werden. Es darf nach Phase 0.5 nur noch **ein** Undo/Restore-System geben: EntityHistory.
**Bestehende Systeme die konsolidiert werden:**
| # | System | Model | Aktuelle Nutzung | Migration nach | Rückbau |
|---|---|---|---|---|---|
| 1 | EntityHistory | `EntityHistory` | Contact (3x), Company (1x) | Bleibt als einziges System | Wird erweitert |
| 2 | AuditLog | `AuditLog` | Calendar, DMS, Mail, Groups, MCP, Contacts | Bleibt als Compliance-Trail (kein Undo) | Kein Rückbau, klarere Trennung |
| 3 | CommMessageEdit | `CommMessageEdit` | Kommunikation Chat | EntityHistory mit `action=edit` | Table wird deprecated, Daten migriert |
| 4 | AgentVersion | `AgentVersion` | Automation Plugin | EntityHistory mit `action=version` | Table wird deprecated, Daten migriert |
| 5 | AutomationVersion | `AutomationVersion` | Automation Plugin | EntityHistory mit `action=version` | Table wird deprecated, Daten migriert |
| 6 | ContactMergeHistory | `ContactMergeHistory` | Contact Merge | EntityHistory mit `action=merge` | Table wird deprecated, Daten migriert |
| 7 | WorkflowStepHistory | `WorkflowStepHistory` | Workflow Engine | Bleibt (Runtime-Log, kein Undo) | Kein Rückbau, anderes Konzept |
| 8 | Backup | `Backup` | Backup Service | Bleibt (Disaster Recovery) | Kein Rückbau, andere Ebene |
**Ziel-Architektur nach Konsolidierung:**
```
┌──────────────────────────────────────────────────┐
│ EntityHistory (EINZIGES Undo/Restore-System) │
│ • snapshot_before / snapshot_after / changes │
│ • action: create | update | delete | edit | │
│ merge | version | import | restore │
│ • Generische restore_from_history() │
│ • Hook-basierte Aufzeichnung für ALLE Entities │
│ • Cascade-Restore für abhängige Entitäten │
└────────────────────────┬─────────────────────────┘
┌──────────────────┼──────────────────┐
│ │ │
┌─────┴─────┐ ┌───────┴───────┐ ┌──────┴──────┐
│ AuditLog │ │ Workflow │ │ Backup │
│ Compliance │ │ StepHistory │ │ Disaster │
│ Wer/Wann/ │ │ Runtime-Status │ │ Recovery │
│ Was/Why │ │ (Log only) │ │ (pg_dump) │
│ Kein Undo │ │ Kein Undo │ │ Kein Entity │
└────────────┘ └───────────────┘ └─────────────┘
Deprecated & Migriert:
✗ CommMessageEdit → EntityHistory (action=edit)
✗ AgentVersion → EntityHistory (action=version)
✗ AutomationVersion → EntityHistory (action=version)
✗ ContactMergeHistory → EntityHistory (action=merge)
```
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| U-K-ANAL | **Bestandsaufnahme** — alle Verwendungen der 7 Systeme dokumentieren, Abhängigkeiten mapping | 0.5 Tage |
| U-K-COMM | **CommMessageEdit migrieren** — bestehende Edit-History in EntityHistory mit `action=edit` importieren, CommMessageEdit deprecated, Services auf EntityHistory umstellen | 1 Tag |
| U-K-AGENT | **AgentVersion migrieren** — bestehende Version-Snapshots in EntityHistory mit `action=version` importieren, AgentVersion deprecated, `restore_version()` auf `restore_from_history()` umstellen | 1 Tag |
| U-K-AUTO | **AutomationVersion migrieren** — gleiche Migration wie AgentVersion | 1 Tag |
| U-K-MERGE | **ContactMergeHistory migrieren** — Merge-Historie in EntityHistory mit `action=merge` importieren, ContactMergeHistory deprecated | 0.5 Tage |
| U-K-AUDIT | **AuditLog trennen** — AuditLog bleibt als Compliance-Trail, aber alle `log_audit()` Aufrufe die aktuell Snapshots speichern werden auf `record_history()` umgestellt. AuditLog speichert nur noch Wer/Wann/Was (keine Snapshots) | 1 Tag |
| U-K-CLEAN | **Deprecated Tables löschen** — nach erfolgreicher Migration und Verifikation: CommMessageEdit, AgentVersion, AutomationVersion, ContactMergeHistory Tables löschen (Migration + Data-Migration) | 1 Tag |
| U-K-TEST | **Migration-Tests** — sicherstellen dass alle migrierten Daten korrekt in EntityHistory liegen, Restore funktioniert, keine Datenverluste | 1 Tag |
### 0.5.1 Generic Restore Engine
Das Kernproblem: `restore_from_history()` ist hardcoded auf Contact. Es braucht eine generische Engine, die jede Entität wiederherstellen kann.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| U-REG | **Entity Registry** — zentrales Mapping `entity_type → ORM Model` mit allen Core- und Plugin-Modellen | 1 Tag |
| U-GEN | **Generic restore_from_history()** — ersetzt hardcoded Contact-Logik durch generisches Model-Lookup + Field-Restore | 1 Tag |
| U-SER | **Generic serialize/deserialize** — einheitliches Snapshot-Format für alle Modelle (UUID→Objekt-Resolution, JSONB-Fields, Relations) | 1 Tag |
| U-REL | **Relation-Restore** — abhängige Entitäten (z.B. Contact→ContactPersons, Mail→Attachments) mit wiederherstellen | 1 Tag |
| U-CON | **Conflict-Detection** — prüft ob Entität zwischenzeitlich geändert wurde (optimistic locking via updated_at-Vergleich) | 0.5 Tage |
| U-CAS | **Cascade-Restore** — wenn Parent wiederhergestellt wird, alle soft-deleted Children ebenfalls wiederherstellen | 1 Tag |
### 0.5.2 Universal History Recording
`record_history()` muss bei JEDER CRUD-Operation auf JEDER Entität aufgerufen werden — nicht nur bei Contacts.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| U-HOOK | **Hook-basierte History**`do_action('entity.after_create/after_update/after_delete')` Hooks, die automatisch record_history aufrufen | 1 Tag |
| U-MW | **Middleware-Integration** — SQLAlchemy-Event-Listener (before_update/after_delete) die Snapshots erstellen | 1 Tag |
| U-CORE | **Core-Modelle** — Contact, Company: record_history in allen CRUD-Operationen (create/update/delete) | 0.5 Tage |
| U-PLUG | **Plugin-Modelle** — Mail, DMS, Tasks, Calendar, Tags, EntityLinks: record_history in allen Services | 2 Tage |
| U-WF | **Workflow-Modelle** — Workflow, WorkflowInstance: History für Definition-Änderungen und Instanz-Status | 0.5 Tage |
| U-AUDIT | **Audit-Log-Dedup** — EntityHistory und AuditLog überschneiden sich. EntityHistory = Snapshots für Undo, AuditLog = Compliance-Trail. Beide behalten, aber klar trennen. | 0.5 Tage |
### 0.5.3 Mail Undo & Restore (Spezialfall)
Mail ist der schwierigste Fall, weil Mails mit IMAP-Servern synchronisiert werden. Eine Löschung auf dem IMAP-Server ist nicht einfach rückgängig zu machen.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| U-MSOFT | **Mail Soft-Delete** — Mail-Löschung in CRM setzt `deleted_at` (DB-only), NICHT IMAP-DELETE. IMAP-DELETE nur bei `?gdpr=true` oder explizitem Hard-Delete | 1 Tag |
| U-MTRASH | **IMAP Trash-Mapping** — Mail-Löschung verschiebt IMAP-Seite in Trash-Folder (nicht permanent löschen). Restore verschiebt zurück in Original-Folder | 1 Tag |
| U-MRESTORE | **Mail-Restore**`deleted_at` zurücksetzen + IMAP-MOVE von Trash zurück in Original-Folder | 1 Tag |
| U-MSEND | **Mail-Send-Undo** — gesendete Mails können nicht ungesendet werden. Stattdessen: "Recall"-Funktion (Delete-Notification an Empfänger) oder Draft-Retention | 0.5 Tage |
| U-MATT | **Attachment-Restore** — Mail-Attachments werden auf Disk gespeichert. Restore muss prüfen ob Datei noch existiert, sonst aus IMAP neu synchronisieren | 1 Tag |
| U-MSYNC | **Sync-Conflict-Resolution** — wenn Mail zwischenzeitlich vom IMAP-Server gelöscht wurde, Restore nur DB-seitig mit Warnung | 0.5 Tage |
| U-MFOLDER | **Folder-Restore** — MailFolder-Löschung: Children-Mails werden nicht gelöscht, sondern auf "unfiled" gesetzt. Folder-Restore stellt Hierarchie wieder her | 0.5 Tage |
| U-MACC | **Account-Restore** — MailAccount-Löschung: Account wird deaktiviert (is_active=false), nicht gelöscht. Restore reaktiviert. Hard-Delete löscht Credentials + sync'd Mails | 0.5 Tage |
### 0.5.4 DMS, Tasks, Calendar Undo & Restore
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| U-DOCS | **DMS File-Restore** — gelöschte Dateien: `deleted_at` zurücksetzen. Physische Datei auf Disk bleibt erhalten (wird erst bei Hard-Delete gelöscht) | 0.5 Tage |
| U-DFOLD | **DMS Folder-Restore** — Folder-Restore stellt auch alle Children (Files + Sub-Folders) wieder her (Cascade) | 0.5 Tage |
| U-DVER | **DMS Version-Restore** — Datei-Versionierung: alte Version kann wiederhergestellt werden (bereits vorhanden? prüfen) | 0.5 Tage |
| U-TASK | **Task-Restore** — gelöschte Tasks wiederherstellen mit allen abhängigen Subtasks | 0.5 Tage |
| U-CAL | **Calendar-Event-Restore** — gelöschte Events wiederherstellen. ICS-Sync: Restore muss prüfen ob Event auf externem Kalender noch existiert | 1 Tag |
| U-CREC | **Calendar-Recurring-Restore** — wiederkehrende Events: einzelne Ausnahme-Events vs. Serie wiederherstellen | 0.5 Tage |
### 0.5.5 Bulk Undo & Batch Operations
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| U-BULK | **Bulk-Undo** — mehrere Entitäten gleichzeitig wiederherstellen (z.B. alle Kontakte die in den letzten 10 Minuten gelöscht wurden) | 1 Tag |
| U-BATCH | **Batch-History** — eine Aktion (z.B. Import von 100 Kontakten) als eine History-Gruppe speichern, Undo stellt alle 100 wieder her | 1 Tag |
| U-IMPEXP | **Import-Undo** — kompletten Import rückgängig machen (alle importierten Entitäten löschen, alle geänderten reverten) | 1 Tag |
| U-MERGE | **Merge-Undo** — Contact-Merge rückgängig machen (merged Contact wiederherstellen, Duplicate-Contact reaktivieren) | 1 Tag |
### 0.5.6 Undo UI
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| U-TOAST | **Undo-Toast** — nach jeder Aktion erscheint ein Toast "Gelöscht — Undo?" für 5 Sekunden (wie Gmail) | 1 Tag |
| U-HIST | **History-Panel** — Timeline-View pro Entität mit allen Änderungen, Diff-View, Restore-Button pro Eintrag | 2 Tage |
| U-TRASH | **Trash-View** — globale Papierkorb-Ansicht: alle gelöschten Entitäten nach Typ filterbar, Multi-Select-Restore | 1 Tag |
| U-CONF | **Restore-Confirmation** — Modal mit Diff-Preview vor Restore: "Diese Aktion wird folgende Felder zurücksetzen: ..." | 0.5 Tage |
| U-LOG | **Undo-Log** — Audit-Trail aller Undo-Operationen (wer hat was wann wiederhergestellt) | 0.5 Tage |
### 0.5.7 Retention & Cleanup
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| U-RET | **Retention-Policy** — EntityHistory-Einträge älter als X Tage werden archiviert/gelöscht (konfigurierbar, default 90 Tage) | 0.5 Tage |
| U-GDPR | **GDPR-Hard-Delete**`?gdpr=true` löscht Entität + History + Snapshots unwiderruflich (DSGVO-Recht auf Vergessenwerden) | 0.5 Tage |
| U-SIZE | **Storage-Management** — EntityHistory kann groß werden. Partitionierung nach Monat (bereits setup_audit_partitioning.sql vorhanden) | 0.5 Tage |
### 0.5.8 Chat & AI History/Undo
Das KI-Chat und der Kommunikations-Chat haben aktuell KEIN Undo-System. Das ist ein systemischer Design-Fehler, nicht nur ein fehlendes Feature.
**Current State (Code-Analyse):**
| Modell | deleted_at | History | Undo | Restore |
|---|---|---|---|---|
| AIConversation (Copilot) | ❌ | ❌ | ❌ | ❌ |
| AIMessage (Copilot) | ❌ | ❌ | ❌ | ❌ |
| AIChatSession (Assistant) | ❌ | ❌ | ❌ | ❌ |
| AIChatMessage (Assistant) | ❌ | ❌ | ❌ | ❌ |
| AIChatAttachment | ❌ | ❌ | ❌ | ❌ |
| AIChatFolder | ❌ | ❌ | ❌ | ❌ |
| CommConversation | ✅ | ❌ | ❌ | ❌ |
| CommMessage | ✅ | 🟡 (CommMessageEdit) | ❌ | ❌ |
| CommMessageBlock | ✅ | ❌ | ❌ | ❌ |
| CommMessageAttachment | ✅ | ❌ | ❌ | ❌ |
| CommMessageReaction | ❌ | ❌ | ❌ | ❌ |
| CommParticipant | ❌ | ❌ | ❌ | ❌ |
**Das Problem:** Eine gelöschte Chat-Nachricht, ein gelöschter Chat-Verlauf, eine gelöschte AI-Konversation — all das ist aktuell unwiederbringlich verloren. CommMessageEdit speichert zwar alte Versionen, aber es gibt keinen Restore-Mechanismus.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| U-AI-DEL | **AI Chat Soft-Delete**`deleted_at` auf AIChatSession, AIChatMessage, AIConversation, AIMessage hinzufügen. Löschung setzt deleted_at, nicht hard-delete | 1 Tag |
| U-AI-HIST | **AI Chat History** — record_history() für AIChatMessage (edit/delete), AIChatSession (rename/delete), AIConversation (delete) | 1 Tag |
| U-AI-RESTORE | **AI Chat Restore** — gelöschte Chat-Sessions wiederherstellen mit allen Messages, Attachments, Tool-Results | 1 Tag |
| U-AI-EDIT | **AI Message Edit** — AIChatMessage editieren (z.B. System-Prompt nachträglich ändern), alte Version in History speichern | 0.5 Tage |
| U-AI-UNDO | **AI Action Undo** — wenn AI eine Aktion ausgeführt hat (proposed_actions → executed_action), Undo stellt den Entity-Zustand vor der Aktion wieder her (nutzt EntityHistory) | 1 Tag |
| U-COM-RESTORE | **CommMessage Restore** — gelöschte Nachrichten wiederherstellen (deleted_at zurücksetzen + Blocks/Attachments/Reactions wiederherstellen) | 1 Tag |
| U-COM-EDIT-RESTORE | **CommMessageEdit Restore** — CommMessageEdit hat bereits alte Versionen. Restore-Endpoint implementieren der alte Version wiederherstellt | 0.5 Tage |
| U-COM-CONV-RESTORE | **CommConversation Restore** — gelöschte Konversationen wiederherstellen mit allen Messages, Participants, Pinned-Items | 1 Tag |
| U-COM-REACT | **CommMessageReaction Undo** — Reactions haben kein deleted_at. Soft-Delete + Restore hinzufügen | 0.5 Tage |
| U-COM-PART | **CommParticipant Restore** — Participant hat left_at. "Re-Join" = left_at zurücksetzen. History für Role-Changes | 0.5 Tage |
| U-CHAT-UI | **Chat Undo UI** — "Nachricht löschen — Undo?" Toast, "Konversation wiederherstellen" in Trash-View, Edit-History-Dropdown pro Nachricht | 1.5 Tage |
**Deliverables:** Vollständiges Undo/Restore-System für alle Entitäten (Core + Plugins + AI Chat + Kommunikation), generische Restore-Engine, Mail-spezifische IMAP-Trash-Logik, Chat-History/Undo, Bulk-Undo, Trash-View UI, Undo-Toast, Retention-Policies.
---
## Phase 0.7 — System-Konsolidierung
**Dauer:** 5 Wochen
**Ziel:** Alle verbleibenden fragmentierten Systeme vereinheitlichen — Attachments, LLM Clients, WebSocket Managers, Redis Connections, Event/Notification, File Upload. Mit Rechte-System für Files. Alle abhängigen Plugins und Code werden mit aktualisiert.
**Begründung:** Genau wie bei History und Search gibt es 6 weitere Bereiche mit fragmentierter Implementierung. Jeder Bereich hat mehrere eigene Modelle, eigene Logik, eigene Endpoints. Das muss vereinheitlicht werden bevor Feature-Phasen gebaut werden.
### 0.7.1 Unified Attachment System
Aktuell: 6 verschiedene Attachment-Modelle (Attachment, EntityAttachment, DMS File, MailAttachment, CommMessageAttachment, AIChatAttachment) mit eigener Storage-Logik, eigenen Upload-Endpoints, eigenen Schemas.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| C-ATT-MODEL | **Unified Attachment Model** — ein generisches Attachment-Model das alle Typen abdeckt: `entity_type` (contact, mail, dms, chat, ai_chat, comm_message), `entity_id`, `filename`, `mime_type`, `size_bytes`, `storage_path`, `metadata` | 1 Tag |
| C-ATT-STORAGE | **Unified Storage Layer** — ein Storage-Backend für alle Files: `core/storage.py` erweitern mit `save_attachment()`, `get_attachment()`, `delete_attachment()`, `get_attachment_url()`. Path-Traversal-Schutz, MIME-Validation, Size-Limits | 1 Tag |
| C-ATT-PERM | **File Permissions** — Rechte-System für Files: `file:read`, `file:write`, `file:delete` Permissions. Entity-Level: wer das Parent-Entity lesen kann, darf auch das Attachment lesen. Owner-Level: Owner darf eigene Attachments verwalten. **Permissions Plugin (`plugins/builtins/permissions/`) wird deprecated** — eigenes `Permission` Model (`permissions` Table) wird migriert zu `EntityPermission` mit `entity_type='attachment'`. ShareLink wird zu Core-Model oder EntityAttachment-Metadata | 1.5 Tage |
| C-ATT-UP | **Unified Upload Endpoint**`POST /api/v1/attachments` mit `entity_type` + `entity_id` Parameter. Alle 6 alten Endpoints werden deprecated und leiten auf diesen um | 1 Tag |
| C-ATT-DOWN | **Unified Download Endpoint**`GET /api/v1/attachments/{id}` mit Permission-Check + Signed-URL-Support | 0.5 Tage |
| C-ATT-MIGRATE | **Migration** — bestehende Attachments aus DMS File, MailAttachment, CommMessageAttachment, AIChatAttachment in neues Unified Attachment Model migrieren. Alte Tables behalten als Views für Übergang | 2 Tage |
| C-ATT-PLUGIN | **Plugin-Integration** — alle Plugins (Mail, DMS, Kommunikation, AI Assistant) auf Unified Attachment umstellen. Eigene Attachment-Models werden deprecated | 2 Tage |
| C-ATT-UI | **Attachment UI** — einheitliche Upload-Komponente, Attachment-Liste pro Entity, Preview (Image/PDF/Office), Download-Button | 1 Tag |
### 0.7.2 Unified LLM Client
Aktuell: 7+ Stellen rufen LiteLLM direkt auf, jede mit eigener Provider-Logik, eigenem API-Key-Lookup, eigener Error-Handling. `llm_client.py` existiert aber wird nicht überall genutzt.
**Prinzip:** LiteLLM ist der zentrale LLM-Manager. Alle KI-Komponenten nutzen denselben Client, denselben Provider-Lookup, dieselbe Error-Handling. Model-Auswahl überall möglich.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| C-LLM-CORE | **Zentraler LLM Client**`app/ai/llm_client.py` erweitern zur einzigen Anlaufstelle: `llm_complete(model, messages, tools, ...)`, `llm_embed(texts, model)`. Provider-Lookup aus DB (AIProvider), Fallback auf ENV | 1.5 Tage |
| C-LLM-MODEL | **Model-Auswahl** — überall wo ein LLM gebraucht wird, kann ein Model aus dem AIProvider/AIModel-System ausgewählt werden. Default-Model pro Use-Case konfigurierbar (Copilot, Proactive, Search, Agent) | 1 Tag |
| C-LLM-ERR | **Unified Error-Handling** — einheitliche Error-Handling für alle LLM-Calls: Retry (3x mit Backoff), Fallback-Model, Rate-Limit-Handling, Timeout | 1 Tag |
| C-LLM-COST | **Cost-Tracking** — jeder LLM-Call loggt Token-Count + Cost. Unified Cost-Tracking in `ai_cost_log` Table | 0.5 Tage |
| C-LLM-MIGRATE | **Migration** — alle 7+ direkten `litellm.acompletion()` Aufrufe umstellen auf `llm_client.llm_complete()`: ai_assistant, ai_proactive, unified_search, automation, ai_copilot | 2 Tage |
| C-LLM-STREAM | **Unified Streaming** — einheitliches SSE-Streaming für alle LLM-Calls (Chat, Agent, Copilot) | 1 Tag |
| C-LLM-PLUGIN | **Plugin-Dev-Guide** — wie Plugins LLM-Calls machen: `from app.ai.llm_client import llm_complete`. Keine direkten LiteLLM-Aufrufe | 0.5 Tage |
### 0.7.3 Unified WebSocket Manager
Aktuell: 2 separate WebSocket-Manager (Kommunikation, AI UI Control) ohne gemeinsame Basis, ohne gemeinsame Auth-Prüfung.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| C-WS-BASE | **Base WebSocket Manager**`core/websocket_manager.py` mit gemeinsamer Basis: Connection-Verwaltung, Auth-Prüfung (Session-Cookie + Origin-Check), Broadcast, Room-Management, Heartbeat | 1.5 Tage |
| C-WS-AUTH | **WebSocket Auth** — Session-Verifikation vor `websocket.accept()`, Origin-Header-Check gegen CORS-Whitelist, CSRF-Schutz | 1 Tag |
| C-WS-PERM | **WebSocket Permissions** — Permission-Check pro Message-Type: wer darf welche Messages senden/empfangen. RBAC wird pro WS-Message geprüft | 1 Tag |
| C-WS-MIGRATE | **Migration** — Kommunikation WebSocketManager und AIUIControlWSManager auf Basis-Klasse umstellen | 1 Tag |
| C-WS-PLUGIN | **Plugin-Dev-Guide** — wie Plugins WebSocket-Endpoints erstellen: erben von BaseWebSocketManager, registrieren Message-Handlers | 0.5 Tage |
### 0.7.4 Unified Redis Connection
Aktuell: 4 verschiedene Wege Redis-Verbindungen zu erstellen (Singleton, Cache, Middleware pro Request, Monitoring).
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| C-RED-SINGLE | **Single Redis Pool**`core/redis.py` als einzige Anlaufstelle: `get_redis()` gibt Singleton-Pool zurück. Alle anderen Module importieren von hier | 0.5 Tage |
| C-RED-MIGRATE | **Migration**`core/cache.py`, `core/middleware.py`, `core/monitoring.py`, `core/auth.py` auf `get_redis()` umstellen. Per-Request-Connection-Erstellung entfernen | 1 Tag |
| C-RED-POOL | **Connection Pool Config** — konfigurierbare Pool-Size, Timeout, Retry. Health-Check für Pool | 0.5 Tage |
| C-RED-TEST | **Tests** — sicherstellen dass keine Connection-Leaks mehr auftreten unter Last | 0.5 Tage |
### 0.7.5 Unified Event/Notification System
Aktuell: 4 Mechanismen (EventBus, HookRegistry, EventOutbox, WebhookDispatcher) die teilweise dasselbe tun.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| C-EVT-CONCEPT | **Klar definierte Rollen** — EventBus = in-process ephemeral (cache invalidation, UI updates), HookRegistry = data modification (before/after create/update/delete), EventOutbox = durable domain events (contact.created, mail.received), WebhookDispatcher = external HTTP delivery | 0.5 Tage |
| C-EVT-DOC | **Decision Guide** — Dokumentation wann welches System zu nutzen ist. Flow-Chart für Plugin-Entwickler | 0.5 Tage |
| C-EVT-CLEANUP | **Bereinigung** — doppelte Handler entfernen, klare Trennung. EventBus-Handler die eigentlich Hooks sein sollten umstellen | 1 Tag |
| C-EVT-NOTIF | **Unified Notification Service**`core/notifications.py` als einzige Notification-API. Alle Plugins nutzen `create_notification()`. Notification-Types aus Plugin-Manifest registrierbar | 1 Tag |
| C-EVT-PLUGIN | **Plugin-Dev-Guide** — wann EventBus vs Hooks vs Outbox vs Webhooks. Klare Regeln | 0.5 Tage |
### 0.7.6 Unified File Upload
Aktuell: 6 verschiedene Upload-Endpoints mit unterschiedlicher Logik, Validierung, Storage-Verhalten.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| C-UP-VALID | **Unified Validation** — Path-Traversal-Schutz, MIME-Type-Whitelist, File-Size-Limit, Content-Type-Check. In `core/storage.py` zentral | 1 Tag |
| C-UP-ENDPOINT | **Unified Upload Endpoint**`POST /api/v1/attachments` (aus 0.7.1) als einziger Upload-Endpoint. Alle alten Endpoints deprecated | 0.5 Tage |
| C-UP-MIGRATE | **Migration** — alle 6 alten Upload-Endpoints (attachments, dms, mail, kommunikation, ai_assistant, plugins) auf Unified Endpoint umstellen | 1.5 Tage |
| C-UP-PERM | **Upload Permissions**`file:upload` Permission + Entity-Level-Check (kann User zu diesem Entity etwas hochladen?) | 0.5 Tage |
| C-UP-PLUGIN | **Plugin-Dev-Guide** — wie Plugins File-Upload implementieren: nutzen `core/storage.py`, keinen eigenen Upload-Endpoint | 0.5 Tage |
### 0.7.7 Plugin-Dev-Guide: System-Konventionen
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| C-PD-ALL | **Unified Plugin-Dev-Guide**`docs/plugin-development-guide.md` erweitern mit: Attachments (0.7.1), LLM (0.7.2), WebSocket (0.7.3), Redis (0.7.4), Events (0.7.5), File Upload (0.7.6). Klare DOs und DON'Ts | 1 Tag |
| C-PD-MANIFEST | **Manifest-Erweiterung**`attachment_config`, `llm_config`, `websocket_config`, `event_config` Felder in PluginManifest | 0.5 Tage |
| C-PD-TEST | **Plugin-Dev-Tests** — Test-Suite die prüft ob ein Plugin alle Konventionen einhält (keine direkten LiteLLM-Calls, keine eigenen Attachment-Models, keine eigenen WS-Managers, etc.) | 1 Tag |
### 0.7.8 Unified Import/Export
Aktuell: Import/Export ist hardcoded auf Contacts/Companies (CSV). Calendar hat ICS-Import/Export. Alle anderen Entitäten (Mail, Tasks, DMS, AI Chat, Workflows, Agenten) haben gar kein Import/Export.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| C-IE-FRAME | **Generic Import/Export Framework**`core/import_export.py` mit generischer API: `export_entities(entity_type, filters, format)` → CSV/JSON/XLSX, `import_entities(entity_type, data, dry_run)` → Preview + Import. Entity Registry liefert Felder-Mapping | 2 Tage |
| C-IE-CONTACT | **Contact/Company** — bestehenden CSV-Import/Export auf generisches Framework umstellen | 0.5 Tage |
| C-IE-MAIL | **Mail Export** — Mails als EML/PST/CSV exportieren (Subject, From, To, Date, Body). Import aus EML/CSV | 1 Tag |
| C-IE-TASKS | **Tasks Import/Export** — CSV/JSON Import/Export für Tasks (Title, Description, Status, Due-Date, Assignee) | 0.5 Tage |
| C-IE-CAL | **Calendar ICS** — bestehenden ICS-Import/Export auf generisches Framework umstellen | 0.5 Tage |
| C-IE-DMS | **DMS Export** — Datei-Metadaten als CSV/JSON exportieren. Bulk-Download als ZIP | 0.5 Tage |
| C-IE-CHAT | **AI Chat Export** — Chat-Verläufe als JSON/Markdown exportieren (für Backup, Archivierung, DSGVO-Auskunft) | 0.5 Tage |
| C-IE-WF | **Workflow Export** — Workflow-Definitionen als JSON exportieren/importieren (für Template-Sharing) | 0.5 Tage |
| C-IE-AGENT | **Agent Export** — Agent-Definitionen als JSON exportieren/importieren | 0.5 Tage |
| C-IE-UI | **Import/Export UI** — einheitliche UI: Entity-Typ auswählen, Format wählen, Filter setzen, Preview, Download/Upload | 1.5 Tage |
| C-IE-PERM | **Permission-Aware Export** — Export respektiert Visibility-Filter (nur sichtbare Entities). Import respektiert Permissions (nur mit write-Permission) | 0.5 Tage |
| C-IE-PLUGIN | **Plugin-Dev-Guide** — wie Plugins Import/Export implementieren: Entity Registry registrieren, Felder-Mapping definieren | 0.5 Tage |
### 0.7.9 Error Handling & Custom Fields Bereinigung
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| C-ERR-REDIS | **Error Rate-Limiter auf Redis** — in-memory Rate-Limiter in `routes/errors.py` durch Redis-basierten `check_rate_limit()` ersetzen (Security Risk H-7) | 0.5 Tage |
| C-CF-PLUGIN | **Custom Fields für Plugins**`custom_field_definition` und `custom_field_service` erweitern sodass Plugin-Entities (Mail, DMS, Tasks, Calendar) Custom Fields nutzen können. Entity Registry muss Plugin-Entities unterstützen | 1.5 Tage |
| C-CF-UI | **Custom Fields UI für Plugins** — Plugin-Detail-Seiten zeigen Custom Fields an, Editor zum Definieren | 1 Tag |
### 0.7.10 Plugin-Specification & Contract
Plugins brauchen klare, exakte Vorgaben was sie mitbringen müssen, wie sie funktionieren, und wie sie sich an alle Systeme anbinden. Dies wird die definitive Plugin-Bauanleitung.
**Grundprinzip:** Jedes Plugin ist ein vollständiger Modul-Baustein der sich nahtlos in die Plattform integriert — mit History, Search, Permissions, LLM, Tools, Events, UI. Ein Plugin ist nicht nur "Routes + Model" — es ist ein vollständiger Bürger der Plattform.
#### Was jedes Plugin MITBRINGEN MUSS (Pflicht)
| # | Vorgabe | Beschreibung |
|---|---|---|
| 1 | **PluginManifest** | Vollständiges Manifest mit name, version, display_name, description, dependencies, permissions, routes, events, hooks, contract_version |
| 2 | **BasePlugin** | Erbt von `BasePlugin`, implementiert `on_activate()` und `on_deactivate()` |
| 3 | **ORM Models** | Alle Models erben von `Base, TenantMixin` (tenant_id Pflicht), haben `deleted_at` (Soft-Delete Pflicht), `created_at`, `updated_at`, `created_by`, `updated_by` |
| 4 | **Entity Registry** | Alle Entitäten in zentraler Entity Registry registrieren: `register_entity("my_entity", MyModel)` |
| 5 | **History/Undo** | Hooks registrieren für automatische History-Aufzeichnung: `register_action("my_entity.after_create/after_update/after_delete")` |
| 6 | **Search Provider** | SearchProvider registrieren für jede durchsuchbare Entität: `register_search_provider(MyEntitySearchProvider)` |
| 7 | **Permissions** | Plugin-Permissions im Manifest deklarieren: `permissions=["my_plugin:read", "my_plugin:write"]`. Permission-Registry wird automatisch aktualisiert |
| 8 | **Migrations** | SQL-Migrations in `migrations/` Ordner, alle Tables müssen `tenant_id` haben, MigrationRunner validiert |
| 9 | **Schemas** | Pydantic Schemas: `<Entity>Create`, `<Entity>Update`, `<Entity>Read` für jede Entität |
| 10 | **Routes** | APIRouter mit korrektem Prefix (`/api/v1/plugin-<name>`), alle Routes mit `require_permission()` geschützt |
| 11 | **Contracts** | Plugin-Contract registrieren für Cross-Plugin-Kommunikation: `get_contract_registry().register("my_plugin", MyPluginContract())` |
| 12 | **Audit Log** | Alle Mutationen erstellen AuditLog-Einträge via `log_audit()` |
#### Was ein Plugin KANN (Optional aber empfohlen)
| # | Feature | Wie |
|---|---|---|
| 13 | **AI Tools** | Tools in ToolRegistry registrieren: `register_tool(name, description, parameters, handler, required_permission)`. Agenten können diese Tools nutzen |
| 14 | **LLM Integration** | LLM-Calls über zentralen Client: `from app.ai.llm_client import llm_complete`. NIE direkte `litellm.acompletion()` Aufrufe |
| 15 | **MCP Tools** | Plugin-Features als MCP-Tools exposed: `register_mcp_tool(name, description, handler)`. Externe KI-Systeme können zugreifen |
| 16 | **Event Bus** | Events subscribieren: `event_bus.subscribe("contact.created", handler)`. Events publishen: `await event_bus.publish("my_plugin.thing_happened", payload)` |
| 17 | **Hooks** | Actions registrieren: `register_action("contact.before_create", handler)`. Filters registrieren: `register_filter("contact.format_name", handler)` |
| 18 | **Outbox Events** | Durable Domain Events: `enqueue_outbox_event(db, tenant_id, "my_plugin.entity_created", {...})`. Werden zuverlässig zugestellt |
| 19 | **Webhooks** | Plugin kann Webhook-Subscriptions anbieten: Events im Manifest deklarieren, WebhookDispatcher liefert automatisch |
| 20 | **Frontend UI** | FrontendMenuItem, FrontendPageRoute, FrontendDetailTab, FrontendSettingsPage, FrontendDashboardWidget im Manifest deklarieren |
| 21 | **Custom Fields** | Plugin-Entities können Custom Fields nutzen: Entity in CustomField-Registry registrieren |
| 22 | **Import/Export** | Import/Export-Mapping im Plugin definieren: Felder-Mapping für generisches Import/Export-System |
| 23 | **WebSocket** | WebSocket-Endpoint über BaseWebSocketManager: erben, Message-Handlers registrieren |
| 24 | **Attachments** | Unified Attachment System nutzen: `save_attachment(entity_type, entity_id, file)`. KEINE eigenen Attachment-Models |
| 25 | **Agent Definitions** | AgentDefinitionContribution im Manifest: Plugin kann autonome Agenten definieren |
| 26 | **Automation Templates** | AutomationTemplateContribution im Manifest: Plugin kann Workflow-Templates beisteuern |
| 27 | **Cron Jobs** | CronJobContribution im Manifest: Plugin kann geplante Jobs definieren |
| 28 | **Dashboard Widgets** | FrontendDashboardWidget im Manifest: Plugin kann Dashboard-Kacheln beisteuern |
| 29 | **Notification Types** | `get_notification_types()` überschreiben: Plugin-spezifische Notification-Types registrieren |
| 30 | **Field Definitions** | FieldDefinitions im Manifest: Plugin kann sensitive Felder deklarieren für Field-Level-Permissions |
#### Was ein Plugin NICHT DARF (Verboten)
| # | Verbot | Warum |
|---|---|---|
| ❌ 1 | Eigene History-Tabellen | EntityHistory ist das einzige Undo-System |
| ❌ 2 | Eigene Version-Tabellen | EntityHistory mit `action=version` nutzen |
| ❌ 3 | Eigene Search-Systeme | Unified Search Provider nutzen |
| ❌ 4 | Eigene Attachment-Models | Unified Attachment System nutzen |
| ❌ 5 | Direkte `litellm.acompletion()` Aufrufe | Zentralen `llm_client.llm_complete()` nutzen |
| ❌ 6 | Eigene WebSocket-Manager | BaseWebSocketManager erben |
| ❌ 7 | Eigene Redis-Verbindungen | `get_redis()` aus `core/redis.py` nutzen |
| ❌ 8 | Eigene File-Upload-Endpoints | `POST /api/v1/attachments` nutzen |
| ❌ 9 | Eigene Import/Export-Logik | Generisches Import/Export-Framework nutzen |
| ❌ 10 | `log_audit()` für Snapshots | AuditLog = Compliance, EntityHistory = Snapshots |
| ❌ 11 | Hard-Delete ohne `?gdpr=true` | Soft-Delete ist Default, Hard-Delete nur mit GDPR-Flag |
| ❌ 12 | Plugin-Tables ohne `tenant_id` | MigrationRunner validiert, aber Pflicht |
| ❌ 13 | Sync I/O in Routes | Async-first: `async def`, asyncpg, aiofiles |
| ❌ 14 | Plaintext Passwörter | bcrypt cost=12 |
| ❌ 15 | JWT Auth | Session-based mit HttpOnly cookies |
| ❌ 16 | Raw SQL ohne tenant_id check | ORM mit auto-filter nutzen |
| ❌ 17 | Server-side HTML rendering | API-only backend, React SPA frontend |
| ❌ 18 | Integer IDs | UUID only |
| ❌ 19 | Naive datetime | TIMESTAMPTZ only |
| ❌ 20 | Class components (Frontend) | Functional components only |
#### Plugin-Manifest-Vollständigkeit
Das Plugin-Manifest wird erweitert um alle neuen Config-Felder:
```python
class PluginManifest(BaseModel):
# Bestehend
name: str
version: str
display_name: str
description: str
dependencies: list[str]
routes: list[PluginRouteDef]
events: list[str]
hooks: list[str]
permissions: list[str]
is_core: bool
author: str
min_app_version: str
contract_version: str
migrations: list[str]
field_definitions: list[FieldDefinition]
# Frontend
frontend_menu_items: list[FrontendMenuItem]
frontend_page_routes: list[FrontendPageRoute]
frontend_detail_tabs: list[FrontendDetailTab]
frontend_settings_pages: list[FrontendSettingsPage]
frontend_dashboard_widgets: list[FrontendDashboardWidget]
# AI / Agenten
agent_definitions: list[AgentDefinitionContribution]
automation_templates: list[AutomationTemplateContribution]
cron_jobs: list[CronJobContribution]
heartbeat_configs: list[HeartbeatConfigContribution]
# NEU: System-Integration
history_config: HistoryConfig # Welche Entitäten History/Undo haben
search_config: SearchConfig # Welche Entitäten durchsuchbar sind
attachment_config: AttachmentConfig # Welche Entitäten Attachments haben
llm_config: LLMConfig # Welche LLM-Modelle/Use-Cases das Plugin nutzt
websocket_config: WebSocketConfig # WebSocket-Endpoints
event_config: EventConfig # Welche Outbox-Events das Plugin publishen
import_export_config: ImportExportConfig # Import/Export-Mappings
custom_field_config: CustomFieldConfig # Welche Entitäten Custom Fields unterstützen
mcp_config: MCPConfig # Welche Features als MCP-Tools exposed werden
class HistoryConfig(BaseModel):
entities: list[str] = []
custom_restore_handlers: bool = False
cascade_dependencies: list[dict] = []
retention_days: int = 90
class SearchConfig(BaseModel):
entities: list[str] = []
fts_columns: dict[str, str] = {} # entity_type -> tsv_column
embedding_columns: dict[str, str] = {} # entity_type -> embedding_column
auto_index: bool = True
class AttachmentConfig(BaseModel):
entities: list[str] = [] # entity_types that can have attachments
allowed_mime_types: list[str] = []
max_file_size_mb: int = 25
class LLMConfig(BaseModel):
use_cases: list[str] = [] # e.g. ["chat", "proactive", "search", "agent"]
default_model: str | None = None
tools: list[dict] = [] # AI tools the plugin registers
class WebSocketConfig(BaseModel):
endpoints: list[dict] = [] # [{path, message_types, auth_required}]
class EventConfig(BaseModel):
publishes: list[str] = [] # outbox events the plugin publishes
subscribes: list[str] = [] # events the plugin subscribes to
class ImportExportConfig(BaseModel):
entities: list[dict] = [] # [{entity_type, fields, required_fields, formats}]
class CustomFieldConfig(BaseModel):
entities: list[str] = [] # entity_types that support custom fields
class MCPConfig(BaseModel):
tools: list[dict] = [] # [{name, description, handler_ref}]
```
#### Plugin-Lifecycle (vollständig)
```
1. Discovery — PluginRegistry.discover_builtins() findet Plugin
2. Install — MigrationRunner läuft, on_install() wird aufgerufen
3. Activate — on_activate(): Entity Registry, Search Providers, Hooks, Tools, Contracts registrieren
4. Running — Plugin verarbeitet Requests, Events, Tool-Calls, Background-Jobs
5. Deactivate — on_deactivate(): alle Registrierungen entfernen
6. Uninstall — on_uninstall(): Cleanup, MigrationRunner droppt Tables
```
#### Plugin-Validation (automatisiert)
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| C-PS-VALIDATOR | **Plugin-Validator** — automatisierte Prüfung beim Installieren: Manifest vollständig? Alle Pflicht-Felder vorhanden? Models haben tenant_id + deleted_at? Migrations validiert? Permissions deklariert? | 1.5 Tage |
| C-PS-TESTS | **Plugin-Test-Suite** — Tests die jedes Plugin durchlaufen muss: History funktioniert? Search funktioniert? Permissions korrekt? Undo/Restore funktioniert? | 1.5 Tage |
| C-PS-DOCS | **Plugin-Dev-Guide**`docs/plugin-development-guide.md` komplett überarbeiten mit allen Vorgaben, DOs, DON'Ts, Code-Beispielen | 2 Tage |
| C-PS-EXAMPLE | **Referenz-Plugin** — vollständiges Beispiel-Plugin das ALLE Features korrekt implementiert (History, Search, Tools, LLM, MCP, Events, Attachments, Import/Export, Custom Fields) | 2 Tage |
| C-PS-MANIFEST | **Manifest-Erweiterung** — alle neuen Config-Felder (HistoryConfig, SearchConfig, AttachmentConfig, LLMConfig, etc.) in PluginManifest implementieren | 1.5 Tage |
| C-PS-CHECK | **Cross-Plugin-Import-Checker** — prüft ob Plugins direkte Imports von anderen Plugin-Internals haben (statt Contracts zu nutzen) | 0.5 Tage |
### 0.7.11 Plugin Public Web Content (Subdomain & Unterordner)
Plugins sollen eigene Web-Inhalte öffentlich zur Verfügung stellen können — über Subdomain (`forms.crm.media-on.de`) oder Unterordner (`crm.media-on.de/public/forms/{id}`). Aktuell gibt es nur `is_public` für API-Routes (ohne Auth), aber keinen Mechanismus für öffentliche Web-Seiten, statische Files, oder Subdomain-Routing.
**Use-Cases:**
- Formular-Plugin: öffentliche Formulare unter `forms.crm.media-on.de/{form_id}` oder `crm.media-on.de/public/forms/{form_id}`
- Booking-Plugin: öffentliche Terminbuchung unter `book.crm.media-on.de`
- Survey-Plugin: öffentliche Umfragen
- Landing-Page-Plugin: öffentliche Landing-Pages
- Portal-Plugin: Kunden-Portal mit Login-Page
- Newsletter-Plugin: öffentliche Anmeldeseite
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| C-PW-SUB | **Subdomain-Routing** — FastAPI Host-Middleware die Subdomain extrahiert und an Plugin-Router weiterleitet. `forms.crm.media-on.de` → Form-Plugin. Konfigurierbares Subdomain-Mapping pro Plugin im Manifest | 2 Tage |
| C-PW-PATH | **Unterordner-Routing**`/public/{plugin_name}/...` Prefix für öffentliche Plugin-Web-Inhalte. Keine Auth, keine CSRF, aber Rate-Limiting | 1 Tag |
| C-PW-STATIC | **Static File Serving** — Plugins können statische Files (HTML, CSS, JS, Images) in `public/` Ordner ablegen. FastAPI StaticFiles mount pro Plugin | 1 Tag |
| C-PW-DYN | **Dynamic Pages** — Plugins können dynamische Web-Seiten generieren (Jinja2-Template-Engine, server-side rendering NUR für öffentliche Seiten — nicht für CRM-UI). Template-Registry pro Plugin | 2 Tage |
| C-PW-MANIFEST | **Manifest-Erweiterung**`public_web_config` Feld: `subdomain: str` (z.B. 'forms'), `path_prefix: str` (z.B. '/public/forms'), `static_dir: str` (z.B. 'public/'), `templates: list[dict]` | 1 Tag |
| C-PW-PROXY | **Reverse-Proxy Config** — nginx/Coolify Konfiguration für Subdomain-Routing. Wildcard-DNS (*.crm.media-on.de) oder explizite Subdomain-Einträge pro Plugin | 1 Tag |
| C-PW-RATE | **Public Rate-Limiting** — öffentliche Seiten brauchen eigenes Rate-Limiting (Redis-basiert, pro IP, höher als auth-Routes). Anti-Abuse-Schutz | 1 Tag |
| C-PW-CORS | **Public CORS** — öffentliche Seiten brauchen eigene CORS-Regeln (keine Cookies, keine CSRF, aber CORS für externe Aufrufe) | 0.5 Tage |
| C-PW-CACHE | **Public Caching** — öffentliche Seiten cachen (Redis + HTTP Cache-Headers). CDN-kompatibel | 0.5 Tage |
| C-PW-THEME | **Theme-Integration** — öffentliche Plugin-Seiten können CRM-Theme nutzen (Farben, Fonts, Logo) oder eigenes Theme | 1 Tag |
| C-PW-FORM | **Form-Plugin (Referenz)** — Referenz-Plugin das öffentliche Formulare bereitstellt: Form-Builder im CRM, öffentliche Form-Seite unter `forms.crm.media-on.de/{form_id}`, Submit → Daten ins CRM, E-Mail-Bestätigung | 3 Tage |
| C-PW-SEC | **Security** — öffentliche Seiten dürfen KEINE CRM-Session-Cookies empfangen, KEINE CSRF-Tokens, KEINE interne API-Endpunkte. Isolierte Public-Surface | 1 Tag |
| C-PW-PLUGIN | **Plugin-Dev-Guide** — wie Plugins öffentliche Web-Inhalte erstellen: Manifest deklarieren, Templates bauen, Static-Files ablegen, Subdomain konfigurieren | 0.5 Tage |
**Deliverables:** Vereinheitlichte Systeme für Attachments (1 Model, 1 Storage, 1 Endpoint, mit Permissions), LLM (1 Client, Model-Auswahl überall, Cost-Tracking), WebSocket (1 Base-Klasse, Auth, Permissions), Redis (1 Pool, keine Leaks), Events (klare Trennung 4 Systeme, Notification-API), File Upload (1 Endpoint, 1 Validation). Alle Plugins und abhängiger Code aktualisiert. Plugin-Dev-Guide erweitert.
### 0.5.9 Plugin-Entwickler-Leitfaden: Undo & Restore
Nach dem Umbau müssen Plugin-Entwickler wissen, wie sie History/Undo/Restore für ihre Plugin-Entitäten implementieren. Dies wird Teil der offiziellen Plugin-Development-Guide (`docs/plugin-development-guide.md`).
**Das Prinzip:** Plugin-Entitäten nutzen DASSELBE EntityHistory-System wie Core-Entitäten. Kein Plugin baut ein eigenes History-System. Alles läuft über die zentrale `record_history()` API und Hook-Integration.
**Was ein Plugin tun muss (Pflicht):**
1. **Entity Registry registrieren** — Plugin registriert seine Modelle in der zentralen Entity Registry:
```python
# In plugin.py on_activate()
from app.core.entity_registry import register_entity
register_entity("my_plugin_entity", MyPluginModel)
```
2. **Hooks nutzen** — Plugin nutzt die zentralen Hooks für automatische History-Aufzeichnung:
```python
# In plugin.py on_activate()
from app.core.hooks import get_hook_registry
reg = get_hook_registry()
reg.register_action("my_plugin_entity.before_create", self._before_create)
reg.register_action("my_plugin_entity.after_update", self._after_update)
reg.register_action("my_plugin_entity.after_delete", self._after_delete)
# Die Hook-Handler rufen automatisch record_history() auf
```
3. **Soft-Delete implementieren** — Plugin-Modelle müssen `deleted_at` haben:
```python
class MyPluginModel(Base, TenantMixin):
deleted_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), nullable=True
)
```
4. **Restore-Handler (optional)** — wenn das Plugin spezielle Restore-Logik braucht (z.B. IMAP-Sync bei Mail, Disk-Files bei DMS):
```python
# In plugin.py on_activate()
from app.core.entity_registry import register_restore_handler
async def my_restore_handler(db, entity_id, snapshot, tenant_id):
# Custom restore logic (z.B. IMAP-MOVE, Disk-File-Check)
...
register_restore_handler("my_plugin_entity", my_restore_handler)
```
5. **Cascade-Dependencies definieren** — wenn das Plugin Parent-Child-Beziehungen hat:
```python
from app.core.entity_registry import register_cascade
register_cascade("my_plugin_parent", "my_plugin_child", fk_field="parent_id")
# Parent-Restore → alle soft-deleted Children werden mit wiederhergestellt
```
**Was ein Plugin NICHT tun darf (Verboten):**
- ❌ Eigene History-Tabellen erstellen (z.B. `MyPluginEditHistory`)
- ❌ Eigene Version-Tabellen erstellen (z.B. `MyPluginVersion`)
- ❌ Eigene Restore-Logik implementieren (stattdessen Restore-Handler registrieren)
- ❌ `log_audit()` für Snapshots nutzen (AuditLog ist nur Compliance-Trail)
- ❌ Hard-Delete ohne `?gdpr=true` Parameter
**Plugin-Manifest-Erweiterung:**
Das Plugin-Manifest bekommt ein neues Feld `history_config`:
```python
class PluginManifest(BaseModel):
history_config: HistoryConfig = Field(default_factory=HistoryConfig)
class HistoryConfig(BaseModel):
entities: list[str] = Field(default_factory=list) # entity_type names
custom_restore_handlers: bool = Field(default=False)
cascade_dependencies: list[dict] = Field(default_factory=list)
retention_days: int = Field(default=90)
```
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| U-PD-REG | **Entity Registry API** — `register_entity()`, `register_restore_handler()`, `register_cascade()` implementieren | 1 Tag |
| U-PD-HOOK | **Auto-Hook-Integration** — Hooks die automatisch record_history aufrufen für registrierte Entities | 1 Tag |
| U-PD-DOC | **Plugin-Dev-Guide Update** — `docs/plugin-development-guide.md` mit Undo/Restore-Kapitel erweitern | 1 Tag |
| U-PD-MANIFEST | **Manifest-Erweiterung** — `history_config` Feld in PluginManifest hinzufügen | 0.5 Tage |
| U-PD-EXAMPLE | **Beispiel-Plugin** — Referenz-Plugin das zeigt wie History/Undo/Restore korrekt implementiert wird | 1 Tag |
| U-PD-TEST | **Plugin-Dev-Tests** — Test-Suite die prüft ob ein Plugin die Undo/Restore-Konventionen einhält | 1 Tag |
---
## Phase 0.8 — Frontend-Konsolidierung & UI-System
**Dauer:** 5 Wochen
**Ziel:** Einheitliches UI-System mit Standard-Komponenten für Plugins, globalem Template-System (Farben, Schriftart, Größe), und Bereinigung aller Regelverletzungen (inline styles, any types, class components, hardcoded strings, dangerouslySetInnerHTML).
**Begründung:** Das Frontend ist größtenteils gut strukturiert (TanStack Query, Zustand, i18n, ARIA, ErrorBoundary), aber es gibt 6 klare Probleme: 96 inline styles, 360 any types, 3 class components, 3 dangerouslySetInnerHTML, 23 hardcoded strings, und fehlendes Plugin-UI-Loading-System. Plugins brauchen Standard-Komponenten und ein Template-System damit die UI vereinheitlich wird.
### 0.8.1 Code-Bereinigung — Regelverletzungen entfernen
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| F-CL-INLINE | **Inline Styles entfernen** — alle 96 `style={}` durch Tailwind-Klassen ersetzen | 2 Tage |
| F-CL-ANY | **any Types entfernen** — alle 360 `: any` / `as any` durch korrekte TypeScript-Types ersetzen | 3 Tage |
| F-CL-CLASS | **Class Components entfernen** — alle 3 class components in functional components umschreiben | 0.5 Tage |
| F-CL-DANGEROUS | **dangerouslySetInnerHTML** — alle 3 Verwendungen prüfen: DOMPurify-Sanitization sicherstellen oder entfernen | 0.5 Tage |
| F-CL-STRINGS | **Hardcoded Strings** — alle 23 hardcoded Strings durch `t()` ersetzen | 1 Tag |
| F-CL-LINT | **ESLint-Strict-Config** — eslint-config auf strict setzen (no-inline-styles, no-any, no-class-components, no-dangerouslySetInnerHTML, no-hardcoded-strings). CI-Pipeline prüft automatisch | 1 Tag |
| F-CL-PWA | **PWA Service Worker** — SW ist aktuell deaktiviert (main.tsx unregister). Entweder reaktivieren mit korrektem Cache-Strategy oder PWA komplett entfernen | 0.5 Tage |
| F-CL-A11Y | **Accessibility ergänzen** — sr-only Texte für Screen-Reader ergänzen (Button-Beschreibungen, Status-Updates, ARIA-Live-Regions). Aktuell nur 4 sr-only — sollte deutlich mehr sein | 1 Tag |
### 0.8.2 Standard-Komponenten-Bibliothek für Plugins
Plugins sollen Standard-Komponenten nutzen können (aber nicht müssen). Diese Bibliothek stellt einheitliche UI-Bausteine zur Verfügung die das CRM-Theme automatisch nutzen.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| F-SC-AUDIT | **Bestandsaufnahme** — alle bestehenden UI-Komponenten (`components/ui/`) und Shared-Komponenten (`components/shared/`) dokumentieren: welche gibt es, welche fehlen, welche inkonsistent sind | 1 Tag |
| F-SC-CORE | **Core-Komponenten vereinheitlichen** — Button, Input, Select, Modal, Table, Card, Badge, Avatar, Pagination, Skeleton, Toast, ConfirmDialog auf einheitliche API bringen. Props standardisieren. Varianten (primary, secondary, danger, ghost) definieren | 2 Tage |
| F-SC-FORM | **Form-Komponenten** — FormField, FormInput, FormSelect, FormCheckbox, FormRadio, FormTextarea, FormDatePicker, FormFileUpload — alle mit React Hook Form + Zod Integration, automatische Error-Anzeige, Label/Helper-Text | 2 Tage |
| F-SC-DATA | **Data-Komponenten** — DataGrid (sortierbar, filterbar, paginierbar), DataList, DataCard, DataTimeline — mit TanStack Query Integration, automatisches Loading/Error/Empty-State | 2 Tage |
| F-SC-LAYOUT | **Layout-Komponenten** — PageHeader, PageContent, Sidebar, TabBar, Breadcrumb, Toolbar — einheitliche Seitenstruktur | 1 Tag |
| F-SC-ENTITY | **Entity-Komponenten** — EntityDetailLayout (Tabs, Sidebar, Header), EntityListLayout, EntityFormLayout — Standard-Layouts für CRM-Entitäten | 1.5 Tage |
| F-SC-AI | **AI-Komponenten** — ChatBubble, ToolCallDisplay, AgentStatusBadge, SuggestionCard, AIProgressIndicator — für KI-Features | 1 Tag |
| F-SC-SEARCH | **Search-Komponenten** — SearchBar, SearchResults, SearchFacets, SearchFilters — für Unified Search | 1 Tag |
| F-SC-EXPORT | **Export-Komponenten** — ExportButton, ImportDialog, CsvPreview — für Import/Export | 0.5 Tage |
| F-SC-DOCS | **Komponenten-Dokumentation** — Storybook oder Markdown-Doku für alle Standard-Komponenten mit Props, Beispielen, Live-Preview | 2 Tage |
### 0.8.3 Template-System (Globale Theme-Einstellungen)
Ein Template-System das globale Einstellungen für Farben, Schriftart, Größe etc. ermöglicht — konfigurierbar über Admin-Settings, gespeichert in SystemSettings, angewendet via CSS Custom Properties.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| F-TS-CSS | **CSS Custom Properties System** — alle Theme-Werte als CSS Custom Properties (`--color-primary`, `--color-secondary`, `--font-family`, `--font-size-base`, `--border-radius`, `--spacing-unit`, etc.). Tailwind nutzt diese Variablen | 1 Tag |
| F-TS-SETTINGS | **Theme-Settings Model** — SystemSettings erweitern mit `theme_config` JSONB: primary_color, secondary_color, accent_color, danger_color, success_color, warning_color, font_family, font_size_base, border_radius, spacing_unit, sidebar_width, content_max_width | 1 Tag |
| F-TS-ADMIN | **Admin Theme-Editor UI** — Settings-Seite mit Color-Picker, Font-Selector, Size-Slider, Live-Preview. Änderungen werden sofort angewendet (CSS-Variablen aktualisieren) | 2 Tage |
| F-TS-PRESET | **Theme-Presets** — vorgefertigte Themes (Default, Dark, Compact, Large, High-Contrast, Brand-Custom). Admin kann Preset wählen und anpassen | 1 Tag |
| F-TS-DARK | **Dark Mode Integration** — Dark Mode nutzt dieselben CSS-Variablen mit anderen Werten. Toggle in Settings + System-Preference-Detection | 1 Tag |
| F-TS-PLUGIN | **Plugin-Theme-Access** — Plugins können Theme-Werte lesen: `useTheme()` Hook gibt aktuelle Theme-Config. Standard-Komponenten nutzen Theme automatisch | 0.5 Tage |
| F-TS-PUBLIC | **Public-Page-Theme** — öffentliche Plugin-Seiten können CRM-Theme nutzen oder eigenes Theme (siehe 0.7.11) | 0.5 Tage |
| F-TS-RESP | **Responsive Breakpoints** — einheitliche Breakpoints (sm, md, lg, xl, 2xl) in Tailwind Config. Standard-Komponenten nutzen diese Breakpoints | 0.5 Tage |
### 0.8.4 Plugin-UI-Loading-System
Aktuell ist `frontend/src/plugins/` leer — das Plugin-UI-Loading-System fehlt oder ist woanders. Plugins müssen ihre Frontend-Komponenten (Pages, Tabs, Widgets, Settings) dynamisch laden können.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| F-PL-REG | **Plugin-UI-Registry** — zentrale Registry die Plugin-Frontend-Komponenten verwaltet: MenuItems, PageRoutes, DetailTabs, SettingsPages, DashboardWidgets. Lädt Manifest vom Backend und registriert Komponenten | 2 Tage |
| F-PL-LOAD | **Dynamic Component Loading** — React.lazy + Suspense für Plugin-Komponenten. ErrorBoundary pro Plugin-Komponente (ein fehlerhaftes Plugin bricht nicht die ganze UI) | 1 Tag |
| F-PL-CACHE | **Component-Cache** — geladene Plugin-Komponenten cachen (nicht bei jedem Render neu laden). Cache invalidation bei Plugin-Update | 0.5 Tage |
| F-PL-SANDBOX | **Plugin-Sandbox** — Plugin-Komponenten laufen in isoliertem Context (eigener ErrorBoundary, eigener State-Scope). Plugins können Core-State lesen aber nicht direkt mutieren | 1 Tag |
| F-PL-MANIFEST | **Manifest-Driven UI** — Frontend liest Plugin-Manifest vom Backend und baut Menu/Pages/Tabs/Widgets dynamisch auf. Keine hardcoded Plugin-Imports im Frontend | 1 Tag |
| F-PL-THEME | **Plugin-Theme-Integration** — Plugin-Komponenten nutzen automatisch CRM-Theme (CSS-Variablen). Plugins können Standard-Komponenten nutzen | 0.5 Tage |
| F-PL-DEV | **Plugin-Dev-Guide (Frontend)** — wie Plugins Frontend-Komponenten erstellen: Standard-Komponenten nutzen, Manifest deklarieren, Theme respektieren, i18n nutzen | 1 Tag |
### 0.8.5 Frontend-Regeln (verbindlich)
Diese Regeln werden in `AGENTS.md` und `docs/ui-design-guidelines.md` als verbindlich dokumentiert und durch ESLint-Config + CI-Pipeline durchgesetzt:
| Regel | Beschreibung | Durchsetzung |
|---|---|---|
| **Tailwind only** | Keine inline styles. Alle Styles als Tailwind-Klassen oder CSS-Variablen | ESLint: no-inline-styles |
| **TypeScript strict** | Keine `any` types. Alle Props und States haben explizite Types | ESLint: no-explicit-any |
| **Functional components only** | Keine class components. React Hooks statt Lifecycle-Methods | ESLint: no-class-components |
| **i18n for all strings** | Keine hardcoded Strings. Alle Texte via `t()` aus react-i18next | ESLint: no-hardcoded-strings |
| **ARIA on interactive elements** | Alle interaktiven Elemente haben ARIA-Attribute. 44px touch targets | ESLint: jsx-a11y |
| **TanStack Query for server state** | Server-Daten via useQuery/useMutation. Kein manuelles fetch/axios in Komponenten | Code-Review |
| **Zustand for client state only** | Keine Server-Daten in Zustand. Zustand nur für UI-State, Theme, Auth, Preferences | Code-Review |
| **React Hook Form + Zod** | Alle Forms nutzen useForm + zodResolver. Keine manuelle Form-Validierung | Code-Review |
| **Standard-Komponenten bevorzugt** | Plugins sollen Standard-Komponenten nutzen (Button, Input, Modal, etc.) wenn möglich | Code-Review |
| **Theme via CSS-Variablen** | Farben, Fonts, Größen via CSS Custom Properties. Keine hardcoded Farben in Komponenten | ESLint: no-hardcoded-colors |
| **ErrorBoundary pro Plugin** | Jedes Plugin hat eigenen ErrorBoundary. Plugin-Fehler bricht nicht die ganze UI | Code-Review |
| **dangerouslySetInnerHTML verboten** | Außer mit DOMPurify-Sanitization | ESLint: no-danger |
**Deliverables:** Bereinigtes Frontend (0 inline styles, 0 any types, 0 class components, 0 hardcoded strings), Standard-Komponenten-Bibliothek für Plugins, globales Template-System (Farben, Schriftart, Größe konfigurierbar), Plugin-UI-Loading-System (dynamisch, manifest-driven, sandboxed), verbindliche Frontend-Regeln in AGENTS.md und ESLint-Config.
**Dauer:** 4 Wochen
**Ziel:** Eine einzige vereinheitlichte Suche über ALLES — alle Entitäten, alle Such-Modi (FTS, Vector, RAG, Graph), selbstständige Hintergrund-Indexierung, KI-voll-nutzbar (Tool, MCP, API). Alle fragmentierten Such-Systeme werden konsolidiert.
**Begründung:** Genau wie bei History gibt es fragmentierte Such-Systeme. Unified Search Plugin ist gut (10 Provider, RRF Fusion, LLM Query-Understanding, pgvector), aber Mail/DMS/Tasks haben eigene ILIKE-Suchen, Agent Memory hat eigene Vector-Suche, AI-Chats/Workflows/Agenten/AuditLog sind gar nicht suchbar. Das muss vereinheitlicht werden — ein System, ein Index, eine API, für alles.
### Aktueller State
| System | Status |
|---|---|
| Unified Search Plugin | ✅ 10 Provider, RRF Fusion (FTS+Vector), LLM Query-Understanding, pgvector |
| Mail eigene Suche | ❌ Eigene ILIKE-Suche in mail/routes.py, nicht unified |
| DMS eigene Suche | ❌ Eigene ILIKE-Suche in dms/routes.py, nicht unified |
| Tasks inline search | ❌ Query-Parameter, keine Vektorsuche |
| Agent Memory Suche | ❌ Eigene pgvector-Suche, nicht unified |
| GraphRAG Suche | ✅ Schon als SearchProvider registriert |
| Kommunikation Suche | 🟡 Registriert, aber auch eigene search() Methode |
| AI Chats (Session/Message) | ❌ Gar nicht suchbar |
| AI Copilot (Conversation/Message) | ❌ Gar nicht suchbar |
| Workflows | ❌ Nicht suchbar |
| Agenten (Definitions/Runs) | ❌ Nicht suchbar |
| AuditLog | ❌ Nicht suchbar |
| EntityHistory | ❌ Nicht suchbar |
| Auto-Indexierung | ❌ Nicht vorhanden — Embeddings werden nicht automatisch aktualisiert |
| KI-Nutzbarkeit | 🟡 AI Proactive nutzt unified_search, aber kein MCP-Exposure |
### 1.0 Konsolidierung & Rückbau
Alle fragmentierten Such-Systeme werden in das Unified Search Plugin migriert. Nach Phase 1 gibt es nur noch **ein** Such-System.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| S-K-MAIL | **Mail-Suche migrieren** — `mail/routes.py:search_mails()` eigene ILIKE-Suche entfernen, MailSearchProvider erweitern, Mail-Routen leiten auf Unified Search um | 1 Tag |
| S-K-DMS | **DMS-Suche migrieren** — `dms/routes.py:search_files()` eigene ILIKE-Suche entfernen, FileSearchProvider erweitern, DMS-Routen leiten auf Unified Search um | 1 Tag |
| S-K-TASKS | **Tasks-Suche migrieren** — inline search-Parameter durch Unified Search ersetzen, TaskSearchProvider erweitern | 0.5 Tage |
| S-K-MEM | **Agent Memory Suche migrieren** — eigene pgvector-Suche in agent_memory/routes.py entfernen, als SearchProvider in Unified Search registrieren | 1 Tag |
| S-K-COMM | **Kommunikation Suche bereinigen** — eigene search() Methode entfernen, nur noch über SearchProvider | 0.5 Tage |
| S-K-DEPREC | **Deprecated Routes entfernen** — alle alten /search Endpoints in Mail/DMS/Tasks durch Redirect auf /api/v1/search ersetzen | 0.5 Tage |
### 1.1 Universal Search Providers — ALLE Entitäten
Jede Entität im System muss suchbar sein. Neue Provider für alle fehlenden Entitäten.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| S-P-AI-CHAT | **AI Chat Search Provider** — AIChatSession (Titel), AIChatMessage (Content, Tool-Calls, Tool-Results) — Vektorsuche über Chat-Inhalte | 1 Tag |
| S-P-AI-COPILOT | **AI Copilot Search Provider** — AIConversation (Titel), AIMessage (Content, Proposed Actions, Execution Results) | 0.5 Tage |
| S-P-COMM | **Kommunikation Messages Provider** — CommMessage (Content, Blocks), CommConversation (Titel) — bereits registriert, prüfen/erweitern | 0.5 Tage |
| S-P-WF | **Workflow Search Provider** — Workflow (Name, Steps), WorkflowInstance (Status, Step-History) | 0.5 Tage |
| S-P-AGENT | **Agent Search Provider** — AgentDefinition (Name, System-Prompt, Tools), AgentRun (Status, Result, Cost) | 0.5 Tage |
| S-P-AUDIT | **AuditLog Search Provider** — AuditLog (Action, Entity-Type, Changes) | 0.5 Tage |
| S-P-HIST | **EntityHistory Search Provider** — EntityHistory (Action, Entity-Type, Snapshot-Fields) | 0.5 Tage |
| S-P-AUTO | **Automation Search Provider** — AutomationDefinition (Name, Trigger, Actions), AutomationRun (Status) | 0.5 Tage |
| S-P-GRAPH | **GraphRAG Provider erweitern** — EntityRelationship (Type, Source, Target, Metadata) — bereits registriert, prüfen/erweitern | 0.5 Tage |
| S-P-SETTINGS | **Settings/System Search Provider** — SystemSettings, AIProvider, AIModel, AIPreset (für Admin-Suche) | 0.5 Tage |
### 1.2 Selbstständige Hintergrund-Indexierung
Die Suche muss sich selbst aktualisieren. Wenn eine Entität erstellt/geändert/gelöscht wird, wird automatisch re-indexiert — ohne manuellen Eingriff.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| S-IX-EVT | **Event-getriebene Auto-Indexierung** — Event Bus Listener für alle CRUD-Events (entity.created, entity.updated, entity.deleted) → ARQ Re-Embedding Job | 1.5 Tage |
| S-IX-HOOK | **Hook-basierte Indexierung** — `do_action('entity.after_create/after_update/after_delete')` Hooks die Auto-Indexierung triggern (wie bei History) | 1 Tag |
| S-IX-QUEUE | **Indexierungs-Queue** — ARQ-Queue mit Prioritäten (Create/Update = normal, Delete = high), Rate-Limit (nicht DB überlasten), Batch-Verarbeitung | 1 Tag |
| S-IX-BATCH | **Batch-Reindex** — CLI-Kommando + API-Endpoint für initiale/manuelle Re-Embedding aller Entitäten (z.B. nach Model-Wechsel) | 0.5 Tage |
| S-IX-DEL | **Delete-Handling** — bei Soft-Delete: Embedding behalten aber als deleted markieren. Bei Hard-Delete (?gdpr=true): Embedding löschen | 0.5 Tage |
| S-IX-MON | **Indexierungs-Monitoring** — Stats: wie viele Entitäten indexiert, wie viele pending, letzte Indexierung, Fehler-Rate | 0.5 Tage |
| S-IX-RETRY | **Retry-Logic** — fehlgeschlagene Indexierungs-Jobs automatisch wiederholen (3x mit Backoff) | 0.5 Tage |
### 1.3 Multi-Mode Search — FTS + Vector + RAG + Graph
Die Suche muss mehrere Such-Modi unterstützen und diese fusionieren.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| S-MM-FTS | **Full-Text-Search** — PostgreSQL tsvector/tsquery für alle Entitäten (bereits vorhanden für 4, auf alle erweitern) | 1 Tag |
| S-MM-VEC | **Vector/Embedding Search** — pgvector cosine similarity für alle Entitäten (bereits vorhanden, auf alle Provider erweitern) | 1 Tag |
| S-MM-RAG | **RAG-Search** — Document-Chunk-Retrieval für DMS-Dokumente (Chunk → Embedding → Query → Top-K) — wird in Phase 4 vertieft, aber Basis hier | 1 Tag |
| S-MM-GRAPH | **Graph-Traversal Search** — GraphRAG BFS-Traversal als Such-Modus ("Zeige mir alle Kontakte die mit Firma X verbunden sind") | 1 Tag |
| S-MM-FUSE | **RRF Fusion erweitern** — Reciprocal Rank Fusion über FTS + Vector + Graph (aktuell nur FTS+Vector) | 1 Tag |
| S-MM-LLM | **LLM Query Understanding** — bereits vorhanden (Intent, Entities, Semantic Terms), erweitern für neue Entitätstypen | 0.5 Tage |
| S-MM-AGG | **LLM Result Aggregation** — bereits vorhanden (Summary, Facets, Suggestions), erweitern für neue Entitätstypen | 0.5 Tage |
### 1.4 KI-Nutzbarkeit — Tool, MCP, API
Die Suche muss für KI-Systeme voll nutzbar sein — als internes Tool, über MCP, und über API.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| S-KI-TOOL | **AI Tool Registry** — `unified_search` als Tool in der ToolRegistry registrieren (OpenAI Function-Calling Schema). Agenten können suchen. | 1 Tag |
| S-KI-MCP | **MCP-Server Exposure** — Suche als MCP-Tool exposed (`search`, `find_similar`, `suggest`, `reindex`). Externe KI-Systeme können über MCP suchen. | 1.5 Tage |
| S-KI-API | **Search API** — REST API für Suche (`/api/v1/search`), bereits vorhanden, erweitern mit Filter-Parametern für alle Entitätstypen | 0.5 Tage |
| S-KI-CTX | **Context-Aware Search** — Suche mit User-Kontext (Tenant, Permissions, Visibility-Filter). KI sieht nur was der User sehen darf. | 1 Tag |
| S-KI-SIM | **Find-Similar** — "Ähnliche Entitäten finden" — bereits vorhanden, erweitern auf alle Entitätstypen | 0.5 Tage |
| S-KI-SUGG | **Search Suggestions** — Auto-Complete, Query-Suggestions, "Meintest du...?" | 0.5 Tage |
### 1.5 Search UI
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| S-UI-CMD | **Command Palette** (Cmd+K / Ctrl+K) — globale Suchleiste wie Raycast/Spotlight, öffnet über Tastatur, sucht über alle Entitäten | 2 Tage |
| S-UI-FAC | **Facetten-Filter** — Type (Contact, Mail, DMS, Task, Chat, Workflow, Agent, ...), Date Range, People, Tags, Tenant | 1 Tag |
| S-UI-PRE | **Result-Preview-Cards** — Entity-Icon, Snippet mit Highlight, Type-Badge, Relevance-Score | 1 Tag |
| S-UI-NAV | **Click-through** — Klick auf Result → Entity-Detail-Ansicht (oder Chat-Verlauf, Workflow-Instanz, etc.) | 0.5 Tage |
| S-UI-REC | **Recent + Saved Searches** — letzte Suchen speichern, Saved Searches mit Namen | 0.5 Tage |
| S-UI-ADV | **Advanced Search** — erweiterte Suche mit Filter-Konstruktor (Type, Date, Owner, Tags, Custom Fields) | 1 Tag |
| S-UI-STATS | **Search Stats UI** — Indexierungs-Status, Provider-Übersicht, Such-Statistiken | 0.5 Tage |
### 1.6 Plugin-Dev-Guide: Search
Genau wie bei History: Plugins müssen wissen wie sie Search implementieren.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| S-PD-PROV | **SearchProvider API** — `register_search_provider()` für Plugins: Provider registriert entity_type, FTS-Column, Embedding-Column, get_embedding_text() | 1 Tag |
| S-PD-AUTO | **Auto-Registration** — Plugin-Manifest `search_config` Feld: Plugins deklarieren welche Entitäten suchbar sind, System registriert automatisch Provider + Hooks | 1 Tag |
| S-PD-DOC | **Plugin-Dev-Guide Update** — `docs/plugin-development-guide.md` mit Search-Kapitel erweitern | 0.5 Tage |
| S-PD-TEST | **Plugin-Dev-Tests** — Test-Suite die prüft ob ein Plugin die Search-Konventionen einhält | 0.5 Tage |
**Deliverables:** Eine vereinheitlichte Such-Plattform über alle Entitäten (Core + Plugins + AI Chat + Workflows + Agenten + AuditLog + EntityHistory), mit FTS + Vector + RAG + Graph Such-Modi, selbstständiger Hintergrund-Indexierung, KI-Nutzbarkeit (Tool, MCP, API), Command-Palette UI, und Plugin-Dev-Guide. Alle fragmentierten Such-Systeme sind konsolidiert und rückgebaut.
---
## Phase 2 — Autonomous Agent Engine (ReAct-Loop)
**Dauer:** 6 Wochen
**Ziel:** Autonome KI-Agenten, die CRM-Workflows selbstständig ausführen können
**Begründung:** Kernstück der Plattform-Vision. Die Infrastruktur (Agent Runner, Coordinator, Tool Registry, CRM API Tool, Scheduler, Memory) existiert. Die ReAct-Loop fehlt.
### 2.1 ReAct Agent Loop
Die zentrale Komponente: Ein Agent-Loop nach dem ReAct-Pattern (Reason → Act → Observe → Repeat), der LiteLLM Function-Calling nutzt.
```
User/Trigger → Agent Loop:
1. System Prompt + Context + Tools → LLM
2. LLM responds with: text + tool_calls
3. Execute tool_calls via ToolRegistry
4. Append tool results to conversation
5. If tool_calls present → goto 1 (next iteration)
6. If no tool_calls → agent is done, return final answer
7. Safety checks after each iteration (max_steps, budget, timeout)
```
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| A-LOOP | `agent_loop.py` — ReAct-Loop mit LiteLLM `acompletion()` + `tools=` Parameter | 3 Tage |
| A-CALL | Tool-Call-Parser — extrahiert function_calls aus LLM-Response, ruft ToolRegistry auf | 1 Tag |
| A-CTX | Context-Builder — sammelt System-Prompt, Agent-Definition, Memory, CRM-API-Spec, Tool-Schemas | 2 Tage |
| A-MAX | Max-Steps-Limit (z.B. 20 Iterationen) + Graceful-Stop mit Zusammenfassung | 0.5 Tage |
| A-ERR | Error-Handling: Tool-Fehler → LLM bekommt Error-Message, kann adaptieren | 1 Tag |
| A-STR | Streaming: SSE-Stream von Agent-Reasoning + Tool-Calls für UI | 1 Tag |
### 2.2 Agent-Definition & Management
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| A-DEF | AgentDefinition CRUD API — erweitert bestehende automation/agent_routes.py | 1 Tag |
| A-TOOL | Tool-Binding — Agent definiert welche Tools er nutzen darf (Subset aus ToolRegistry) | 1 Tag |
| A-PERM | Permission-Context — Agent agiert im Kontext eines Users (RBAC wird geprüft pro Tool-Call) | 1 Tag |
| A-MEM | Memory-Integration — Agent nutzt agent_memory Plugin für persistente Erinnerungen | 1 Tag |
| A-HEART | Heartbeat — proactive Agenten pollen regelmäßig Kontext und generieren Vorschläge | 1 Tag |
### 2.3 Agent UI
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| A-LIST | Agent-Liste — alle Agenten mit Status, letzter Run, Kosten. **Kartenansicht und Listenansicht** (Toggle zwischen Grid-Cards und Table-List). Karten zeigen: Name, Beschreibung, Status-Badge, Modell, letzte Aktivität, Kosten-Summe. Liste zeigt: alle Spalten sortierbar/filterbar | 1.5 Tage |
| A-EDIT | Agent-Editor — System-Prompt, Modell, Tools, Limits, Trigger konfigurieren | 2 Tage |
| A-CHAT | Agent-Chat-UI — interaktive Konversation mit Agent (wie AI Copilot, aber mit Tool-Calls) | 2 Tage |
| A-LOG | Agent-Run-Log — Step-by-Step Reasoning-Trace, Tool-Calls, Results, Kosten | 1 Tag |
| A-MON | Agent-Monitoring — Live-Status, aktive Runs, Queue, Budget-Verbrauch | 1 Tag |
### 2.4 Pre-Built Agenten
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| A-EMAIL | E-Mail-Triage-Agent — liest Inbox, kategorisiert, schlägt Antworten vor, erstellt Tasks | 2 Tage |
| A-CONTACT | Contact-Enrichment-Agent — sucht fehlende Daten, dedupliziert, aktualisiert | 1 Tag |
| A-FOLLOW | Follow-up-Agent — erinnert an unbeantwortete Mails, schlägt Follow-ups vor | 1 Tag |
| A-REPORT | Report-Agent — generiert wöchentliche Zusammenfassungen, Dashboards | 1 Tag |
### 2.5 Guardrails & Safety
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| A-APPR | Approval-Pipeline — destruktive Aktionen (DELETE, bulk UPDATE) erfordern User-Approval | 2 Tage |
| A-DRY | Dry-Run-Mode — Agent plant Aktionen, führt aber nichts aus (nur Vorschläge) | 0.5 Tage |
| A-REV | Reversibility-Check — Agent prüft ob Aktion umkehrbar ist vor Ausführung | 1 Tag |
| A-AUDIT | Audit-Log für jeden Tool-Call (wer, was, wann, result, cost) | 1 Tag |
### 2.6 KI-Agent Permission-Integration
KI-Agenten müssen wie User behandelt werden und vollständig ins Rechte-System integriert werden. Aktuell nutzt der Agent Runner nur `tenant_id` — kein `user_id`, kein Permission-Kontext. Das muss sich ändern.
**Prinzip:** Jeder Agent agiert im Kontext eines Users. Jeder Tool-Call wird gegen die Permissions dieses Users geprüft. Ein Agent kann niemals mehr als sein User darf.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| A-PERM-CTX | **Agent Permission Context** — AgentDefinition bekommt `acting_user_id` Feld. Agent agiert im Kontext dieses Users. Permission-Resolution wird beim Agent-Start geladen (wie bei normalem User-Login) | 1 Tag |
| A-PERM-CHECK | **RBAC pro Tool-Call** — jeder Tool-Call wird gegen `check_permission(user_context, required_permission)` geprüft. Tool hat `required_permission` (bereits im ToolRegistry). Agent darf Tool nur aufrufen wenn User die Permission hat | 1 Tag |
| A-PERM-VIS | **Visibility-Filter** — Agent-Queries (z.B. "zeige alle Kontakte") werden mit `apply_visibility_filter()` gefiltert. Agent sieht nur was der User sehen darf | 1 Tag |
| A-PERM-ENTITY | **Entity-Level-Permissions** — Agent respektiert EntityPermission (ABAC). Wenn User nur Read-Zugriff auf Kontakt X hat, kann Agent Kontakt X nicht ändern | 1 Tag |
| A-PERM-ROLE | **Agent-Rollen** — AgentDefinition kann eine Rolle zugewiesen bekommen (z.B. "read-only-agent", "mail-agent"). Rolle definiert welche Tools/Permissions der Agent nutzen darf — unabhängig vom User | 1 Tag |
| A-PERM-AUDIT | **Permission-Audit-Trail** — jeder Permission-Check wird geloggt: Agent-ID, User-ID, Tool, Required-Permission, Granted/Denied. Nachvollziehbar wer was erlaubt hat | 0.5 Tage |
| A-PERM-ESCAL | **Escalation-Prevention** — Agent kann keine Permissions eskalieren. Kein Tool-Call der Permissions ändert (roles:write, permissions:write) ohne User-Approval | 0.5 Tage |
| A-PERM-UI | **Permission-UI im Agent-Editor** — Admin sieht welche Permissions der Agent braucht, kann sie genehmigen/entziehen. Permission-Matrix pro Agent | 1 Tag |
| A-PERM-VIS-USER | **User-Agent Visibility** — User sehen nur Agenten die für sie freigeschaltet sind. Nutzt bestehendes Rechte-System: `agents:read` Permission + EntityPermission mit `entity_type='agent_definition'`. Admin kann Agenten für bestimmte User/Gruppen freischalten. KEIN extra Bauten — alles über bestehendes RBAC/ABAC | 1 Tag |
| A-PERM-USE | **User-Agent Usage Permission** — User können nur Agenten benutzen die für sie freigeschaltet sind. `agents:execute` Permission pro Agent. Agent-Chat-UI prüft Permission vor Start. KEIN extra System — über bestehendes `require_permission()` | 0.5 Tage |
**Deliverables:** Funktionierende autonome Agenten mit ReAct-Loop, Tool-Calling, Memory, Guardrails, UI für Definition/Monitoring/Chat, 4 Pre-Built Agenten.
---
## Phase 3 — Workflow Platform (n8n-Ersatz)
**Dauer:** 6 Wochen
**Ziel:** Visuelle Workflow-Engine die n8n ersetzt — tief in das CRM integriert
**Begründung:** Die Workflow-Engine (action/approval/notification/condition) und das Automation-Plugin (execution_engine, scheduler, cron) existieren. Es fehlen: visuelle Editor, erweiterte Step-Types, Integration-Nodes.
### 3.1 Erweiterte Step-Types
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| W-LOOP | Loop-Step — iteriere über Array/Query-Result | 1 Tag |
| W-PAR | Parallel-Branch — mehrere Steps gleichzeitig ausführen | 1 Tag |
| W-WAIT | Wait/Delay-Step — pausiert für Duration oder bis Datum | 0.5 Tage |
| W-WEB | Webhook-Trigger-Step — externer HTTP-Call startet Workflow | 1 Tag |
| W-CODE | Code-Step — sichere Ausführung von Python/JS-Snippet (Sandbox) | 2 Tage |
| W-AGENT | Agent-Step — ruft autonomen Agenten auf (Phase 2 Integration) | 1 Tag |
| W-TRANS | Transform-Step — Daten-Transformation (Mapping, Filter, Aggregation) | 1 Tag |
### 3.2 Integration-Nodes
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| W-HTTP | HTTP-Request-Node — generischer REST-Aufruf (wie n8n HTTP Request) | 1 Tag |
| W-DB | DB-Query-Node — SQL-Query ausführen (tenant-scoped, read-only default) | 1 Tag |
| W-MAIL | Mail-Send-Node — E-Mail über CRM-Mail-Plugin senden | 0.5 Tage |
| W-CAL | Calendar-Node — Termine erstellen/lesen | 0.5 Tage |
| W-DMS | DMS-Node — Dokumente hochladen/metadaten aktualisieren | 0.5 Tage |
| W-AI | AI-Node — LLM-Call (einzelner Prompt, nicht voller Agent) | 0.5 Tage |
| W-SEARCH | Search-Node — Unified Search als Workflow-Step | 0.5 Tage |
| W-SLACK | Webhook-Node — Slack/Teams/Discord Notification via Webhook | 0.5 Tage |
### 3.3 Workflow-Editor (Hybrid: Form + JSON)
Statt eines visuellen Drag-and-Drop-Canvas (wie n8n) wird ein form-basierter Editor mit JSON-Expert-Mode gebaut. Spart 3.5 Tage, ist schneller fertig, und ein visueller Editor kann später nachgerüstet werden.
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| W-FORM | Form-basierter Step-Editor — Step-Liste mit Up/Down-Reihenfolge, Formular pro Step-Typ | 2 Tage |
| W-JSON | JSON-Expert-Mode — Toggle zwischen Form und JSON-Editor (Monaco/CodeMirror) | 0.5 Tage |
| W-VALID | Validation — Required-Field-Check, Type-Compatibility, Step-Reihenfolge-Check | 0.5 Tage |
| W-EXPORT | JSON-Export/Import — Workflow als JSON speichern/laden (Versionierung) | 0.5 Tage |
| W-TEMPL | Template-Gallery — vorgefertigte Workflows zum Importieren | 1 Tag |
### 3.4 Workflow-Execution-Erweiterung
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| W-ENG | Engine-Erweiterung — neue Step-Types in workflow engine.py integrieren | 2 Tage |
| W-CTX | Execution-Context — Daten-Flow zwischen Steps (Variablen, Expressions) | 2 Tage |
| W-RETRY | Retry-Logic — fehlgeschlagene Steps automatisch wiederholen | 1 Tag |
| W-TIME | Timeout-Handling — pro-Step Timeout mit konfigurierbarer Aktion | 0.5 Tage |
| W-LOG | Execution-Log — detailliertes Logging pro Step (Input, Output, Duration, Status) | 1 Tag |
### 3.5 Trigger-System
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| W-EVT | Event-Trigger — CRM-Event startet Workflow (contact.created, mail.received, etc.) | 1 Tag |
| W-CRON | Cron-Trigger — zeitgesteuerte Ausführung (bestehender scheduler erweitern) | 0.5 Tage |
| W-MAN | Manual-Trigger — Button in UI startet Workflow | 0.5 Tage |
| W-WEB2 | Webhook-Trigger — externe Systeme starten Workflow via HTTP | 1 Tag |
| W-AGT | Agent-Trigger — Agent startet Workflow als Teil seiner Tool-Calls | 1 Tag |
**Deliverables:** Vollständige Workflow-Plattform mit visuellem Editor, 7+ Step-Types, 8+ Integration-Nodes, Event/Cron/Webhook/Manual-Triggers, Execution-Logging, Template-Gallery.
---
## Phase 4 — Knowledge Management & RAG
**Dauer:** 6 Wochen
**Ziel:** Komplettes Wissensmanagement — Wissensgraph, Document-RAG, Wiki, automatische Relationship-Extraktion
**Begründung:** GraphRAG, DMS, Unified Search und Agent Memory sind vorhanden. Es fehlen: Document-RAG-Pipeline, automatische Wissensgraph-Extraktion, Wiki-System, Knowledge-UI.
### 4.1 Document-RAG-Pipeline
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| K-CHUNK | Document-Chunking — DMS-Dokumente in semantische Chunks zerlegen | 1 Tag |
| K-EMB | Chunk-Embedding — pgvector Embeddings pro Chunk (ARQ Background Job) | 1 Tag |
| K-RET | Retrieval-Pipeline — Query → Semantic Search über Chunks → Top-K Results | 1 Tag |
| K-GEN | Generation-Pipeline — Chunks + Query → LLM → Antwort mit Quellenangabe | 1 Tag |
| K-INDEX | Index-Management — Re-Indexierung bei Dokument-Änderung, Versionierung | 1 Tag |
| K-MCP | MCP-Server-Exposure — RAG als MCP-Tool für externe Agenten verfügbar | 0.5 Tage |
### 4.2 Automatische Wissensgraph-Extraktion
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| K-EXT | LLM-Relationship-Extraktion — analysiert Texte (Mails, Doks, Notes) und extrahiert Beziehungen | 2 Tage |
| K-ENT | Entity-Extraction — erkennt Personen, Firmen, Projekte, Themen in Texten | 1 Tag |
| K-AUTO | Auto-Relationship-Creation — extrahierte Beziehungen in GraphRAG speichern | 1 Tag |
| K-CONF | Confidence-Score — extrahierte Beziehungen mit Confidence, Low-Confidence → Review-Queue | 1 Tag |
| K-EVT | Event-Driven-Extraction — neue Mail/Dokument → ARQ-Job → Extraktion → GraphRAG | 1 Tag |
### 4.3 Wiki / Knowledge-Base
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| K-WIKI | Wiki-Plugin — Knowledge-Artikel mit Markdown-Editor, Kategorien, Tags | 2 Tage |
| K-VER | Versionierung — Artikel-Historie, Diff-View, Restore | 1 Tag |
| K-LINK | Auto-Linking — Artikel verlinken automatisch auf Entitäten (Contact, Company) | 1 Tag |
| K-SEARCH | Wiki Search Provider — Artikel in Unified Search integrieren | 0.5 Tage |
| K-EMB2 | Wiki-Embedding — Artikel als Chunks in RAG-Pipeline | 0.5 Tage |
### 4.4 Knowledge-UI
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| K-GRAPH | Wissensgraph-Visualisierung — interaktiver Graph (D3.js / Cytoscape) | 2 Tage |
| K-EDITOR | Wiki-Artikel-Editor — Markdown-Editor mit Live-Preview, Auto-Save | 1 Tag |
| K-BROWSE | Knowledge-Browser — Baumansicht Kategorien, Artikel-Liste, Suche | 1 Tag |
| K-ASK | "Ask Knowledge Base" — Chat-Interface für RAG-Queries mit Quellenangabe | 1 Tag |
| K-REV | Review-Queue — bestätigte/abgelehnte extrahierte Beziehungen | 0.5 Tage |
**Deliverables:** Document-RAG-Pipeline, automatische Wissensgraph-Extraktion, Wiki-System mit Versionierung, Knowledge-UI mit Graph-Visualisierung und "Ask KB"-Chat.
---
## Phase 5 — Platform Integration & Polish
**Dauer:** 4 Wochen
**Ziel:** Alle Systeme integrieren, UX-Polish, Performance, Dokumentation
**Begründung:** Die einzelnen Phasen produzieren funktionierende Komponenten. Phase 5 verbindet sie zu einer kohärenten Plattform.
### 5.1 Cross-System-Integration
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| P-AW | Agent → Workflow — Agenten können Workflows als Tools aufrufen | 1 Tag |
| P-WA | Workflow → Agent — Workflows können Agenten als Steps aufrufen (bereits W-AGENT) | 0.5 Tage |
| P-AS | Agent → Search — Agenten nutzen Unified Search als Tool | 0.5 Tage |
| P-AK | Agent → Knowledge — Agenten nutzen RAG-Pipeline für Queries | 0.5 Tage |
| P-KS | Knowledge → Search — Wiki-Artikel in Unified Search | 0.5 Tage |
| P-MCP | MCP-Server — alle Platform-Features als MCP-Tools für externe Systeme | 1 Tag |
### 5.2 Dashboard & Analytics
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| P-DASH | Platform-Dashboard — Agent-Status, Workflow-Stats, Search-Metrics, Knowledge-Coverage | 2 Tage |
| P-COST | Cost-Tracking — LLM-Kosten pro Agent/Workflow/User, Budget-Alerts | 1 Tag |
| P-USE | Usage-Analytics — meistgenutzte Features, Search-Queries, Agent-Runs | 1 Tag |
### 5.3 Performance & Scale
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| P-CACHE | Search-Caching — häufige Queries cachen (Redis) | 1 Tag |
| P-BATCH | Batch-Embedding — mehrere Entities in einem LLM-Call embedden | 0.5 Tage |
| P-QUEUE | ARQ-Queue-Tuning — Prioritäten, Concurrency-Limits, Dead-Letter-Queue | 1 Tag |
| P-IDX | DB-Index-Optimierung — pgvector HNSW-Parameter, FTS-Index-Tuning | 1 Tag |
### 5.4 Documentation & Onboarding
| Task | Beschreibung | Aufwand |
|------|-------------|---------|
| P-DOC | Platform-Dokumentation — Architektur, Plugin-Dev-Guide, Agent-Dev-Guide | 2 Tage |
| P-ONB | Platform-Onboarding — Setup-Wizard, Sample-Agenten, Sample-Workflows | 1 Tag |
| P-VID | Feature-Videos — kurze Screencasts für Agent-Builder, Workflow-Editor, Knowledge-Base | 1 Tag |
**Deliverables:** Vollständig integrierte Plattform mit Dashboard, Cost-Tracking, optimierter Performance, Dokumentation und Onboarding-Material.
---
## Abhängigkeitsgraph
```
Phase 0 (Foundation)
├──→ Phase 0.5 (Undo & Restore) ──→ alle Phasen profitieren
├──→ Phase 0.7 (System-Konsolidierung) ──→ alle Phasen profitieren
├──→ Phase 1 (Search) ──────────────→ P-AS, P-KS
│ │
├──→ Phase 2 (Agents) ──────────────→ P-AW, P-WA, P-AK
│ │ │
│ └──→ Phase 3 (Workflows) ────→ P-AW (bidirectional)
│ │
│ └──→ Phase 4 (Knowledge) ──→ P-AK, P-KS
│ │
│ └──→ Phase 5 (Integration)
└──────────────────────────────────────────────────────┘
```
**Wichtige Abhängigkeiten:**
- Phase 0.5 (Undo & Restore) ist foundational — alle späteren Phasen profitieren davon
- Phase 2 (Agents) benötigt Phase 1 (Search) für Search-as-Tool
- Phase 3 (Workflows) benötigt Phase 2 (Agents) für Agent-Step
- Phase 4 (Knowledge) benötigt Phase 2 (Agents) für LLM-Extraktion
- Phase 5 (Integration) benötigt alle vorherigen Phasen
- Phase 1 und Phase 2 können teilweise parallel laufen (ab Phase 0.1 Abschluss)
---
## Technologie-Entscheidungen
| Entscheidung | Wahl | Begründung |
|-------------|------|------------|
| Agent-Loop | LiteLLM `acompletion()` + `tools=` | Bereits im Stack, OpenAI-kompatibel, alle Provider |
| Visueller Editor | React Flow | De-facto-Standard, MIT-Lizenz, gut dokumentiert |
| Graph-Visualisierung | Cytoscape.js | Performance bei großen Graphen, interaktiv |
| Code-Sandbox | Pyodide / QuickJS | Isolierte Ausführung, kein Server-Side-Code-Injection |
| Document-Chunking | LangChain TextSplitter (recursive) | Bewährt, konfigurierbar, Python-native |
| Embedding-Model | text-embedding-3-small (768-dim) | Bereits konfiguriert, kostengünstig |
| Wiki-Editor | TipTap (React) | Markdown + Rich-Text, Auto-Save, kollaborativ erweiterbar |
---
## Risiken & Mitigation
| Risiko | Wahrscheinlichkeit | Impact | Mitigation |
|--------|-------------------|--------|------------|
| LLM-Kosten explodieren durch autonome Agenten | Mittel | Hoch | Budget-Limits pro Agent (bereits im Manifest), Cost-Tracking, Dry-Run-Mode |
| Agenten führen destruktive Aktionen aus | Mittel | Kritisch | Approval-Pipeline, Reversibility-Check, RBAC pro Tool-Call, Audit-Log |
| Workflow-Editor wird zu komplex | Hoch | Mittel | Inkrementell bauen, Template-Gallery, User-Testing |
| pgvector-Performance bei vielen Embeddings | Mittel | Mittel | HNSW-Parameter-Tuning, Batch-Embedding, Re-Index-Strategie |
| React-Flow-Lizenzänderung | Niedrig | Mittel | MIT-Lizenz ist stabil, Alternative: Drawflow |
| Multi-Agent-Deadlocks | Niedrig | Hoch | Timeout in Coordinator (bereits vorhanden), Deadlock-Detection |
| Mail-Undo verliert Daten auf IMAP-Server | Mittel | Hoch | Soft-Delete zuerst, IMAP-Trash-Mapping, Sync-Conflict-Resolution |
| EntityHistory-Storage wächst unkontrolliert | Mittel | Mittel | Retention-Policy, Monats-Partitionierung, GDPR-Hard-Delete |
---
## Erfolgsmetriken
| Metrik | Ziel | Messung |
|--------|------|---------|
| Search-Query-Latenz | < 500ms (P95) | APM / Endpoint-Timing |
| Search-Abdeckung | 100% aller Entitäten | Provider-Count vs Entity-Count |
| Auto-Indexierung-Latenz | < 30s nach Entity-Änderung | ARQ-Job-Timing |
| Search-KI-Nutzbarkeit | MCP + Tool + API | MCP-Tool-Verfügbarkeit |
| Agent-Run-Erfolgsrate | > 85% | AgentRun.status = completed / total |
| Workflow-Execution-Latenz | < 2s pro Step (ohne externe Calls) | Execution-Log |
| RAG-Query-Accuracy | > 80% relevante Results | User-Feedback (Thumbs Up/Down) |
| LLM-Kosten pro Tenant/Monat | < 50€ (Standard-Nutzung) | Cost-Tracking-Dashboard |
| Platform-Aktive-Nutzer | +30% nach 3 Monaten | Analytics |
| Undo/Restore-Erfolgsrate | > 95% | Restore-Operationen erfolgreich / total |
| Mail-Restore-Latenz | < 3s (DB-only), < 10s (mit IMAP-Sync) | Endpoint-Timing |
---
## Zusammenfassung
| Phase | Dauer | Hauptdeliverable |
|-------|-------|----------------|
| 0 — Foundation | 4 Wochen | Stabile Frontend-UI, Test-Coverage, Cleanup |
| 0.5 — Undo & Restore | 5 Wochen | Universal Undo/Restore für alle Entitäten, Konsolidierung aller History-Systeme, Plugin-Dev-Guide |
| 0.7 — System-Konsolidierung | 10 Wochen | Attachments, LLM, WebSocket, Redis, Events, File Upload, Import/Export, Error/Custom Fields, Plugin-Specification & Contract, Plugin Public Web Content |
| 0.8 — Frontend-Konsolidierung | 5 Wochen | Standard-Komponenten, Template-System, Plugin-UI-Loading, Code-Bereinigung, Frontend-Regeln |
| 1 — Search | 4 Wochen | Unified Search Platform — vereinheitlichte Suche über alles, KI-nutzbar, Auto-Indexierung |
| 2 — Agents | 6 Wochen | Autonome Agenten mit ReAct-Loop, 4 Pre-Built Agenten |
| 3 — Workflows | 6 Wochen | Visueller Workflow-Editor, n8n-Ersatz |
| 4 — Knowledge | 6 Wochen | Document-RAG, Wissensgraph, Wiki, Knowledge-UI |
| 5 — Integration | 4 Wochen | Integrierte Plattform, Dashboard, Polish |
| **Total** | **50 Wochen** | **LeoPlatform — KI-gesteuerte Business-Plattform** |
---
*Diese Roadmap basiert auf einer tiefen Code-Analyse des bestehenden LeoCRM-Codebases. Alle Phasen bauen auf vorhandener Infrastruktur auf — keine Architektur-Umbrüche erforderlich.*
### Undo & Restore — Detail-Analyse
Das bestehende EntityHistory-System ist nur halb implementiert:
- **EntityHistory Model** existiert mit `snapshot_before` / `snapshot_after` / `changes`
- **restore_from_history()** ist hardcoded auf `entity_type == "contact"` — kein generisches Restore
- **record_history()** wird nur in `contact_service.py` (3x) und `companies.py` (1x) aufgerufen
- **Kein Plugin** (Mail, DMS, Tasks, Calendar, Tags) nutzt record_history
- **Mail** ist besonders schwierig: IMAP-Sync bedeutet dass Löschungen auf dem Mailserver passieren, nicht nur in der DB
- **Undo UI** existiert nicht
Phase 0.5 adressiert all dies mit einer generischen Restore-Engine, Hook-basierter History-Aufzeichnung für alle Entitäten, Mail-spezifischer IMAP-Trash-Logik, Bulk-Undo und einer Trash-View UI.