### BUG-024: Plugin Detail Route fehlt (GET /api/v1/plugins/{name} gibt 404)
- **Kategorie:** API
- **Modul:** Plugins
- **Endpoint:** GET /api/v1/plugins/{name}
- **Erwartet:** 200 mit Plugin-Details
- **Tatsächlich:** 404 Not Found für alle Plugins
- **Schweregrad:** Medium
- **Ursache:** Es gibt `/{name}/config`, `/{name}/activate`, `/{name}/deactivate` aber keine reine `GET /{name}` Route
- **Status:** ⏳ Nicht gefixt
### BUG-025: Workflow Execute und Instances API-Pfade falsch
- **Kategorie:** API
- **Modul:** Workflows
- **Endpoint:** POST /api/v1/workflows/{id}/execute, GET /api/v1/workflows/{id}/instances
- **Erwartet:** 200/201 für Execute und Instances
- **Tatsächlich:** 405 Method Not Allowed für Execute, 404 für Instances
- **Schweregrad:** Medium
- **Ursache:** Execute ist `POST /{workflow_id}/instances` nicht `POST /{workflow_id}/execute`. Instances sind unter `/instances` (global) nicht unter `/{workflow_id}/instances`
- **Status:** ⏳ Nicht gefixt — API-Pfade in Doku/Test korrigieren
### BUG-038: Audit-Log fehlt für tag, task, wiki, mail, calendar
- **Kategorie:** API / Audit
- **Modul:** Audit Log
- **Erwartet:** Audit-Einträge für alle Mutationen (Contacts, Tags, Tasks, Wiki, Mail, Calendar, etc.)
- **Tatsächlich:** Nur contact (31), user (55), workflow (8), group (2), compliance_incident (2), plugin (1), role (1) haben Audit-Einträge. **tag, task, wiki, mail, calendar haben KEINE Audit-Einträge**
- **Schweregrad:** High
- **Ursache:** Tags/Tasks/Wiki/Mail/Calendar Routes erstellen keine Audit-Log-Einträge bei Mutationen
- **Problem:** registry.activate() ruft on_activate() auf und setzt record.active=True BEVOR plugin_service.py Permissions registriert (Zeile 99-114). Bei Fehlern ist Plugin aktiv ohne Permissions.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-002: Plugin on_activate() wird pro Tenant mehrfach aufgerufen
- **Datei:** app/main.py:292-302
- **Problem:** `for tenant_id in all_tenant_ids: plugin.on_activate(plugin_db, container, event_bus)` — dieselbe Plugin-Instanz bekommt on_activate() pro Tenant. Event-Handler werden doppelt registriert.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-003: /plugins/active-manifests hängt an plugins:read
- **Datei:** app/routes/plugins.py:95
- **Problem:** Normaler User ohne plugins:read bekommt keine Plugin-Menüs/Routes.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-004: Workspace/Sidebar is_visible nicht konsistent
- **Problem:** `if (!ctx?.workspace_id || !ctx?.modules?.length) return true` — wenn kein Workspace-Kontext, werden ALLE Module sichtbar. visibleModuleKeys() gibt alle Module zurück.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-005: Contacts ist Core UND Plugin (Doppelarchitektur)
- **Problem:** on_deactivate() deregistriert nur Handler aus _event_handlers. Wenn Plugin in Override zusätzliche Handler registriert, werden diese nicht deregistriert.
- **Problem:** sync_notification_types() läuft bei Aktivierung. Bei Deaktivierung werden Types gelöscht, aber nur wenn on_deactivate() nicht fehlschlägt.
- **Problem:** tasks importiert von kommunikation (dependencies=[]), wiki importiert von unified_search (dependencies=[]), self_improvement importiert von kommunikation (dependencies=[]).
- **Problem:** `AutomationDefinition = automation_contract.Automation` (Zeile 123) wird ausgeführt BEVOR `if automation_contract is None` (Zeile 127). Wenn Contract None ist → AttributeError.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-030: step_handlers.py — Contract.get_function() existiert nicht
- **Problem:** `MailContract.get_function("send_email")` — MailContract ist eine Klasse ohne get_function() Methode. Alle 5 Step-Handler Contracts haben dieses Problem.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-031: pluginStore.ts — getAllMenuItems ohne Permission-Filter
- **Problem:** 6 verschiedene `path: '*'` catch-all Routes. React Router kann nur einen catch-all pro Route-Level haben. Die letzten überschreiben die ersten.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-035: wiki/plugin.py — unified_search nicht in dependencies
- **Problem:** `unregister_actions_by_owner("wiki")` — Funktion erwartet (hook_name, owner_tag), nicht nur owner_tag. Sollte `unregister_actions_by_owner("wiki.article.created", "wiki")` etc. sein.
- **Problem:** `showMessageSidebar = !location.pathname.startsWith('/ai-assistant')` — AI Assistant wurde in Kommunikation integriert, Pfad existiert nicht mehr.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-046: commStore.ts und api/comm.ts — doppelte Type-Definitionen
- **Problem:** SYSTEM_PERMISSIONS in roles.py ist eine statische Liste die CORE_PERMISSIONS in permission_registry.py dupliziert. Zwei Quellen für dieselben Permissions.
### ARCH-050: notifications.py — deprecated aber aktiv (Doppelarchitektur)
- **Datei:** app/routes/notifications.py:1-3
- **Problem:** 'deprecated — delegates to Communication system channel' aber Routes sind immer noch aktiv und registriert in main.py:546. Doppelarchitektur.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-051: workspaces.py — X-Workspace-ID nicht validiert
- **Datei:** app/routes/workspaces.py:7
- **Problem:** X-Workspace-ID Header wird akzeptiert aber nicht validiert ob User zum Workspace gehört.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-052: models/contact.py — indexed_at Spalte an falscher Stelle
- **Datei:** app/models/contact.py:30
- **Problem:** `indexed_at` Spalte wird vor `__table_args__` definiert, was unüblich ist und zu Verwirrung führt.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-053: models/session.py — Session hat TenantMixin aber nicht tenant-scoped
- **Datei:** app/models/session.py:23
- **Problem:** Session erbt TenantMixin aber Sessions sind nicht tenant-scoped (User kann mehrere Tenants haben). tenant_id wird gesetzt aber nicht für RLS verwendet.
- **Problem:** useActivePluginManifests() fetcht /plugins/active-manifests die plugins:read erfordert. Normaler User bekommt keine Plugin-Manifests → keine Plugin-Menüs/Routes.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-059: useWorkspace.ts — visibleModuleKeys wird bei jedem Render neu berechnet
- **Problem:** `const visibleModuleKeys = useWorkspaceStore(s => s.visibleModuleKeys())` — bei jedem Render wird ein neues Set erstellt. Sollte useMemo verwenden.
- **Problem:** `MailContract.get_function("send_email")` — MailContract hat keine get_function() Methode. Es hat nur `Mail = Mail`. Alle 5 Step-Handler (mail, calendar, dms, search, automation) sind kaputt.
- **Problem:** `get_contract()` erstellt eine NEUE Instanz statt die registrierte aus der Registry zu verwenden. Umgeht die Contract Registry und Plugin-Aktivierungsstatus-Prüfung.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-062: mail/contracts.py — MailContract hat keine send_email Funktion
- **Problem:** MailContract hat nur `Mail = Mail` aber step_handlers.py erwartet `get_function("send_email")`. Contract ist unvollständig.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-063: cache.py — Cache und Session-Store verwenden dieselbe Redis-Instanz
- **Datei:** app/core/cache.py:12
- **Problem:** `get_cache()` delegiert an `get_redis()` — Cache und Session-Store verwenden dieselbe Redis-Instanz. Keine Trennung, kein Namespace-Prefix.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-064: middleware.py — CSP erlaubt WebSocket zu jedem Server
- **Datei:** app/core/middleware.py:33
- **Problem:** `connect-src 'self' wss: ws:` — WebSocket-Verbindungen zu jedem wss/ws Server erlaubt, nicht nur zum eigenen Server. Sollte `connect-src 'self'` sein.
- **Problem:** `_perms_contract = get_perms_contract()` und `Permission = _perms_contract.Permission` werden beim Modul-Import ausgeführt. Wenn permissions Plugin nicht aktiv ist, schlägt der Import fehl.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-078: dms/models.py — Spalten vor __table_args__ (SQLAlchemy Anti-Pattern)
- **Problem:** `indexed_at`, `content_tsv`, `content_text`, `embedding` werden vor `__table_args__` definiert. SQLAlchemy erwartet alle Spalten vor __table_args__, aber die Reihenfolge ist unüblich und kann zu Verwirrung führen.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-079: calendar/models.py — Spalten vor __table_args__
- **Problem:** `api_key: Mapped[str] = mapped_column(Text, nullable=False, default="")` — API-Key als Plaintext in DB. Sollte verschlüsselt sein (wie mail/models.py encrypted_password).
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-084: automation/models.py — hardcoded default LLM model
- **Problem:** MIME-Allowlist ist hardcoded. Sollte über Settings konfigurierbar sein.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-090: core/tenant.py — apply_tenant_filter verwendet Klassen-Attribut
- **Datei:** app/core/tenant.py:12
- **Problem:** `TenantMixin.tenant_id == tenant_id` — verwendet Klassen-Attribut statt Instanz-Attribut. Kann zu falschen Queries führen.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-091: main.py — Plugin-Aktivierung pro Tenant: break bei Fehler verhindert alle Tenants
- **Datei:** app/main.py:298
- **Problem:** Wenn Plugin-Aktivierung für einen Tenant fehlschlägt, wird `break` ausgeführt. Plugin wird für KEINEN Tenant aktiviert, auch nicht für die die schon funktioniert haben.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-092: base.py — on_activate() überschreibt Event-Handler ohne unsubscribe (Handler-Leak)
- **Datei:** app/plugins/base.py:59-62
- **Problem:** `self._event_handlers[event_name] = handler` — wenn on_activate() mehrfach aufgerufen wird (pro Tenant), wird der alte Handler im Dict überschrieben. Aber der alte Handler wurde nicht bei event_bus.unsubscribe() abgemeldet. Event-Handler-Leak.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-093: contracts.py — unregister() entfernt _loaded was _try_lazy_load() erneut triggert
- **Problem:** `unregister()` entfernt Contract und _loaded. get_contract() sieht plugin_name nicht in _loaded → ruft _try_lazy_load() auf → Contract wird neu geladen. Deaktivierte Plugins werden wieder sichtbar. (Bestätigung von ARCH-014)
- **Problem:** Dateien existieren aber sind leer (0 Zeilen). Entweder tot oder unvollständig.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-096: main.tsx — window.__AUTH_STORE__ in Dev Mode
- **Datei:** frontend/src/main.tsx:16-18
- **Problem:** `(window as any).__AUTH_STORE__ = useAuthStore` — exponiert Auth-Store global im Dev Mode. Kann in Production leaken wenn DEV-Flag nicht korrekt gesetzt ist.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-097: schemas/contact.py — ContactPersonCreate hat keine Pflichtfelder
- **Datei:** app/schemas/contact.py:12-26
- **Problem:** Alle Felder sind Optional (None). Ein ContactPerson ohne Name/E-Mail wird akzeptiert.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-098: schemas/role.py — RoleCreate.permissions ist dict[str, Any]
- **Datei:** app/schemas/role.py:11
- **Problem:** `permissions: dict[str, Any]` — keine Validierung der Permission-Keys. Jeder Key wird akzeptiert, auch ungültige.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-099: ErrorBoundary.tsx — hardcoded deutsche Strings ohne i18n
- **Problem:** `registerItems` setzt `activePlugin: plugin` automatisch. Wenn mehrere Plugins gleichzeitig registrieren, gewinnt das letzte. Sollte separaten setActivePlugin Call erfordern.
- **Problem:** Pfad zu backup.py wird mit os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) konstruiert. Sollte über Settings konfigurierbar sein.
- **Problem:** approximate_count liest pg_class.reltuples — kann ungenau sein bei seltenen ANALYZE/VACUUM. Wird für Pagination verwendet → falsche Seitenzahlen.
- **Problem:** `delattr(wrapper, '__wrapped__')` löscht __wrapped__ Attribut. Debugging-Tools die __wrapped__ verwenden um Original-Funktion zu finden, funktionieren nicht mehr.
- **Problem:** _DEFAULT_EXCLUDED ist statisch. Neue Felder (z.B. indexed_at, content_tsv) werden nicht automatisch ausgeschlossen.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-113: core/history_hooks.py — register_history_hooks ohne Duplikatsprüfung
- **Datei:** app/core/history_hooks.py:30
- **Problem:** register_history_hooks registriert Hooks ohne Duplikatsprüfung. Bei mehrfachem Aufruf (z.B. pro Tenant) werden Hooks doppelt registriert.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-114: core/state_machine.py — contact_state_machine erlaubt Überspringen von 'qualified'
- **Datei:** app/core/state_machine.py:42
- **Problem:** `"lead": ["qualified", "customer", "inactive"]` — erlaubt direkten Übergang von lead → customer ohne qualified. Business-Logik fraglich.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-115: core/principals.py — ContextVar nicht in Worker-Jobs verfügbar
- **Datei:** app/core/principals.py:25
- **Problem:** ContextVar ist async-safe aber nicht serialisierbar. Bei Worker-Jobs (ARQ) ist der Context nicht verfügbar → principals müssen neu geladen werden.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-116: core/ws_pubsub.py — subscribe_to_channel ohne Error-Handling
- **Datei:** app/core/ws_pubsub.py:25
- **Problem:** subscribe_to_channel erstellt asyncio.Task ohne Error-Handling. Task kann still fehlschlagen wenn Redis nicht verfügbar ist.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-117: core/ws_helpers.py — authenticate_ws prüft nicht auf deaktivierte Plugins
- **Datei:** app/core/ws_helpers.py:25-45
- **Problem:** authenticate_ws authentifiziert User aber prüft nicht ob das Plugin (kommunikation) aktiv ist. WebSocket bleibt offen auch wenn Plugin deaktiviert ist.
- **Problem:** COMPANY_COLUMNS und CONTACT_COLUMNS sind statisch. Neue Felder (z.B. Custom Fields) werden nicht berücksichtigt.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-130: models/webhook.py — Webhook.secret als Plaintext
- **Datei:** app/models/webhook.py:28
- **Problem:** `secret: Mapped[str | None] = mapped_column(String(255), nullable=True, default=None)` — HMAC Secret als Plaintext in DB. Sollte verschlüsselt sein.
- **Problem:** _validate_webhook_url macht socket.getaddrinfo() für DNS-Auflösung. Das ist ein synchroner Call in einer async Service-Funktion — kann den Event Loop blockieren.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-132: services/user_service.py — _UNSET Sentinel nicht serialisierbar
- **Datei:** app/services/user_service.py:15
- **Problem:** `_UNSET: Any = object()` — Sentinel-Objekt. Nicht serialisierbar, kann bei Logging/Debugging Probleme verursachen.
- **Problem:** Kommentar: '4 Workspace-Tabellen sind überdimensioniert für ein Mini-CRM'. Workspace, WorkspaceModule, WorkspaceUser, WorkspaceWidget — 4 Tabellen für UI-Navigation.
### ARCH-136: models/entity_history.py — keine deleted_at Spalte
- **Datei:** app/models/entity_history.py
- **Problem:** EntityHistory hat keine deleted_at Spalte. History-Einträge können nicht soft-deleted werden. Bei GDPR-Requests müssen sie manuell gelöscht werden.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-137: models/audit.py — search_tsv vor __table_args__
- **Datei:** app/models/audit.py:25
- **Problem:** search_tsv Spalte wird vor __table_args__ definiert. Gleicher Anti-Pattern wie ARCH-078.
- **Problem:** health_ready() ruft get_health_status() auf aber gibt ReadyResponse zurück nicht HealthResponse. Response-Format inkonsistent.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-144: Systematisches Problem — Frontend API-Clients duplizieren Backend Models
- **Dateien:** frontend/src/api/tags.ts, tasks.ts, calendar.ts, reports.ts, knowledge.ts, comm.ts, ai.ts, etc.
- **Problem:** Jeder API-Client definiert eigene TypeScript Types die die Backend SQLAlchemy Models duplizieren. Contract-Mismatch-Risiko bei Änderungen.
- **Problem:** `import { createSession, fetchSessions } from '@/api/ai'` — AI Sessions wurden in Phase 2 entfernt. Funktionen existieren möglicherweise nicht mehr.
- **Problem:** Erstellt comm conversation bei mount, aber bei unmount wird nur `cancelled = true` gesetzt. Die Konversation wird nicht gelöscht. Leak von leeren Konversationen.
- **Problem:** `import { useAIUIControlStore } from '@/store/aiUIControlStore'` — ContactDetail hängt von AI UI Control Plugin ab. Core-Component hängt von Plugin ab.
- **Problem:** Drag-and-drop ändert nur local state (`setWidgets`). Widget-Position wird nicht in Backend gespeichert. Bei Reload geht die Anordnung verloren.
- **Problem:** `password: str = Field(..., min_length=1, max_length=512)` — Mail-Account Password als Plaintext im Schema. Wird zwar verschlüsselt gespeichert aber im Request unverschlüsselt.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-178: schemas/custom_field_definition.py — entity ohne Validierung
- **Problem:** `principal_type: str = Field(..., pattern="^(user|group|role|guest)$")` — hardcoded. Neue Principal-Types können nicht dynamisch hinzugefügt werden.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-180: Systematisches Problem — Schemas mit hardcoded Regex Patterns
- **Dateien:** tasks/schemas.py, calendar/schemas.py, report_generator/schemas.py, etc.
- **Problem:** Viele Schemas haben hardcoded Regex Patterns für Enums (status, type, etc.). Diese sollten mit den Model-Defaults synchronisiert sein, sind aber dupliziert.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-181: Systematisches Problem — entity_type/entity ohne ENTITY_MODELS Validierung
- **Problem:** Webhook.secret, ShareLink.token, McpServerConfig.api_token werden in API Responses an Frontend gesendet. Secrets sollten nie in Responses stehen.
- **Problem:** _validate_entity_type Funktion ist jetzt in 4 Dateien identisch (tags, entity_links, saved_filters, saved_views). Sollte zentralisiert werden.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-189: routes/groups.py — redundant import uuid as _uuid
- **Datei:** app/routes/groups.py:27
- **Problem:** `import uuid as _uuid` inside list_groups Funktion — uuid ist bereits am Datei-Anfang importiert. Redundant.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-190: Systematisches Problem — falsche Permissions in mehreren Routes
- **Problem:** Mehrere Routes verwenden falsche Permissions die nicht zu ihrem Modul passen. Permission-Namen sind inkonsistent und zugeordnet zu falschen Modulen.
### ARCH-191: models/compliance.py — ComplianceIncident ohne OwnedMixin
- **Datei:** app/models/compliance.py:18
- **Problem:** ComplianceIncident hat kein OwnedMixin. Kein owner_id, keine Visibility-Filterung. Jeder User kann alle Incidents sehen.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-192: models/outbox.py — EventOutbox hat tenant_id aber kein TenantMixin
- **Datei:** app/models/outbox.py:20
- **Problem:** EventOutbox hat `tenant_id: Mapped[uuid.UUID]` aber erbt nicht von TenantMixin. Inkonsistent mit anderen Models.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-193: models/entity_policy.py — ABAC EntityPolicy nicht aktiv genutzt (toter Code)
- **Datei:** app/models/entity_policy.py:7
- **Problem:** Kommentar: 'ABAC EntityPolicy ist implementiert aber wird nicht aktiv genutzt'. Toter Code der verwirrt.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-194: models/address.py — bekannte Inkonsistenz (inline vs Tabelle)
- **Datei:** app/models/address.py:5
- **Problem:** Kommentar: 'Address-Tabelle wird für Bank-Accounts genutzt. Contacts nutzen inline Address-Felder. Diese Inkonsistenz ist bekannt'. Bekanntes Architektur-Problem.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-195: models/bank_account.py — IBAN als Plaintext
- **Datei:** app/models/bank_account.py:25
- **Problem:** `iban: Mapped[str] = mapped_column(String(34), nullable=False)` — IBAN als Plaintext in DB. Sollte verschlüsselt sein.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-196: models/system_settings.py — Sensitive Daten als Plaintext
- **Datei:** app/models/system_settings.py:35-37
- **Problem:** tax_number, iban, bic als Plaintext in DB. Sensitive Finanzdaten unverschlüsselt.
- **Problem:** source_contact_id hat ondelete='SET NULL', target_contact_id hat ondelete='CASCADE'. Inkonsistent — wenn Target gelöscht wird, wird Merge-History gelöscht. Wenn Source gelöscht wird, bleibt History mit NULL.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-200: Systematisches Problem — Sensitive Daten als Plaintext in DB
- **Problem:** Mehrere Models speichern sensitive Daten als Plaintext. Nur mail/models.py verschlüsselt passwords. Andere sensitive Felder (IBAN, API-Keys, Webhook-Secrets, Tax-Numbers) sind unverschlüsselt.
- **Problem:** `noUnusedLocals: false` und `noUnusedParameters: false` — TypeScript strict mode ist nicht vollständig aktiviert. Unbenutzte Variablen werden nicht erkannt.
- **Problem:** `ALTER ROLE {role} WITH LOGIN PASSWORD '{pwd}'` — pwd wird direkt in SQL eingefügt. Wenn pwd Sonderzeichen enthält (z.B. '), kann SQL injection auftreten.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-204: vite.config.ts — PWA Reste (manifest.json ohne PWA plugin)
- **Problem:** `from app.models import *` — wildcard import. Unklar welche Models importiert werden. Kann zu fehlenden Migrationen führen wenn neue Models nicht in __init__.py stehen.
- **Problem:** `passlib[bcrypt]==1.7.4` — exact version pinned. passlib 1.7.4 ist veraltet, neuere Versionen haben Bugfixes.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-208: tailwind.config.js — Hardcoded color values
- **Datei:** frontend/tailwind.config.js:10-80
- **Problem:** Alle Farben sind hardcoded (primary: #2563eb, etc.). themeStore.ts hat DEFAULT_THEME mit denselben Werten — zwei Quellen für dieselben Farben. Sollte CSS variables verwenden.
- **Problem:** `target: ES2020` — moderne JavaScript Features (top-level await, class fields, etc.) werden nicht genutzt. Sollte ES2022+ sein.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-210: docker-compose.yaml — DB_PASSWORD als einzelnes Password für alle Roles
- **Datei:** docker-compose.yaml:38-40
- **Problem:** `DB_PASSWORD` wird für alle DB-Roles (crm_api, crm_auth, crm_worker, crm_user) verwendet. Jede Role sollte ein eigenes Password haben für Security-Isolation.
- **Problem:** `visibleModuleKeys: () => new Set(ctx?.modules?.map(m => m.module_key) || [])` — gibt alle Module zurück, nicht nur sichtbare. is_visible wird nicht gefiltert.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-215: useAIContext.ts — POST ohne Error-Handling
- **Problem:** _rank() Funktion ist jetzt in 5 Dateien definiert (visibility.py, permission_resolver.py, bulk_permission_service.py, contact_folder_permission_service.py, und in permissions.py als PERM_RANK). Sollte zentralisiert werden.
### ARCH-217: auth.py — Dead Code: Response Objekt wird erstellt aber nie verwendet
- **Datei:** app/routes/auth.py:52-53
- **Problem:** `response = Response(status_code=status.HTTP_200_OK)` wird erstellt und `response.set_cookie(...)` aufgerufen, aber dann wird ein neues `JSONResponse` Objekt erstellt (Zeile 57). Das erste Response-Objekt ist Dead Code.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-218: auth.py — logout hat ungenutzten db Parameter
- **Datei:** app/routes/auth.py:74
- **Problem:** `db: AsyncSession = Depends(get_auth_db)` wird injiziert aber nie verwendet. Nur redis wird für logout genutzt. Verschwendet DB-Connection.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-219: auth.py — me_permissions verwendet zwei verschiedene DB-Sessions
- **Datei:** app/routes/auth.py:150
- **Problem:** `db: AsyncSession = Depends(get_auth_db)` UND `current_user: dict = Depends(get_current_user)` — get_current_user verwendet get_db (crm_api role), get_auth_db verwendet crm_auth role. Zwei verschiedene DB-Sessions in einem Request.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-220: users.py — user.created direkt published statt über Outbox
- **Datei:** app/routes/users.py:140
- **Problem:** `event_bus.publish('user.created', ...)` direkt statt über `enqueue_outbox_event()`. outbox.py sagt 'domain events must go through outbox for durability'. user.created ist nicht durable — geht verloren bei Crash.
- **Problem:** `await db.commit()` im Route-Handler, aber `get_db()` committet bereits bei Erfolg (Zeile 248 in db/__init__.py). Double-Commit kann zu Fehlern führen.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-222: users.py — delete_user verwendet users:write statt users:delete
- **Datei:** app/routes/users.py:260
- **Problem:** `require_permission('users:write')` für DELETE, aber CORE_PERMISSIONS hat `users:delete`. Falsche Permission — User mit write aber ohne delete können User löschen.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-223: contacts.py — pydantic Import in der Mitte der Datei
- **Datei:** app/routes/contacts.py:25
- **Problem:** `from pydantic import BaseModel, Field` wird in der Mitte der Datei importiert (nach dem Router-Import), nicht am Anfang. Anti-Pattern — alle Imports sollten am Datei-Anfang stehen.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-224: companies.py — create_company ohne Pydantic Schema
- **Datei:** app/routes/companies.py:85
- **Problem:** `body: dict[str, Any]` statt Pydantic Schema. Keine Validierung — beliebige Felder werden akzeptiert.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-225: companies.py — export_companies ohne visibility filter
- **Datei:** app/routes/companies.py:200
- **Problem:** Exportiert alle Companies ohne `apply_visibility_filter()`. Jeder User mit contacts:read kann ALLE Companies exportieren, auch solche die er nicht sehen dürfte.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-226: companies.py — update_company ohne Pydantic Schema
- **Datei:** app/routes/companies.py:260
- **Problem:** `body: dict[str, Any]` — keine Validierung. Gleicher Fehler wie ARCH-224.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-227: companies.py — get_company_emails returns empty list (Stub)
- **Datei:** app/routes/companies.py:340
- **Problem:** `return []` — Stub/Placeholder. Endpoint existiert aber gibt immer leere Liste zurück.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-228: companies.py — created_by/updated_by Felder existieren nicht auf Contact Model
- **Datei:** app/routes/companies.py:100
- **Problem:** `Contact(created_by=user_id, updated_by=user_id)` — aber Contact Model hat `owner_id` von OwnedMixin, nicht `created_by`/`updated_by`. Diese Felder werden still ignoriert oder verursachen Fehler.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-229: companies.py — Hooks direkt published statt über Outbox
- **Datei:** app/routes/companies.py:100,115
- **Problem:** `do_action('company.before_create', ...)` und `do_action('company.after_create', ...)` — domain events direkt am Event Bus statt über Outbox. Nicht durable.
### ARCH-231: roles.py — delete_role verwendet roles:write statt roles:delete
- **Datei:** app/routes/roles.py:230
- **Problem:** `require_permission('roles:write')` für DELETE, aber CORE_PERMISSIONS hat `roles:delete`. User mit write aber ohne delete können Rollen löschen.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-232: groups.py — get_group ohne require_permission
- **Datei:** app/routes/groups.py:100
- **Problem:** `get_group` hat nur `get_current_user`, kein `require_permission`. Jeder eingeloggte User kann jede Gruppe sehen inkl. Permissions und field_permissions.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-233: groups.py — list_group_members ohne require_permission
- **Datei:** app/routes/groups.py:200
- **Problem:** `list_group_members` hat nur `get_current_user`. Jeder eingeloggte User kann alle Gruppen-Mitglieder sehen.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-234: groups.py — get_user_groups ohne require_permission
- **Datei:** app/routes/groups.py:240
- **Problem:** `get_user_groups` hat nur `get_current_user`. Jeder eingeloggte User kann alle Gruppen eines beliebigen Users sehen.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-235: workflows.py — delete_workflow verwendet workflows:write statt workflows:delete
- **Datei:** app/routes/workflows.py:200
- **Problem:** `require_permission('workflows:write')` für DELETE, aber CORE_PERMISSIONS hat `workflows:delete` nicht — nur `workflows:read` und `workflows:write`. Delete sollte separate Permission haben.
- **Problem:** `create_approval_request()` und sofort `resolve_approval_request(decision='approved')` — Approval wird in selben Request erstellt und approved. Approval ist bedeutungslos.
- **Problem:** Gleicher Pattern wie ARCH-236 — ApprovalRequest wird erstellt und sofort rejected.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-238: workflows.py — webhook_trigger ohne Auth
- **Datei:** app/routes/workflows.py:580
- **Problem:** `webhook_trigger` hat keine Auth-Dependency. Jeder mit dem Token kann Workflows triggern. Keine Rate-Limiting, keine IP-Whitelist.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-239: workflows.py — webhook.workflow_id existiert nicht auf Webhook Model
- **Datei:** app/routes/workflows.py:595
- **Problem:** `webhook.workflow_id if hasattr(webhook, 'workflow_id') else webhook.entity_id` — Webhook Model hat kein `workflow_id` Feld. Der hasattr-Check ist ein Workaround für ein nicht existierendes Feld.
- **Problem:** `from app.plugins.registry import get_registry` — Core Route importiert direkt von Plugin Registry. Core darf nicht von Plugins abhängen.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-242: dashboard.py — Company count über Contact.type statt Company Model
- **Datei:** app/routes/dashboard.py:75
- **Problem:** `Contact.type == 'company'` für Company count. Companies werden als Contacts mit type='company' behandelt, aber es gibt separate companies.py Routes. Doppelarchitektur.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-243: notifications.py — Deprecated Route existiert weiterhin (Doppelarchitektur)
- **Datei:** app/routes/notifications.py:1
- **Problem:** Route ist deprecated (delegiert an Communication), aber existiert weiterhin und wird in main.py registriert. Legacy Notifications und Communication laufen parallel.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-244: notifications.py — N+1 Query in list_notifications_endpoint
- **Datei:** app/routes/notifications.py:55
- **Problem:** `entity_permission_service.check_entity_access()` wird für jede Notification in einer Schleife aufgerufen. Bei 100 Notifications = 100 DB-Queries.
- **Problem:** `from app.plugins.builtins.automation.models import AgentDefinition` — Core Route importiert direkt von Plugin Model. Core darf nicht von Plugins abhängen.
- **Problem:** Retention Policies sind hardcoded in der Route-Datei. Sollte in Config, DB oder Plugin-Manifest stehen.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-248: system_settings.py — dsgvo_export NameError (datetime/timezone nicht importiert)
- **Datei:** app/routes/system_settings.py:200
- **Problem:** `datetime.now(timezone.utc)` wird verwendet, aber `datetime` und `timezone` sind nicht importiert. Weder am Datei-Anfang noch in der Funktion. Das wird einen NameError geben beim Aufruf.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-249: system_settings.py — update_backup_config ohne Pydantic Schema
- **Datei:** app/routes/system_settings.py:160
- **Problem:** `body: dict` statt Pydantic Schema. Keine Validierung von backup_enabled, backup_interval, backup_retention_days, backup_destination.
- **Problem:** `except Exception: pass` — Fehler beim Senden von Alert-Notifications werden still ignoriert.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-253: audit.py — audit_retention_cleanup verwendet audit:read statt audit:delete
- **Datei:** app/routes/audit.py:160
- **Problem:** `require_permission('audit:read')` für DELETE-Endpoint. Jeder mit Leserecht kann Audit-Logs löschen. Sollte `audit:delete` oder `system:admin` sein.
- **Problem:** Gleicher Fehler wie saved_views.py — statische ENTITY_MODELS.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-274: import_export.py — export_data ohne visibility filter
- **Datei:** app/routes/import_export.py:280
- **Problem:** export_data exportiert alle Contacts/Companies ohne Ownership-Check. user_id und is_system_admin werden übergeben, aber der Service könnte sie nicht filtern.
- **Problem:** export_data parst CSV-Daten zurück zu Rows um sie in XLSX umzuwandeln. Ineffizient — sollte direkt XLSX generieren statt CSV→parse→XLSX.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-276: attachments.py — download_attachment liest gesamte Datei in Memory
- **Datei:** app/routes/attachments.py:100
- **Problem:** `file_bytes = await storage.read(storage_path)` liest gesamte Datei in Memory. Bei großen Dateien (100MB) kann das OOM verursachen. Sollte StreamingResponse verwenden.
- **Problem:** `except Exception: pass` beim Session-Invalidate. Fehler werden ignoriert.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-304: guests.py — settings am Module-Level
- **Datei:** app/routes/guests.py:22
- **Problem:** `settings = get_settings()` am Module-Level. Settings werden beim Import geladen, nicht bei Request. Änderungen zur Laufzeit werden nicht erkannt.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-305: permission_templates.py — delete verwendet permissions:templates:write statt :delete
### ARCH-312: plugin_service.py — activate_plugin prüft Zustand nach registry.activate()
- **Datei:** app/services/plugin_service.py:100
- **Problem:** `was_already_active = record.active and record.status == 'active'` wird NACH `registry.activate()` geprüft. Problem 1 bestätigt — wenn Plugin bereits aktiv war, werden Permissions trotzdem neu registriert.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-313: plugin_service.py — direkter Zugriff auf _active_plugins
- **Datei:** app/services/plugin_service.py:110
- **Problem:** `get_permission_registry()._active_plugins.add(name)` greift direkt auf private Attribute zu. Sollte eine public Methode verwenden.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-314: user_service.py — delete_user ohne Audit-Log
- **Datei:** app/services/user_service.py:200
- **Problem:** delete_user hat kein Audit-Log. User-Löschung sollte auditiert werden.
### ARCH-350: contact.py — indexed_at Spalte vor __table_args__
- **Datei:** app/models/contact.py:50
- **Problem:** `indexed_at` Spalte wird vor `__table_args__` definiert — SQLAlchemy Anti-Pattern.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-351: contact.py — IBAN/BIC als Plaintext
- **Datei:** app/models/contact.py:170
- **Problem:** `bank_account` (IBAN) und `bic` werden als Plaintext gespeichert. Sensitive Finanzdaten.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-352: contact.py — vat_code/fiscal_code als Plaintext
- **Datei:** app/models/contact.py:160
- **Problem:** `vat_code` (USt-IdNr.) und `fiscal_code` (Steuernummer) als Plaintext. Sensitive Steuerdaten.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-353: webhook.py — secret als Plaintext
- **Datei:** app/models/webhook.py:30
- **Problem:** `secret` wird als Plaintext in DB gespeichert. Sollte verschlüsselt werden.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-354: system_settings.py — tax_number/vat_id/iban/bic als Plaintext
- **Datei:** app/models/system_settings.py:35
- **Problem:** `tax_number`, `vat_id`, `iban`, `bic` werden als Plaintext gespeichert. Sensitive Unternehmensdaten.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-355: bank_account.py — iban/bic als Plaintext
- **Datei:** app/models/bank_account.py:20
- **Problem:** `iban` und `bic` als Plaintext. Sensitive Finanzdaten.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-356: compliance.py — ComplianceIncident ohne OwnedMixin
- **Datei:** app/models/compliance.py
- **Problem:** ComplianceIncident hat kein OwnedMixin (kein owner_id). Entity-Permissions nicht möglich.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-357: audit.py — search_tsv Spalte vor __table_args__
- **Datei:** app/models/audit.py:30
- **Problem:** `search_tsv` Spalte wird vor `__table_args__` definiert — SQLAlchemy Anti-Pattern.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-358: group.py — UserGroup.deleted_at vor __table_args__
- **Datei:** app/models/group.py:40
- **Problem:** `deleted_at` Spalte wird vor `__table_args__` definiert — SQLAlchemy Anti-Pattern.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-359: notification.py — NotificationType.deleted_at vor __table_args__
- **Datei:** app/models/notification.py:60
- **Problem:** `deleted_at` Spalte wird vor `__table_args__` definiert — SQLAlchemy Anti-Pattern.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-360: ai_conversation.py — AIConversation/AIMessage sollten entfernt sein (Phase 2)
- **Datei:** app/models/ai_conversation.py
- **Problem:** AIConversation/AIMessage existieren noch, aber Phase 2 hat AI Chat in Kommunikation integriert und 5 AI-Tabellen gedropped. Diese Models sollten entfernt werden.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-361: attachment.py — Attachment parallel zu EntityAttachment (Doppelarchitektur)
- **Datei:** app/models/attachment.py
- **Problem:** Attachment Model existiert parallel zu EntityAttachment. Doppelarchitektur — zwei Modelle für ähnliche Funktionalität.
- **Problem:** Importiert direkt von `app.plugins.builtins.mail.contracts`, `calendar.contracts`, `dms.contracts`, `unified_search.contracts`, `automation.contracts`. Core→Plugin Verstöße.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-373: step_handlers.py — crm handler importiert contact_service direkt
- **Datei:** app/workflows/step_handlers.py:450
- **Problem:** `from app.services.contact_service import create_contact, update_contact` — direkter Service-Import in Step Handler. Sollte über Contract oder generische Interface gehen.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-374: engine.py — acquire_lock fail-open
- **Datei:** app/workflows/engine.py:550
- **Problem:** `return True # Fail open — allow processing without lock` — wenn Redis-Lock nicht akquiriert werden kann, wird der Workflow trotzdem ausgeführt. Das kann zu Race Conditions führen.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-375: engine.py — `from app.core.redis import get_redis` aber app/core/redis.py existiert nicht
- **Datei:** app/workflows/engine.py:540
- **Problem:** `from app.core.redis import get_redis` — aber es gibt keine `app/core/redis.py`. Redis wird über `app.core.auth.get_redis` importiert. Das wird einen ImportError geben.
### ARCH-376: registry.py — `from app.core.redis import get_redis` aber app/core/redis.py existiert nicht
- **Datei:** app/plugins/registry.py:600, 650
- **Problem:** `from app.core.redis import get_redis` — aber es gibt keine `app/core/redis.py`. Redis wird über `app.core.auth.get_redis` importiert. ImportError bei Cache-Invalidation.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-377: registry.py — sync_notification_types löscht Types nicht vollständig bei Deaktivierung
- **Datei:** app/plugins/registry.py:181
- **Problem:** sync_notification_types löscht nur Types wenn das Plugin nicht mehr aktiv ist. Aber die Reihenfolge ist: on_deactivate() → sync_notification_types(). Wenn on_deactivate fehlschlägt, bleiben Types.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-378: registry.py — activate() ruft on_activate() vor sync_notification_types() auf
- **Datei:** app/plugins/registry.py:580
- **Problem:** Reihenfolge: on_activate() → register_contributions() → sync_notification_types(). Wenn on_activate Event-Handler registriert die Notification-Types verwenden, sind die Types noch nicht in DB.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-379: contracts.py — _try_lazy_load lädt deaktivierte Plugins neu
- **Problem:** `get_contract()` macht `_try_lazy_load()` auch nach `unregister()`. `unregister()` entfernt Contract und setzt `_loaded`, aber `_try_lazy_load` kann ihn wiederherstellen. Problem 14 bestätigt.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-380: base.py — on_activate registriert Event-Handler ohne Duplikatsprüfung
- **Datei:** app/plugins/base.py:59
- **Problem:** `event_bus.subscribe(event_name, handler)` wird bei jedem `on_activate()` aufgerufen. Bei mehrfachem `on_activate()` (pro Tenant) werden Handler doppelt registriert. Problem 2 und 20 bestätigt.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-381: base.py — on_deactivate überschreibt _event_handlers nicht
- **Datei:** app/plugins/base.py:75
- **Problem:** `on_deactivate()` ruft `self._event_handlers.clear()` auf, aber wenn eine Subclass `on_deactivate()` überschreibt und `super().on_deactivate()` nicht aufruft, werden Event-Handler nicht deregistriert.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-382: contacts/plugin.py — Routes=[] aber Core hat contacts routes (Doppelarchitektur)
- **Problem:** Manifest hat noch `menu_items` und `page_routes` für `/ai-assistant` — aber AIAssistant.tsx wurde in Phase 2 entfernt. Frontend wird versuchen eine nicht existierende Seite zu laden.
- **Schweregrad:** High
- **Status:** ⏳ Nicht gefixt
### ARCH-384: knowledge/plugin.py — uuid wird verwendet aber nicht importiert
- **Problem:** `unregister_actions_by_owner('wiki')` wird aufgerufen, dann `await super().on_deactivate()`. Aber wenn super().on_deactivate() fehlschlägt, sind Actions bereits deregistriert. Reihenfolge sollte umgekehrt sein.
- **Schweregrad:** Low
- **Status:** ⏳ Nicht gefixt
### ARCH-387: system_notif/plugin.py — Legacy Notifications parallel zu Kommunikation
- **Problem:** system_notif konvertiert System-Events in Chat-Nachrichten über kommunikation. Aber es gibt auch noch die Legacy Notification Routes (notifications.py). Doppelarchitektur. Problem 18 bestätigt.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-388: self_improvement/plugin.py — dependencies deklariert ai_proactive aber nicht kommunikation
- **Problem:** `dependencies=['permissions', 'automation', 'ai_proactive']` — aber services.py importiert von kommunikation. Nicht deklariert. Problem 13/29 bestätigt.
- **Schweregrad:** Medium
- **Status:** ⏳ Nicht gefixt
### ARCH-389: tasks/plugin.py — dependencies deklariert nicht kommunikation
- **Datei:** app/plugins/builtins/tasks/plugin.py
- **Problem:** `dependencies=['permissions']` — aber tasks/workstream.py importiert von kommunikation. Nicht deklariert. Problem 29 bestätigt.