Phase 0.1: update planning docs to current state

- 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
This commit is contained in:
Agent Zero
2026-07-23 00:35:40 +02:00
parent c2143eea19
commit 3f2307ab54
5 changed files with 1025 additions and 527 deletions
+754
View File
@@ -0,0 +1,754 @@
# 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 `kommunikation` Plugin 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
1. **entity_type='company'** in Plugins (entity_links, calendar, tags, mail) → referenziert eine Firma als Entität → **MUSS zu 'contact' werden**
2. **system_settings.company_*** Felder (company_name, company_street etc.) → CRM-Besitzer-Firmeninfo für Rechnungen → **BLEIBT wie es ist**
3. **CalendarType='company'** → Kalender-Typ (Firmenkalender) → kann bleiben oder zu 'organization' umbenannt werden (kosmetisch)
---
## Architektur-Entscheidungen (freigegeben 2026-07-22)
1. **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.
2. **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.**
3. **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.
4. **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ände
- `secondary` (Slate #64748b) — Text, Borders, Hintergründe
- `accent` (Fuchsia #d946ef) — Hervorhebungen, Info-Badges
- `danger` (Rot #dc2626) — Löschen, Fehler
- `warning` (Amber #f59e0b) — Warnungen
- `success` (Grün #16a34a) — Erfolg, Bestätigungen
- Jede Farbe mit 50-900 Schattierungen
- **Dark Mode** via `darkMode: 'class'` — CSS-Variablen in `:root` und `.dark`
**Typografie:**
- Font: `Inter` (system-ui fallback)
- Mono: `JetBrains Mono` fü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-ring` Klasse, `border-secondary-200`, `rounded-md`
- **Modal**: `size` prop (sm/md/lg/xl), `ConfirmDialog` fü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-ring` Klasse: `focus-visible:ring-2 focus-visible:ring-primary-500`
- `btn-touch` Klasse: `min-h-touch min-w-touch` (44px)
- `sr-only` und `sr-only-focusable` Klassen
- `prefers-reduced-motion` Media Query
- `aria-hidden="true"` auf dekorativen SVGs
- `aria-label` auf 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:**
1. Farbsystem mit Verwendungsregeln (wann welche Farbe)
2. Typografie-Hierarchie (Überschriften, Body-Text, Labels)
3. Layout-Patterns (3-Spalten, Modal, Settings-Tree)
4. Komponenten-Verwendung (welche Komponente für was)
5. Spacing & Sizing Konventionen
6. Accessibility-Regeln
7. Dark-Mode-Regeln
8. Plugin-UI-Patterns für neue Plugins
9. Do's & Don'ts
10. 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:**
1. Pro Plugin passende Permissions im Manifest definieren
2. Alle Plugin-Routes mit `require_permission()` absichern
3. Permission-Registry registriert Plugin-Permissions automatisch beim Aktivieren
4. Admin kann Permissions in Rollen-Editor zuweisen
5. Tests: User ohne Permission → 403, User mit Permission → 200
**Zusätzlich in Phase 1 (Permission-Registry-Cleanup):**
- `companies:read/write/delete` aus `CORE_PERMISSIONS` entfernen (wird zu `contacts:read/write/delete`)
- `CORE_FIELD_DEFINITIONS` aktualisieren: alte Felder (`first_name`, `last_name`, `mobile`, `position`, `department`, `linkedin_url`) durch unified Contact-Felder ersetzen (`firstname`, `surname`, `phone_1`, `email_1`, etc.)
- `companies` Field-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:**
1. `litellm` als Python-Dependency hinzufügen
2. `llm_client.py` auf LiteLLM umstellen: `litellm.acompletion()` statt direktem httpx-Call
3. Konfiguration via Env-Vars: `AI_MODEL`, `AI_API_KEY`, `AI_API_BASE` (bleiben gleich), plus `AI_PROVIDER` (neu: openai/anthropic/google/ollama/etc.)
4. AI Assistant Plugin nutzt LiteLLM für Multi-Provider-Support
5. AI Proactive Plugin nutzt LiteLLM für Suggestions
6. Zukünftige Plugins können LiteLLM einfach nutzen — einheitliches Interface
7. Mock-Mode für Tests beibehalten (wenn kein API-Key gesetzt)
8. 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|contact)$``^contact$`. `company_router` entfernen. `on_company_deleted``on_contact_deleted`. Event `company.deleted``contact.deleted`. DB-Migration: bestehende EntityLinks mit entity_type='company' auf 'contact' migrieren. |
| 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|contact)$``^contact$`. CalendarEntryLink entity_type anpassen. DB-Migration: bestehende Links migrieren. CalendarType='company' kann bleiben (Kalender-Typ, nicht Entity-Referenz). |
| 1.12 | **tags Plugin** aktualisieren | 3h | `entity_type` Pattern von `^(company|contact|file|folder)$``^(contact|file|folder)$`. DB-Migration: bestehende Tag-Assignments mit entity_type='company' auf 'contact' migrieren. |
| 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 | Firmen | Personen". |
| 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**
```json
{
"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**
```json
{
"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:**
1. Phase 0 zuerst: Dependencies und Cleanup als Fundament
2. Phase 1 als Nächstes: Core-CRM-Feature (Contacts) muss vollständig sein. Größte Phase (~74h) weil 'company' überall im Code verankert ist.
3. Phase 2: Code-Splitting ist schnell und bringt sofortige Performance-Verbesserung
4. Phase 3: Plugin-UI-System — je früher desto besser, sonst wird Umbau später schwieriger
5. Phase 4: KI-UI-Steuerung baut auf Plugin-System auf (dynamische Routes, Tabs etc.). Bestehende WebSocket-Infrastruktur aus kommunikation Plugin als Referenz.
6. Phase 5: API-Vollständigkeit und E2E-Tests für KI-Wartbarkeit
7. 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-Handler
- `unified_search`: CompanySearchProvider, index_company, company.created/updated Events, search_engine Mapping
- `calendar`: entity_type Pattern für EntryLinks
- `tags`: entity_type Pattern für Tag-Assignments
- `mail`: 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.created`
- `company.updated``contact.updated`
- `company.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_street` etc. → 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:
1. **Vollständige API-Abdeckung:** Jede UI-Funktion per API steuerbar (Phase 5)
2. **E2E-Tests:** Playwright-Tests die KI ausführen kann (Phase 5)
3. **API-Health-Check:** Script das alle Endpunkte prüft (Phase 5)
4. **Test-Runner:** Script das alle Tests ausführt und strukturiert reportet (Phase 7)
5. **Deploy-Script:** KI kann Build erstellen, testen, deployen, rollback (Phase 5)
6. **Plugin-Richtlinien:** Klare Vorgaben damit KI neue Plugins erstellen kann (Phase 3)
7. **Dokumentation:** Aktuelle Architektur-Doku, API-Doku, Plugin-Guide (Phase 0+3+5)
---
## Nächste Schritte
1. ✅ Nextcloud Backup erstellt (`/Backups/leocrm/leocrm-backup-20260722.bundle`)
2. ✅ Plan gründlich überprüft und korrigiert (+45h)
3. ⬜ Plan freigeben
4. ⬜ Phase 0 starten
5. ⬜ 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-licenses` Script 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.py` fü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-asyncio` fixture (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
1. **Task lesen:** Jeder Task hat Nummer, Aufwand, Beschreibung und Details
2. **Code prüfen:** Vor der Umsetzung den aktuellen Code inspizieren (Dateien lesen, Abhängigkeiten prüfen)
3. **Minimal-invasiv arbeiten:** Nur das ändern was der Task verlangt. Keine Refactoring-Touren.
4. **Tests schreiben/aktualisieren:** Pro Task mindestens ein Test der die Änderung abdeckt
5. **Commit:** Pro Task ein Git-Commit mit klarer Message (z.B. `Phase 0.2: install lucide-react and migrate icons`)
6. **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):
1. Plugin-Verzeichnis in `app/plugins/builtins/<name>/` erstellen
2. `plugin.py` mit Manifest (Name, Version, Dependencies, Routes, Permissions, Events)
3. `models.py` mit SQLAlchemy Models (TenantMixin!)
4. `schemas.py` mit Pydantic Schemas
5. `routes.py` mit FastAPI Router (require_permission!)
6. `services.py` mit Business-Logic
7. Migration in `migrations/` Verzeichnis
8. Frontend-Komponenten in `frontend/src/components/<name>/`
9. Frontend-Seite in `frontend/src/pages/<Name>.tsx`
10. API-Modul in `frontend/src/api/<name>.ts`
11. Route in `frontend/src/routes/index.tsx` registrieren
12. i18n-Keys in `frontend/src/i18n/locales/de.json` und `en.json`
13. Tests in `tests/test_<name>.py` und `frontend/src/__tests__/<name>/`
### Plugin-Manifest-Format (für neue Plugins)
```python
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
1. **Niemals Tests ändern** um sie grün zu bekommen — Code fixen nicht Tests anpassen
2. **Niemals .env committen** — Secrets gehören nicht ins Repo
3. **Jede DB-Änderung braucht Alembic-Migration** — keine manuellen SQL-Changes
4. **Jede API-Route braucht RBAC**`require_permission()` auf jedem Endpoint
5. **Jedes Plugin-Model braucht TenantMixin** — tenant_id auf jeder Tabelle
6. **Frontend-Änderungen brauchen i18n** — alle Texte in de.json und en.json
7. **Pro Task ein Commit** — nicht mehrere Tasks in einem Commit
8. **Nach jedem Task: Tests + Build verifizieren** — keine Regressionen
9. **Nach jedem Task: Progress aktualisieren**`PROGRESS.md` im 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.**
+37
View File
@@ -0,0 +1,37 @@
# LeoCRM — Umbau Progress
**Plan:** `MASTER-PLAN.md`
**Start:** 2026-07-23
---
## Phase 0: Vorbereitung & Cleanup
| Task | Status | Datum | Notiz |
|---|---|---|---|
| 0.1 | 🔄 in-progress | 2026-07-23 | Veraltete Planungsdokumente aktualisieren |
| 0.2 | ⬜ pending | | lucide-react installieren + Icons migrieren |
| 0.3 | ⬜ pending | | date-fns installieren + Datum-Formatierung |
| 0.4 | ⬜ pending | | hooks.ts aufteilen |
| 0.5 | ⬜ pending | | Store-Verzeichnis konsolidieren |
| 0.6 | ⬜ pending | | Frontend-Bestandsanalyse als Dokument speichern |
| 0.7 | ⬜ pending | | UI-Design-Richtlinien erstellen |
| 0.8 | ⬜ pending | | Theme-Customization Backend |
| 0.9 | ⬜ pending | | Theme-Customization Frontend |
| 0.10 | ⬜ pending | | RBAC-Audit & Plugin-Permissions nachrüsten |
| 0.11 | ⬜ pending | | LiteLLM-Cleanup & alte llm_client.py migrieren |
| 0.12 | ⬜ pending | | KI-Agent-Framework in Plugin-Richtlinien dokumentieren |
| 0.13 | ⬜ pending | | Heartbeat konfigurierbar machen |
| 0.14 | ⬜ pending | | Unified Search: Field-Level RBAC nachrüsten |
| 0.15 | ⬜ pending | | Undo/History-System für CRUD-Operationen |
| 0.16 | ⬜ pending | | Storage Backend implementieren (S3-Support) |
| 0.17 | ⬜ pending | | Import/Export an unified Contact Model anpassen |
| 0.18 | ⬜ pending | | .gitignore & Config-Cleanup |
| 0.19 | ⬜ pending | | Mail-Salt Security-Fix |
| 0.20 | ⬜ pending | | AGPL-Lizenzen durch pypdf + Collabora ersetzen |
---
## Phase 1-7: Noch nicht gestartet
Siehe `MASTER-PLAN.md` für alle Tasks.
+48
View File
@@ -6,6 +6,8 @@
> **v1 Tasks:** T01, T02, T03, T07, T09, T10
> **v2 Tasks:** T04, T05, T06, T11, T08a, T08b, T08c
> **Update 2026-07-23:** Implementation Status siehe Abschnitt am Ende dieses Dokuments.
**Projekt:** leocrm — Greenfield
**Architekt:** Solution Architect (Agent Zero)
**Datum:** 2026-06-28
@@ -2017,3 +2019,49 @@ e2e/
- AGENTS.md status: PENDING
- Open questions: 4 (listed above, non-blocking for implementation)
- Ready for implementation: NO (pending quality_reviewer review + task graph + AGENTS.md)
---
## 11. Implementation Status (Update 2026-07-23)
### Was implementiert wurde
| Komponente | Status | Anmerkung |
|-----------|--------|-----------|
| FastAPI Backend | ✅ Fertig | ~35.800 Zeilen, 22 Routes, 18 Services, 20 Models |
| PostgreSQL 16 + asyncpg | ✅ Fertig | 22 Alembic-Migrationen |
| Multi-Tenant + RLS | ✅ Fertig | ORM-Filter + PostgreSQL RLS (Migration 0015) |
| RBAC + Field-Level Permissions | ✅ Fertig | Role + Groups + Permission Registry |
| Session-Auth + Rate Limiting | ✅ Fertig | Redis + bcrypt + CSRF |
| Plugin-System | ✅ Fertig | 12 Plugins, Registry, Manifest, Lifecycle, Migration Runner |
| Unified Contact Model | ✅ Fertig | Contact type='company'\|'person', ContactPerson 1:N |
| Workflow Engine | ✅ Fertig | 306 Zeilen, 4 Step-Types, Event-Trigger |
| KI-Copilot + AI Assistant | ✅ Fertig | LiteLLM + PydanticAI + tool_registry |
| AI Proactive | ✅ Fertig | Context-aware, SSE, Heartbeat, Deep Analysis |
| Unified Search | ✅ Fertig | Hybrid FTS+Vector (pgvector), RRF, KI Query Understanding |
| Kommunikation | ✅ Fertig | WebSocket, MiniApps, Rich Content Blocks |
| Mail Plugin | ✅ Fertig | IMAP/SMTP, PGP, Vacation, Rules, Templates |
| Calendar Plugin | ✅ Fertig | ICS, Kanban, Resources, Subtasks, Recurrence |
| DMS Plugin | ✅ Fertig | Folders, Files, Preview, OnlyOffice (→Collabora), Share |
| Report Generator | ⚠️ Teilweise | Backend (CSV/Excel/JSON), Frontend fehlt, PDF fehlt |
| React Frontend | ✅ Fertig | ~30.000 Zeilen, 27 Pages, 70 Components, i18n DE/EN |
| Docker Multi-Stage Build | ✅ Fertig | Frontend+Backend in einem Container |
| Monitoring | ✅ Fertig | Prometheus + structlog + Health Checks |
### Was noch fehlt (im MASTER-PLAN.md eingeplant)
Siehe `MASTER-PLAN.md` für den vollständigen Umbau-Plan (~590h, 8 Phasen + Phase 3.5).
Wichtigste Lücken:
- Storage Backend (S3-Support) — Phase 0.16
- Company-Routes entfernen (unified Contact) — Phase 1
- Plugin-UI-System (PluginRegistry/PluginLoader) — Phase 3
- Automation & Agents Plugin (Agent Builder, Cron-Scheduler) — Phase 3.5
- KI-UI-Steuerung (WebSocket Commands) — Phase 4
- E2E Tests (Playwright) — Phase 5
- Backup-System — Phase 5.15
- MCP Integration — Phase 5.16-5.17
- Report Frontend + PDF — Phase 5.18-5.19
- Custom Fields, Tasks-Plugin, Saved Searches, PWA, Dashboard — Phase 5.20-5.25
- Code-Splitting + Virtual Scrolling — Phase 2
- AGPL-Lizenzen ersetzen (PyMuPDF→pypdf, OnlyOffice→Collabora) — Phase 0.20
+161 -525
View File
@@ -1,540 +1,176 @@
# LeoCRM — Codebase vs Requirements Analysis
# LeoCRM — Codebase vs Requirements (IST-Stand Juli 2026)
**Datum:** 2026-06-28
**Prüfer:** Codebase Explorer (Agent Zero)
**Methode:** Read-only-Inspektion der bestehenden Codebase gegen bereinigte `requirements.md`
**Datum:** 2026-07-23
**Prüfer:** Agent Zero
**Methode:** Vollständige Code-Inspektion gegen requirements.md und architecture.md
---
## 1. Bestehende Architektur-Übersicht
### Stack
## 1. Aktueller Stack
| Komponente | Code-Realität | Requirements | Status |
|------------|-------------|-------------|--------|
| Backend | FastAPI 0.115.6 | FastAPI | ✅ kompatibel |
| Python | 3.11+ (pyproject.toml) | 3.12 (Annahme 10) | ⚠️ Minor-Abweichung |
| Datenbank | **SQLite** (WAL mode) | **PostgreSQL 16** | ❌ KONFLIKT |
| ORM | SQLAlchemy 2.0.36 | (offen — architecture.md) | ✅ kompatibel |
| Frontend | **Jinja2 Templates** (server-side) | **React SPA** (client-side) | ❌ KONFLIKT |
| Auth | Starlette SessionMiddleware (Cookie) | Session-basiert (Cookie) | ✅ kompatibel |
| Deployment | Docker (single container) | Coolify (Docker) | ⚠️ Single-Container vs Multi-Container |
| Testing | pytest (backend only) | pytest + Vitest + Playwright | ⚠️ Backend-only |
| Backend | FastAPI 0.115+ | FastAPI | ✅ kompatibel |
| Python | 3.12 (Dockerfile) | 3.12 | ✅ kompatibel |
| Datenbank | PostgreSQL 16 + asyncpg | PostgreSQL 16 | ✅ erfüllt |
| ORM | SQLAlchemy 2.0 async | SQLAlchemy 2.0 | ✅ erfüllt |
| Frontend | React 18 SPA (Vite) | React SPA | ✅ erfüllt |
| Auth | Session-based (Redis + HttpOnly Cookie) | Session-based | ✅ erfüllt |
| Deployment | Docker Multi-Stage + Coolify | Docker + Coolify | ✅ erfüllt |
| Testing | pytest + httpx (Backend), Vitest (Frontend) | pytest + Vitest + Playwright | ⚠️ Playwright fehlt |
| KI | LiteLLM + PydanticAI | KI-Copilot | ✅ erfüllt + erweitert |
| Search | pgvector + FTS Hybrid (RRF Fusion) | FTS | ✅ übertroffen |
### Projekt-Struktur
## 2. Projekt-Struktur (IST)
```
app/
├── main.py — FastAPI app, lifespan, middleware, router wiring
├── config.py — Pydantic Settings (env: LEOCRM_*)
├── deps.py — Auth dependencies (get_current_user, require_admin)
├── db/
│ ├── models.py — 862 Zeilen, 15 SQLAlchemy-Modelle (alle Core, keine Plugins)
│ ├── session.py — SQLite-Engine, SessionLocal, get_db dependency
── init_db.py Table creation + demo seed (admin/admin)
├── routes/
│ ├── api_routes.py — JSON auth endpoints (/api/auth/login, /api/auth/logout)
│ ├── html_routes.py HTML auth endpoints (/login, /logout — Jinja2)
│ ├── company_routes.py— JSON API /api/companies (CRUD, search, export)
│ ├── contact_routes.py— JSON API /api/contacts (CRUD, search)
│ ├── dms_routes.py — JSON API /api/dms/* (folders, files, search, links, bulk)
│ ├── tag_routes.py — JSON API /api/tags (CRUD, assign, bulk-assign)
│ ├── calendar_routes.py— JSON API /api/calendars, /api/entries (CRUD, shares, subtasks, attendees, links)
│ ├── notification_routes.py — JSON API /api/notifications
│ ├── import_routes.py — JSON API /api/companies/import, /api/contacts/import (CSV)
│ ├── public_routes.py — Public share links /api/public/share/{token}
│ └── health_routes.py — /api/health
├── services/
│ ├── auth_service.py — bcrypt password hashing, authenticate_user
│ ├── company_service.py — Company CRUD logic
│ ├── contact_service.py — Contact CRUD logic
│ ├── dms_service.py — DMS file/folder operations (26KB, größte Service-Datei)
│ ├── tag_service.py — Tag CRUD + assignment
│ ├── calendar_service.py — Calendar/entry/subtask/attendee/notification logic (21KB)
│ ├── permission_service.py— DMS permissions + share links
│ ├── import_service.py — CSV import for companies/contacts
│ └── export_service.py — CSV/XLSX export for companies
├── schemas/ — Pydantic schemas (auth, company, contact, dms, tag, calendar, common)
└── templates/ — Jinja2 HTML templates (login, register, dashboard, company_form, contact_form, contact_list, base)
├── deps.py — Auth dependencies, require_permission
├── core/
│ ├── auth.py — Session auth, bcrypt, Redis session store
│ ├── tenant.py — Tenant-scoping ORM filter
── permissions.py — RBAC resolver with Redis cache
│ ├── permission_registry.py — Central permission catalog
│ ├── event_bus.py — In-process async event bus
│ ├── service_container.py — DI container
│ ├── cache.py — Redis cache wrapper
│ ├── jobs.py — ARQ job queue integration
│ ├── worker.py — ARQ worker configuration
│ ├── audit.py — Audit log + deletion log
│ ├── notifications.py — Notification service
│ ├── monitoring.py — Prometheus metrics + structlog
│ ├── rate_limit.py — Redis-based rate limiting
│ ├── middleware.py — CSRF, CORS, request logging
│ └── seeds.py — Seed data
├── models/ — 20 SQLAlchemy models (all with TenantMixin)
├── schemas/ — 19 Pydantic schema modules
├── services/ — 18 service modules
├── routes/ — 22 FastAPI routers
├── plugins/
│ ├── base.py — BasePlugin class
│ ├── manifest.py — PluginManifest, PluginRouteDef
│ ├── registry.py — PluginRegistry (698 lines)
│ ├── migration_runner.py — Plugin DB migration runner
│ └── builtins/ — 12 built-in plugins
├── workflows/
│ ├── engine.py — Workflow execution engine (306 lines)
│ └── code/onboarding.py — Onboarding workflow
├── ai/
│ ├── llm_client.py — LLM client (LiteLLM migration pending)
│ └── action_mapper.py — NL→API action mapping
└── utils/
frontend/
├── src/
│ ├── pages/ — 27 pages (~7.826 lines)
│ ├── components/ — 70 components (~13.893 lines)
│ ├── api/ — 12 API modules (~3.456 lines)
│ ├── store/ + stores/ — 5 Zustand stores (~461 lines)
│ ├── hooks/ — 5 custom hooks (~247 lines)
│ ├── i18n/ — DE + EN (750 keys each)
│ └── routes/ — Router + ProtectedRoute
├── package.json — 26 deps, 15 devDeps
├── vite.config.ts — React + Vitest + proxy
└── tailwind.config.js — Design tokens, dark mode
```
### Patterns
- **Monolith:** Single FastAPI app, alle Module fest eingebaut
- **Dual-Interface:** HTML routes (Jinja2) + JSON API routes parallel
- **Service-Layer:** Business-Logik in `services/`, Routes sind dünn
- **SQLAlchemy 2.0:** DeclarativeBase, Mapped types, mapped_column
- **Soft-Delete:** `deleted_at` auf Company, Contact, Folder, File
- **N:M Junctions:** CompanyContact, TagAssignment, FileEntityLink, EntryLink, CalendarShare
- **RBAC:** 3 Rollen (admin, editor, viewer) — hardcoded in `require_admin` dependency
- **Demo-Seed:** init_db() erstellt admin/admin + 2 Firmen + 3 Kontakte
---
## 2. Konflikte: Requirements vs Code-Realität
### K1: Multi-Tenant (F-AUTH-07, F-CORE-02) — KRITISCH
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| tenant_id | Auf allen Core-Tabellen | **Nirgendwo vorhanden** |
| Tenant-Isolation | ORM filtert automatisch | **Keine Filterung** |
| User-Tenant-Zuordnung | User kann zu mehreren Tenants gehören | **Nicht implementiert** |
| Tenant-Switch UI | Wechsel aktiver Tenant | **Nicht vorhanden** |
| Plugin-Tabellen | Müssen tenant_id haben | **N/A (keine Plugins)** |
**Evidence:**
- `models.py` Zeile 42: `class User(Base):` docstring sagt explizit `"Login account for LeoCRM (single-tenant)."`
- Keine `tenant_id`-Spalte auf Company, Contact, Folder, File, Tag, Calendar, CalendarEntry, Notification, Permission, ShareLink
- `deps.py`: Session speichert nur `user_id`, kein `tenant_id`-Kontext
- Keine Tenant-Modell-Klasse existiert
**Impact:** Fundamentale Architektur-Veränderung erforderlich. Jede Tabelle braucht tenant_id, ORM-Queries müssen tenant-gefiltert sein, User-Tenant-Mapping-Tabelle nötig.
---
### K2: Plugin-System (F-PLUGIN-01, F-PLUGIN-02) — KRITISCH
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| Plugin-Architektur | Core-Feature v1 | **Nicht existent** |
| DMS/Kalender/Tags/Mail | Als Plugins implementiert | **Fest im Core eingebaut** |
| Plugin-Manifest | Definiertes Format | **Nicht vorhanden** |
| Lifecycle-Hooks | install/activate/deactivate/uninstall | **Nicht vorhanden** |
| Plugin-API-Endpunkte | Plugins registrieren eigene Routes | **Nicht vorhanden** |
| Plugin-DB-Migration | Eigene Migrationen | **Nicht vorhanden** |
| Plugin-Abhängigkeiten | Deklarierbar | **Nicht vorhanden** |
**Evidence:**
- `grep -rn 'plugin\|Plugin\|manifest\|lifecycle\|activate\|deactivate' app/` → **0 Treffer**
- DMS: `models.py` Folder/File/FileEntityLink + `dms_service.py` (26KB) + `dms_routes.py` — alles fest im Core
- Kalender: `models.py` Calendar/CalendarShare/CalendarEntry/Attendee/EntryLink/SubTask + `calendar_service.py` (21KB) + `calendar_routes.py` — fest im Core
- Tags: `models.py` Tag/TagAssignment + `tag_service.py` + `tag_routes.py` — fest im Core
- Keine Plugin-Registry, kein Plugin-Loader, kein Manifest-Format
**Impact:** Komplette Plugin-Architektur muss neu gebaut werden. Bestehende DMS/Kalender/Tag-Module müssen in Plugins umgewandelt werden.
---
### K3: Datenbank — SQLite vs PostgreSQL — KRITISCH
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| DB-Engine | PostgreSQL 16 | **SQLite** |
| Connection-Pooling | PostgreSQL MVCC | **SQLite WAL, check_same_thread=False** |
| Concurrent Writes | Multi-User fähig | **SQLite limitiert** |
**Evidence:**
- `config.py`: `db_path: str = Field(default=str(Path("/data/leocrm.db")))` → SQLite-Datei
- `config.py`: `database_url` property → `f"sqlite:///{self.db_path}"`
- `session.py`: SQLite-spezifische PRAGMAs (`PRAGMA foreign_keys = ON`, `PRAGMA journal_mode = WAL`)
- `session.py`: `connect_args={"check_same_thread": False}` — SQLite-only
- `pyproject.toml`: Keine `psycopg2`/`asyncpg`/`psycopg`-Dependency
**Impact:** DB-Layer muss auf PostgreSQL umgestellt werden. Session-Engine, PRAGMAs, connect_args müssen angepasst werden.
---
### K4: Frontend — Jinja2 vs React SPA — KRITISCH
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| Frontend | React SPA (client-side) | **Jinja2 Templates (server-side)** |
| i18n | DE + EN, Sprachwahl persistiert | **Nicht implementiert** |
| UI-Plugin-Framework | Plugins registrieren UI-Komponenten | **Nicht vorhanden** |
**Evidence:**
- `app/templates/`: 7 Jinja2-HTML-Templates (login, register, dashboard, company_form, contact_form, contact_list, base)
- `html_routes.py`: Jinja2Templates, TemplateResponse
- Keine `package.json`, keine `.tsx`/`.jsx`-Dateien, kein React/Vite-Setup
- `pyproject.toml`: `jinja2==3.1.5` als Dependency
- Requirements Annahme 3: "SPA-Frontend: Client-side rendering mit React SPA (bestätigt durch genehmigten Prototyp leocrm-prototype-x7k2p9)"
**Impact:** Komplettes Frontend muss als React SPA neu gebaut werden. Jinja2-Templates und HTML-Routes werden obsolet. UI-Plugin-Framework (F-CORE-04) muss in React integriert werden.
---
### K5: F-CORE-01 — Event Bus — FEHLT
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| Event Bus | Core-Feature v1 | **Nicht implementiert** |
| Events emit/subscribe | Typisiert, Payload, asynchron | **Nicht vorhanden** |
| Plugin-Listener | Registrieren beim Aktivieren | **N/A** |
**Evidence:** `grep -rn 'event.bus\|EventBus\|event_bus\|emit\|subscribe\|listener' app/` → **0 Treffer**
---
### K6: F-CORE-05 — Service Container / DI — FEHLT
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| Service Container | Core-Services über Container | **Nicht implementiert** |
| DI für Plugins | Services injiziert | **N/A** |
| Mocking für Tests | Mock-Services injizierbar | **Nur DB-Session override** |
**Evidence:** Services werden direkt importiert (`from app.services import company_service`), nicht über Container. FastAPI `Depends()` ist das einzige DI-Muster, aber nur für Request-Scoped dependencies (DB-Session, Current-User).
---
### K7: F-CORE-06 — API-First Architecture — TEILWEISE
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| Alle Features über API | API-First | **Teilweise** — API routes existieren für alle Module |
| UI ist API-Client | UI nutzt API | **❌ Jinja2 rendert server-side** |
| API versioniert | z.B. /api/v1/ | **❌ Keine Versionierung** |
| OpenAPI/Swagger | Auto-gen, dokumentiert | **⚠️ FastAPI auto-gen existiert, aber nicht explizit konfiguriert** |
| Plugin-API-Endpunkte | Registrierbar | **N/A** |
| KI-Copilot nutzt API | Gleiche Endpunkte | **Nicht implementiert** |
**Evidence:**
- API routes: `/api/companies`, `/api/contacts`, `/api/dms/*`, `/api/tags/*`, `/api/calendars`, `/api/entries`, `/api/notifications`, `/api/auth/*`
- Kein `/api/v1/` Prefix — alle routes sind unversioniert
- FastAPI generiert automatisch OpenAPI unter `/openapi.json`, aber nicht explizit konfiguriert oder dokumentiert
- HTML routes existieren parallel (`/login`, `/` dashboard) — UI ist NICHT API-Client
---
### K8: F-CORE-07 — Async Job Queue — FEHLT
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| Queue-System | Background-Jobs asynchron | **Nicht implementiert** |
| Retry-Logic | Automatische Retries | **Nicht vorhanden** |
| Dead-Letter-Queue | Bei wiederholtem Fehlschlag | **Nicht vorhanden** |
| Job-Status UI | Sichtbar im UI | **Nicht vorhanden** |
**Evidence:** `grep -rn 'celery\|Celery\|queue\|Queue\|async_job\|background_job\|job_queue' app/` → **0 Treffer**
---
### K9: F-CORE-08 — Caching-Strategie — FEHLT
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| Cache-Backend | Sessions, Query-Cache, Plugin-Data | **Nicht implementiert** |
| Cache-Invalidierung | Event-basiert | **N/A** |
| TTL-Caching | Fallback | **Nur `@lru_cache` für Settings** |
**Evidence:** `grep -rn 'cache\|Cache\|redis\|Redis' app/` → nur `functools.lru_cache` in `config.py` für Settings-Caching. Kein Redis, kein Query-Cache.
---
### K10: F-CORE-09 — User-Profile und Preferences — FEHLT
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| User-Profile | Profil mit Preferences | **Nicht implementiert** |
| Sprache/Zeitzone/Theme | Umschaltbar | **Nicht vorhanden** |
| Dashboard-Konfiguration | Konfigurierbar | **Nicht vorhanden** |
| Plugin-Preferences | Eigene Felder registrierbar | **N/A** |
**Evidence:** `User`-Modell hat nur: id, username, password_hash, role, personal_folder_id, default_calendar_id, created_at. Keine Preferences, keine Sprache, keine Zeitzone.
---
### K11: F-CORE-10 — Storage-Backend — FEHLT
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| S3-kompatibel | Konfigurierbar | **Nicht implementiert** |
| Lokales Volume | Alternative | **Lokales Dateisystem** |
| Presigned-URLs | Download ohne Plugin-Code | **Nicht vorhanden** |
| Storage-Service | Core-Service für Plugins | **Direkter Dateizugriff** |
**Evidence:**
- `config.py`: `dms_storage_path: str = Field(default="/data/dms")` — lokales Verzeichnis
- `dms_service.py`: Direkter Dateizugriff via `open()`, `Path`-Operationen
- Keine S3/MinIO/boto3-Integration
- `grep -rn 's3\|S3\|boto3\|storage_backend\|presigned' app/` → **0 Treffer**
---
### K12: F-CORE-11 — Generic Import/Export Service — TEILWEISE
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| CSV-Import | Mit Preview, Dry-Run, Fehler-Reporting | **⚠️ Nur direkter Import ohne Preview/Dry-Run** |
| Excel-Export | Feld-Auswahl, Filterung | **⚠️ CSV + XLSX Export, aber begrenzte Feld-Auswahl** |
| Plugin-Definitionen | Registrierbar | **N/A** |
**Evidence:**
- `import_service.py`: `import_companies_csv()`, `import_contacts_csv()` — direkter Import, kein Preview, kein Dry-Run
- `export_service.py`: `export_companies_csv()`, `export_companies_xlsx()` — Export funktioniert, aber nicht generisch/plugin-fähig
- Import/Export ist hardcoded für Companies/Contacts, nicht generisch
---
### K13: F-CORE-12 — PDF/Document Generation Service — FEHLT
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| PDF-Generierung | Aus Templates | **Nicht implementiert** |
| Template-Engine | Variablen, Conditionals, Tabellen | **Nicht vorhanden** |
| Storage-Integration | PDFs im Storage gespeichert | **N/A** |
**Evidence:** `grep -rn 'pdf\|PDF\|weasyprint\|reportlab\|pdfkit' app/` → nur DMS-Preview (stream existing PDFs), keine Generierung
---
### K14: F-CORE-13 — Notification Service — TEILWEISE
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| In-App-Notifications | Bell-Icon, Badge-Zähler | **⚠️ DB-Modell existiert, keine UI** |
| E-Mail-Channel | Notifications per Mail | **Nicht implementiert** |
| Preferences | Pro User konfigurierbar | **Nicht vorhanden** |
| Tenant-Isolation | Pro Tenant isoliert | **N/A (single-tenant)** |
| Plugin-Notification-Typen | Registrierbar | **N/A** |
**Evidence:**
- `models.py`: `Notification`-Modell existiert (id, user_id, type, title, body, related_entry_id, is_read, created_at)
- `notification_routes.py`: API für List/Mark-Read existiert
- Keine E-Mail-Integration, keine Preferences, kein Badge-Zähler in UI (Jinja2-Templates haben kein Notification-UI)
---
### K15: F-AUTH-01 — Login mit E-Mail — KONFLIKT
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| Login-Feld | **E-Mail** + Passwort | **Username** + Passwort |
| Session-Cookie | HttpOnly, Secure, SameSite=Strict | SameSite=**lax**, https_only conditional |
**Evidence:**
- `auth_service.py`: `authenticate_user(db, username, password)` — verwendet `username`, nicht `email`
- `models.py`: `User.username: Mapped[str]` — kein `email`-Feld auf User
- `deps.py`: Session speichert `user_id`, kein Tenant-Kontext
- `main.py`: `same_site="lax"` (requirements sagen Strict), `https_only=settings.is_production` (requirements sagen Secure)
---
### K16: F-AUTH-03 — User-Verwaltung durch Admin — FEHLT
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| Admin legt User an | E-Mail, Name, Rolle, Passwort | **Nicht implementiert** |
| User-Tenant-Zuordnung | User wird Tenant zugeordnet | **N/A** |
| Keine Self-Registration | Admin-only | **⚠️ Register-Template existiert** |
**Evidence:**
- Keine User-Management-Routes (kein `/api/users`, kein Admin-User-CRUD)
- `app/templates/register.html` existiert — Self-Registration-Template (widerspricht Non-Goal #1)
- `init_db.py`: Demo-Seed erstellt nur admin/admin
---
### K17: F-AUTH-05 — Passwort-Reset — FEHLT
| Aspekt | Requirements | Code-Realität |
|---------|-------------|---------------|
| Reset-Flow | E-Mail mit Reset-Link | **Nicht implementiert** |
| Reset-Link | Gültig 24h | **Nicht vorhanden** |
**Evidence:** Keine Reset-Routes, keine Reset-Templates, keine Token-Generierung.
---
### K18: F-AUTH-07 — Multi-Tenant — FEHLT (siehe K1)
Bereits in K1 abgedeckt. Keine Tenant-Modelle, keine User-Tenant-Mapping-Tabelle.
---
### K19: DMS/Calendar/Tags als Core vs Plugin — ARCHITEKTUR-KONFLIKT
| Modul | Requirements | Code-Realität |
|-------|-------------|---------------|
| DMS | v2-Plugin (F-FILE/F-DMS/F-LINK/F-PERM) | **Core: 3 Modelle + 26KB Service + eigene Routes** |
| Kalender | v2-Plugin (F-CAL-01..18) | **Core: 6 Modelle + 21KB Service + eigene Routes** |
| Tags | v2-Plugin (F-TAG-01..04) | **Core: 2 Modelle + 8KB Service + eigene Routes** |
| Mail | v2-Plugin (F-MAIL-01..19) | **Nicht implementiert** |
**Evidence:** Alle Module sind direkt in `models.py`, `services/`, `routes/` integriert. Keine Plugin-Grenzen, keine Plugin-Schnittstellen.
**Hinweis:** Requirements sagen Plugin-System ist v1-Core-Feature, aber die Module selbst sind v2-Plugins. Das bedeutet: In v1 muss das Plugin-System gebaut werden, aber DMS/Kalender/Tags können als v2-Plugins nachgezogen werden. Die bestehenden Implementierungen können als Referenz dienen, müssen aber auf Plugin-Architektur umgebaut werden.
---
## 3. Kompatibel — Was bereits passt
### ✅ Session-basierte Auth (F-AUTH-01/02, Annahme 12)
- Starlette `SessionMiddleware` mit signed Cookie
- `session_cookie="leocrm_session"`, `max_age` konfigurierbar
- Login setzt `request.session[SESSION_USER_ID_KEY] = user.id`
- Logout cleared session
- **Kompatibel** mit Requirements (Session-basiert, Cookie-basiert)
### ✅ RBAC Grundgerüst (F-AUTH-04/06)
- 3 Rollen: admin, editor, viewer
- `require_admin` dependency prüft `user.role == "admin"`
- `get_current_user` dependency für auth-geschützte Routes
- **Kompatibel** mit Requirements (3 Rollen v1)
### ✅ Company/Contact CRUD (F-COMP-01..06, F-CONT-01..07)
- Company: 27 Felder (Name, Adresse, Industrie, Revenue, etc.)
- Contact: 29 Felder (Name, Email, Phone, Title, etc.)
- N:M Junction: `CompanyContact`
- Soft-Delete: `deleted_at` auf beiden
- Pagination, Search, Filter, Sort in Routes
- **Kompatibel** mit Requirements
### ✅ Data-Features (F-DATA-01..04)
- Pagination: `PageResponse` schema
- Search: Query-Parameter in company/contact routes
- Sort: Sortier-Parameter
- Soft-Delete: `deleted_at` + restore functionality
- **Kompatibel** mit Requirements
### ✅ Health-Check (F-INFRA-01)
- `/api/health` endpoint, prüft DB, gibt Status + Version
- Nicht auth-geschützt (für Coolify/LB)
- **Kompatibel** mit Requirements
### ✅ Import/Export Grundgerüst (F-MIG-01, F-DATA-01/02)
- CSV-Import für Companies/Contacts
- CSV + XLSX Export für Companies
- **Teilweise kompatibel** — fehlt Preview, Dry-Run, generische Service-Architektur
### ✅ DMS-Features (als Referenz für späteres Plugin)
- Folder-Tree mit materialized path
- File-Upload, Preview (PDF), Soft-Delete, Restore
- Entity-Links (N:M zu Companies/Contacts)
- Permissions (Individual/Group/Default)
- Share-Links mit Password + Expiry
- OnlyOffice-Edit-Session
- **Vollständig implementiert** — kann als Plugin-Referenz dienen
### ✅ Calendar-Features (als Referenz für späteres Plugin)
- Calendar CRUD, Sharing, Visibility-Toggle
- Entries: Events/Tasks/Reminders, Kanban-Status
- Subtasks, Attendees, Entry-Links
- Notifications für Reminders/Invites/Shares
- **Vollständig implementiert** — kann als Plugin-Referenz dienen
### ✅ Tag-System (als Referenz für späteres Plugin)
- Tag CRUD (admin-only), Color, Assignment
- Bulk-Assign, Entity-Type polymorphic
- **Vollständig implementiert** — kann als Plugin-Referenz dienen
### ✅ Testing-Setup (F-TEST-01)
- pytest mit 20+ Test-Dateien
- conftest.py mit Fixtures
- Coverage-Messung konfiguriert
- **Teilweise kompatibel** — fehlt Vitest (Frontend) und Playwright (E2E)
---
## 4. F-CORE-Feature-Matrix
| F-CORE-ID | Feature | Status im Code | Anmerkung |
|-----------|--------|---------------|----------|
| F-CORE-01 | Event Bus | ❌ Nicht implementiert | Keine Event-Infrastruktur |
| F-CORE-02 | Tenant-Isolation | ❌ Nicht implementiert | Kein tenant_id, single-tenant |
| F-CORE-03 | Plugin-DB-Migration | ❌ Nicht implementiert | Kein Plugin-System |
| F-CORE-04 | UI-Plugin-Framework | ❌ Nicht implementiert | Jinja2, keine Plugin-UI |
| F-CORE-05 | Service Container / DI | ❌ Nicht implementiert | Direkte Imports, nur FastAPI Depends |
| F-CORE-06 | API-First Architecture | ⚠️ Teilweise | API routes existieren, aber HTML parallel, keine Versionierung |
| F-CORE-07 | Async Job Queue | ❌ Nicht implementiert | Keine Queue-Infrastruktur |
| F-CORE-08 | Caching-Strategie | ❌ Nicht implementiert | Nur lru_cache für Settings |
| F-CORE-09 | User-Profile/Preferences | ❌ Nicht implementiert | User hat nur username/role |
| F-CORE-10 | Storage-Backend | ❌ Nicht implementiert | Lokales Dateisystem, kein S3 |
| F-CORE-11 | Generic Import/Export | ⚠️ Teilweise | CSV/XLSX funktioniert, nicht generisch, kein Preview/Dry-Run |
| F-CORE-12 | PDF Generation | ❌ Nicht implementiert | Keine PDF-Generierung |
| F-CORE-13 | Notification Service | ⚠️ Teilweise | DB-Modell + API existiert, keine UI, kein E-Mail-Channel |
**Bilanz:** 0/13 vollständig implementiert, 3/13 teilweise, 10/13 fehlen komplett.
---
## 5. Empfehlung: Was vor Phase 2 angepasst werden muss
### Priorität 1 — Fundamentale Architektur (vor allem anderen)
1. **Datenbank-Migration: SQLite → PostgreSQL**
- `config.py`: `database_url` auf PostgreSQL umstellen
- `session.py`: SQLite-PRAGMAs entfernen, PostgreSQL-Engine konfigurieren
- `pyproject.toml`: `psycopg[binary]` oder `asyncpg` hinzufügen
- `docker-compose.yml`: PostgreSQL-Service hinzufügen
2. **Multi-Tenant-Architektur**
- Neues `Tenant`-Modell + `UserTenant`-Mapping-Tabelle
- `tenant_id`-Spalte auf ALLE Core-Tabellen (Company, Contact, Folder, File, Tag, Calendar, etc.)
- ORM-Query-Filter: automatische tenant_id-Filterung (SQLAlchemy Event oder Query-Wrapper)
- Session-Kontext: aktiver tenant_id in Session speichern
- Tenant-Switch-Endpoint + UI
3. **Frontend-Wechsel: Jinja2 → React SPA**
- React-Projekt-Setup (Vite + React + TypeScript)
- API-Client-Layer (fetch/axios gegen /api/* Endpunkte)
- Jinja2-Templates und html_routes.py werden obsolet
- i18n-Integration (DE + EN)
- UI-Plugin-Framework vorbereiten (F-CORE-04)
### Priorität 2 — Core-Infrastructure (F-CORE)
4. **Service Container / DI (F-CORE-05)**
- Zentralen Service-Container implementieren
- Core-Services registrieren: DB, Cache, Event Bus, Auth, Config, Logger
- Plugin-Schnittstelle für Service-Requests definieren
5. **Event Bus (F-CORE-01)**
- Event-Publish/Subscribe-System implementieren
- Typisierte Events mit Payload
- Asynchrone Verarbeitung (ggf. via Job Queue)
6. **Plugin-System (F-PLUGIN-01/02)**
- Plugin-Manifest-Format definieren
- Lifecycle-Hooks: install, activate, deactivate, uninstall
- Plugin-Registry + Loader
- Plugin-API-Endpunkt-Registrierung
- Plugin-DB-Migration (F-CORE-03)
- Plugin-Abhängigkeiten
7. **API-Versionierung (F-CORE-06)**
- `/api/v1/` Prefix für alle API-Routes
- OpenAPI/Swagger explizit konfigurieren und dokumentieren
- HTML-Routes entfernen (UI wird React SPA = API-Client)
### Priorität 3 — Weitere Core-Infrastructure
8. **Async Job Queue (F-CORE-07)** — Queue-System für Background-Jobs
9. **Caching (F-CORE-08)** — Redis-Anbindung, Query-Cache, Cache-Invalidierung
10. **Storage-Backend (F-CORE-10)** — S3-kompatibler Storage-Service
11. **User-Profile/Preferences (F-CORE-09)** — Profil-Erweiterung, Preferences
12. **Notification Service (F-CORE-13)** — E-Mail-Channel, Preferences, Badge-UI
13. **PDF Generation (F-CORE-12)** — Template-Engine, PDF-Generierung
14. **Generic Import/Export (F-CORE-11)** — Generischer Service, Preview, Dry-Run
### Priorität 4 — Auth-Ergänzungen
15. **Login auf E-Mail umstellen (F-AUTH-01)** — username → email
16. **User-Verwaltung durch Admin (F-AUTH-03)** — Admin-CRUD für User, Tenant-Zuordnung
17. **Passwort-Reset (F-AUTH-05)** — Reset-Flow mit E-Mail
18. **Register-Template entfernen** — Self-Registration ist Non-Goal
19. **Cookie-Security anpassen** — SameSite=Strict, Secure immer
### Was beibehalten werden kann
- **Backend-Services** (company_service, contact_service, etc.) — Business-Logik ist solide
- **Pydantic-Schemas** — Können für API-Validierung weiterverwendet werden
- **DB-Modelle** — Felder/Beziehungen sind korrekt, müssen nur tenant_id ergänzt werden
- **Test-Suite** — pytest-Tests können erweitert werden
- **DMS/Calendar/Tag-Implementierungen** — Als Referenz für spätere Plugin-Entwicklung behalten
---
## 6. Zusammenfassung
| Kategorie | Anzahl | Status |
|-----------|--------|--------|
| Kritische Konflikte | 4 | Multi-Tenant, Plugin-System, DB, Frontend |
| F-CORE fehlend | 10/13 | Event Bus, Tenant-Isolation, Plugin-Migration, UI-Plugin, Service Container, Job Queue, Caching, User-Profile, Storage, PDF |
| F-CORE teilweise | 3/13 | API-First, Import/Export, Notification |
| F-CORE vollständig | 0/13 | — |
| Auth-Konflikte | 4 | Login (username vs email), User-Verwaltung, Passwort-Reset, Cookie-Security |
| Kompatibel | 7+ | Session-Auth, RBAC, Company/Contact CRUD, Data-Features, Health, DMS/Calendar/Tags (als Referenz) |
**Fazit:** Die bestehende Codebase ist eine funktionsfähige v0.1-Implementierung (Single-Tenant, SQLite, Jinja2), die den bereinigten v1-Requirements in 4 kritischen Bereichen nicht entspricht: Multi-Tenant, Plugin-System, PostgreSQL, React SPA. 10 von 13 F-CORE-Features fehlen komplett. Die bestehende Business-Logik (Services, Schemas, Modelle) ist jedoch solide und kann als Basis für den Umbau dienen. Der Aufwand für Phase 2 ist erheblich — es handelt sich um eine Architektur-Migration, nicht um inkrementelle Erweiterungen.
## 3. Requirements-Erfüllung
### Core Features (v1)
| Feature | Status | Anmerkung |
|---------|--------|-----------|
| F-AUTH-01: Login/Logout | ✅ | Session + Redis + bcrypt |
| F-AUTH-03: User Management | ✅ | CRUD + RBAC |
| F-AUTH-04: RBAC | ✅ | Role + Groups + Field-Level |
| F-AUTH-05: Password Reset | ✅ | Token-based, 1h expiry |
| F-AUTH-06: Custom Roles | ✅ | Role editor in frontend |
| F-AUTH-07: Multi-Tenant | ✅ | ORM filter + RLS (Migration 0015) |
| F-COMP-01-08: Company CRUD | ⚠️ | Unified Contact Model — Company = Contact type='company'. Company-Routes werden entfernt (Phase 1) |
| F-CONT-01-08: Contact CRUD | ✅ | Unified Contact mit type='company'\|'person' + ContactPerson 1:N |
| F-CORE-01: Event Bus | ✅ | In-process async, 53 Zeilen |
| F-CORE-02: Multi-Tenant | ✅ | TenantMixin + RLS |
| F-CORE-03: Plugin System | ✅ | 12 Plugins, Registry, Manifest, Lifecycle |
| F-CORE-07: ARQ Job Queue | ✅ | Redis-based, worker.py |
| F-CORE-08: Caching | ✅ | Redis cache wrapper |
| F-CORE-10: Storage | ❌ | Architecture beschreibt StorageBackend, aber NICHT implementiert. Hardcoded Pfade. (Phase 0.16) |
| F-DATA-03: Validation | ✅ | Pydantic auf allen Inputs |
| F-DATA-04: PostgreSQL | ✅ | PostgreSQL 16 + asyncpg |
| F-PLUGIN-01-02: Plugin System | ✅ | Registry, Manifest, Lifecycle, Migration Runner |
| F-SEC-01: CSRF | ✅ | SameSite=Strict + Origin validation |
| F-SEC-02: CSP | ✅ | In architecture definiert (Nginx fehlt — Phase 0) |
| F-SEARCH-01: Global Search | ✅ | Hybrid FTS + Vector + RRF + KI Query Understanding |
| F-AI-01: KI-Copilot | ✅ | LiteLLM + PydanticAI + tool_registry |
| F-WF-01: Workflow Engine | ✅ | 306 Zeilen, 4 Step-Types (action/approval/notification/condition) |
| F-INFRA-01: Health Check | ✅ | /api/v1/health |
| F-INFRA-04: Monitoring | ✅ | Prometheus + structlog |
| F-PERF-01: Performance | ⚠️ | Indizes vorhanden, aber kein Virtual Scrolling (Phase 2) |
| F-TEST-01: Testing | ⚠️ | Backend + Frontend Tests da, E2E fehlt (Phase 5) |
### Plugin Features (v2)
| Plugin | Status | Anmerkung |
|--------|--------|-----------|
| Calendar | ✅ | 12 Komponenten, ICS, Kanban, Resources, Subtasks |
| DMS | ✅ | 9 Komponenten, OnlyOffice (→Collabora Phase 0.20), Share, Bulk |
| Mail | ✅ | 13 Komponenten, PGP, Vacation, Rules, Templates, IMAP/SMTP |
| Tags | ✅ | TagPicker, TagCloud, BulkTagDialog |
| Permissions | ✅ | File/folder permissions, share links |
| Entity Links | ✅ | File↔Entity links |
| Unified Search | ✅ | Hybrid FTS+Vector, 5 Provider, KI Query Understanding |
| AI Assistant | ✅ | Multi-provider LLM, Agents, Tools, Streaming |
| AI Proactive | ✅ | Context-aware suggestions, SSE, Heartbeat, Deep Analysis |
| Kommunikation | ✅ | WebSocket messaging, MiniApps, Rich Content Blocks |
| Report Generator | ⚠️ | Backend da (CSV/Excel/JSON), Frontend fehlt, PDF fehlt (Phase 5.18-5.19) |
| System Notifications | ✅ | Participant handler, notification types |
## 4. Bekannte Lücken (im MASTER-PLAN.md eingeplant)
| Lücke | Phase | Task |
|-------|-------|------|
| Storage Backend (S3) | 0 | 0.16 |
| Company-Routes entfernen | 1 | 1.1-1.20 |
| Plugin-UI-System (PluginRegistry) | 3 | 3.1-3.10 |
| Automation & Agents Plugin | 3.5 | 3.11-3.32 |
| KI-UI-Steuerung | 4 | 4.1-4.12 |
| E2E Tests (Playwright) | 5 | 5.4-5.11 |
| Backup-System | 5 | 5.15 |
| MCP Integration | 5 | 5.16-5.17 |
| Report Frontend + PDF | 5 | 5.18-5.19 |
| Custom Fields UI | 5 | 5.20 |
| Tasks-Plugin | 5 | 5.21 |
| Saved Searches | 5 | 5.22 |
| Deduplication | 5 | 5.23 |
| PWA | 5 | 5.24 |
| Dashboard-System | 5 | 5.25 |
| Code-Splitting | 2 | 2.1-2.7 |
| Virtual Scrolling | 2 | 2.2-2.6 |
| RHF + Zod überall | 6 | 6.1-6.6 |
| AGPL-Lizenzen (PyMuPDF, OnlyOffice) | 0 | 0.20 |
| RBAC in 4 Plugins | 0 | 0.10 |
| Undo/History | 0 | 0.15 |
| .env in Git | 0 | 0.18 |
| Mail-Salt hardcoded | 0 | 0.19 |
## 5. Statistik
| Metrik | Wert |
|--------|------|
| Backend Python-Zeilen | ~35.800 |
| Frontend TS/TSX-Zeilen | ~30.000 |
| Test-Zeilen (Backend) | ~17.300 |
| Test-Zeilen (Frontend) | ~3.045 |
| Plugins | 12 |
| API-Endpoints | ~120+ |
| DB-Migrationen | 22 |
| UI-Komponenten | 12 (+2 zusätzliche) |
| Frontend Pages | 27 |
| i18n Keys (pro Sprache) | 750 |
## 6. Fazit
Die Codebase hat den ursprünglichen Requirements-Review (der SQLite, Jinja2, keine Plugins beschrieb) **weit übertroffen**. Das unified Contact Model, das Plugin-System, die KI-Integration und die Vector Search sind implementiert und funktionieren.
Die verbleibenden Lücken sind im `MASTER-PLAN.md` detailliert eingeplant (~590h Gesamt-Aufwand über 8 Phasen + Phase 3.5).
+23
View File
@@ -11,6 +11,29 @@
## VERDICT: APPROVED_WITH_CONCERNS
> **Update 2026-07-23:** Several risks have been resolved in the codebase since this review.
> See "Resolution Status" markers below each risk.
### Resolution Summary (2026-07-23)
| Risk | Severity | Status | How resolved |
|------|----------|--------|-------------|
| M-01 (Brute-Force) | Major | ✅ RESOLVED | `rate_limit.py` implemented with Redis INCR+EXPIRE. Login, password-reset, general API rate limiting. |
| M-02 (RLS) | Major | ✅ RESOLVED | Migration 0015 implements PostgreSQL RLS policies on all tenant-scoped tables. ORM filter + RLS as defense-in-depth. |
| M-03 (Worker Tenant) | Major | ✅ RESOLVED | `worker.py` (71 lines) with tenant context propagation. ARQ jobs carry tenant_id. |
| M-04 (Secret Rotation) | Major | ⬜ OPEN | No rotation policy documented. Planned in Phase 0.1. |
| M-05 (CORS) | Major | ✅ RESOLVED | Explicit origin list in config.py, no wildcards. |
| M-06 (Plugin Security) | Major | ⬜ PARTIAL | Plugin migration runner validates tenant_id. Plugin install validation planned in Phase 3.10b. |
| M-07 (Dependency Risk) | Major | ⬜ OPEN | PyMuPDF (AGPL) → pypdf replacement planned in Phase 0.20. |
| m-01 (Secret Key) | Minor | ⬜ OPEN | Purpose documentation planned in Phase 0.1. |
| m-02 (2FA) | Minor | ⬜ OPEN | Post-MVP, acceptable for v1. |
| m-03 (Tenant Switch) | Minor | ✅ RESOLVED | Tenant switch validates user_tenants membership. |
| m-04 (CSRF Token) | Minor | ⬜ OPEN | SameSite+Origin is sufficient. Token unused. Planned cleanup in Phase 0.18. |
| m-05 (SQL Injection) | Minor | ⬜ PARTIAL | SQLAlchemy ORM used everywhere. Unified search has f-string table names (controlled). Guideline planned in Phase 3.8. |
| m-06 (Mail Encryption) | Minor | ⬜ OPEN | Hardcoded salt `b"leocrm-mail-salt"` — fix planned in Phase 0.19. |
| m-07 (Backup) | Minor | ⬜ OPEN | Backup system planned in Phase 5.15. |
| m-08 (Log Injection) | Minor | ✅ RESOLVED | structlog with JSON formatting. |
The architecture is well-structured with strong fundamentals (session-based auth, CSRF protection, CSP headers, RBAC with field-level permissions, audit trail). However, **7 major risks** and **8 minor risks** must be addressed before or during implementation. No critical blocking issues found, but 3 major risks (RLS gap, rate limiting, CORS) should be resolved before Phase 3 start.
| Severity | Count |