- codebase-vs-requirements.md: rewritten to reflect actual IST-stand (PostgreSQL, React, 12 plugins, unified contacts) - security-review-phase2.md: added resolution summary for M-01/M-02/M-03/M-05/m-03/m-08 - architecture.md: added section 11 'Implementation Status' with what's built and what's missing - MASTER-PLAN.md: comprehensive 754-line plan with 8 phases + Phase 3.5 (~590h total) - PROGRESS.md: progress tracking file for agent work
55 KiB
LeoCRM — Master Plan: Umbau & Vollendung
Erstellt: 2026-07-22 Status: Draft — zur Freigabe Letzte Revision: 2026-07-22 (gründliche Überprüfung nach Code-Tiefenanalyse)
Ausgangslage
Was bereits gut ist
- Backend: ~35.800 Zeilen, 12 Plugins, Multi-Tenant mit RLS, Rate Limiting, Audit Log
- Unified Contact Model: BEREITS implementiert (Migration 0021) — Contact mit type='company'|'person', ContactPerson als 1:N child (wie Rentman)
- Frontend: ~30.000 Zeilen, 27 Pages, 70 Components, i18n DE/EN, TanStack Query, TipTap
- Tests: ~17.300 Zeilen Backend-Tests, 38 Vitest-Dateien
- Docker: Multi-Stage-Build (Frontend+Backend in einem Container)
- Datenbank: PostgreSQL 16 als separater docker-compose Service
- WebSocket-Infrastruktur: Bereits im
kommunikationPlugin vorhanden (/api/v1/comm/ws) — kann als Referenz für KI-UI-Steuerung dienen
Was fehlt oder nicht stimmt
- Frontend nutzt unified Contact Model nicht vollständig (keine Contact-Detail-Route, ContactPerson-Verwaltung fehlt in UI)
- 'company' als entity_type ist in 6 Plugins verankert — muss zu 'contact' vereinheitlicht werden
- Plugin-UI-System fehlt (hartkodierte Routes statt dynamische Registry)
- Code-Splitting fehlt (alle 27 Pages im Main Bundle)
- E2E Tests fehlen komplett
- KI-UI-Steuerung fehlt
- Virtual Scrolling fehlt
- React Hook Form + Zod nicht überall
- hooks.ts ist Monolith (1.298 Zeilen)
- Fehlende Dependencies (lucide-react, date-fns)
- Plugin-Richtlinien fehlen
Wichtige Unterscheidung: 'company' hat zwei Bedeutungen
- entity_type='company' in Plugins (entity_links, calendar, tags, mail) → referenziert eine Firma als Entität → MUSS zu 'contact' werden
- system_settings.company_* Felder (company_name, company_street etc.) → CRM-Besitzer-Firmeninfo für Rechnungen → BLEIBT wie es ist
- CalendarType='company' → Kalender-Typ (Firmenkalender) → kann bleiben oder zu 'organization' umbenannt werden (kosmetisch)
Architektur-Entscheidungen (freigegeben 2026-07-22)
- KI-UI-Steuerung: Keine Mausbewegung nötig. KI muss zu Kontakten springen und einen Kontakt öffnen können. Die UI muss das Ergebnis zeigen — Kontaktliste und spezieller Kontakt ausgewählt. Implementierungsweg (WebSocket, postMessage, etc.) ist offen, Hauptsache das Ergebnis wird in der UI sichtbar.
- Company-Routes: Komplett entfernen. Keine deprecated-Routes, keine Redirects. Kontakte wie in Rentman — ein unified Contact-Modell, kein separates Company-Modell mehr. Alle Plugin-Referenzen auf entity_type='company' müssen zu 'contact' migriert werden.
- PostgreSQL: Aktuell egal (Coolify-managed oder docker-compose). Reine Docker-Lösung soll später möglich sein. Keine Code-Änderung nötig — nur Konfiguration.
- S3-Storage: Provider egal. Wichtig ist nur dass die Architektur es später ermöglicht. Bereits vorbereitet in config.py (STORAGE_BACKEND=s3).
Phasen-Plan
PHASE 0: Vorbereitung & Cleanup
Ziel: Codebasis bereinigen, Dependencies installieren, veraltete Dokumente aktualisieren
| # | Aufgabe | Aufwand | Details |
|---|---|---|---|
| 0.1 | Veraltete Planungsdokumente aktualisieren | 2h | codebase-vs-requirements.md neu schreiben (beschreibt alten Stand), architecture.md um Implementation-Status erweitern, security-review-phase2.md um 'Resolved' Markierungen ergänzen |
| 0.2 | lucide-react installieren + Icons migrieren |
4h | Inline SVGs durch lucide-react Icons ersetzen. Konsistente Icon-Bibliothek. |
| 0.3 | date-fns installieren + Datum-Formatierung |
3h | Alle toLocaleDateString() etc. durch date-fns ersetzen. Konsistente Datum-Formatierung. |
| 0.4 | hooks.ts aufteilen |
3h | 1.298 Zeilen aufteilen in api/auth.ts, api/contacts.ts, api/settings.ts etc. Generische Hooks bleiben in hooks.ts. Company-Hooks werden in Phase 1 entfernt, nicht aufgeteilt. |
| 0.5 | Store-Verzeichnis konsolidieren | 1h | store/ und stores/ zusammenführen. |
| 0.6 | Frontend-Bestandsanalyse als Dokument speichern | 1h | frontend-gap-analysis.md mit vollständiger Analyse. |
| 0.7 | UI-Design-Richtlinien erstellen | 6h | docs/ui-design-guidelines.md basierend auf bestehenden Plugin-Patterns (siehe unten). |
| 0.8 | Theme-Customization Backend | 4h | system_settings um Theme-Felder erweitern (primary_color, accent_color, font_family, border_radius). Neue Alembic-Migration. API-Endpoints zum Lesen/Schreiben der Theme-Settings. |
| 0.9 | Theme-Customization Frontend | 6h | SettingsTheme.tsx Seite mit Color-Picker, Font-Auswahl, Live-Preview. Tailwind-CSS-Variablen dynamisch aus API-Settings überschreiben. Dark-Mode-Toggle. Theme wird beim App-Start geladen und angewendet. |
| 0.10 | RBAC-Audit & Plugin-Permissions nachrüsten | 6h | 4 Plugins haben permissions=[] (calendar, dms, entity_links, tags) → keine Rechte-Prüfung! Pro Plugin passende Permissions definieren und in Manifest eintragen. Routes mit require_permission() absichern. Siehe Details unten. |
| 0.11 | LiteLLM-Cleanup & alte llm_client.py migrieren | 3h | LiteLLM ist BEREITS in ai_assistant und ai_proactive integriert (litellm.acompletion()). Nur die alte llm_client.py (Copilot) nutzt noch httpx direkt. Diese auf LiteLLM umstellen oder entfernen. System-Prompt in llm_client.py referenziert noch /api/v1/companies → auf Contacts umstellen. |
| 0.12 | KI-Agent-Framework in Plugin-Richtlinien dokumentieren | 2h | PydanticAI + tool_registry existieren bereits. In docs/plugin-development-guide.md dokumentieren: Wie Plugins KI-Agenten, Tools und LLM-Funktionen nutzen. Plugin-Manifest um agent_capabilities Feld erweitern. |
| 0.13 | Heartbeat konfigurierbar machen | 3h | Heartbeat-Intervall, Aktivierung, Ziel-Room in ProactiveSettings (DB) speichern. Settings-UI für Heartbeat-Konfiguration. |
| 0.14 | Unified Search: Field-Level RBAC nachrüsten | 4h | Search-Provider prüfen aktuell KEINE Feld-Level-Permissions. Nutzer mit search:read sieht alle Felder. Provider müssen resolved_perms prüfen und hidden Felder ausblenden. to_search_result() um Permission-Filter ergänzen. |
| 0.15 | Undo/History-System für CRUD-Operationen | 8h | Globale Undo-History: Jede CRUD-Aktion (Create/Update/Delete) wird mit Snapshot in entity_history Tabelle gespeichert. User kann Änderungen rückgängig machen oder zu früherer Version zurückkehren. Nutzt bestehenden Audit-Log als Basis. Frontend: Undo-Button + History-Viewer pro Entity. |
| 0.16 | Storage Backend implementieren (S3-Support) | 8h | Architecture.md beschreibt abstract StorageBackend (local/S3), aber existiert NICHT im Code. Attachments nutzen hardcoded /data/uploads. Storage-Klasse erstellen: LocalStorage + S3Storage. Config um STORAGE_BACKEND, S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY erweitern. DMS und Attachments auf Storage-Backend umstellen. .env.example um S3-Variablen ergänzen. |
| 0.17 | Import/Export an unified Contact Model anpassen | 4h | Import/Export nutzt alte Feldnamen (first_name, last_name, mobile, position, department). Auf unified Contact-Felder umstellen (firstname, surname, phone_1, email_1, etc.). Company-Import auf Contact mit type='company' umstellen. |
| 0.18 | .gitignore & Config-Cleanup | 2h | .gitignore hat webui/ statt frontend/ — frontend/node_modules und frontend/dist werden nicht ignoriert! Korrigieren. python-jose (JWT) aus requirements.txt entfernen — Code nutzt Session-Auth. pyproject.toml Python-Version auf 3.12 aktualisieren. .env.docker.example JWT-Variablen entfernen. .env aus Git entfernen (ist committet aber sollte nicht sein). dump.rdb und test.txt aus Repo löschen. frontend/dist/ aus Git entfernen (sollte nicht committet sein). |
| 0.19 | Mail-Salt Security-Fix | 2h | mail/services.py hat hardcoded salt b"leocrm-mail-salt" für Passwort-Verschlüsselung. Salt sollte random pro Account sein. Fix: Random salt generieren und mit encrypted_password zusammen speichern. DB-Migration für bestehende Accounts. |
| 0.20 | AGPL-Lizenzen durch kommerziell nutzbare Alternativen ersetzen | 6h | PyMuPDF (AGPL-3.0) → ersetzen durch pypdf (BSD). Text-Extraktion in unified_search anpassen. OnlyOffice (AGPL-3.0) → ersetzen durch Collabora Online (LGPL/MPL). DMS Edit-Sessions auf Collabora umstellen. requirements.txt, Dockerfile, docker-compose.yml, architecture.md aktualisieren. DMS Plugin OnlyOfficeConfig → CollaboraConfig. Frontend DMS-Komponenten anpassen. Lizenz-Datei (LICENSE) und THIRD_PARTY_LICENSES.md erstellen. |
Phase 0 Gesamt: ~77h
UI-Design-Richtlinien (Task 0.7)
Basierend auf Analyse der bestehenden Plugins (Calendar, Mail, DMS, Contacts):
Layout-Patterns:
- 3-Spalten-Explorer-Layout (Tree | Liste/Explorer | Detail) — verwendet von Calendar, Mail, DMS
- ResizablePanel für drag-to-resize Spalten — bereits implementiert
- PluginToolbar für Plugin-Aktionen (oben) — bereits implementiert
- Modal für Formulare (Create/Edit/Delete-Bestätigung) — bereits implementiert
- EmptyState für leere Listen — bereits implementiert
- LoadingState/Skeleton für Lade-Zustände — bereits implementiert
Farbsystem (Tailwind Design Tokens):
primary(Blau #2563eb) — Hauptaktionen, aktive Zuständesecondary(Slate #64748b) — Text, Borders, Hintergründeaccent(Fuchsia #d946ef) — Hervorhebungen, Info-Badgesdanger(Rot #dc2626) — Löschen, Fehlerwarning(Amber #f59e0b) — Warnungensuccess(Grün #16a34a) — Erfolg, Bestätigungen- Jede Farbe mit 50-900 Schattierungen
- Dark Mode via
darkMode: 'class'— CSS-Variablen in:rootund.dark
Typografie:
- Font:
Inter(system-ui fallback) - Mono:
JetBrains Monofür Code/Daten - Größen: xs (0.75rem) bis 4xl (2.25rem)
- Zeilenhöhen definiert pro Größe
Komponenten-Konventionen:
- Button: 4 Varianten (primary/secondary/danger/ghost), 3 Größen (sm/md/lg),
min-h-touch(44px),focus-visible:ring-2 - Card: Titel + Beschreibung + Actions (header), Body, optional Footer (bg-secondary-50)
- Badge: 7 Varianten (default/primary/success/warning/danger/info/secondary), optional dot
- Input/Select:
focus-ringKlasse,border-secondary-200,rounded-md - Modal:
sizeprop (sm/md/lg/xl),ConfirmDialogfür Bestätigungen - Table/DataGrid: TanStack Table, ARIA-labels auf sortierbare Headers
- Toast:
useToast()Hook für Benachrichtigungen
Spacing & Layout:
- Standard-Padding:
px-6 py-4(Card body),p-4(Panel) - Gap:
gap-2(Buttons),gap-4(Sections),gap-6(Columns) - Border-Radius:
rounded-md(0.5rem) Standard,rounded-lg(0.75rem) für Cards - Shadow:
shadow-sm(Cards),shadow-md(Dropdowns),shadow-lg(Modals)
Accessibility (bereits implementiert):
focus-ringKlasse:focus-visible:ring-2 focus-visible:ring-primary-500btn-touchKlasse:min-h-touch min-w-touch(44px)sr-onlyundsr-only-focusableKlassenprefers-reduced-motionMedia Queryaria-hidden="true"auf dekorativen SVGsaria-labelauf interaktiven Elementen ohne sichtbaren Text
Plugin-UI-Patterns (für neue Plugins):
- Jede Plugin-Seite folgt dem 3-Spalten-Layout (wenn anwendbar)
- PluginToolbar für Aktionen (Create, Import, Export, etc.)
- Plugin-Settings als eigene Settings-Sub-Seite
- Plugin-Detail-Tabs (z.B. "Dateien" bei Contact-Detail)
- Konsistente EmptyState-Komponente wenn keine Daten
- Konsistente LoadingState/Skeleton-Komponente beim Laden
- Toast für Erfolg/Fehler-Meldungen nach Aktionen
- ConfirmDialog vor destruktiven Aktionen
Was im Design-Guide dokumentiert wird:
- Farbsystem mit Verwendungsregeln (wann welche Farbe)
- Typografie-Hierarchie (Überschriften, Body-Text, Labels)
- Layout-Patterns (3-Spalten, Modal, Settings-Tree)
- Komponenten-Verwendung (welche Komponente für was)
- Spacing & Sizing Konventionen
- Accessibility-Regeln
- Dark-Mode-Regeln
- Plugin-UI-Patterns für neue Plugins
- Do's & Don'ts
- Code-Beispiele aus bestehenden Plugins
RBAC-Audit & Plugin-Permissions (Task 0.10)
Problem: 4 Plugins haben permissions=[] im Manifest → keine Rechte-Prüfung auf ihren Routes:
| Plugin | Aktuell | Muss definiert werden |
|---|---|---|
| calendar | permissions=[] |
calendar:read, calendar:write, calendar:delete, calendar:share, calendar:admin |
| dms | permissions=[] |
dms:read, dms:write, dms:delete, dms:share, dms:admin |
| entity_links | permissions=[] |
entity_links:read, entity_links:write, entity_links:delete |
| tags | permissions=[] |
tags:read, tags:write, tags:delete, tags:admin |
Was zu tun ist:
- Pro Plugin passende Permissions im Manifest definieren
- Alle Plugin-Routes mit
require_permission()absichern - Permission-Registry registriert Plugin-Permissions automatisch beim Aktivieren
- Admin kann Permissions in Rollen-Editor zuweisen
- Tests: User ohne Permission → 403, User mit Permission → 200
Zusätzlich in Phase 1 (Permission-Registry-Cleanup):
companies:read/write/deleteausCORE_PERMISSIONSentfernen (wird zucontacts:read/write/delete)CORE_FIELD_DEFINITIONSaktualisieren: alte Felder (first_name,last_name,mobile,position,department,linkedin_url) durch unified Contact-Felder ersetzen (firstname,surname,phone_1,email_1, etc.)companiesField-Definitions entfernen
LiteLLM-Integration (Task 0.11)
Problem: Aktuelle llm_client.py spricht nur OpenAI-compatible API direkt via httpx. Keine Unterstützung für Anthropic, Google, lokale Modelle etc.
Lösung: LiteLLM als unified LLM-Interface integrieren.
Was LiteLLM bietet:
- 100+ LLM-Provider über eine einheitliche API (OpenAI, Anthropic, Google, Azure, AWS Bedrock, Ollama, etc.)
- Konsistente Request/Response-Formate
- Streaming-Support
- Fallback/Routing-Regeln
- Cost-Tracking
- Rate-Limiting
Was zu tun ist:
litellmals Python-Dependency hinzufügenllm_client.pyauf LiteLLM umstellen:litellm.acompletion()statt direktem httpx-Call- Konfiguration via Env-Vars:
AI_MODEL,AI_API_KEY,AI_API_BASE(bleiben gleich), plusAI_PROVIDER(neu: openai/anthropic/google/ollama/etc.) - AI Assistant Plugin nutzt LiteLLM für Multi-Provider-Support
- AI Proactive Plugin nutzt LiteLLM für Suggestions
- Zukünftige Plugins können LiteLLM einfach nutzen — einheitliches Interface
- Mock-Mode für Tests beibehalten (wenn kein API-Key gesetzt)
- Plugin-Entwickler-Richtlinien: Wie man LiteLLM in neuen Plugins nutzt
Architektur:
Plugin (ai_assistant, ai_proactive, zukünftige)
↓
LiteLLM (unified LLM interface)
↓
Provider (OpenAI, Anthropic, Google, Ollama, ...)
Vorteil für zukünftige Plugins:
- Ein Plugin kann LLM-Funktionen nutzen ohne sich um den Provider zu kümmern
- Admin kann Provider in Settings konfigurieren
- KI-Modelle können ausgetauscht werden ohne Code-Änderung
PHASE 1: Unified Contact Model — Vollendung (Backend + Frontend)
Ziel: 'company' als separates Konzept komplett entfernen. Alles ist 'contact' mit type='company'|'person'. Wie Rentman.
1A: Backend — Company-Routes & Services entfernen
| # | Aufgabe | Aufwand | Details |
|---|---|---|---|
| 1.1 | app/routes/companies.py entfernen |
1h | 303 Zeilen. Router aus main.py/routes/__init__.py austragen. |
| 1.2 | app/services/company_service.py entfernen |
1h | 273 Zeilen. Importe aus services/__init__.py entfernen. |
| 1.3 | app/models/company.py entfernen |
1h | Backward-compat shim. Importe überall auf Contact umstellen. |
| 1.4 | app/schemas/company.py entfernen |
1h | CompanyCreate, CompanyUpdate, CompanyResponse etc. |
| 1.5 | app/ai/action_mapper.py aktualisieren |
3h | Company-Intents (create_company, delete_company, update_company, list_company) auf Contact-API umstellen. Regex-Patterns anpassen. |
| 1.6 | app/workflows/engine.py aktualisieren |
1h | Event company.created → contact.created. Workflow-Trigger anpassen. |
| 1.7 | app/core/worker.py aktualisieren |
1h | index_company Referenzen → index_contact. |
| 1.8 | app/core/seeds.py prüfen/aktualisieren |
1h | Falls Company-Seed-Daten existieren, auf Contact mit type='company' umstellen. |
1A Gesamt: ~10h
1B: Backend — Plugins von entity_type='company' befreien
| # | Aufgabe | Aufwand | Details |
|---|---|---|---|
| 1.9 | entity_links Plugin aktualisieren | 4h | entity_type Pattern von `^(company |
| 1.10 | unified_search Plugin aktualisieren | 6h | CompanySearchProvider → wird zu ContactSearchProvider oder bleibt als Provider für type='company' Kontakte. index_company → index_contact. Events company.created/updated → contact.created/updated. search_engine.py Mapping "company" → "contacts" anpassen. jobs.py aktualisieren. |
| 1.11 | calendar Plugin aktualisieren | 3h | entity_type Pattern von `^(company |
| 1.12 | tags Plugin aktualisieren | 3h | entity_type Pattern von `^(company |
| 1.13 | mail Plugin aktualisieren | 4h | mail.company_id Spalte → mail.contact_id (DB-Migration). Routes, Schemas, Services aktualisieren. company_id Referenzen in Frontend-API-Modul. |
| 1.14 | test_sample Plugin aktualisieren | 1h | company.created Event → contact.created. Test-Plugin ist Referenz für Plugin-Entwicklung. |
| 1.15 | Event-Namen vereinheitlichen | 2h | Alle company.created/updated/deleted Events → contact.created/updated/deleted. Event-Publisher in contact_service.py prüfen. |
| 1.16 | DB-Migration: entity_type 'company' → 'contact' | 3h | Alembic-Migration: UPDATE entity_links SET entity_type='contact' WHERE entity_type='company'. UPDATE tag_assignments SET entity_type='contact' WHERE entity_type='company'. UPDATE calendar_entry_links SET entity_type='contact' WHERE entity_type='company'. ALTER TABLE mails RENAME COLUMN company_id TO contact_id. |
| 1.17 | Backend-Tests aktualisieren | 4h | Alle Tests die Company-Routes oder entity_type='company' referenzieren umstellen. test_companies.py entfernen oder zu Contact-Tests umschreiben. |
| 1.18 | Permission-Registry-Cleanup | 3h | companies:read/write/delete aus CORE_PERMISSIONS entfernen. CORE_FIELD_DEFINITIONS aktualisieren: alte Felder durch unified Contact-Felder ersetzen. companies Field-Definitions entfernen. |
| 1.19 | Addresses entity_type='company' → 'contact' | 2h | address_service.py VALID_ENTITY_TYPES von {"company", "contact"} → {"contact"}. address.py Model anpassen. DB-Migration: bestehende Adressen mit entity_type='company' auf 'contact' migrieren. |
| 1.20 | conftest.py aktualisieren | 2h | conftest.py importiert Company und CompanyContact aus alten Modellen. Auf unified Contact Model umstellen. Test-Fixtures anpassen. |
1B Gesamt: ~33h
1C: Frontend — Unified Contact UI
| # | Aufgabe | Aufwand | Details |
|---|---|---|---|
| 1.18 | Contact-Detail-Route hinzufügen | 2h | Route /contacts/:id in routes/index.tsx. ContactDetail.tsx (372 Zeilen) existiert bereits als Komponente. |
| 1.19 | ContactList mit Type-Filter (company/person) | 4h | ContactsList.tsx (445 Zeilen) um Type-Filter erweitern. Tabs oder Toggle: "Alle |
| 1.20 | ContactDetail um ContactPerson-Verwaltung erweitern | 8h | Bei type='company': Ansprechpartner-Liste, Ansprechpartner hinzufügen/bearbeiten/löschen. ContactPerson API-Hooks in Frontend. |
| 1.21 | ContactEditModal für beide Types | 6h | Formular je nach type unterschiedlich: company → name, person → firstname/surname. Adressen (mailing/visit/invoice). |
| 1.22 | Company-Hooks aus hooks.ts entfernen |
2h | useCompanies, useCompany, useCreateCompany, useUpdateCompany, useDeleteCompany, useCompanyExport, useCompanyImport entfernen. Company-Interface entfernen. |
| 1.23 | Frontend Type-Definitions aktualisieren | 2h | calendar.ts: entity_type 'company' → 'contact'. tags.ts: EntityType 'company' entfernen. search.ts: type 'company' → 'contact'. mail.ts: company_id → contact_id. |
| 1.24 | Dashboard.tsx aktualisieren | 1h | useUnifiedContacts(1, 1, undefined, 'company') → useUnifiedContacts(1, 1, undefined, 'company') (type-Filter bleibt, ist jetzt Contact type nicht Company entity). |
| 1.25 | GlobalSearchResults.tsx aktualisieren | 2h | Search result type 'company' → 'contact'. Grouping, Icons, Labels anpassen. |
| 1.26 | ContactFolderTree in ContactList integrieren | 4h | Ordner-Baum links, Kontaktliste rechts. Drag & Drop Kontakte in Ordner. |
| 1.27 | React Hook Form + Zod in ContactEditModal | 3h | Strukturierte Validierung für alle Contact-Felder. |
| 1.28 | Frontend-Tests aktualisieren | 4h | Tests für Contact-Detail, ContactEditModal, ContactPerson-Verwaltung. Company-Test-Referenzen entfernen. |
1C Gesamt: ~38h
Phase 1 Gesamt: ~81h (vorher 33h — unterschätzt um 48h!)
PHASE 2: Code-Splitting & Performance
Ziel: Frontend lädt nur was nötig ist. Virtual Scrolling überall.
| # | Aufgabe | Aufwand | Details |
|---|---|---|---|
| 2.1 | React.lazy + Suspense für alle Routes | 4h | Alle Page-Imports in routes/index.tsx auf React.lazy() umstellen. <Suspense> mit Loading-Fallback. |
| 2.2 | @tanstack/react-virtual installieren |
1h | Dependency hinzufügen. |
| 2.3 | Virtual Scrolling in DataGrid | 6h | DataGrid.tsx um Virtual Scrolling erweitern. Nur sichtbare Zeilen rendern. |
| 2.4 | Virtual Scrolling in MailList | 4h | MailList.tsx um Virtual Scrolling erweitern. |
| 2.5 | Virtual Scrolling in ContactList | 4h | ContactList.tsx um Virtual Scrolling erweitern. |
| 2.6 | Virtual Scrolling in allen anderen Listen | 4h | AuditLog, Calendar Entries, DMS FileGrid, etc. |
| 2.7 | Bundle-Analyse & Optimierung | 2h | vite-bundle-visualizer prüfen, manuelle Chunks für große Dependencies. |
Phase 2 Gesamt: ~25h
PHASE 3: Plugin-UI-System (WordPress-Style)
Ziel: Dynamisches Plugin-UI-Loading. Plugins registrieren sich selbst.
| # | Aufgabe | Aufwand | Details |
|---|---|---|---|
| 3.1 | Plugin-Manifest-Frontend-Endpoint | 4h | Backend-Endpoint GET /api/v1/plugins/active-manifests liefert alle aktiven Plugin-Manifeste mit UI-Definitionen (routes, menu_items, detail_tabs, settings_pages, dashboard_widgets). |
| 3.2 | PluginRegistry.tsx erstellen |
8h | Fetcht aktive Plugin-Manifeste beim App-Start. Registriert Routes, Menu-Items, Detail-Tabs, Settings-Pages dynamisch. |
| 3.3 | PluginLoader.tsx erstellen |
6h | Lazy-loaded Plugin-Komponenten via React.lazy(). Suspense-Boundaries pro Plugin. Error-Boundary falls Plugin nicht lädt. |
| 3.4 | Sidebar dynamisch aus Plugin-Manifesten | 4h | Sidebar rendert Menu-Items aus Plugin-Registry statt hartkodierte Items. |
| 3.5 | Settings-Baum dynamisch aus Plugin-Manifesten | 4h | Settings-Pages werden dynamisch aus Plugin-Manifesten generiert. |
| 3.6 | Detail-Tabs dynamisch (Contact-Detail) | 4h | Plugin-Detail-Tabs (z.B. "Dateien", "E-Mails", "Kalender") werden dynamisch gerendert. |
| 3.7 | Plugin-Routen aus hartkodiertem Router entfernen | 4h | Statische Plugin-Imports aus routes/index.tsx entfernen. Alles über PluginRegistry. |
| 3.8 | Plugin-Entwickler-Richtlinien erstellen | 8h | docs/plugin-development-guide.md: Manifest-Format, Lifecycle, UI-Registrierung, Event-Bus, Migration-Runner, Service-Container, Beispiele, Do's & Don'ts, Testing-Guide. |
| 3.9 | Plugin-Templates / Boilerplate | 4h | templates/plugin-template/: Minimal-Plugin als Startpunkt für neue Plugins. Mit Manifest, Routes, Models, Schemas, Migration, Tests. |
| 3.10 | Tests für Plugin-UI-System | 4h | Vitest-Tests für PluginRegistry, PluginLoader, dynamische Sidebar/Settings. |
| 3.10b | Plugin-Install-System | 8h | Plugins einfach installierbar machen: ZIP-Upload, URL-Install, Plugin-Marketplace-Integration. Plugin-Upload-Endpoint, Validierung (Manifest prüfen, tenant_id-Check, Security-Scan), automatische Migration bei Install. Install-UI in SettingsPlugins.tsx. |
Phase 3 Gesamt: ~58h
PHASE 3.5: Automation & Agents Plugin
Ziel: Zentrale Oberfläche für Automatisierungen und selbst-arbeitende KI-Agenten. Plugins können Agenten und Automation-Templates mitbringen.
Architektur:
┌─────────────────────────────────────────────┐
│ Automation & Agents UI │
│ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Automation │ │ Agent Builder │ │
│ │ Builder │ │ - Agent definieren │ │
│ │ - Trigger │ │ - Tools auswählen │ │
│ │ - Schedule │ │ - LLM-Modell wählen │ │
│ │ - Conditions │ │ - Heartbeat setzen │ │
│ │ - Actions │ │ - Proaktiv/Reaktiv │ │
│ └─────────────┘ └─────────────────────┘ │
├─────────────────────────────────────────────┤
│ Cron-Scheduler │ Workflow-Timeouts │ HB │
├─────────────────────────────────────────────┤
│ Plugins bringen mit: │
│ - agent_definitions (Agent-Templates) │
│ - automation_templates (Automation-Tpl) │
│ - cron_jobs (periodische Tasks) │
│ - heartbeat_configs │
└─────────────────────────────────────────────┘
| # | Aufgabe | Aufwand | Details |
|---|---|---|---|
| 3.11 | Plugin-Manifest um Agent/Automation-Felder erweitern | 4h | Manifest um agent_definitions, automation_templates, cron_jobs, heartbeat_configs erweitern. Plugins deklarieren was sie mitbringen. |
| 3.12 | Cron-Scheduler Backend | 6h | ARQ-basierter Scheduler für periodische Tasks. Cron-Expressions (z.B. 0 8 * * * = täglich 8 Uhr). Scheduler liest aktive Cron-Jobs aus DB und enqueued sie. Ersetzt hartkodierten Heartbeat. |
| 3.13 | Workflow-Timeout-Worker | 4h | ARQ-Job der regelmäßig Workflow-Instanzen mit abgelaufenem timeout_at prüft. Bei Timeout: Status auf cancelled, Notification an Initiator. |
| 3.14 | Agent Builder Backend | 8h | API für Agent-Definitionen: Name, Beschreibung, LLM-Modell, Tools (aus tool_registry), System-Prompt, Heartbeat-Intervall, Proaktiv/Reaktiv-Modus. Agent-Definitionen in DB gespeichert. |
| 3.15 | Automation Builder Backend | 6h | API für Automation-Definitionen: Trigger (Event/Schedule/Manual), Conditions, Actions (API-Call/Notification/Workflow-Start). Automation-Definitionen in DB gespeichert. |
| 3.16 | Automation Execution Engine | 6h | Engine die Automations ausführt: Event-Trigger → Conditions prüfen → Actions ausführen. Nutzt Event-Bus für Event-Trigger, Cron-Scheduler für Schedule-Trigger. |
| 3.17 | Agent Runner | 8h | Führt Agenten aus: Proaktiv (Heartbeat-getriggert, sammelt Kontext, generiert Vorschläge) oder Reaktiv (auf Event/Message, reagiert). Nutzt LiteLLM + tool_registry + PydanticAI. |
| 3.18 | Automation & Agents UI — Automation Builder | 8h | Visueller Builder für Automations: Trigger auswählen, Conditions definieren, Actions zusammenstellen. Drag & Drop oder Form-basiert. Live-Preview. |
| 3.19 | Automation & Agents UI — Agent Builder | 8h | Visueller Builder für Agenten: Name, Modell, Tools, System-Prompt, Heartbeat. Test-Run Button. Agent-Liste mit Status (aktiv/inaktiv). |
| 3.20 | Automation & Agents UI — Dashboard | 4h | Übersicht: Aktive Automations, Aktive Agenten, Letzte Ausführungen, Logs, Fehler. Heartbeat-Status pro Agent. |
| 3.21 | Plugin-Beiträge registrieren | 4h | Wenn Plugin aktiviert wird: Agent-Definitionen, Automation-Templates, Cron-Jobs aus Manifest registrieren. Bei Deaktivierung: entfernen. |
| 3.22 | Heartbeat-Verwaltung migrieren | 3h | Hartkodierten Heartbeat aus ai_proactive in Automation & Agents Plugin migrieren. Heartbeat wird zu einem konfigurierbaren Cron-Job. |
| 3.23 | Settings für Automation & Agents | 3h | Einstellungen: Default-LLM-Modell für Agenten, Heartbeat-Default-Intervall, Max-Concurrent-Agents, Log-Level. |
| 3.24 | Tests für Automation & Agents | 6h | Tests für Cron-Scheduler, Workflow-Timeouts, Agent Runner, Automation Engine, Plugin-Beiträge. |
| 3.25 | Agent- & Automation-Logs | 4h | Jede Agent-Ausführung und Automation-Ausführung wird geloggt: Start, Ende, Status, Dauer, Ergebnis, Fehler. Log-Viewer in Dashboard UI. Historie pro Agent/Automation. |
| 3.26 | RBAC für Automation & Agents | 3h | Permissions definieren: automation:read, automation:write, automation:delete, automation:execute, agents:read, agents:write, agents:delete, agents:execute. Nur Admin/Editor dürfen Agenten/Automations erstellen. |
| 3.27 | Dry-Run / Test-Modus | 3h | Automations und Agenten können im Dry-Run getestet werden: Führt Conditions aus, zeigt was passieren würde, aber führt keine destruktiven Actions aus. Test-Button in Builder UI. |
| 3.28 | Agent Rate-Limiting & Safety | 3h | Max-Ausführungen pro Agent pro Stunde. Max-Dauer pro Ausführung. Auto-Stop bei Endlosschleife (wenn Agent dieselbe Action 5x hintereinander ausführt). Budget-Limit pro Agent (LiteLLM Cost-Tracking). |
| 3.29 | Plugin-Beitrags-Konfliktlösung | 2h | Wenn zwei Plugins denselben Agent-Namen/Templat-Namen mitbringen: Plugin-Name als Prefix (mail.mail_sorter statt mail_sorter). Dedup-Logik bei Registrierung. |
| 3.30 | Agent-zu-Agent-Kommunikation | 8h | Agenten können Nachrichten an andere Agenten senden. Nutzt kommunikation Plugin-Infrastruktur (WebSocket, Rooms). Agent-Message-Router: Agent A sendet {to: 'mail_sorter', message: 'Neuer Termin gefunden'}. Empfänger-Agent reagiert. Agent-Chatrooms in Dashboard sichtbar. |
| 3.31 | Versionshistorie für Agenten & Automations | 4h | Jede Änderung an Agent/Automation erstellt neue Version. Alte Versionen können wiederhergestellt werden. Versions-Diff in UI. agent_versions und automation_versions Tabellen. |
| 3.32 | MiniApps: Plugin-MiniApps im Chat | 6h | Bereits implementiert: MiniAppRegistry, MiniAppDef, Routes (GET /miniapps, POST /conversations/{id}/miniapps), MiniAppBlock.tsx Frontend. Was fehlt: Plugin-Manifest um miniapps Feld erweitern (Plugins deklarieren welche MiniApps sie mitbringen). MiniApp-Builder UI (visuell MiniApps erstellen). MiniApp-Store in Settings. Dokumentation in Plugin-Entwickler-Richtlinien. |
Phase 3.5 Gesamt: ~105h
Was Plugins mitbringen können:
- Agent-Definitionen: Ein Plugin kann vordefinierte Agenten mitbringen (z.B. Mail-Plugin bringt "E-Mail-Sortier-Agent" mit)
- Automation-Templates: Ein Plugin kann Automation-Vorlagen mitbringen (z.B. Calendar-Plugin bringt "Terminerinnerung 24h vorher" mit)
- Cron-Jobs: Ein Plugin kann periodische Tasks deklarieren (z.B. Mail-Plugin: "IMAP-Sync alle 15 Minuten")
- Heartbeat-Configs: Ein Plugin kann Heartbeat-Konfigurationen mitbringen
Beispiel: Mail-Plugin bringt Agent mit
{
"agent_definitions": [{
"name": "mail_sorter",
"display_name": "E-Mail-Sortier-Assistent",
"description": "Sortiert eingehende E-Mails automatisch nach Regeln",
"model": "ollama/deepseek-v4-flash",
"tools": ["mail.read", "mail.move", "mail.label"],
"system_prompt": "Du sortierst E-Mails...",
"mode": "reactive",
"trigger_event": "mail.received"
}]
}
Beispiel: Calendar-Plugin bringt Automation mit
{
"automation_templates": [{
"name": "appointment_reminder",
"display_name": "Terminerinnerung 24h vorher",
"trigger": {"type": "schedule", "cron": "0 8 * * *"},
"conditions": [{"field": "entry.start_at", "operator": "lt", "value": "now + 24h"}],
"actions": [{"type": "notification", "title": "Terminerinnerung", "body": "Morgen: ${entry.title}"}]
}]
}
PHASE 4: KI-UI-Steuerung
Ziel: KI-Agent kann UI steuern — Kontakte öffnen, Filter setzen, navigieren. User sieht das Ergebnis in der UI.
Wichtig: Bestehende WebSocket-Infrastruktur im kommunikation Plugin (/api/v1/comm/ws, websocket_manager.py) kann als Referenz dienen.
| # | Aufgabe | Aufwand | Details |
|---|---|---|---|
| 4.1 | UI-Command-Protokoll definieren | 4h | JSON-Protokoll für UI-Befehle: {action: 'navigate', path: '/contacts/123'}, {action: 'filter', entity: 'contacts', filter: {type: 'company'}}, {action: 'open_contact', id: '...'}. |
| 4.2 | WebSocket-Endpoint für KI-UI-Steuerung | 6h | Backend-WebSocket /ws/ai-ui-control. Authentifiziert via Session. KI-Agent sendet Commands, Frontend empfängt. Basiert auf bewährter WebSocket-Infrastruktur aus kommunikation Plugin. |
| 4.3 | Frontend useAIUIControl Hook |
6h | WebSocket-Client im Frontend. Empfängt Commands und führt sie aus. Nutzt React Router, TanStack Query, Zustand Stores. |
| 4.4 | Command: Navigate | 2h | useNavigate() für Route-Wechsel. KI kann zu jeder Seite navigieren. |
| 4.5 | Command: Filter setzen | 4h | URL-Search-Params setzen für Listen-Filter. KI kann Filter setzen (z.B. "Zeige nur Firmen in Berlin"). |
| 4.6 | Command: Contact öffnen | 3h | Navigate zu /contacts/:id + Detail-Daten laden. KI kann Kontakt öffnen und User sieht ihn. |
| 4.7 | Command: Modal öffnen/schließen | 3h | EditModal, CreateModal etc. per Command steuerbar. |
| 4.8 | Command: Tab wechseln | 2h | Detail-Tabs (Dateien, E-Mails, Kalender) per Command wechseln. |
| 4.9 | Command: Settings ändern | 3h | System-Settings, User-Preferences per UI-Command ändern. Wird in UI sichtbar. |
| 4.10 | UI-Action-Feedback an KI | 4h | Frontend sendet Bestätigung zurück: {action: 'navigate', status: 'success', current_path: '/contacts/123'}. KI weiß, dass Command ausgeführt wurde. |
| 4.11 | Visuelle KI-Indikation | 3h | Wenn KI eine Aktion ausführt: kurzer Highlight-Effekt oder Toast "KI führt Aktion aus...". User sieht dass KI agiert. |
| 4.12 | Tests für KI-UI-Steuerung | 4h | Vitest-Tests für Command-Protokoll, useAIUIControl Hook, Command-Ausführung. |
Phase 4 Gesamt: ~44h
PHASE 5: API-Vollständigkeit & KI-Testbarkeit
Ziel: App komplett per API steuerbar. KI kann selbstständig testen und Updates einspielen.
| # | Aufgabe | Aufwand | Details |
|---|---|---|---|
| 5.1 | API-Audit: Alle UI-Funktionen per API erreichbar | 8h | Systematische Prüfung: Jede UI-Aktion hat einen API-Endpoint. Fehlende Endpoints identifizieren und implementieren. Sidebar-Zustand, Tab-Auswahl, Filter-Zustand per API speichern/laden. |
| 5.2 | User-Preferences-API erweitern | 4h | UI-Einstellungen (Sidebar collapsed, theme, language, active tab, sort preferences) per API speichern/laden. |
| 5.3 | Workflow-API-Frontend-Modul | 4h | api/workflows.ts erstellen. Workflow-Definitions CRUD, Instances, Step-History. |
| 5.4 | Playwright E2E-Tests: Setup | 4h | @playwright/test installieren. playwright.config.ts. Test-Helper für Login, API-Calls. |
| 5.5 | Playwright: auth.spec.ts | 3h | Login → Logout E2E-Test. |
| 5.6 | Playwright: contact-crud.spec.ts | 4h | Contact erstellen → bearbeiten → Ansprechpartner hinzufügen → löschen. |
| 5.7 | Playwright: search.spec.ts | 3h | Globale Suche, Filter, Ergebnisse prüfen. |
| 5.8 | Playwright: plugin-toggle.spec.ts | 3h | Plugin aktivieren/deaktivieren, UI-Änderung prüfen. |
| 5.9 | Playwright: mail.spec.ts | 4h | Mail-Konto anlegen, Ordner anzeigen, Mail öffnen. |
| 5.10 | Playwright: dms.spec.ts | 4h | Ordner erstellen, Datei hochladen, Vorschau, teilen. |
| 5.11 | Playwright: calendar.spec.ts | 4h | Termin erstellen, Kalender wechseln, Kanban-View. |
| 5.12 | API-Health-Check-Script für KI | 4h | scripts/ai_health_check.py: Prüft alle API-Endpunkte, gibt strukturierten Report. KI kann das vor/nach Updates laufen lassen. |
| 5.13 | CI/CD-Pipeline für KI-Updates | 6h | scripts/ai_deploy.py: KI kann Build erstellen, Tests laufen, bei Erfolg deployen. Rollback bei Fehler. |
| 5.14 | API-Dokumentation vervollständigen | 4h | OpenAPI/Swagger prüfen. Alle Endpoints dokumentiert. Beispiele für KI. |
| 5.15 | Automatisiertes Backup-System | 8h | pg_dump + Storage-Backup als Cron-Job (nutzt Cron-Scheduler aus Phase 3.5). Backup-Konfiguration in Settings (Intervall, Aufbewahrung, Ziel: lokal/S3/Nextcloud). Restore-Script. Backup-Status in Dashboard. Notification bei Backup-Fehler. |
| 5.16 | MCP-Server Integration | 10h | LeoCRM als MCP-Server: Externe Tools (Claude Desktop, andere KI-Clients) können auf LeoCRM-Daten zugreifen. MCP-Tools für Contacts, Calendar, Mail, DMS. Authentifiziert via API-Token. MCP-Config-Endpoint GET /api/v1/mcp/tools. |
| 5.17 | MCP-Client Integration | 6h | LeoCRM-Agenten können externe MCP-Server nutzen (z.B. Web-Search, Code-Execution, externe Datenquellen). MCP-Client in tool_registry integriert. Admin kann MCP-Server in Settings konfigurieren. Agenten nutzen MCP-Tools wie native Tools. |
| 5.18 | Report Generator: PDF-Support & Druck-Funktionen | 8h | Backend: WeasyPrint für PDF-Generierung aus Jinja2-Templates. Vorgefertigte Berichte: Kontaktliste, Kalender (Woche/Monat), Firmenliste, Audit-Log. Druck-Optimierte Templates (A4, Landscape). output_format um pdf und print erweitern. |
| 5.19 | Report Generator: Frontend-Oberfläche | 10h | Reports.tsx Seite: Template-Liste, Template-Editor (Code-Editor für Jinja2), Report-Generierung mit Live-Preview, Download-History. Vorgefertigte Berichte als Buttons ("Kontakt-Liste drucken", "Kalender drucken"). Druck-Dialog mit Format-Auswahl (A4/A5/Landscape). |
| 5.20 | Custom Fields: Plugin-Felder in UI | 6h | Plugins sollen Custom Fields mitbringen können. Plugin-Manifest um custom_fields Definition erweitern. Frontend: Dynamische Custom-Field-Renderer in Contact-Detail, ContactEditModal. Feld-Typen: text, number, date, select, multiselect, boolean. Felder werden in contacts.custom JSONB gespeichert. |
| 5.21 | Tasks-Plugin | 12h | Eigenes Tasks-Plugin: Freie Aufgaben/Aktivitäten verwalten (Anruf protokollieren, Notiz, Besuch). Verknüpfung mit Kontakten. Tasks haben Status (open/in_progress/done), Priorität, Fälligkeitsdatum, Zuweisung an Nutzer. Tasks-Liste mit Filter. ARQ-Reminder für fällige Tasks. Plugin-Manifest, Models, Routes, Schemas, Frontend-Seite. |
| 5.22 | Saved Searches / Smart Lists | 6h | Jede Listen-Ansicht (Contacts, Mail, Calendar, DMS) bekommt Filter-Funktionalität. Filter können gespeichert werden (Name, Filter-Kriterien). Gespeicherte Filter erscheinen als Tabs oder Sidebar-Einträge. saved_filters Tabelle (tenant-scoped, user-scoped). Frontend: Filter-Builder UI, Save-Button, Load-Gespeicherte-Filter. |
| 5.23 | Deduplication / Merge (über KI/Automatisierung) | 6h | Contacts-Plugin bietet Dubletten-Erkennung: KI-gestützter Vergleich von Kontakten (Name, E-Mail, Telefon). Automation-Template: "Dubletten finden und zusammenführen". Merge-UI: Zwei Kontakte vergleichen, Felder auswählen, zusammenführen. contact_merge_history Tabelle. |
| 5.24 | PWA (Progressive Web App) | 6h | Frontend als PWA planen: manifest.json, Service Worker, Offline-Caching für statische Assets, Add-to-Home-Screen, App-Icon. Vite PWA Plugin installieren. Push-Notifications vorbereiten (Notification API). |
| 5.25 | Dashboard-System ausbauen | 8h | Plugins bringen Dashboard-Komponenten mit und melden diese an. Plugin-Manifest um dashboard_widgets erweitern (bereits in Architektur definiert aber nicht implementiert). Dashboard lädt Widgets dynamisch aus Plugin-Registry. Widget-Typen: Stat-Cards, Charts, Recent-Activity, Quick-Actions. Frontend: Dashboard-Grid mit drag-and-drop Widget-Positionierung. |
Phase 5 Gesamt: ~145h
PHASE 6: React Hook Form + Zod überall
Ziel: Konsistente Form-Validierung in allen Formularen
| # | Aufgabe | Aufwand | Details |
|---|---|---|---|
| 6.1 | ComposeModal (Mail) auf RHF + Zod | 4h | E-Mail-Validierung, Pflichtfelder, CC/BCC. |
| 6.2 | AppointmentModal (Calendar) auf RHF + Zod | 4h | Datum-Validierung, Pflichtfelder, Recurrence. |
| 6.3 | SettingsForms auf RHF + Zod | 6h | SettingsUsers, SettingsRoles, SettingsGroups, SettingsCurrencies, SettingsTaxes, SettingsSequences, SettingsSystem. |
| 6.4 | DMS-Forms (Folder create, Share) auf RHF + Zod | 3h | |
| 6.5 | Tag-Forms auf RHF + Zod | 2h | |
| 6.6 | Mail-Settings-Forms auf RHF + Zod | 4h | Account-Erstellung, Rules, Signatures, Templates. |
Phase 6 Gesamt: ~23h
PHASE 7: Test-Vollendung & Wartbarkeit
Ziel: Vollständige Test-Abdeckung für KI-Wartbarkeit
| # | Aufgabe | Aufwand | Details |
|---|---|---|---|
| 7.1 | Tests für ungetestete Settings-Pages | 6h | SettingsGroups, SettingsSystem, SettingsCurrencies, SettingsTaxes, SettingsSequences, SettingsNotifications, SettingsPlugins. |
| 7.2 | Tests für AI-Komponenten | 4h | ChatWindow, SessionList, SuggestionSidebar, AISettings, ProactiveAISettings. |
| 7.3 | Tests für Calendar-Page | 3h | Calendar.tsx (717 Zeilen), CalendarKanban.tsx. |
| 7.4 | Tests für DMS-Sub-Komponenten | 4h | FileExplorer, SourceTree, FileGrid, FileDetails, BulkActions. |
| 7.5 | Tests für Contact-Sub-Komponenten | 3h | ContactDetail, ContactEditModal, ContactFolderTree. |
| 7.6 | Tests für Comm-Blocks | 3h | BlockRenderer und alle Block-Typen. |
| 7.7 | Tests für Stores | 2h | authStore, uiStore, commStore, pluginToolbarStore, calendarStore. |
| 7.8 | Backend-Test-Lücken schließen | 8h | Tests für fehlende Plugin-Routes, Edge-Cases, Multi-Tenant-Szenarien. |
| 7.9 | Test-Runner-Script für KI | 3h | scripts/ai_run_tests.py: Führt alle Tests aus (Backend + Frontend + E2E), gibt strukturierten Report. |
Phase 7 Gesamt: ~36h
Zusammenfassung: Aufwandsschätzung (korrigiert)
| Phase | Thema | Aufwand | Vorher | Änderung |
|---|---|---|---|---|
| 0 | Vorbereitung & Cleanup | ~77h | ~14h | +63h (Design, Theme, RBAC, LiteLLM, Search-RBAC, Undo, Storage, Import/Export, Config-Cleanup, Mail-Salt, PyMuPDF→pypdf, OnlyOffice→Collabora) |
| 1 | Unified Contact (Backend+Frontend) | ~81h | ~33h | +48h — Company-Referenzen in 6 Plugins + Permission-Registry + Addresses + conftest unterschätzt |
| 2 | Code-Splitting & Performance | ~25h | ~25h | — |
| 3 | Plugin-UI-System | ~58h | ~48h | +10h (Plugin-Install-System) |
| 3.5 | Automation & Agents Plugin | ~105h | — | NEU — Agent Builder, Automation, Cron, Logs, Safety, Agent-zu-Agent, Versionshistorie, MiniApps |
| 4 | KI-UI-Steuerung | ~44h | ~44h | — |
| 5 | API, Testbarkeit, Backup, MCP, Reports, Custom Fields, Tasks, Saved Searches, Dedup, PWA, Dashboard | ~145h | ~57h | +88h |
| 6 | React Hook Form + Zod | ~23h | ~23h | — |
| 7 | Test-Vollendung | ~36h | ~36h | — |
| GESAMT | ~590h | ~280h | +310h |
Empfohlene Reihenfolge
Phase 0 (Vorbereitung & Cleanup)
↓
Phase 1 (Unified Contact — Backend+Frontend) ← Core-CRM-Feature, größte Phase
↓
Phase 2 (Code-Splitting & Performance)
↓
Phase 3 (Plugin-UI-System) ← WordPress-Style, nicht zu lange schieben
↓
Phase 3.5 (Automation & Agents Plugin) ← Agent Builder, Cron-Scheduler, Automation
↓
Phase 4 (KI-UI-Steuerung) ← Baut auf Plugin-System auf
↓
Phase 5 (API-Vollständigkeit & Testbarkeit) ← KI kann selbstständig testen
↓
Phase 6 (React Hook Form + Zod) ← Qualität
↓
Phase 7 (Test-Vollendung) ← Wartbarkeit für KI
Begründung der Reihenfolge:
- Phase 0 zuerst: Dependencies und Cleanup als Fundament
- Phase 1 als Nächstes: Core-CRM-Feature (Contacts) muss vollständig sein. Größte Phase (~74h) weil 'company' überall im Code verankert ist.
- Phase 2: Code-Splitting ist schnell und bringt sofortige Performance-Verbesserung
- Phase 3: Plugin-UI-System — je früher desto besser, sonst wird Umbau später schwieriger
- Phase 4: KI-UI-Steuerung baut auf Plugin-System auf (dynamische Routes, Tabs etc.). Bestehende WebSocket-Infrastruktur aus kommunikation Plugin als Referenz.
- Phase 5: API-Vollständigkeit und E2E-Tests für KI-Wartbarkeit
- Phase 6+7: Qualität und Test-Vollendung
Was bei der Überprüfung gefunden wurde
Phase 1 Korrektur: +41h Aufwand
Die ursprüngliche Schätzung von 33h für Phase 1 war massiv unterschätzt. Die gründliche Code-Analyse zeigte:
'company' als entity_type ist in 6 Plugins verankert:
entity_links: entity_type Pattern, company_router, on_company_deleted Event-Handlerunified_search: CompanySearchProvider, index_company, company.created/updated Events, search_engine Mappingcalendar: entity_type Pattern für EntryLinkstags: entity_type Pattern für Tag-Assignmentsmail: company_id Spalte in mails Tabelle (DB-Migration nötig!)ai/action_mapper: Company-Intents (create/delete/update/list)
Event-Namen müssen migriert werden:
company.created→contact.createdcompany.updated→contact.updatedcompany.deleted→contact.deleted- Betroffen: unified_search, entity_links, workflows, test_sample, manifest.py
DB-Migration nötig:
entity_links.entity_type = 'company'→'contact'tag_assignments.entity_type = 'company'→'contact'calendar_entry_links.entity_type = 'company'→'contact'mails.company_id→mails.contact_id(Spalte umbenennen)
Was NICHT geändert wird:
system_settings.company_name,company_streetetc. → Das ist die CRM-Besitzer-Firmeninfo für Rechnungen. Bleibt wie es ist.CalendarType = 'company'→ Das ist ein Kalender-Typ (Firmenkalender), keine Entity-Referenz. Kann bleiben.
Bestehende WebSocket-Infrastruktur
Das kommunikation Plugin hat bereits eine vollständige WebSocket-Implementierung (/api/v1/comm/ws, websocket_manager.py). Diese kann als Referenz für die KI-UI-Steuerung (Phase 4) dienen — das spart Entwicklungszeit.
KI-Wartbarkeit: Schlüssel-Anforderungen
Damit ein KI-Agent die App selbstständig warten kann:
- Vollständige API-Abdeckung: Jede UI-Funktion per API steuerbar (Phase 5)
- E2E-Tests: Playwright-Tests die KI ausführen kann (Phase 5)
- API-Health-Check: Script das alle Endpunkte prüft (Phase 5)
- Test-Runner: Script das alle Tests ausführt und strukturiert reportet (Phase 7)
- Deploy-Script: KI kann Build erstellen, testen, deployen, rollback (Phase 5)
- Plugin-Richtlinien: Klare Vorgaben damit KI neue Plugins erstellen kann (Phase 3)
- Dokumentation: Aktuelle Architektur-Doku, API-Doku, Plugin-Guide (Phase 0+3+5)
Nächste Schritte
- ✅ Nextcloud Backup erstellt (
/Backups/leocrm/leocrm-backup-20260722.bundle) - ✅ Plan gründlich überprüft und korrigiert (+45h)
- ⬜ Plan freigeben
- ⬜ Phase 0 starten
- ⬜ Planungsdokumente aktualisieren
Test-Strategie (pro Phase)
Phase 0: Vorbereitung & Cleanup
- Pro Task: Unit-Test für geänderte Funktionalität (z.B. Test dass lucide-react Icons rendern, Test dass date-fns formatiert, Test dass Storage Backend local+S3 funktioniert)
- Regression: Alle bestehenden Tests müssen weiterhin durchlaufen
- Lizenz-Test:
pip-licensesScript prüft dass keine AGPL-Packages mehr in requirements.txt
Phase 1: Unified Contact Model
- Pro Task: API-Integration-Test (httpx + pytest) für jeden geänderten Endpoint
- DB-Migration-Test: Test dass Migration 0023 (entity_type company→contact) korrekt ausführt und rollbackbar ist
- Plugin-Test: Pro Plugin (entity_links, unified_search, calendar, tags, mail) Test dass entity_type='contact' funktioniert
- Frontend-Test: Vitest für ContactDetail, ContactEditModal, ContactPerson-Verwaltung
- Cross-Tenant-Test: Test dass Tenant-Isolation nach Migration noch funktioniert
Phase 2: Code-Splitting & Performance
- Bundle-Test: Test dass Initial-Bundle < 300KB (vorher alle Pages im Bundle)
- Virtual Scrolling Test: Test mit 10.000 Datensätzen — Rendering-Zeit < 500ms
- Lazy-Loading Test: Test dass Plugin-Pages nicht im Initial-Bundle sind
Phase 3: Plugin-UI-System
- PluginRegistry-Test: Test dass Manifests korrekt geladen und gerendert werden
- PluginLoader-Test: Test dass lazy-loaded Komponenten mit Suspense funktionieren
- Plugin-Install-Test: Test dass ZIP-Upload validiert und installiert wird
- Error-Boundary-Test: Test dass fehlerhaftes Plugin nicht die ganze App crashen lässt
Phase 3.5: Automation & Agents
- Cron-Scheduler-Test: Test dass Cron-Jobs zur richtigen Zeit enqueued werden
- Workflow-Timeout-Test: Test dass abgelaufene Workflows cancelled werden
- Agent-Runner-Test: Test dass Agent LLM-Call ausführt und Ergebnis zurückgibt (Mock-LLM)
- Automation-Engine-Test: Test dass Event-Trigger → Conditions → Actions korrekt ausgeführt werden
- Agent-zu-Agent-Test: Test dass Agent A Nachricht an Agent B sendet und B reagiert
- Rate-Limiting-Test: Test dass Agent nach Max-Ausführungen gestoppt wird
- Dry-Run-Test: Test dass Dry-Run keine destruktiven Actions ausführt
Phase 4: KI-UI-Steuerung
- WebSocket-Test: Test dass Commands korrekt gesendet und empfangen werden
- Command-Test: Pro Command-Typ (navigate, filter, open_contact, modal, tab, settings) ein Test
- Feedback-Test: Test dass Frontend Bestätigung an KI zurücksendet
Phase 5: API-Vollständigkeit & Features
- E2E-Tests (Playwright): auth, contact-crud, search, plugin-toggle, mail, dms, calendar (7 Specs)
- API-Health-Check-Test: Test dass alle Endpoints erreichbar und korrekt responden
- Backup-Test: Test dass Backup erstellt wird und Restore funktioniert
- MCP-Test: Test dass MCP-Server Tools bereitstellt und MCP-Client Tools nutzt
- Report-Test: Test dass PDF/CSV/Excel generiert wird und korrekt formatiert ist
- Custom-Fields-Test: Test dass Plugin-Felder in UI gerendert und gespeichert werden
- Tasks-Plugin-Test: Vollständige CRUD-Tests für Tasks
- Saved-Searches-Test: Test dass Filter gespeichert und geladen werden
- Dedup-Test: Test dass Dubletten erkannt und gemerged werden
- PWA-Test: Test dass Service Worker registriert wird und Offline-Caching funktioniert
- Dashboard-Test: Test dass Plugin-Widgets dynamisch gerendert werden
Phase 6: React Hook Form + Zod
- Pro Form: Test dass Validierung korrekt funktioniert (Pflichtfelder, E-Mail-Format, Datum-Range)
- Error-Display-Test: Test dass Fehlermeldungen korrekt angezeigt werden
Phase 7: Test-Vollendung
- Coverage-Target: >80% Backend, >70% Frontend
- Test-Runner-Script:
scripts/ai_run_tests.pyführt alle Tests aus und gibt strukturierten Report - Multi-Tenant-Test: Test mit 3 Tenants — Isolation, Cross-Tenant-Access → 404
- Performance-Test: 200k Contacts — List < 500ms, FTS < 500ms
Test-Infrastruktur
- Backend: pytest + httpx + pytest-asyncio + pytest-cov (bereits vorhanden)
- Frontend: Vitest + @testing-library/react (bereits vorhanden)
- E2E: Playwright (neu in Phase 5)
- Test-DB: PostgreSQL mit
pytest-asynciofixture (bereits in conftest.py) - Test-Redis: Redis-Mock oder echte Redis-Instanz
- Mock-LLM: LiteLLM mock mode für AI-Tests (bereits vorhanden)
Agent-Anleitung: Wie ein KI-Agent diesen Plan umsetzt
Dieser Plan ist so strukturiert dass ein KI-Agent (wie Agent Zero) ihn Task-für-Task umsetzen kann.
Vorgehensweise pro Task
- Task lesen: Jeder Task hat Nummer, Aufwand, Beschreibung und Details
- Code prüfen: Vor der Umsetzung den aktuellen Code inspizieren (Dateien lesen, Abhängigkeiten prüfen)
- Minimal-invasiv arbeiten: Nur das ändern was der Task verlangt. Keine Refactoring-Touren.
- Tests schreiben/aktualisieren: Pro Task mindestens ein Test der die Änderung abdeckt
- Commit: Pro Task ein Git-Commit mit klarer Message (z.B.
Phase 0.2: install lucide-react and migrate icons) - Verifizieren: Nach jedem Task: Tests laufen, Build funktioniert, keine Regressionen
Phasen-Reihenfolge ist verbindlich
- Phase N+1 darf erst starten wenn Phase N abgeschlossen ist
- Innerhalb einer Phase können Tasks parallel sein (z.B. 0.2 und 0.3 unabhängig)
- Abhängigkeiten sind in den Task-Beschreibungen genannt
Was ein Agent pro Task braucht
- Dateipfade der zu ändernden Dateien (in Task-Beschreibung genannt)
- Akzeptanzkriterien (in Task-Beschreibung genannt)
- Test-Strategie (pro Task mindestens ein Test)
- Git-Commit pro Task
Plugin-Entwicklung
Wenn ein Agent ein neues Plugin erstellt (z.B. Tasks-Plugin 5.21):
- Plugin-Verzeichnis in
app/plugins/builtins/<name>/erstellen plugin.pymit Manifest (Name, Version, Dependencies, Routes, Permissions, Events)models.pymit SQLAlchemy Models (TenantMixin!)schemas.pymit Pydantic Schemasroutes.pymit FastAPI Router (require_permission!)services.pymit Business-Logic- Migration in
migrations/Verzeichnis - Frontend-Komponenten in
frontend/src/components/<name>/ - Frontend-Seite in
frontend/src/pages/<Name>.tsx - API-Modul in
frontend/src/api/<name>.ts - Route in
frontend/src/routes/index.tsxregistrieren - i18n-Keys in
frontend/src/i18n/locales/de.jsonunden.json - Tests in
tests/test_<name>.pyundfrontend/src/__tests__/<name>/
Plugin-Manifest-Format (für neue Plugins)
manifest = PluginManifest(
name="my_plugin",
version="1.0.0",
display_name="My Plugin",
description="What it does",
dependencies=["permissions"], # other plugins this depends on
routes=[PluginRouteDef(path="/api/v1/my-plugin", module="...", router_attr="router")],
events=["my.event"], # events this plugin listens to
migrations=["0001_initial.sql"],
permissions=["my_plugin:read", "my_plugin:write"],
is_core=False,
# Neue Felder (nach Phase 3+3.5):
# agent_definitions=[...], # Agent-Templates
# automation_templates=[...], # Automation-Vorlagen
# cron_jobs=[...], # Periodische Tasks
# custom_fields=[...], # Custom Field Definitionen
# dashboard_widgets=[...], # Dashboard-Komponenten
# miniapps=[...], # MiniApp-Definitionen
)
Wichtige Regeln für Agent-Updates
- Niemals Tests ändern um sie grün zu bekommen — Code fixen nicht Tests anpassen
- Niemals .env committen — Secrets gehören nicht ins Repo
- Jede DB-Änderung braucht Alembic-Migration — keine manuellen SQL-Changes
- Jede API-Route braucht RBAC —
require_permission()auf jedem Endpoint - Jedes Plugin-Model braucht TenantMixin — tenant_id auf jeder Tabelle
- Frontend-Änderungen brauchen i18n — alle Texte in de.json und en.json
- Pro Task ein Commit — nicht mehrere Tasks in einem Commit
- Nach jedem Task: Tests + Build verifizieren — keine Regressionen
- Nach jedem Task: Progress aktualisieren —
PROGRESS.mdim Repo aktualisieren mit: Task-Nummer, Status (done/in-progress/blocked), Datum, was gemacht wurde, was als Nächstes ansteht. Zwingend für jeden Agenten der am Plan arbeitet.