247d4165ea
- .env.example: Add ADMIN_EMAIL/ADMIN_PASSWORD - SANIERUNGS_FORTSCHRITT.md: Update UUIDs - IMPLEMENTATION_PLAN.md: Update UUID - promptinclude: Worker/DB/Redis are now part of Docker-Compose-App
199 lines
7.7 KiB
Markdown
199 lines
7.7 KiB
Markdown
ÜBERHOLT – NICHT ALS UMSETZUNGSANWEISUNG VERWENDEN
|
||
# LeoCRM Sanierungsfortschritt
|
||
|
||
**Letztes Update:** 2026-08-03
|
||
**Git-Commit:** 310a9f0 (main)
|
||
**Alembic-Head:** 0092
|
||
**Produktion:** https://crm.media-on.de — healthy
|
||
|
||
> Diese Datei ist der kompakte Fortschritts-Tracker für den Sanierungsplan.
|
||
> Der vollständige Sanierungsplan steht in `docs/ABSCHLUSSBERICHT_PHASE0_PHASE1.md`.
|
||
> Die Installationsanleitung steht in `docs/INSTALL.md`.
|
||
|
||
---
|
||
|
||
## Phasen-Status
|
||
|
||
| Phase | Status | Commit | Tests | Migration |
|
||
|-------|--------|--------|-------|----------|
|
||
| 0 — Ausgangsbasis | ✅ Abgeschlossen | v-phase0-baseline | — | — |
|
||
| 1 — Login, DB-Rollen, RLS | ✅ Abgeschlossen | 733fa1c | 35 Backend + 14 Plugin | 0085–0090 |
|
||
| 2 — Datenintegrität | ✅ Abgeschlossen | 745bc4f | FK-Tests auf Produktion | 0091 |
|
||
| 3 — Plugin-Lifecycle | ✅ Abgeschlossen | dfd9e77 | 14/14 pytest | — |
|
||
| 4 — KI-Delegation | ⏳ Nicht begonnen | — | — | — |
|
||
| 5 — Outbox | ✅ Abgeschlossen | 07a9997 | 18/18 pytest + Prod-Smoke | 0092 |
|
||
| 6 — Workspaces | ✅ Abgeschlossen | 310a9f0 | 25 Backend + 12 Frontend | 0072–0074 |
|
||
| 7 — DMS/Attachments | ⏳ Nicht begonnen | — | — | — |
|
||
| 8 — Sicherheitsreste | ⏳ Nicht begonnen | — | — | — |
|
||
| 9 — CI/Quality Gates | ⏳ Nicht begonnen | — | — | — |
|
||
| 10 — Backup/Monitoring/Pilot | ⏳ Nicht begonnen | — | — | — |
|
||
|
||
---
|
||
|
||
## Abgenommene Gates (Phase 0+1)
|
||
|
||
| Gate | Beschreibung | Status |
|
||
|------|-------------|--------|
|
||
| Gate 1 | Reproduzierbares Coolify-Deployment | ✅ |
|
||
| Gate 2 | Neuinstallation auf leerer Datenbank | ✅ |
|
||
| Gate 3 | Vollständiger Restore-Test | ✅ |
|
||
| Gate 4 | Passwort-Reset end-to-end | ✅ |
|
||
| Gate 5 | Worker und Eventhandler | ✅ |
|
||
|
||
---
|
||
|
||
## Produktions-Setup
|
||
|
||
### Coolify-Ressourcen
|
||
|
||
| Ressource | UUID | Typ |
|
||
|-----------|------|------|
|
||
| API (crm.media-on.de) | dx4pqdziu4uj6x9fxs1u5z0x | Application |
|
||
| Worker | | Service |
|
||
| PostgreSQL | (Coolify Service) | Service |
|
||
| Redis | (Coolify Service) | Service |
|
||
|
||
### Datenbankrollen
|
||
|
||
| Rolle | Superuser | BYPASSRLS | Verwendung |
|
||
|-------|----------|-----------|------------|
|
||
| crm_user | Ja | Ja | Bootstrap (POSTGRES_USER) |
|
||
| crm_migration | Nein | Ja | Alembic + Plugin-Migrationen (DDL) |
|
||
| crm_auth | Nein | Nein | Login, Authentifizierung |
|
||
| crm_api | Nein | Nein | API-Abfragen |
|
||
| crm_worker | Nein | Nein | ARQ-Worker, Outbox |
|
||
|
||
### Volumes
|
||
|
||
| Volume | Verwendung |
|
||
|--------|------------|
|
||
| crm-postgres-data | PostgreSQL-Daten |
|
||
| crm-redis-data | Redis-Daten |
|
||
| dx4pqdziu4uj6x9fxs1u5z0x_storage | API + Worker Storage (geteilt) |
|
||
|
||
### Deployment
|
||
|
||
```bash
|
||
# Full deploy (API + Worker) über Coolify API
|
||
COOLIFY_API_TOKEN=<token> python scripts/deploy.py
|
||
|
||
# Nur Verifikation
|
||
COOLIFY_API_TOKEN=<token> python scripts/deploy.py --verify-only
|
||
|
||
# Nur Worker
|
||
COOLIFY_API_TOKEN=<token> python scripts/deploy.py --worker-only
|
||
```
|
||
|
||
---
|
||
|
||
## Was erledigt ist
|
||
|
||
### Phase 0+1 (Security & RLS)
|
||
- 5 DB-Rollen mit separaten Verbindungen
|
||
- RLS fail-closed auf 108 Tenant-Tabellen
|
||
- FORCE ROW LEVEL SECURITY aktiviert
|
||
- 0 legacy app.tenant_id Policies
|
||
- Plugin-Migrationen über crm_migration (DDL)
|
||
- Worker per-Tenant Outbox-Processing mit RLS-Kontext
|
||
- Event-Handler nur für aktive Plugins
|
||
- Passwort-Reset end-to-end mit SMTP getestet
|
||
- Leere DB-Installation ohne manuelle Eingriffe
|
||
- Restore + Upgrade verifiziert
|
||
- Coolify Redeploy/Stop/Start funktioniert ohne manuelles Eingreifen
|
||
|
||
### Phase 2 (Datenintegrität)
|
||
- 74 FK-Constraints (tenant_id → tenants.id ON DELETE CASCADE) hinzugefügt
|
||
- 10 globale Tabellen ausgeschlossen
|
||
- Orphan-Cleanup durchgeführt
|
||
- FK-Tests auf Produktion: INSERT mit ungültiger tenant_id blockiert ✅
|
||
|
||
### Phase 3 (Plugin-Lifecycle)
|
||
- 14 Tests: Registry, Lifecycle, Idempotency, Dependencies, Core-Schutz
|
||
- Plugin-Lifecycle war bereits korrekt implementiert
|
||
- Tests bestätigen: activate → deactivate → reactivate funktioniert
|
||
|
||
---
|
||
|
||
## Was als nächstes zu tun ist
|
||
|
||
### Phase 5 (Outbox) — abgeschlossen (produktionsverifiziert)
|
||
- Per-Tenant Outbox-Processing (Gate 5)
|
||
- Dead-Letter-Queue: error_message + failed_at Spalten, Replay-Funktionen
|
||
- Monitoring: /api/v1/outbox/stats, /failed, /consumer-registry Endpoints
|
||
- Consumer-Registry: outbox_deliveries pro Consumer-Handler geschrieben
|
||
- Processing-Recovery: recover_stuck_events (stuck processing -> pending)
|
||
- Retention-Cleanup: cleanup_published_events (hourly cron job, 30 days)
|
||
- Replay setzt outbox_deliveries zurueck (clean retry)
|
||
- 23/23 Unit-Tests + Produktions-Verifikation:
|
||
- outbox_deliveries: 4 Eintraege mit status=delivered
|
||
- recover-stuck: 200, 0 stuck events
|
||
- cleanup-published: 200, 22 alte Events geloescht
|
||
- consumer-registry: 200, alle Handler gelistet
|
||
- failed: 200, 0 failed events
|
||
- stats: 200, korrekte counts
|
||
- deploy.py repariert: Worker-Deploy funktioniert jetzt korrekt
|
||
|
||
### Phase 7 (DMS/Attachments) — nicht begonnen
|
||
- Streaming Upload/Download
|
||
- Deduplikation tenantlokal
|
||
- Keine Cross-Tenant-Dateireferenzen
|
||
- Aufwand: 10–16h
|
||
|
||
### Phase 4 (KI-Delegation) — nicht begonnen
|
||
- Delegation-Contract, Tenant-scoped Permissions
|
||
- Audit, Rollback, Approval
|
||
- Aufwand: 10–16h
|
||
|
||
### Phase 6 (Workspaces) — abgeschlossen (produktionsverifiziert)
|
||
- Backend: Widget CRUD (create, list, update, delete), Manager-Role-Check, Cross-Tenant-Validierung
|
||
- Default-Workspace Seeding (12 Standard-Module), Set-User-Default-Workspace
|
||
- Fix: create_workspace Default-Uniqueness (unset others before insert)
|
||
- Frontend: workspaceStore (Zustand) mit sessionStorage Persistenz
|
||
- API-Client Interceptor: X-Workspace-ID Header auf allen Requests
|
||
- useWorkspace hook auf workspaceStore umgestellt
|
||
- Widget API hooks: useWorkspaceWidgets, useCreateWorkspaceWidget, etc.
|
||
- Settings-Route: /settings/workspaces mit WorkspaceManagerPage
|
||
- 25 Backend-Tests + 12 Frontend-Tests (alle bestanden)
|
||
- Produktions-Verifikation:
|
||
- 2 Workspaces (Verkauf/Einkauf) mit unterschiedlichen Modulen ✅
|
||
- Hidden module (calendar in Einkauf) nicht in Context ✅
|
||
- Multiple widgets mit gleichem key (2x recent_contacts) ✅
|
||
- Widget CRUD: create, update, delete ✅
|
||
- Set-default: Workspace-Wechsel funktioniert ✅
|
||
- Manager-Role: Creator ist Manager ✅
|
||
- Cross-Tenant: RLS isoliert Workspaces pro Tenant ✅
|
||
|
||
### Phase 8–10 — nicht begonnen
|
||
- Sicherheitsreste, CI, Backup/Monitoring
|
||
- Aufwand: 38–66h
|
||
|
||
---
|
||
## Wichtige Dateien
|
||
|
||
| Datei | Inhalt |
|
||
|-------|--------|
|
||
| `docs/ABSCHLUSSBERICHT_PHASE0_PHASE1.md` | Vollständiger Abschlussbericht + Sanierungsplan |
|
||
| `docs/INSTALL.md` | Vollständige Installationsanleitung |
|
||
| `docs/phase0_phase1_acceptance_report.md` | Abnahmeprotokoll Phase 0+1 |
|
||
| `scripts/deploy.py` | Coolify API Deployment-Skript |
|
||
| `scripts/seed_admin.py` | Admin-User erstellen |
|
||
| `docker-compose.yml` | Referenz-Compose (API + Worker + DB + Redis) |
|
||
| `.env.docker.example` | ENV-Template |
|
||
| `prestart.sh` | Container-Entrypoint (Migrationen + Rollen) |
|
||
| `worker.sh` | Worker-Entrypoint |
|
||
|
||
---
|
||
|
||
## Wichtige Regeln für den nächsten Agenten
|
||
|
||
1. **Keine manuellen Docker-Befehle** — alles über Coolify API oder deploy.py
|
||
2. **Repo lesen bevor ändern** — docker-compose.yml und deploy.py beachten
|
||
3. **Migrationen sind Forward-Only** — keine alten Migrationen verändern
|
||
4. **RLS ist fail-closed** — kein Tenant-Kontext = kein Zugriff
|
||
5. **crm_api hat keine DDL-Rechte** — Plugin-Migrationen über get_migration_engine()
|
||
6. **Worker ist Coolify Service** — UUID
|
||
7. **Alle DB-Passwörter sind identisch** — siehe .env.docker.example
|
||
8. **pgvector/pgvector:pg16** als DB-Image — nicht postgres:16-alpine
|
||
9. **Tests müssen mit echten unprivilegierten Rollen laufen** — nicht mit Superuser
|
||
10. **Jede Phase: analysieren → implementieren → migrieren → testen → dokumentieren**
|