# LeoCRM — Codebase vs Requirements Analysis **Datum:** 2026-06-28 **Prüfer:** Codebase Explorer (Agent Zero) **Methode:** Read-only-Inspektion der bestehenden Codebase gegen bereinigte `requirements.md` --- ## 1. Bestehende Architektur-Übersicht ### 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 | ### Projekt-Struktur ``` 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) ``` ### 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.