From 0d59389c40319160e1d59b36c26b10f66c22a845 Mon Sep 17 00:00:00 2001 From: Agent Zero Date: Sat, 22 Aug 2026 23:39:49 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20unzuverl=C3=A4ssige=20Script-basierte?= =?UTF-8?q?=20Fehler=20gel=C3=B6scht=20=E2=80=94=20nur=20verifizierte=20be?= =?UTF-8?q?halten?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/test-bugs.md | 3126 --------------------------------------------- 1 file changed, 3126 deletions(-) diff --git a/docs/test-bugs.md b/docs/test-bugs.md index 8c40512..3aa7d2f 100644 --- a/docs/test-bugs.md +++ b/docs/test-bugs.md @@ -992,3129 +992,3 @@ Playwright E2E: 10 passed, 24 failed (BUG-011/012/013 — Mock-Daten und data-te - **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 -- **Datei:** frontend/src/store/pluginStore.ts:127-131 -- **Problem:** getAllMenuItems() gibt alle Menüs zurück ohne Permission-Filter. Sidebar.tsx filtert zwar, aber der Store selbst nicht. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-032: usePermission.ts — gleiche Segmentanzahl wie Backend -- **Datei:** frontend/src/hooks/usePermission.ts:12-18 -- **Problem:** `if (pParts.length === rParts.length)` — gleiche Segmentanzahl-Bedingung wie Backend. `core:*:read` (3 Segmente) matcht nicht `contacts:read` (2 Segmente). -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-033: PluginLoader.tsx — hardcoded deutsche Strings ohne i18n -- **Datei:** frontend/src/components/plugins/PluginLoader.tsx:55,59,62,82,88 -- **Problem:** 'Plugin konnte nicht geladen werden', 'Erneut versuchen', 'Neu laden', 'Fehlerdetails' — ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-034: routes/index.tsx — multiple catch-all routes -- **Datei:** frontend/src/routes/index.tsx:167,179,192,200,231,268 -- **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 -- **Datei:** app/plugins/builtins/wiki/plugin.py:25 -- **Problem:** `dependencies=["permissions"]` aber on_activate importiert von unified_search. unified_search nicht deklariert. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-036: knowledge/plugin.py — uuid import fehlt -- **Datei:** app/plugins/builtins/knowledge/plugin.py -- **Problem:** Verwendet `uuid.UUID()` in on_activate aber `import uuid` fehlt in plugin.py. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-037: wiki/plugin.py on_deactivate — unregister_actions_by_owner falsch aufgerufen -- **Datei:** app/plugins/builtins/wiki/plugin.py:40 -- **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. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-038: knowledge/plugin.py on_deactivate — unregister_actions_by_owner falsch aufgerufen -- **Datei:** app/plugins/builtins/knowledge/plugin.py:65 -- **Problem:** `unregister_actions_by_owner("knowledge")` — gleicher Fehler wie ARCH-037. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-039: contacts/plugin.py — routes=[] aber Routes in main.py -- **Datei:** app/plugins/builtins/contacts/plugin.py:29 -- **Problem:** `routes=[]` — Routes sind in main.py als Core-Routes registriert. Doppelarchitektur: Contacts ist Core UND Plugin. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-040: tasks/plugin.py — ai_assistant nicht in dependencies -- **Datei:** app/plugins/builtins/tasks/plugin.py:on_activate -- **Problem:** Importiert von ai_assistant.contracts aber ai_assistant nicht in dependencies. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-041: self_improvement — kommunikation nicht in dependencies -- **Datei:** app/plugins/builtins/self_improvement/plugin.py -- **Problem:** `dependencies=["permissions", "automation", "ai_proactive"]` aber services.py importiert von kommunikation. Nicht deklariert. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-042: wiki/plugin.py — unified_search nicht in dependencies (Bestätigung ARCH-035) -- **Datei:** app/plugins/builtins/wiki/plugin.py:25 -- **Problem:** on_activate importiert von unified_search.contracts aber dependencies=["permissions"]. unified_search fehlt. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-043: PluginRouteRenderer.tsx — KEINE Permission-Prüfung (bestätigt) -- **Datei:** frontend/src/components/plugins/PluginRouteRenderer.tsx -- **Problem:** grep nach 'permission|Permission|canAccess|hasPermission' = 0 Ergebnisse. Jeder eingeloggte User kann jede Plugin-Seite sehen. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-044: routes/index.tsx — 6 catch-all path:'*' Routes -- **Datei:** frontend/src/routes/index.tsx:167,179,192,200,231,268 -- **Problem:** 6 verschiedene catch-all Routes. React Router kann nur einen catch-all pro Route-Level haben. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-045: AppShell.tsx — hardcoded '/ai-assistant' Pfad -- **Datei:** frontend/src/components/layout/AppShell.tsx:42 -- **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 -- **Datei:** frontend/src/store/commStore.ts, frontend/src/api/comm.ts -- **Problem:** Participant, Conversation, MessageBlock werden in beiden Dateien definiert. Sollten in einer shared types-Datei stehen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-047: api/client.ts — activeWorkspaceId ohne Validierung -- **Datei:** frontend/src/api/client.ts:28 -- **Problem:** `activeWorkspaceId` wird als X-Workspace-ID Header gesendet ohne Validierung dass der User tatsächlich zum Workspace gehört. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-048: roles.py — SYSTEM_PERMISSIONS dupliziert permission_registry.py -- **Datei:** app/routes/roles.py:18-40, app/core/permission_registry.py:21-60 -- **Problem:** SYSTEM_PERMISSIONS in roles.py ist eine statische Liste die CORE_PERMISSIONS in permission_registry.py dupliziert. Zwei Quellen für dieselben Permissions. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-049: dashboard.py — Core→Plugin Import -- **Datei:** app/routes/dashboard.py:15 -- **Problem:** `from app.plugins.registry import get_registry` — Core importiert von Plugin Registry. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### 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. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-054: workflow_service.py — importiert post_system_message (Core→Plugin Kette) -- **Datei:** app/services/workflow_service.py:10 -- **Problem:** `from app.core.notifications import post_system_message` — notifications.py importiert wiederum von plugins.builtins.contracts. Indirekte Core→Plugin Abhängigkeit. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-055: Settings.tsx — hardcoded deutsche Strings ohne i18n -- **Datei:** frontend/src/pages/Settings.tsx:30-40 -- **Problem:** hardcodedNavItems hat 'Stammdaten', 'Nutzerverwaltung', 'System', 'KI Einstellungen', 'Custom Fields', 'Webhooks', 'Workspaces', 'Backup & Restore' — ohne t(). -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-056: Settings.tsx — statische UND dynamische Settings-Seiten (Doppelarchitektur) -- **Datei:** frontend/src/pages/Settings.tsx:30-40, 42-50 -- **Problem:** hardcodedNavItems (statisch) UND pluginSettingsPages (dynamisch via PluginStore). Doppelarchitektur. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-057: Communication.tsx — doppelte Type-Definitionen (3. Kopie) -- **Datei:** frontend/src/pages/Communication.tsx:15-50 -- **Problem:** Definiert eigene Conversation/Participant/Message/MessageBlock Types — dupliziert commStore.ts und api/comm.ts (3. Kopie). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-058: PluginRegistry.tsx — fetcht active-manifests die plugins:read erfordert -- **Datei:** frontend/src/components/plugins/PluginRegistry.tsx:10 -- **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 -- **Datei:** frontend/src/hooks/useWorkspace.ts:62 -- **Problem:** `const visibleModuleKeys = useWorkspaceStore(s => s.visibleModuleKeys())` — bei jedem Render wird ein neues Set erstellt. Sollte useMemo verwenden. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-060: step_handlers.py — MailContract.get_function() existiert nicht -- **Datei:** app/workflows/step_handlers.py:221,261,306,351,394 -- **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. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-061: unified_search/contracts.py — get_contract() umgeht Registry -- **Datei:** app/plugins/builtins/unified_search/contracts.py:38-43 -- **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 -- **Datei:** app/plugins/builtins/mail/contracts.py -- **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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-065: automation/execution_engine.py — Core Model in Plugin-Code -- **Datei:** app/plugins/builtins/automation/execution_engine.py:8 -- **Problem:** `from app.models.notification import Notification` — Plugin importiert Core Model. Plugin→Core ist erlaubt aber Notification ist deprecated (ARCH-050). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-066: SuggestionBadge.tsx — hardcoded deutsche Strings ohne i18n -- **Datei:** frontend/src/components/ai/SuggestionBadge.tsx:28 -- **Problem:** `title="KI Vorschläge"` und `🤖` — ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-067: SuggestionBadge.tsx — EventSource ohne Auth -- **Datei:** frontend/src/components/ai/SuggestionBadge.tsx:17 -- **Problem:** `new EventSource('/api/v1/ai-proactive/suggestions/stream')` — EventSource (SSE) sendet keine Cookies/CSRF-Token. Stream ist ungeschützt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-068: CommandPalette.tsx — hardcoded TYPE_LABELS/ICONS -- **Datei:** frontend/src/components/search/CommandPalette.tsx:2 -- **Problem:** TODO: 'Replace hardcoded TYPE_LABELS/ICONS with dynamic config'. Hardcoded Labels und Icons für Search-Typen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-069: OnboardingTour.tsx — hardcoded deutsche Fallback-Strings -- **Datei:** frontend/src/components/onboarding/OnboardingTour.tsx:30-35 -- **Problem:** titleFallback und descFallback sind hardcoded deutsche Strings. Fallback sollte englisch sein oder leer. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-070: permission_resolver.py — zirkuläre Abhängigkeit mit entity_permission_service -- **Datei:** app/services/permission_resolver.py:28 -- **Problem:** `from app.services.entity_permission_service import ENTITY_MODELS` — entity_permission_service importiert permission_resolver (Zeile 1-10). Zirkuläre Abhängigkeit. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-071: permissions/contracts.py — get_contract() umgeht Registry -- **Datei:** app/plugins/builtins/permissions/contracts.py:28-33 -- **Problem:** get_contract() erstellt neue Instanz statt Registry zu verwenden. Gleicher Fehler wie ARCH-061. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-072: graph_rag/contracts.py — get_contract() umgeht Registry -- **Datei:** app/plugins/builtins/graph_rag/contracts.py:28-33 -- **Problem:** Gleicher Fehler wie ARCH-061 und ARCH-071. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-073: calendar/contracts.py — get_contract() umgeht Registry -- **Datei:** app/plugins/builtins/calendar/contracts.py:28-33 -- **Problem:** Gleicher Fehler wie ARCH-061, ARCH-071, ARCH-072. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-074: permissions/public_routes.py — Plugin→Plugin ohne dependencies -- **Datei:** app/plugins/builtins/permissions/public_routes.py:14 -- **Problem:** `from app.plugins.builtins.dms.contracts import DmsContract` — permissions hat dependencies=[] aber importiert von dms. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-075: permissions/routes.py — permissions:admin aber Manifest hat keine permissions -- **Datei:** app/plugins/builtins/permissions/routes.py:24, app/plugins/builtins/permissions/plugin.py:35 -- **Problem:** Routes erfordern `permissions:admin` aber Manifest hat `permissions=[]`. Permission wird nie registriert. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-076: mail/services.py — Core→Plugin Kette über notifications -- **Datei:** app/plugins/builtins/mail/services.py:38 -- **Problem:** `from app.core.notifications import create_notification` — notifications.py importiert wiederum von plugins.builtins.contracts. Indirekte Plugin→Core→Plugin Kette. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-077: dms/routes.py — Permission Model wird beim Modul-Import geladen -- **Datei:** app/plugins/builtins/dms/routes.py:40-43 -- **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) -- **Datei:** app/plugins/builtins/dms/models.py:48-51 -- **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__ -- **Datei:** app/plugins/builtins/calendar/models.py:52-54 -- **Problem:** Gleicher Fehler wie ARCH-078. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-080: tags/models.py — Spalten vor __table_args__ -- **Datei:** app/plugins/builtins/tags/models.py:27-28 -- **Problem:** Gleicher Fehler wie ARCH-078. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-081: mail/models.py — MailAccount.user_id ohne ForeignKey -- **Datei:** app/plugins/builtins/mail/models.py:38 -- **Problem:** `user_id: Mapped[uuid.UUID]` hat keine ForeignKey auf users.id. Datenintegrität nicht gewährleistet. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-082: knowledge/models.py — KnowledgeExtraction ohne OwnedMixin -- **Datei:** app/plugins/builtins/knowledge/models.py:16 -- **Problem:** `KnowledgeExtraction(Base, TenantMixin)` — kein OwnedMixin. Kein owner_id, keine Visibility-Filterung möglich. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-083: ai_assistant/models.py — AIProvider.api_key als Plaintext -- **Datei:** app/plugins/builtins/ai_assistant/models.py:35 -- **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 -- **Datei:** app/plugins/builtins/automation/models.py:38 -- **Problem:** `llm_model: Mapped[str] = mapped_column(String(100), nullable=False, default="ollama/deepseek-v4-flash")` — hardcoded Model-Name. Sollte aus Settings kommen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-085: errorTypes.ts — hardcoded deutsche Strings ohne i18n -- **Datei:** frontend/src/utils/errorTypes.ts:40-45 -- **Problem:** 'Netzwerkfehler', 'Nicht authentifiziert', 'Keine Berechtigung', 'Validierungsfehler', 'Serverfehler', 'Unbekannter Fehler' — ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-086: errorLogger.ts — POST /api/v1/errors ohne CSRF-Token -- **Datei:** frontend/src/utils/errorLogger.ts:62 -- **Problem:** `fetch('/api/v1/errors', { method: 'POST' })` ohne X-CSRF-Token. CSRF-Middleware wird den Request blocken (403). -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-087: date.ts — hardcoded German locale -- **Datei:** frontend/src/utils/date.ts:2 -- **Problem:** `import { de } from 'date-fns/locale'` — hardcoded German locale. Sollte dynamisch basierend auf User-Preference sein. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-088: hooks.py — do_action/apply_filters verschlucken Exceptions -- **Datei:** app/core/hooks.py:140,150 -- **Problem:** `except Exception: logger.exception(...)` — alle Exceptions werden nur geloggt, nicht weitergeworfen. Fehler in Hooks sind unsichtbar. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-089: storage.py — _DEFAULT_ALLOWED_MIMES hardcoded -- **Datei:** app/core/storage.py:38-55 -- **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 -- **Datei:** app/plugins/builtins/contracts.py:72-74 -- **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) -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-094: StartPage.tsx — hardcoded deutsche Strings ohne i18n -- **Datei:** frontend/src/pages/StartPage.tsx:24-25 -- **Problem:** 'Haupt-Workspace', 'Kontakte, Kalender, Mail und mehr' — hardcoded deutsche Strings ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-095: Contacts.tsx, DMS.tsx, NoAccess.tsx — leere Dateien -- **Datei:** frontend/src/pages/Contacts.tsx, DMS.tsx, NoAccess.tsx -- **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 -- **Datei:** frontend/src/components/common/ErrorBoundary.tsx:60-75 -- **Problem:** 'Etwas ist schiefgelaufen', 'Ein unerwarteter Fehler ist aufgetreten', 'Erneut versuchen', 'Neu laden', 'Fehlerdetails' — ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-100: SavedFilterBar.tsx — hardcoded deutsche Strings ohne i18n -- **Datei:** frontend/src/components/common/SavedFilterBar.tsx:10 -- **Problem:** 'Speichern' und andere Strings im Docstring — hardcoded deutsch. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-101: windowStore.ts — globale windowIdCounter Variable -- **Datei:** frontend/src/store/windowStore.ts:30 -- **Problem:** `let windowIdCounter = 0` — globale Variable außerhalb des Stores. Bei Hot-Module-Replacement kann es zu doppelten IDs kommen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-102: themeStore.ts — DEFAULT_THEME hardcoded -- **Datei:** frontend/src/store/themeStore.ts:22-28 -- **Problem:** DEFAULT_THEME hat hardcoded Werte (#2563eb, #d946ef, Inter, 0.5rem) die nicht aus Settings kommen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-103: calendarStore.ts — Set nicht serialisierbar -- **Datei:** frontend/src/store/calendarStore.ts -- **Problem:** `visibleCalendarIds: Set` — Set ist nicht JSON-serialisierbar. Persistierung mit zustand persist() funktioniert nicht. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-104: pluginToolbarStore.ts — registerItems überschreibt activePlugin -- **Datei:** frontend/src/store/pluginToolbarStore.ts:25 -- **Problem:** `registerItems` setzt `activePlugin: plugin` automatisch. Wenn mehrere Plugins gleichzeitig registrieren, gewinnt das letzte. Sollte separaten setActivePlugin Call erfordern. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-105: core/approval.py — Model in core/ statt models/ -- **Datei:** app/core/approval.py:38 -- **Problem:** ApprovalRequest Model ist in core/ definiert, nicht in models/. Unübliche Platzierung, inkonsistent mit anderen Models. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-106: core/job_registry.py — _registry nicht thread-safe -- **Datei:** app/core/job_registry.py:22 -- **Problem:** `_registry: dict[str, JobFunc] = {}` — globales dict ohne Locks. Bei gleichzeitigen Registrierungen kann es zu Race Conditions kommen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-107: core/backup_job.py — _BACKUP_SCRIPT Pfad hardcoded -- **Datei:** app/core/backup_job.py:18-21 -- **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. -- **Schwertegrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-108: core/sensitive_data.py — SENSITIVE_FIELDS statisch -- **Datei:** app/core/sensitive_data.py:22-40 -- **Problem:** SENSITIVE_FIELDS ist ein statisches dict. Neue Plugin-Entities werden nicht automatisch erfasst. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-109: core/monitoring.py — REGISTRY globale Variable -- **Datei:** app/core/monitoring.py:18 -- **Problem:** `REGISTRY = CollectorRegistry()` — globale Variable, nicht thread-safe. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-110: core/pagination.py — approximate_count ungenau -- **Datei:** app/core/pagination.py:22 -- **Problem:** approximate_count liest pg_class.reltuples — kann ungenau sein bei seltenen ANALYZE/VACUUM. Wird für Pagination verwendet → falsche Seitenzahlen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-111: core/plugin_error_handler.py — delattr __wrapped__ erschwert Debugging -- **Datei:** app/core/plugin_error_handler.py:35 -- **Problem:** `delattr(wrapper, '__wrapped__')` löscht __wrapped__ Attribut. Debugging-Tools die __wrapped__ verwenden um Original-Funktion zu finden, funktionieren nicht mehr. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-112: core/restore_registry.py — _DEFAULT_EXCLUDED statisch -- **Datei:** app/core/restore_registry.py:24-31 -- **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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-118: ai/agent_tools.py — _user_has_permission dupliziert check_permission -- **Datei:** app/ai/agent_tools.py:22-40 -- **Problem:** _user_has_permission() dupliziert die Logik aus app/core/permissions.py:check_permission(). Zwei Implementierungen desselben Checks. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-119: ai/data_policy.py — _CATEGORY_ENTITY_MAP statisch -- **Datei:** app/ai/data_policy.py:24-28 -- **Problem:** _CATEGORY_ENTITY_MAP ist statisch. Neue Plugin-Entities werden nicht erfasst. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-120: ai/oversight.py — DecisionRecord als @dataclass statt Model -- **Datei:** app/ai/oversight.py:30 -- **Problem:** DecisionRecord ist ein @dataclass, nicht in models/. Inkonsistent mit anderen Models. Wird nicht in DB gespeichert. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-121: ai/action_mapper.py — _PATTERNS hardcoded Regex -- **Datei:** app/ai/action_mapper.py:12-25 -- **Problem:** _PATTERNS und _NAME_PATTERNS sind hardcoded Regex. Nicht konfigurierbar, nicht erweiterbar durch Plugins. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-122: workflows/decision_guard.py — HIGH_RISK_ACTIONS statisch -- **Datei:** app/workflows/decision_guard.py:25 -- **Problem:** HIGH_RISK_ACTIONS ist statisch. Neue Actions können nicht dynamisch hinzugefügt werden. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-123: workflows/engine.py — importiert post_system_message (Core→Plugin Kette) -- **Datei:** app/workflows/engine.py:13 -- **Problem:** `from app.core.notifications import post_system_message` — notifications.py importiert wiederum von plugins.builtins.contracts. Indirekte Core→Plugin Abhängigkeit. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-124: workflows/step_handlers.py — StepResult ohne __slots__ -- **Datei:** app/workflows/step_handlers.py:22 -- **Problem:** StepResult ist eine Klasse ohne __slots__. Memory-Verschwendung bei vielen Instanzen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-125: ai/skill_registry.py — SkillRegistry nicht thread-safe -- **Datei:** app/ai/skill_registry.py:40 -- **Problem:** SkillRegistry hat ein globales _skills dict ohne Locks. Bei gleichzeitiger Registrierung kann es zu Race Conditions kommen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-126: ai/ai_use_case.py — KNOWN_DATA_CATEGORIES statisch -- **Datei:** app/ai/ai_use_case.py:18 -- **Problem:** KNOWN_DATA_CATEGORIES ist statisch. Neue Plugin-Kategorien werden nicht erfasst. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-127: ai/transparency.py — AI_PARTICIPANT_TYPES statisch -- **Datei:** app/ai/transparency.py:14 -- **Problem:** AI_PARTICIPANT_TYPES ist statisch. Neue AI-Participant-Types können nicht dynamisch hinzugefügt werden. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-128: services/dedup_service.py — DUPLICATE_FIELDS statisch -- **Datei:** app/services/dedup_service.py:18 -- **Problem:** DUPLICATE_FIELDS ist statisch. Neue Felder können nicht dynamisch hinzugefügt werden. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-129: services/import_export_service.py — COMPANY_COLUMNS/CONTACT_COLUMNS statisch -- **Datei:** app/services/import_export_service.py:24-26 -- **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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-131: services/webhook_service.py — _validate_webhook_url macht DNS-Auflösung -- **Datei:** app/services/webhook_service.py:30 -- **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. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-133: models/workspace.py — 4 Tabellen überdimensioniert -- **Datei:** app/models/workspace.py:7 -- **Problem:** Kommentar: '4 Workspace-Tabellen sind überdimensioniert für ein Mini-CRM'. Workspace, WorkspaceModule, WorkspaceUser, WorkspaceWidget — 4 Tabellen für UI-Navigation. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-134: services/bulk_permission_service.py — _rank() dupliziert -- **Datei:** app/services/bulk_permission_service.py:18, app/core/visibility.py:30, app/services/permission_resolver.py:14 -- **Problem:** _rank() Funktion ist in 3 Dateien definiert. Sollte zentralisiert werden. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-135: services/entity_permission_service.py — post_system_message (Core→Plugin Kette) -- **Datei:** app/services/entity_permission_service.py:25 -- **Problem:** `from app.core.notifications import post_system_message` — notifications.py importiert wiederum von plugins.builtins.contracts. Indirekte Core→Plugin Abhängigkeit. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### 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. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-138: api/search.ts — hardcoded ENTITY_URL_MAP (TODO P2-F3) -- **Datei:** frontend/src/api/search.ts:2 -- **Problem:** TODO: 'Replace hardcoded ENTITY_URL_MAP with dynamic backend config'. Hardcoded URL-Mapping für Search-Entities. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-139: api/tags.ts — EntityType hardcoded -- **Datei:** frontend/src/api/tags.ts:11 -- **Problem:** `export type EntityType = 'contact' | 'file' | 'calendar_entry'` — hardcoded. Nicht erweiterbar durch Plugins. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-140: routes/system_dashboard.py — Core→Plugin Import -- **Datei:** app/routes/system_dashboard.py:15 -- **Problem:** `from app.plugins.registry import get_registry` — Core importiert von Plugin Registry. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-141: routes/guests.py — SHA-256 statt bcrypt für Token -- **Datei:** app/routes/guests.py:28 -- **Problem:** `_hash_token` verwendet SHA-256 statt bcrypt. Inkonsistent mit auth.py die bcrypt verwendet. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-142: api/webhooks.ts — Webhook.secret an Frontend gesendet -- **Datei:** frontend/src/api/webhooks.ts:17 -- **Problem:** `secret: string | null` — Webhook.secret wird an Frontend gesendet. HMAC Secret sollte nicht an Client gesendet werden. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-143: routes/health.py — Response-Format inkonsistent -- **Datei:** app/routes/health.py:35 -- **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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-145: routes/system_dashboard.py — post_system_message (Core→Plugin Kette) -- **Datei:** app/routes/system_dashboard.py:16 -- **Problem:** `from app.core.notifications import post_system_message` — notifications.py importiert wiederum von plugins.builtins.contracts. Indirekte Core→Plugin Abhängigkeit. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-146: knowledge/routes.py — falsche Permission für /extract -- **Datei:** app/plugins/builtins/knowledge/routes.py:16 -- **Problem:** `require_permission("wiki:read")` für /knowledge/extract — sollte `knowledge:read` sein. Falsche Permission. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-147: mcp_client/routes.py — api_token in Response -- **Datei:** app/plugins/builtins/mcp_client/routes.py:38 -- **Problem:** `_config_to_response` gibt `api_token=cfg.api_token` zurück. API-Token wird an Frontend gesendet. Security Issue. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-148: self_improvement/routes.py — falsche Permission für /signals/collect -- **Datei:** app/plugins/builtins/self_improvement/routes.py:33 -- **Problem:** `require_permission("automation:read")` für /signals/collect — sollte `improvement:read` sein. Falsche Permission. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-149: tags/routes.py und entity_links/routes.py — _is_valid_entity_type dupliziert -- **Datei:** app/plugins/builtins/tags/routes.py:26, app/plugins/builtins/entity_links/routes.py:23 -- **Problem:** _is_valid_entity_type Funktion ist in beiden Dateien identisch. Sollte zentralisiert werden. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-150: tags/routes.py und entity_links/routes.py — ENTITY_MODELS Import bei jedem Call -- **Datei:** app/plugins/builtins/tags/routes.py:27, app/plugins/builtins/entity_links/routes.py:24 -- **Problem:** `from app.services.entity_permission_service import ENTITY_MODELS` wird bei jedem Call ausgeführt. Sollte einmal importiert werden. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-151: mcp_server/routes.py — Bearer-Token Auth neben Session-Cookie -- **Datei:** app/plugins/builtins/mcp_server/routes.py:17 -- **Problem:** `get_current_user_or_bearer` — Bearer-Token Auth neben Session-Cookie. Zwei Auth-Methoden können zu Security-Problemen führen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-152: marketplace/routes.py — require_admin vs require_permission inkonsistent -- **Datei:** app/plugins/builtins/marketplace/routes.py:22,28 -- **Problem:** Einige Endpoints verwenden require_admin, andere require_permission. Inkonsistent. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-153: ai_proactive/routes.py — SSE Streaming ohne Auth -- **Datei:** app/plugins/builtins/ai_proactive/routes.py -- **Problem:** SSE Streaming Endpoint ohne Auth-Check. Wie ARCH-067 (SuggestionBadge.tsx EventSource ohne Auth). -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-154: tasks/routes.py — hardcoded Regex Patterns -- **Datei:** app/plugins/builtins/tasks/routes.py:16-18 -- **Problem:** TASK_STATUS_PATTERN, TASK_TYPE_PATTERN, ASSIGNEE_TYPE_PATTERN sind hardcoded Regex. Sollten mit Model-Defaults synchronisiert werden. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-155: report_generator/routes.py — importiert Contact Model (Plugin→Core/Plugin) -- **Datei:** app/plugins/builtins/report_generator/routes.py:18 -- **Problem:** `from app.models.contact import Contact` — Plugin importiert Core Model. Contact ist Core aber auch Plugin (ARCH-005). Doppelarchitektur. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-156: CustomFieldRenderer.tsx — Duplikat in zwei Ordnern -- **Datei:** frontend/src/components/contacts/CustomFieldRenderer.tsx, frontend/src/components/custom-fields/CustomFieldRenderer.tsx -- **Problem:** CustomFieldRenderer existiert in beiden Ordnern. Duplikat. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-157: components/knowledge/ — leerer Ordner -- **Datei:** frontend/src/components/knowledge/ -- **Problem:** Ordner existiert aber enthält 0 Dateien. Entweder tot oder unvollständig. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-158: components/contact/ — leerer Ordner -- **Datei:** frontend/src/components/contact/ -- **Problem:** Ordner existiert aber enthält 0 Dateien. Entweder tot oder unvollständig. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-159: components/agents/AgentChat.tsx — AI Chat wurde in Kommunikation integriert -- **Datei:** frontend/src/components/agents/AgentChat.tsx -- **Problem:** AI Chat wurde in Phase 2 in Kommunikation integriert. AgentChat.tsx ist möglicherweise ungenutzt. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-160: ContactList.tsx — hardcoded ALL_COLUMNS (TODO P2-F18) -- **Datei:** frontend/src/components/contacts/ContactList.tsx:2 -- **Problem:** TODO: 'Replace hardcoded ALL_COLUMNS with backend/manifest config'. Hardcoded Column-Definitions. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-161: MailList.tsx — inline style (TODO P3-F6) -- **Datei:** frontend/src/components/mail/MailList.tsx:2 -- **Problem:** TODO: 'Replace inline style with Tailwind classes'. Inline styles statt Tailwind. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-162: NotificationBell.tsx — TODO Migrate to communication API -- **Datei:** frontend/src/components/layout/NotificationBell.tsx:2 -- **Problem:** TODO: 'Migrate from /notifications to communication API'. Verwendet noch deprecated /notifications API. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-163: DashboardWidgetLoader.tsx — hardcoded widgetRegistry (TODO P2-F17) -- **Datei:** frontend/src/components/dashboard/DashboardWidgetLoader.tsx:2 -- **Problem:** TODO: 'Replace hardcoded widgetRegistry with dynamic manifest config'. Hardcoded Widget-Registry. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-164: AISidebar.tsx — importiert createSession, fetchSessions (Phase 2 entfernt) -- **Datei:** frontend/src/components/layout/AISidebar.tsx:6 -- **Problem:** `import { createSession, fetchSessions } from '@/api/ai'` — AI Sessions wurden in Phase 2 entfernt. Funktionen existieren möglicherweise nicht mehr. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-165: WorkspaceSwitcher.tsx — hardcoded Tailwind dark: classes -- **Datei:** frontend/src/components/layout/WorkspaceSwitcher.tsx:35 -- **Problem:** `dark:bg-gray-900`, `dark:text-gray-300` — hardcoded Tailwind dark: classes statt design tokens (secondary-*, primary-*). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-166: BlockRenderer.tsx — hardcoded switch-case für Block-Typen -- **Datei:** frontend/src/components/comm/blocks/BlockRenderer.tsx:30 -- **Problem:** Hardcoded switch-case für Block-Typen. Neue Block-Typen können nicht dynamisch hinzugefügt werden. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-167: AiChatPanel.tsx — kein API cancel bei unmount -- **Datei:** frontend/src/components/window/AiChatPanel.tsx:50 -- **Problem:** Erstellt comm conversation bei mount, aber bei unmount wird nur `cancelled = true` gesetzt. Die Konversation wird nicht gelöscht. Leak von leeren Konversationen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-168: ContactDetail.tsx — importiert useAIUIControlStore (Plugin-Abhängigkeit) -- **Datei:** frontend/src/components/contacts/ContactDetail.tsx:14 -- **Problem:** `import { useAIUIControlStore } from '@/store/aiUIControlStore'` — ContactDetail hängt von AI UI Control Plugin ab. Core-Component hängt von Plugin ab. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-169: CalendarTree.tsx — TYPE_ORDER hardcoded -- **Datei:** frontend/src/components/calendar/CalendarTree.tsx:15 -- **Problem:** `const TYPE_ORDER: CalendarType[] = ['personal', 'team', 'project', 'company']` — hardcoded. Nicht dynamisch erweiterbar. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-170: DashboardGrid.tsx — drag-and-drop speichert nicht in Backend -- **Datei:** frontend/src/components/dashboard/DashboardGrid.tsx:35 -- **Problem:** Drag-and-drop ändert nur local state (`setWidgets`). Widget-Position wird nicht in Backend gespeichert. Bei Reload geht die Anordnung verloren. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-171: schemas/common.py — Deprecated Notification Schemas noch aktiv -- **Datei:** app/schemas/common.py:15-40 -- **Problem:** Deprecated Notification Schemas (NotificationResponse, NotificationListResponse, etc.) noch aktiv. Doppelarchitektur mit kommunikation. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-172: schemas/webhook.py — WebhookResponse gibt secret zurück -- **Datei:** app/schemas/webhook.py:40 -- **Problem:** WebhookResponse gibt secret zurück. HMAC Secret sollte nicht in API Response stehen. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-173: automation/schemas.py — llm_model default hardcoded -- **Datei:** app/plugins/builtins/automation/schemas.py:18 -- **Problem:** `llm_model: str = Field(default="ollama/deepseek-v4-flash")` — hardcoded Model-Name. Sollte aus Settings kommen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-174: ai_assistant/schemas.py — api_key als Plaintext String -- **Datei:** app/plugins/builtins/ai_assistant/schemas.py:18 -- **Problem:** `api_key: str = Field(default="", max_length=2000)` — API-Key als Plaintext im Schema. Sollte verschlüsselt gespeichert werden. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-175: wiki/schemas.py — ArticleCreate erfordert slug -- **Datei:** app/plugins/builtins/wiki/schemas.py:22 -- **Problem:** `slug: str = Field(..., min_length=1, max_length=300)` — slug ist Pflichtfeld. Sollte auto-generiert werden aus title. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-176: permissions/schemas.py — ShareLinkResponse gibt token zurück -- **Datei:** app/plugins/builtins/permissions/schemas.py:35 -- **Problem:** ShareLinkResponse gibt token zurück. Share-Token sollte nicht in API Response stehen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-177: mail/schemas.py — MailAccountCreate password als Plaintext -- **Datei:** app/plugins/builtins/mail/schemas.py:25 -- **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 -- **Datei:** app/schemas/custom_field_definition.py:15 -- **Problem:** `entity: str = Field(...)` — keine Validierung gegen ENTITY_MODELS. Jeder String wird akzeptiert. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-179: schemas/entity_permission.py — principal_type pattern hardcoded -- **Datei:** app/schemas/entity_permission.py:12 -- **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 -- **Dateien:** entity_links/schemas.py, tags/schemas.py, custom_field_definition.py, graph_rag/schemas.py -- **Problem:** entity_type und entity Felder in Schemas haben keine Validierung gegen ENTITY_MODELS. Jeder String wird akzeptiert. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-182: Systematisches Problem — API Secrets in Responses -- **Dateien:** schemas/webhook.py, permissions/schemas.py, mcp_client/routes.py, api/webhooks.ts -- **Problem:** Webhook.secret, ShareLink.token, McpServerConfig.api_token werden in API Responses an Frontend gesendet. Secrets sollten nie in Responses stehen. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-183: routes/api_tokens.py — falsche Permission (mcp:write) -- **Datei:** app/routes/api_tokens.py:33 -- **Problem:** `require_permission("mcp:write")` für API Tokens — sollte `api_tokens:write` oder ähnlich sein. Falsche Permission. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-184: routes/backups.py — falsche Permission (automation:admin) -- **Datei:** app/routes/backups.py:18 -- **Problem:** `require_permission("automation:admin")` für Backups — sollte `backups:admin` oder ähnlich sein. Falsche Permission. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-185: routes/custom_fields.py — Core→Plugin Import -- **Datei:** app/routes/custom_fields.py:15 -- **Problem:** `from app.plugins.registry import get_registry` — Core importiert von Plugin Registry. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-186: routes/webhooks.py — falsche Permission (workflows:read) -- **Datei:** app/routes/webhooks.py:22 -- **Problem:** `require_permission("workflows:read")` für Webhooks — sollte `webhooks:read` oder ähnlich sein. Falsche Permission. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-187: routes/entity_permissions.py — list_entity_permissions ohne require_permission -- **Datei:** app/routes/entity_permissions.py:26 -- **Problem:** `list_entity_permissions` hat nur `get_current_user`, kein `require_permission`. Jeder eingeloggte User kann alle Permissions sehen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-188: routes/saved_filters.py und saved_views.py — _validate_entity_type dupliziert (3. und 4. Kopie) -- **Datei:** app/routes/saved_filters.py:20, app/routes/saved_views.py:20 -- **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 -- **Dateien:** api_tokens.py (mcp:write), backups.py (automation:admin), webhooks.py (workflows:read), custom_field_definitions.py (contacts:read), knowledge/routes.py (wiki:read), self_improvement/routes.py (automation:read) -- **Problem:** Mehrere Routes verwenden falsche Permissions die nicht zu ihrem Modul passen. Permission-Namen sind inkonsistent und zugeordnet zu falschen Modulen. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### 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. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-197: models/tenant.py — resolution_strategy hardcoded -- **Datei:** app/models/tenant.py:25 -- **Problem:** `CheckConstraint("resolution_strategy IN ('highest_wins')")` — hardcoded. Nur eine Strategie erlaubt. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-198: models/workflow.py — steps als JSONB ohne Validierung -- **Datei:** app/models/workflow.py:30 -- **Problem:** `steps: Mapped[list[dict[str, Any]]] = mapped_column(JSONB, nullable=False)` — keine Validierung der Step-Struktur. Jedes JSON wird akzeptiert. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-199: models/contact_merge.py — inkonsistente ondelete policies -- **Datei:** app/models/contact_merge.py:25-28 -- **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 -- **Dateien:** models/bank_account.py (iban), models/system_settings.py (tax_number, iban, bic), ai_assistant/models.py (api_key), mail/models.py (encrypted_password — OK), models/webhook.py (secret) -- **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. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-201: .env.example und .env.docker.example — ADMIN_PASSWORD hardcoded -- **Datei:** .env.example:79, .env.docker.example:55, docker-compose.yaml:55 -- **Problem:** `ADMIN_PASSWORD=Admin123!` — hardcoded Default-Admin-Password in allen Config-Dateien. Security Risk. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-202: tsconfig.json — noUnusedLocals/noUnusedParameters false -- **Datei:** frontend/tsconfig.json:16-17 -- **Problem:** `noUnusedLocals: false` und `noUnusedParameters: false` — TypeScript strict mode ist nicht vollständig aktiviert. Unbenutzte Variablen werden nicht erkannt. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-203: prestart.sh — f-string SQL injection risk -- **Datei:** prestart.sh:42 -- **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) -- **Datei:** frontend/public/manifest.json, frontend/vite.config.ts -- **Problem:** public/manifest.json existiert aber vite-plugin-pwa ist nicht in vite.config.ts importiert. PWA-Reste die verwirren. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-205: pyproject.toml — mypy disallow_untyped_defs = false -- **Datei:** pyproject.toml:55 -- **Problem:** `disallow_untyped_defs = false` — mypy strict mode ist nicht vollständig aktiviert. Ungetypte Funktionen werden akzeptiert. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-206: alembic/env.py — wildcard import `from app.models import *` -- **Datei:** alembic/env.py:14 -- **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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-207: requirements.txt — passlib[bcrypt]==1.7.4 gepinnt -- **Datei:** requirements.txt:14 -- **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. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-209: tsconfig.json — target ES2020 statt ES2022+ -- **Datei:** frontend/tsconfig.json:4 -- **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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-211: permission_audit.py — hardcoded deutsche Strings in Notifications -- **Datei:** app/services/permission_audit.py:30-32 -- **Problem:** 'Neue Berechtigung', '{perm.entity_type} wurde mit dir geteilt' — hardcoded deutsche Strings in create_notification(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-212: owner_transfer_service.py — ENTITY_TABLES statisch -- **Datei:** app/services/owner_transfer_service.py:16-26 -- **Problem:** ENTITY_TABLES ist statisch. Neue Plugin-Tabellen werden nicht erfasst. Owner Transfer funktioniert nur für Core-Tabellen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-213: policy_service.py — ABAC_ALLOWED_FIELDS statisch -- **Datei:** app/services/policy_service.py:33-36 -- **Problem:** ABAC_ALLOWED_FIELDS ist statisch. Neue Plugin-Entities können keine ABAC Policies verwenden. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-214: workspaceStore.ts — visibleModuleKeys() gibt ALLE Module zurück (bestätigt ARCH-004) -- **Datei:** frontend/src/store/workspaceStore.ts:88-91 -- **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 -- **Datei:** frontend/src/hooks/useAIContext.ts:14 -- **Problem:** `apiClient.post('/ai-proactive/context', {...}).catch(() => {})` — Fehler werden still verschluckt. Kein Logging, kein Error-Handling. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-216: contact_folder_permission_service.py — _rank() dupliziert (5. Kopie) -- **Datei:** app/services/contact_folder_permission_service.py:22 -- **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. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### 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. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-221: users.py — update_menu_order Double-Commit -- **Datei:** app/routes/users.py:350 -- **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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-230: roles.py — Core→Plugin Import (get_registry) -- **Datei:** app/routes/roles.py:22 -- **Problem:** `from app.plugins.registry import get_registry` — Core importiert von Plugin Registry. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### 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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-236: workflows.py — approve_workflow_step auto-approves (sinnlos) -- **Datei:** app/routes/workflows.py:480 -- **Problem:** `create_approval_request()` und sofort `resolve_approval_request(decision='approved')` — Approval wird in selben Request erstellt und approved. Approval ist bedeutungslos. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-237: workflows.py — reject_workflow_step auto-rejects (sinnlos) -- **Datei:** app/routes/workflows.py:530 -- **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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-240: workflows.py — WORKFLOW_TEMPLATES hardcoded -- **Datei:** app/routes/workflows.py:620 -- **Problem:** `WORKFLOW_TEMPLATES` ist eine hardcoded Liste in der Route-Datei. Sollte in Config, DB oder Plugin-Manifest stehen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-241: dashboard.py — Core→Plugin Import (get_registry) -- **Datei:** app/routes/dashboard.py:22 -- **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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-245: compliance.py — Core→Plugin Import (AgentDefinition) -- **Datei:** app/routes/compliance.py:22 -- **Problem:** `from app.plugins.builtins.automation.models import AgentDefinition` — Core Route importiert direkt von Plugin Model. Core darf nicht von Plugins abhängen. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-246: compliance.py — Doppelte Permission-Dependency -- **Datei:** app/routes/compliance.py:120 -- **Problem:** `dependencies=[Depends(require_permission('system:admin'))]` UND `current_user: dict = Depends(require_permission('system:admin'))` — Permission wird zweimal geprüft. Redundant. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-247: compliance.py — _DEFAULT_RETENTION_POLICIES hardcoded -- **Datei:** app/routes/compliance.py:380 -- **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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-250: system_dashboard.py — Core→Plugin Import (get_registry) -- **Datei:** app/routes/system_dashboard.py:22 -- **Problem:** `from app.plugins.registry import get_registry` — Core Route importiert direkt von Plugin Registry. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-251: system_dashboard.py — Sync I/O in async Context -- **Datei:** app/routes/system_dashboard.py:200 -- **Problem:** `os.path.exists()`, `os.walk()`, `shutil.disk_usage()` in async Funktion `_get_storage_stats()` — sync I/O blockiert Event Loop. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-252: system_dashboard.py — _send_alert_notifications verschluckt Fehler -- **Datei:** app/routes/system_dashboard.py:260 -- **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. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-254: audit.py — datetime.utcnow() deprecated -- **Datei:** app/routes/audit.py:165 -- **Problem:** `datetime.utcnow()` ist deprecated in Python 3.12+. Sollte `datetime.now(UTC)` sein. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-255: entity_permissions.py — _check_entity_ownership importiert statische ENTITY_MODELS -- **Datei:** app/routes/entity_permissions.py:100 -- **Problem:** `from app.services.entity_permission_service import ENTITY_MODELS` — statische Liste, neue Plugin-Entities nicht erfasst. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-256: entity_permissions.py — list_entity_registry hardcoded Entity-Liste -- **Datei:** app/routes/entity_permissions.py:250 -- **Problem:** Statische Liste mit 12 Entity-Typen und deutschen Labels. Neue Plugin-Entities werden nicht erfasst. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-257: entity_permissions.py — bulk_share_permissions ohne Pydantic Schema -- **Datei:** app/routes/entity_permissions.py:280 -- **Problem:** `body: dict` statt Pydantic Schema. Keine Validierung von entity_type, entity_ids, principal_type, principal_id, level. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-258: entity_permissions.py — bulk_unshare_permissions ohne Pydantic Schema -- **Datei:** app/routes/entity_permissions.py:300 -- **Problem:** `body: dict` statt Pydantic Schema. Keine Validierung. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-259: entity_permissions.py — Hardcoded deutsche Fehlermeldung -- **Datei:** app/routes/entity_permissions.py:60 -- **Problem:** `"Sie benötigen Admin-Rechte auf diesen Datensatz, um Berechtigungen zu verwalten"` — hardcoded deutsch ohne i18n. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-260: custom_field_definitions.py — Custom Fields an contacts:read gekoppelt -- **Datei:** app/routes/custom_field_definitions.py:25 -- **Problem:** `require_permission('contacts:read')` für generische Custom Field Definitions. Custom Fields sind nicht Contacts-spezifisch. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-261: custom_field_definitions.py — Custom Fields Create an contacts:write gekoppelt -- **Datei:** app/routes/custom_field_definitions.py:45 -- **Problem:** `require_permission('contacts:write')` für Create. Sollte generisch sein (z.B. `custom_fields:write`). -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-262: custom_fields.py — Core→Plugin Import (get_registry) -- **Datei:** app/routes/custom_fields.py:15 -- **Problem:** `from app.plugins.registry import get_registry` — Core Route importiert direkt von Plugin Registry. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-263: custom_fields.py — Route prefix an Contacts gekoppelt -- **Datei:** app/routes/custom_fields.py:20 -- **Problem:** `prefix="/api/v1/contacts"` — Custom Fields sind generisch aber Route ist an Contacts gekoppelt. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-264: custom_fields.py — _collect_custom_field_definitions iteriert über Plugin Manifeste -- **Datei:** app/routes/custom_fields.py:100 -- **Problem:** Core Route iteriert über alle Plugin-Manifeste um Custom Fields zu sammeln. Core sollte nicht wissen dass Plugins Custom Fields haben. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-265: webhooks.py — Inkonsistente Permissions (workflows:read vs automation:read) -- **Datei:** app/routes/webhooks.py:25 vs :80 -- **Problem:** list_webhooks verwendet `workflows:read`, get_webhook verwendet `automation:read`. Inkonsistente Permissions für dasselbe Modul. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-266: webhooks.py — Inkonsistente Permissions (workflows:write vs automation:write) -- **Datei:** app/routes/webhooks.py:45 vs :120 vs :160 -- **Problem:** create_webhook verwendet `workflows:write`, update/delete/test verwenden `automation:write`. Inkonsistent. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-267: saved_views.py — create_saved_view an contacts:read gekoppelt -- **Datei:** app/routes/saved_views.py:100 -- **Problem:** `require_permission('contacts:read')` für generische Saved Views. Saved Views sind nicht Contacts-spezifisch. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-268: saved_views.py — update_saved_view verwendet contacts:read statt contacts:write -- **Datei:** app/routes/saved_views.py:140 -- **Problem:** Update verwendet `contacts:read` statt `contacts:write`. Update sollte Write-Recht erfordern. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-269: saved_views.py — delete_saved_view verwendet contacts:read statt contacts:delete -- **Datei:** app/routes/saved_views.py:170 -- **Problem:** Delete verwendet `contacts:read` statt `contacts:delete`. Delete sollte Delete-Recht erfordern. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-270: saved_views.py — _validate_entity_type importiert statische ENTITY_MODELS -- **Datei:** app/routes/saved_views.py:30 -- **Problem:** `from app.services.entity_permission_service import ENTITY_MODELS` — statische Liste, neue Plugin-Entities nicht erfasst. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-271: saved_filters.py — create_saved_filter an contacts:read gekoppelt -- **Datei:** app/routes/saved_filters.py:80 -- **Problem:** `require_permission('contacts:read')` für generische Saved Filters. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-272: saved_filters.py — delete_saved_filter verwendet contacts:read statt contacts:delete -- **Datei:** app/routes/saved_filters.py:120 -- **Problem:** Delete verwendet `contacts:read` statt `contacts:delete`. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-273: saved_filters.py — _validate_entity_type importiert statische ENTITY_MODELS -- **Datei:** app/routes/saved_filters.py:30 -- **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. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-275: import_export.py — ineffiziente CSV→XLSX Konvertierung -- **Datei:** app/routes/import_export.py:300 -- **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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-277: addresses.py — _validate_entity_type importiert statische ENTITY_MODELS -- **Datei:** app/routes/addresses.py:20 -- **Problem:** Gleicher Fehler wie saved_views/saved_filters — statische ENTITY_MODELS. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-278: bank_accounts.py — delete verwendet bank-accounts:write statt bank-accounts:delete -- **Datei:** app/routes/bank_accounts.py:90 -- **Problem:** Delete verwendet `bank-accounts:write` statt `bank-accounts:delete`. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-279: bank_accounts.py — IBAN/BIC als Plaintext in DB -- **Datei:** app/routes/bank_accounts.py (implizit über BankAccount Model) -- **Problem:** BankAccount Model speichert IBAN und BIC als Plaintext. Sensitive Daten sollten verschlüsselt werden. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-280: currencies.py — delete verwendet currencies:write statt currencies:delete -- **Datei:** app/routes/currencies.py:70 -- **Problem:** Delete verwendet `currencies:write` statt `currencies:delete`. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-281: taxes.py — delete verwendet taxes:write statt taxes:delete -- **Datei:** app/routes/taxes.py:70 -- **Problem:** Delete verwendet `taxes:write` statt `taxes:delete`. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-282: sequences.py — delete verwendet sequences:write statt sequences:delete -- **Datei:** app/routes/sequences.py:85 -- **Problem:** Delete verwendet `sequences:write` statt `sequences:delete`. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-283: Systematischer Fehler — Alle Core-Routes verwenden :write für DELETE statt :delete -- **Datei:** app/routes/ (currencies, taxes, sequences, bank_accounts, workflows, roles, users) -- **Problem:** Systematischer Architektur-Fehler — alle Core-Routes verwenden `:write` Permission für DELETE-Operationen statt `:delete`. Betroffen: currencies, taxes, sequences, bank_accounts, workflows, roles, users. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-284: delegations.py — delete verwendet permissions:delegations:write statt :delete -- **Datei:** app/routes/delegations.py:80 -- **Problem:** Delete verwendet `permissions:delegations:write` statt `permissions:delegations:delete`. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-285: policies.py — delete verwendet permissions:policies:write statt :delete -- **Datei:** app/routes/policies.py:80 -- **Problem:** Delete verwendet `permissions:policies:write` statt `permissions:policies:delete`. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-286: owner_transfer.py — Kein Audit-Log für Ownership-Transfer -- **Datei:** app/routes/owner_transfer.py:35 -- **Problem:** transfer_ownership hat kein Audit-Log. Ownership-Transfer ist eine kritische Operation die auditiert werden muss. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-287: api_tokens.py — create_token verwendet mcp:write statt api_tokens:write -- **Datei:** app/routes/api_tokens.py:30 -- **Problem:** `require_permission('mcp:write')` für API Token Creation. API Tokens sind nicht MCP-spezifisch. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-288: api_tokens.py — list_tokens verwendet mcp:read statt api_tokens:read -- **Datei:** app/routes/api_tokens.py:60 -- **Problem:** `require_permission('mcp:read')` für API Token List. Sollte `api_tokens:read` sein. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-289: api_tokens.py — revoke_token verwendet mcp:write statt api_tokens:delete -- **Datei:** app/routes/api_tokens.py:65 -- **Problem:** `require_permission('mcp:write')` für Token Revoke. Sollte `api_tokens:delete` sein. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-290: approvals.py — __import__('sqlalchemy').func.count() in Query -- **Datei:** app/routes/approvals.py:120 -- **Problem:** `__import__('sqlalchemy').func.count()` — dynamischer Import in Query-Construction. Sollte `from sqlalchemy import func` am Datei-Anfang stehen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-291: backups.py — create_backup ohne Audit-Log -- **Datei:** app/routes/backups.py:60 -- **Problem:** create_backup hat kein Audit-Log. Backup-Erstellung sollte auditiert werden. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-292: backups.py — restore_backup ohne Audit-Log -- **Datei:** app/routes/backups.py:80 -- **Problem:** restore_backup hat kein Audit-Log. Restore ist eine kritische destruktive Operation die auditiert werden muss. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-293: contact_folder_permissions.py — delete verwendet contacts:write statt contacts:delete -- **Datei:** app/routes/contact_folder_permissions.py:80 -- **Problem:** Delete verwendet `contacts:write` statt `contacts:delete`. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-294: contact_folders.py — delete_folder verwendet contacts:write statt contacts:delete -- **Datei:** app/routes/contact_folders.py:75 -- **Problem:** Delete verwendet `contacts:write` statt `contacts:delete`. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-295: contact_folders.py — reorder_folders ohne Pydantic Schema -- **Datei:** app/routes/contact_folders.py:90 -- **Problem:** `body: list[dict]` statt Pydantic Schema. Keine Validierung. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-296: entity_history.py — restore_from_history manuelle Permission-Prüfung -- **Datei:** app/routes/entity_history.py:100 -- **Problem:** Permission wird manuell geprüft statt `require_permission` Dependency. Inkonsistent mit anderen Routes. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-297: entity_history.py — undo_last_action manuelle Permission-Prüfung -- **Datei:** app/routes/entity_history.py:150 -- **Problem:** Gleiche manuelle Permission-Prüfung wie restore_from_history. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-298: entity_history.py — list_trash ohne require_permission -- **Datei:** app/routes/entity_history.py:200 -- **Problem:** `get_current_user` ohne `require_permission` — jeder eingeloggte User kann Trash sehen ohne spezifische Permission. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-299: errors.py — error.userAgent statt error.user_agent -- **Datei:** app/routes/errors.py:120 -- **Problem:** `error.userAgent` wird verwendet aber Pydantic Model hat `user_agent` (snake_case). AttributeError möglich. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-300: errors.py — Core→Plugin Import (get_contract) -- **Datei:** app/routes/errors.py:130 -- **Problem:** `from app.plugins.builtins.contracts import get_contract` — Core Route importiert direkt von Plugin Contracts. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-301: guests.py — invite_guest ohne Pydantic Schema -- **Datei:** app/routes/guests.py:50 -- **Problem:** `body: dict` statt Pydantic Schema. Keine Validierung von email und name. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-302: guests.py — inkonsistente Transaction-Handling -- **Datei:** app/routes/guests.py:100 -- **Problem:** `db.commit()` und `db.refresh()` in einem Branch (neuer User) aber nicht im anderen (existing User). Inkonsistent. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-303: guests.py — delete_guest verschluckt Fehler -- **Datei:** app/routes/guests.py:170 -- **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 -- **Datei:** app/routes/permission_templates.py:80 -- **Problem:** Delete verwendet `permissions:templates:write` statt `permissions:templates:delete`. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-306: tenants.py — create_tenant ohne Audit-Log -- **Datei:** app/routes/tenants.py:40 -- **Problem:** create_tenant hat kein Audit-Log. Tenant-Erstellung ist eine kritische Operation. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-307: tenants.py — assign_user_to_tenant ohne Audit-Log -- **Datei:** app/routes/tenants.py:65 -- **Problem:** assign_user_to_tenant hat kein Audit-Log. User-Tenant-Zuweisung sollte auditiert werden. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-308: user_preferences.py — delete verwendet user_preferences:write statt :delete -- **Datei:** app/routes/user_preferences.py:160 -- **Problem:** Delete verwendet `user_preferences:write` statt `user_preferences:delete`. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-309: workspaces.py — workspace_context return empty modules wenn kein Workspace -- **Datei:** app/routes/workspaces.py:100 -- **Problem:** Wenn kein Workspace gefunden wird, return `{"modules": []}` — User sieht keine Module. Problem 4 bestätigt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-310: entity_permission_service.py — Hardcoded deutsche Strings in Notifications -- **Datei:** app/services/entity_permission_service.py:200 -- **Problem:** `'Neue Berechtigung'`, `'Berechtigung entfernt'` — hardcoded deutsch ohne i18n. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-311: entity_permission_service.py — String-Concatenation in SQL für distinct count -- **Datei:** app/services/entity_permission_service.py:380 -- **Problem:** `EntityPermission.entity_type + ":" + EntityPermission.entity_id.cast(String)` für distinct count — ineffizient. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### 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. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-315: workspace_service.py — list_workspaces N+1 Query -- **Datei:** app/services/workspace_service.py:40 -- **Problem:** Count users per workspace in einer Schleife — N+1 Query. Bei 10 Workspaces = 10 Count-Queries. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-316: workspace_service.py — hardcoded deutscher String -- **Datei:** app/services/workspace_service.py:580 -- **Problem:** `'Standard-Workspace mit allen Modulen'` — hardcoded deutsch ohne i18n. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-317: role_service.py — delete_role ohne Audit-Log -- **Datei:** app/services/role_service.py:95 -- **Problem:** delete_role hat kein Audit-Log. Rollen-Löschung sollte auditiert werden. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-318: webhook_service.py — __import__('datetime').datetime.utcnow() -- **Datei:** app/services/webhook_service.py:200 -- **Problem:** `__import__('datetime').datetime.utcnow()` — deprecated und ugly. Sollte `datetime.now(UTC)` sein. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-319: webhook_service.py — socket.getaddrinfo sync I/O in async Context -- **Datei:** app/services/webhook_service.py:50 -- **Problem:** `socket.getaddrinfo(hostname, None)` ist sync I/O in async Function. Blockiert Event Loop. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-320: webhook_service.py — secret als Plaintext gespeichert -- **Datei:** app/services/webhook_service.py:150 -- **Problem:** `secret=data.get('secret')` — Webhook Secret wird als Plaintext in DB gespeichert. Sollte verschlüsselt werden. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-321: backup_service.py — datetime.utcnow() deprecated -- **Datei:** app/services/backup_service.py:180 -- **Problem:** `datetime.utcnow()` ist deprecated in Python 3.12+. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-322: backup_service.py — subprocess.run() sync I/O in async Function -- **Datei:** app/services/backup_service.py:200 -- **Problem:** `subprocess.run()` ist sync I/O in async Function. Blockiert Event Loop. Sollte `asyncio.create_subprocess_exec()` verwenden. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-323: owner_transfer_service.py — ENTITY_TABLES statisch -- **Datei:** app/services/owner_transfer_service.py:30 -- **Problem:** `ENTITY_TABLES` ist statisch. Neue Plugin-Entities nicht erfasst. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-325: ai_copilot_service.py — AIConversation/AIMessage mit try/except ImportError -- **Datei:** app/services/ai_copilot_service.py:20 -- **Problem:** `try: from app.models.ai_conversation import AIConversation, AIMessage except ImportError: AIConversation = None` — Models könnten nicht existieren. Wenn None, wird process_query crashen. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-326: ai_copilot_service.py — get_history N+1 Query -- **Datei:** app/services/ai_copilot_service.py:300 -- **Problem:** get_history fragt Messages pro Conversation in einer Schleife ab — N+1 Query. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-327: delegation_service.py — create_delegation verwendet db.commit() -- **Datei:** app/services/delegation_service.py:80 -- **Problem:** `db.commit()` in Service — sollte `db.flush()` sein. Route macht den Commit. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-328: delegation_service.py — delete_delegation verwendet db.commit() -- **Datei:** app/services/delegation_service.py:120 -- **Problem:** `db.commit()` in Service — sollte `db.flush()` sein. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-329: delegation_service.py — keine Audit-Logs -- **Datei:** app/services/delegation_service.py -- **Problem:** Keine Audit-Logs für Delegation-Erstellung/Update/Löschung. Permission-Delegation ist sicherheitsrelevant. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-330: group_service.py — delete_group ohne Audit-Log -- **Datei:** app/services/group_service.py:160 -- **Problem:** delete_group hat kein Audit-Log. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-331: group_service.py — add_user_to_group ohne Audit-Log -- **Datei:** app/services/group_service.py:200 -- **Problem:** add_user_to_group hat kein Audit-Log. Gruppen-Mitgliedschaft ist sicherheitsrelevant. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-332: group_service.py — remove_user_from_group ohne Audit-Log -- **Datei:** app/services/group_service.py:230 -- **Problem:** remove_user_from_group hat kein Audit-Log. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-333: dedup_service.py — merge_contacts ohne Audit-Log -- **Datei:** app/services/dedup_service.py:280 -- **Problem:** merge_contacts hat kein Audit-Log. Contact-Merge ist kritische Operation. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-334: permission_audit.py — hardcoded deutsche Strings -- **Datei:** app/services/permission_audit.py:40 -- **Problem:** `'Neue Berechtigung'`, `'Berechtigung entfernt'` — hardcoded deutsch ohne i18n. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-335: policy_service.py — ABAC_ALLOWED_FIELDS statisch -- **Datei:** app/services/policy_service.py:60 -- **Problem:** `ABAC_ALLOWED_FIELDS` ist statisch. Neue Plugin-Entities nicht erfasst. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-336: policy_service.py — create_policy verwendet db.commit() -- **Datei:** app/services/policy_service.py:200 -- **Problem:** `db.commit()` in Service — sollte `db.flush()` sein. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-337: policy_service.py — update_policy verwendet db.commit() -- **Datei:** app/services/policy_service.py:240 -- **Problem:** `db.commit()` in Service — sollte `db.flush()` sein. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-338: policy_service.py — delete_policy verwendet db.commit() -- **Datei:** app/services/policy_service.py:260 -- **Problem:** `db.commit()` in Service — sollte `db.flush()` sein. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-339: policy_service.py — apply_policy_filter Group/Role nicht aufgelöst -- **Datei:** app/services/policy_service.py:300 -- **Problem:** Group/Role policies werden nicht richtig aufgelöst — nur `principal_id == user_id` wird geprüft, nicht Group-Membership. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-340: permission_template_service.py — create_template db.commit() -- **Datei:** app/services/permission_template_service.py:80 -- **Problem:** `db.commit()` in Service — sollte `db.flush()` sein. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-341: permission_template_service.py — update_template db.commit() -- **Datei:** app/services/permission_template_service.py:120 -- **Problem:** `db.commit()` in Service — sollte `db.flush()` sein. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-342: permission_template_service.py — delete_template db.commit() -- **Datei:** app/services/permission_template_service.py:140 -- **Problem:** `db.commit()` in Service — sollte `db.flush()` sein. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-343: permission_template_service.py — _evaluate_trigger gibt immer True -- **Datei:** app/services/permission_template_service.py:200 -- **Problem:** `_evaluate_trigger()` gibt immer True zurück. Trigger-Conditions werden nicht ausgewertet. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-344: permission_template_service.py — apply_template db.commit() -- **Datei:** app/services/permission_template_service.py:210 -- **Problem:** `db.commit()` in Service — Route kann nicht rollbacken. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-345: contact_folder_service.py — reorder_folders db.commit() in Service -- **Datei:** app/services/contact_folder_service.py:200 -- **Problem:** `db.commit()` in Service — sollte `db.flush()` sein. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-346: currency_service.py — seed_default_currencies hardcoded Strings -- **Datei:** app/services/currency_service.py:140 -- **Problem:** `code='EUR'`, `name='Euro'`, `symbol='€'` hardcoded. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-347: tax_service.py — seed_default hardcoded deutsche Strings -- **Datei:** app/services/tax_service.py:140 -- **Problem:** `name='Mehrwertsteuer 19%'`, `name='Mehrwertsteuer 7%'` hardcoded deutsch. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-348: address_service.py — hardcoded 'Privat' Label -- **Datei:** app/services/address_service.py:250 -- **Problem:** `label='Privat'` hardcoded deutsch. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-349: tenant_service.py — assign_user_to_tenant ohne Audit-Log -- **Datei:** app/services/tenant_service.py:80 -- **Problem:** assign_user_to_tenant hat kein Audit-Log. User-Tenant-Zuweisung ist sicherheitsrelevant. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### 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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-362: address.py — Address-Tabelle für Bank-Accounts, Contacts nutzen inline Felder -- **Datei:** app/models/address.py:10 -- **Problem:** Bekannte Inkonsistenz: Address-Tabelle wird für Bank-Accounts genutzt, Contacts nutzen inline Address-Felder. Doppelarchitektur. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-363: system_settings.py — SystemSettingsResponse gibt sensitive Felder zurück -- **Datei:** app/schemas/system_settings.py:50 -- **Problem:** SystemSettingsResponse gibt tax_number, vat_id, iban, bic in Response zurück. Route maskiert für non-admin, aber Schema erlaubt es. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-364: bank_account.py — BankAccountResponse gibt iban/bic zurück -- **Datei:** app/schemas/bank_account.py:35 -- **Problem:** BankAccountResponse gibt iban und bic in Response zurück. Sensitive Finanzdaten. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-365: agent_loop.py — Core→Plugin Imports (contracts, kommunikation, ai_assistant) -- **Datei:** app/ai/agent_loop.py:280, 300 -- **Problem:** Importiert `from app.plugins.builtins.contracts import get_contract_registry`, `from app.plugins.builtins.kommunikation.models import CommConversation`, `from app.plugins.builtins.ai_assistant.tool_registry import ToolRegistry`. Core→Plugin Verstöße. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-366: llm_client.py — Core→Plugin Import (get_contract) -- **Datei:** app/ai/llm_client.py:292 -- **Problem:** `from app.plugins.builtins.contracts import get_contract` — Core→Plugin Import. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-367: context_builder.py — Core→Plugin Import (ai_assistant contracts) -- **Datei:** app/ai/context_builder.py:224 -- **Problem:** `from app.plugins.builtins.ai_assistant.contracts import get_tool_registry` — Core→Plugin Import. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-368: agent_permissions.py — Core→Plugin Import (ai_assistant contracts) -- **Datei:** app/ai/agent_permissions.py:64 -- **Problem:** `from app.plugins.builtins.ai_assistant.contracts import get_tool_registry` — Core→Plugin Import. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-369: oversight.py — DB Model in ai/ Module statt models/ -- **Datei:** app/ai/oversight.py:50 -- **Problem:** `DecisionRecordDB` ist ein SQLAlchemy Model definiert in `app/ai/oversight.py` statt in `app/models/`. Sollte in models/ sein. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-370: agent_loop.py — `pass # agent_workstream removed` Dead Code -- **Datei:** app/ai/agent_loop.py:280 -- **Problem:** `pass # agent_workstream removed` — Dead Code Kommentar, Code wurde entfernt aber Kommentar bleibt. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-371: engine.py — Core→Plugin Imports (contracts, kommunikation) -- **Datei:** app/workflows/engine.py:100, 110 -- **Problem:** Importiert `from app.plugins.builtins.contracts import get_contract_registry`, `from app.plugins.builtins.kommunikation.models import CommConversation`. Core→Plugin Verstöße. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-372: step_handlers.py — Core→Plugin Imports (mail, calendar, dms, search, automation contracts) -- **Datei:** app/workflows/step_handlers.py:200, 250, 300, 350, 400 -- **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. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### 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 -- **Datei:** app/plugins/builtins/contracts.py:109 -- **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) -- **Datei:** app/plugins/builtins/contacts/plugin.py:40 -- **Problem:** `routes=[]` mit Kommentar 'Routes are registered as core routes in main.py'. Contacts ist halb Plugin halb Core — Problem 5 bestätigt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-383: ai_assistant/plugin.py — menu_items und page_routes für AIAssistant (Phase 2 entfernt) -- **Datei:** app/plugins/builtins/ai_assistant/plugin.py:80 -- **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 -- **Datei:** app/plugins/builtins/knowledge/plugin.py:40 -- **Problem:** `uuid.UUID(str(tenant_id))` wird verwendet, aber `import uuid` fehlt am Datei-Anfang. Problem 12 bestätigt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-385: wiki/plugin.py — Cross-Plugin Import (unified_search) -- **Datei:** app/plugins/builtins/wiki/plugin.py:30 -- **Problem:** `from app.plugins.builtins.unified_search.providers.wiki_provider import WikiSearchProvider` — direkter Plugin→Plugin Import. Sollte über Contract gehen. Problem 6/15 bestätigt. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-386: wiki/plugin.py — on_deactivate ruft unregister_actions_by_owner aber nicht base on_deactivate -- **Datei:** app/plugins/builtins/wiki/plugin.py:35 -- **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 -- **Datei:** app/plugins/builtins/system_notif/plugin.py -- **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 -- **Datei:** app/plugins/builtins/self_improvement/plugin.py:30 -- **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. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-390: App.tsx — Hardcoded deutsche Strings ohne i18n -- **Datei:** frontend/src/App.tsx:49,61,79 -- **Problem:** `'Sie sind offline...'`, `'Ihre Sitzung ist abgelaufen...'`, `'Zum Hauptinhalt springen'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-391: routes/index.tsx — TODO P2-F1 hardcoded plugin routes -- **Datei:** frontend/src/routes/index.tsx:1 -- **Problem:** `// TODO: P2-F1 — Replace hardcoded plugin routes with dynamic PluginRouteRenderer`. Statische Routes für /calendar, /dms, /mail, /reports etc. existieren parallel zu PluginRouteRenderer. Problem 6 bestätigt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-392: routes/index.tsx — /kein-zugriff hardcoded deutscher Pfad -- **Datei:** frontend/src/routes/index.tsx:100 -- **Problem:** `path: '/kein-zugriff'` — hardcoded deutscher Pfad. Sollte `/no-access` sein. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-393: routes/index.tsx — PluginRouteRenderer als catch-all ohne Permission-Check -- **Datei:** frontend/src/routes/index.tsx:270 -- **Problem:** `{ path: '*', element: {} }` — PluginRouteRenderer als catch-all ohne Permission-Check. Problem 7/28 bestätigt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-394: routes/index.tsx — /wiki ohne PermissionRoute -- **Datei:** frontend/src/routes/index.tsx:260 -- **Problem:** `{ path: '/wiki', element: withSuspense() }` — keine PermissionRoute. Alle anderen Plugin-Seiten haben PermissionRoute. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-395: routes/index.tsx — /system-dashboard ohne PermissionRoute -- **Datei:** frontend/src/routes/index.tsx:261 -- **Problem:** `{ path: '/system-dashboard', element: withSuspense() }` — keine PermissionRoute. Sollte system:admin erfordern. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-396: routes/index.tsx — /tags ohne führenden Slash -- **Datei:** frontend/src/routes/index.tsx:255 -- **Problem:** `{ path: 'tags', ... }` — fehlender führender Slash. Alle anderen Paths haben `/`. Inkonsistent. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-397: routes/index.tsx — communication:read Permission existiert nicht -- **Datei:** frontend/src/routes/index.tsx:245 -- **Problem:** `` — aber das kommunikation Plugin definiert `comm:read`, nicht `communication:read`. Problem 8 bestätigt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-398: routes/index.tsx — activity:read Permission existiert nicht -- **Datei:** frontend/src/routes/index.tsx:257 -- **Problem:** `` — aber kein Plugin definiert `activity:read`. Problem 8 bestätigt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-399: AppShell.tsx — showMessageSidebar prüft /ai-assistant aber AIAssistant wurde entfernt -- **Datei:** frontend/src/components/layout/AppShell.tsx:40 -- **Problem:** `location.pathname.startsWith('/ai-assistant')` — aber AIAssistant.tsx wurde in Phase 2 entfernt. Dead Code. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-400: workspaceStore.ts — visibleModuleKeys gibt alle Module zurück wenn kein Workspace -- **Datei:** frontend/src/store/workspaceStore.ts:100 -- **Problem:** `if (!ctx?.workspace_id || !ctx?.modules?.length) return true` — wenn kein Workspace-Kontext, werden ALLE Module sichtbar. Problem 4 bestätigt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-401: Sidebar.tsx — Statische UND dynamische Menü-Items (Doppelarchitektur) -- **Datei:** frontend/src/components/layout/Sidebar.tsx:54-60 -- **Problem:** `singleItems` ist hardcoded (dashboard, contacts, system-dashboard). Gleichzeitig kommen Plugin-Menüs via `usePluginStore(s => s.getAllMenuItems())`. Doppelarchitektur — Problem 6/22 bestätigt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-402: Sidebar.tsx — dashboard:read Permission existiert nicht -- **Datei:** frontend/src/components/layout/Sidebar.tsx:100 -- **Problem:** `permission: item.to === '/dashboard' ? 'dashboard:read'` — aber kein Plugin definiert `dashboard:read`. Problem 8 bestätigt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-403: PluginRouteRenderer.tsx — Keine Permission-Prüfung -- **Datei:** frontend/src/components/plugins/PluginRouteRenderer.tsx:18-50 -- **Problem:** PluginRouteRenderer rendert jede Plugin-Seite ohne Permission-Check. Problem 7/28 bestätigt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-404: PluginLoader.tsx — @vite-ignore im Production-Build -- **Datei:** frontend/src/components/plugins/PluginLoader.tsx:108 -- **Problem:** `import(/* @vite-ignore */ importPath)` — @vite-ignore funktioniert im Dev-Modus, kann aber im Production-Build Probleme machen. Problem 19 bestätigt. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-405: PluginLoader.tsx — Hardcoded deutsche Strings ohne i18n -- **Datei:** frontend/src/components/plugins/PluginLoader.tsx:70,75,80 -- **Problem:** `'Plugin konnte nicht geladen werden'`, `'Erneut versuchen'`, `'Neu laden'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-406: PluginRouteRenderer.tsx — 'Page Not Found' hardcoded englisch -- **Datei:** frontend/src/components/plugins/PluginRouteRenderer.tsx:60 -- **Problem:** `'Page Not Found'` — hardcoded englisch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-407: useAIContext.ts — .catch(() => {}) verschluckt Fehler -- **Datei:** frontend/src/hooks/useAIContext.ts:16 -- **Problem:** `.catch(() => {})` — Fehler beim AI Context Update werden still ignoriert. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-408: usePermission.ts — Wildcard-Matching prüft Segment-Anzahl -- **Datei:** frontend/src/hooks/usePermission.ts:25 -- **Problem:** `if (pParts.length === rParts.length)` — Wildcard-Matching prüft Segment-Anzahl. `core:*:read` (3 Segmente) matcht nicht `contacts:read` (2 Segmente). Problem 9 bestätigt. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-409: contacts.ts — TODO P2-F9 dual API clients -- **Datei:** frontend/src/api/contacts.ts:1 -- **Problem:** `// TODO: P2-F9 — Consolidate dual API clients` — contacts.ts und unifiedContacts.ts existieren parallel. Doppelarchitektur. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-410: ai.ts — AIProvider.api_key in Type definiert -- **Datei:** frontend/src/api/ai.ts:20 -- **Problem:** `api_key: string` im AIProvider Interface — API Key sollte nie im Frontend Type definiert sein. Wird in Responses zurückgegeben. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-411: pluginManifests.ts — /plugins/active-manifests erfordert plugins:read -- **Datei:** frontend/src/api/pluginManifests.ts:10 -- **Problem:** `apiGet('/plugins/active-manifests')` — dieser Endpoint erfordert `plugins:read` (Problem 3). Normaler User ohne plugins:read bekommt keine Plugin-Menüs. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-412: ai_assistant/models.py — api_key als Plaintext in DB -- **Datei:** app/plugins/builtins/ai_assistant/models.py:35 -- **Problem:** `api_key: Mapped[str] = mapped_column(Text, nullable=False, default="")` — API Key wird als Plaintext gespeichert. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-413: mcp_client/models.py — api_token als Plaintext in DB -- **Datei:** app/plugins/builtins/mcp_client/models.py:30 -- **Problem:** `api_token: Mapped[str | None] = mapped_column(String(500), nullable=True)` — API Token wird als Plaintext gespeichert. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-414: permissions/models.py — ShareLink.token als Plaintext -- **Datei:** app/plugins/builtins/permissions/models.py:50 -- **Problem:** `token: Mapped[str] = mapped_column(String(64), nullable=False, unique=True)` — Share Link Token als Plaintext. Sollte gehasht werden. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-415: calendar/models.py — CalendarEntry Spalten vor __table_args__ -- **Datei:** app/plugins/builtins/calendar/models.py:60 -- **Problem:** `indexed_at`, `embedding`, `search_tsv` werden vor `__table_args__` definiert — SQLAlchemy Anti-Pattern. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-416: dms/models.py — File Spalten vor __table_args__ -- **Datei:** app/plugins/builtins/dms/models.py:50 -- **Problem:** `indexed_at`, `content_tsv`, `content_text`, `embedding` vor `__table_args__` — SQLAlchemy Anti-Pattern. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-417: mail/models.py — Mail Spalten vor __table_args__ -- **Datei:** app/plugins/builtins/mail/models.py:100 -- **Problem:** `indexed_at`, `embedding`, `body_tsv`, `company_id` vor `__table_args__` — SQLAlchemy Anti-Pattern. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-418: tags/models.py — Tag Spalten vor __table_args__ -- **Datei:** app/plugins/builtins/tags/models.py:30 -- **Problem:** `embedding`, `search_tsv` vor `__table_args__` — SQLAlchemy Anti-Pattern. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-419: mail/models.py — MailAccount.encrypted_password mit password_salt -- **Datei:** app/plugins/builtins/mail/models.py:40 -- **Problem:** `encrypted_password` und `password_salt` — gut dass verschlüsselt, aber der Salt sollte pro-Account random sein, nicht hardcoded default="". -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-420: mail/models.py — PgpKey.encrypted_private_key in DB -- **Datei:** app/plugins/builtins/mail/models.py:300 -- **Problem:** `encrypted_private_key: Mapped[str] = mapped_column(Text, nullable=False)` — PGP Private Key in DB gespeichert. Auch wenn verschlüsselt, ist das ein hohes Risiko. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-421: forgejo_error_reporter/models.py — Integer auto-increment PK statt UUID -- **Datei:** app/plugins/builtins/forgejo_error_reporter/models.py:20 -- **Problem:** `id = Column(Integer, primary_key=True, autoincrement=True)` — Integer auto-increment PK. AGENTS.md verbietet Integer IDs, UUID only. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-422: forgejo_error_reporter/models.py — Kein TenantMixin -- **Datei:** app/plugins/builtins/forgejo_error_reporter/models.py -- **Problem:** `ReportedError` hat kein TenantMixin — nicht tenant-scoped. Kann für Cross-Tenant Data Leaks führen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-423: marketplace/models.py — Kein TenantMixin (global) -- **Datei:** app/plugins/builtins/marketplace/models.py:30 -- **Problem:** `MarketplaceListing` hat kein TenantMixin — bewusst global, aber muss dokumentiert sein. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-424: ai_assistant/services.py — hardcoded deutsche Strings in seed_default_providers -- **Datei:** app/plugins/builtins/ai_assistant/services.py:450 -- **Problem:** `'Standard Assistent'`, `'Allgemeiner KI-Assistent'`, `'Du bist ein hilfreicher KI-Assistent...'` — hardcoded deutsch. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-425: ai_assistant/schemas.py — AIProviderCreate.api_key in Schema -- **Datei:** app/plugins/builtins/ai_assistant/schemas.py:15 -- **Problem:** `api_key: str = Field(default="", max_length=2000)` — API Key in Pydantic Schema. Wird in Create/Update akzeptiert und in Response zurückgegeben. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-426: permissions/schemas.py — ShareLinkResponse.token in Response -- **Datei:** app/plugins/builtins/permissions/schemas.py:35 -- **Problem:** `token: str` in ShareLinkResponse — Share Link Token wird in API Response zurückgegeben. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-427: mcp_client/schemas.py — McpServerConfigResponse gibt api_token zurück -- **Datei:** app/plugins/builtins/mcp_client/schemas.py:40 -- **Problem:** McpServerConfigResponse enthält `api_token` — wird in API Response zurückgegeben. -- **Schweregrad:** High -- **Status:** ⏳ Nicht gefixt - -### ARCH-428: knowledge/services.py — Core→Plugin Import (graph_rag) -- **Datei:** app/plugins/builtins/knowledge/services.py:200 -- **Problem:** `from app.plugins.builtins.graph_rag.services import create_relationship` — Plugin→Plugin direkter Import. Sollte über Contract gehen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-429: agent_memory/services.py — Core→Plugin Import (unified_search) -- **Datei:** app/plugins/builtins/agent_memory/services.py:15 -- **Problem:** `from app.plugins.builtins.unified_search.contracts import generate_embedding` — Plugin→Plugin Import. Sollte über Contract Registry gehen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-430: ai_proactive/services.py — Core→Plugin Import (create_notification) -- **Datei:** app/plugins/builtins/ai_proactive/services.py:20 -- **Problem:** `from app.core.notifications import create_notification` — Plugin importiert von Core. Das ist OK (Plugin→Core ist erlaubt). -- **Schweregrad:** Low -- **Status:** ⏳ Kein Bug (Plugin→Core ist erlaubt) - -### ARCH-431: mail/services.py — 3086 Zeilen (God Object) -- **Datei:** app/plugins/builtins/mail/services.py -- **Problem:** 3086 Zeilen — massives God Object. Sollte aufgeteilt werden in: imap_sync.py, smtp_send.py, encryption.py, rules.py, vacation.py, pgp.py. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-432: kommunikation/services.py — 1340 Zeilen (God Object) -- **Datei:** app/plugins/builtins/kommunikation/services.py -- **Problem:** 1340 Zeilen — God Object. Sollte aufgeteilt werden. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-433: self_improvement/services.py — 1058 Zeilen (God Object) -- **Datei:** app/plugins/builtins/self_improvement/services.py -- **Problem:** 1058 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-434: automation/services.py — 896 Zeilen (God Object) -- **Datei:** app/plugins/builtins/automation/services.py -- **Problem:** 896 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-435: ai_proactive/services.py — 867 Zeilen (God Object) -- **Datei:** app/plugins/builtins/ai_proactive/services.py -- **Problem:** 867 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-436: SuggestionCard.tsx — Hardcoded deutsche Strings ohne i18n -- **Datei:** frontend/src/components/ai/SuggestionCard.tsx:80 -- **Problem:** `'✓ Ausgeführt'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-437: SuggestionSidebar.tsx — Hardcoded deutsche Strings -- **Datei:** frontend/src/components/ai/SuggestionSidebar.tsx:20 -- **Problem:** `'Alle'`, `'Info'`, `'Warnung'`, `'Aktion'`, `'Erkenntnis'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-438: AIUIControlIndicator.tsx — Hardcoded deutsche Strings -- **Datei:** frontend/src/components/ai-ui-control/AIUIControlIndicator.tsx:70 -- **Problem:** `'Navigation'`, `'Filter setzen'`, `'Kontakt öffnen'`, `'Dialog öffnen'`, `'Tab wechseln'`, `'Einstellungen ändern'` — hardcoded deutsch. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-439: ImprovementPanel.tsx — Hardcoded deutsche Strings -- **Datei:** frontend/src/components/ai/ImprovementPanel.tsx:150 -- **Problem:** `'Messen'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-440: ApprovalRequestBlock.tsx — Hardcoded englische Strings -- **Datei:** frontend/src/components/comm/blocks/ApprovalRequestBlock.tsx:25 -- **Problem:** `'Approval Required'`, `'Approve'`, `'Reject'` — hardcoded englisch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-441: ContactCardBlock.tsx — Hardcoded deutsche Strings -- **Datei:** frontend/src/components/comm/blocks/ContactCardBlock.tsx:20 -- **Problem:** `'Unbekannter Kontakt'`, `'Kontakt anzeigen'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-442: AudioBlock.tsx — Hardcoded deutscher String -- **Datei:** frontend/src/components/comm/blocks/AudioBlock.tsx:35 -- **Problem:** `'Dauer:'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-443: KnowledgeCardBlock.tsx — Hardcoded englische Strings -- **Datei:** frontend/src/components/comm/blocks/KnowledgeCardBlock.tsx:20 -- **Problem:** `'Knowledge'`, `'Confidence:'`, `'Open'` — hardcoded englisch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-444: MiniAppBlock.tsx — Hardcoded deutscher String -- **Datei:** frontend/src/components/comm/blocks/MiniAppBlock.tsx:80 -- **Problem:** `'Keine Konfiguration'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-445: ProtectedRoute.tsx — /kein-zugriff hardcoded deutscher Pfad -- **Datei:** frontend/src/components/common/ProtectedRoute.tsx:25 -- **Problem:** `` — hardcoded deutscher Pfad. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-446: PrintButton.tsx — Hardcoded deutscher String -- **Datei:** frontend/src/components/common/PrintButton.tsx:100 -- **Problem:** `'Als PDF'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-447: ShareDialog.tsx — Hardcoded deutscher String -- **Datei:** frontend/src/components/common/ShareDialog.tsx:300 -- **Problem:** `'Schließen'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-448: FolderPermissionDialog.tsx — Hardcoded deutscher String -- **Datei:** frontend/src/components/contacts/FolderPermissionDialog.tsx:280 -- **Problem:** `'Schließen'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-449: ContactList.tsx — TODO P2-F18 hardcoded ALL_COLUMNS -- **Datei:** frontend/src/components/contacts/ContactList.tsx:2 -- **Problem:** `// TODO: P2-F18 — Replace hardcoded ALL_COLUMNS with backend/manifest config` — hardcoded Spalten-Definition. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-450: FilterPanel.tsx — TODO P2-F10 hardcoded FIELD_DEFS -- **Datei:** frontend/src/components/contacts/FilterPanel.tsx:2 -- **Problem:** `// TODO: P2-F10 — Replace hardcoded FIELD_DEFS with backend/manifest config` — hardcoded Feld-Definitionen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-451: FilterPanel.tsx — Hardcoded deutscher String 'Fertig' -- **Datei:** frontend/src/components/contacts/FilterPanel.tsx:600 -- **Problem:** `'Fertig'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-452: GroupPanel.tsx — TODO P2-F12 hardcoded GROUP_FIELDS -- **Datei:** frontend/src/components/contacts/GroupPanel.tsx:2 -- **Problem:** `// TODO: P2-F12 — Replace hardcoded GROUP_FIELDS with shared constant` — hardcoded Gruppierungs-Felder. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-453: GroupPanel.tsx — Hardcoded deutscher String 'Fertig' -- **Datei:** frontend/src/components/contacts/GroupPanel.tsx:420 -- **Problem:** `'Fertig'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-454: SortPanel.tsx — TODO P2-F11 hardcoded SORT_FIELDS -- **Datei:** frontend/src/components/contacts/SortPanel.tsx:2 -- **Problem:** `// TODO: P2-F11 — Replace hardcoded SORT_FIELDS with shared constant` — hardcoded Sortier-Felder. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-455: SortPanel.tsx — Hardcoded deutscher String 'Fertig' -- **Datei:** frontend/src/components/contacts/SortPanel.tsx:430 -- **Problem:** `'Fertig'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-456: SaveViewDialog.tsx — Hardcoded deutscher String 'Speichern' -- **Datei:** frontend/src/components/contacts/SaveViewDialog.tsx:120 -- **Problem:** `'Speichern'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-457: DashboardWidgetLoader.tsx — TODO P2-F17 hardcoded widgetRegistry -- **Datei:** frontend/src/components/dashboard/DashboardWidgetLoader.tsx:2 -- **Problem:** `// TODO: P2-F17 — Replace hardcoded widgetRegistry with dynamic manifest config` — hardcoded Widget Registry. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-458: ContactFolderTree.tsx — Hardcoded 'OK' String -- **Datei:** frontend/src/components/contacts/ContactFolderTree.tsx:580 -- **Problem:** `'OK'` — hardcoded ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-459: NotificationBell.tsx — TODO P2-F8 Legacy Notifications -- **Datei:** frontend/src/components/layout/NotificationBell.tsx:2 -- **Problem:** `// TODO: P2-F8 — Migrate from /notifications to communication API` — Legacy Notification System läuft parallel zu Kommunikation. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-460: NotificationDropdown.tsx — TODO P2-F7 Legacy Notifications -- **Datei:** frontend/src/components/notifications/NotificationDropdown.tsx:2 -- **Problem:** `// TODO: P2-F7 — Migrate from /notifications to communication API` — Legacy Notification System. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-461: MailFilterPanel.tsx — TODO P2-F14 hardcoded FIELD_DEFS -- **Datei:** frontend/src/components/mail/MailFilterPanel.tsx:2 -- **Problem:** `// TODO: P2-F14 — Replace hardcoded FIELD_DEFS with backend config` — hardcoded Feld-Definitionen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-462: MailFolderTree.tsx — TODO P2-F13 hardcoded FOLDER_NAME_MAP -- **Datei:** frontend/src/components/mail/MailFolderTree.tsx:2 -- **Problem:** `// TODO: P2-F13 — Replace hardcoded FOLDER_NAME_MAP with i18n keys` — hardcoded Ordner-Namen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-463: MailGroupPanel.tsx — TODO P2-F16 hardcoded GROUP_FIELDS -- **Datei:** frontend/src/components/mail/MailGroupPanel.tsx:2 -- **Problem:** `// TODO: P2-F16 — Replace hardcoded GROUP_FIELDS with shared constant` — hardcoded Gruppierungs-Felder. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-464: MailList.tsx — TODO P3-F6 inline style -- **Datei:** frontend/src/components/mail/MailList.tsx:2 -- **Problem:** `// TODO: P3-F6 — Replace inline style with Tailwind classes` — inline style statt Tailwind. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-465: MailSortPanel.tsx — TODO P2-F15 hardcoded SORT_FIELDS -- **Datei:** frontend/src/components/mail/MailSortPanel.tsx:2 -- **Problem:** `// TODO: P2-F15 — Replace hardcoded SORT_FIELDS with shared constant` — hardcoded Sortier-Felder. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-466: CommandPalette.tsx — TODO P2-F4 hardcoded TYPE_LABELS/ICONS -- **Datei:** frontend/src/components/search/CommandPalette.tsx:2 -- **Problem:** `// TODO: P2-F4 — Replace hardcoded TYPE_LABELS/ICONS with dynamic config` — hardcoded Type-Labels und Icons. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-467: WorkflowEditor.tsx — TODO P2-F21 hardcoded triggerEventOptions -- **Datei:** frontend/src/components/workflows/WorkflowEditor.tsx:3 -- **Problem:** `// TODO: P2-F21 — Replace hardcoded triggerEventOptions with backend config` — hardcoded Trigger-Event-Optionen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-468: WorkspaceManager.tsx — hardcoded CORE_MENU_ITEMS -- **Datei:** frontend/src/components/settings/WorkspaceManager.tsx:10 -- **Problem:** `const CORE_MENU_ITEMS = [{ key: 'dashboard', label: 'Dashboard' }, { key: 'contacts', label: 'Kontakte' }]` — hardcoded deutsche Labels und statische Core-Module. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-469: SortableMenuItem.tsx — import * as LucideIcons -- **Datei:** frontend/src/components/layout/SortableMenuItem.tsx:5 -- **Problem:** `import * as LucideIcons from 'lucide-react'` — lädt ALLE Icons, kann OOM in Tests verursachen. Sidebar.tsx hat bereits einen kommentierten Fix dafür. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-470: ImportWizard.tsx — 1083 Zeilen (God Object) -- **Datei:** frontend/src/components/import-export/ImportWizard.tsx -- **Problem:** 1083 Zeilen — God Object. Sollte aufgeteilt werden. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-471: ContactList.tsx — 1311 Zeilen (God Object) -- **Datei:** frontend/src/components/contacts/ContactList.tsx -- **Problem:** 1311 Zeilen — God Object. Sollte aufgeteilt werden. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-472: ContactFolderTree.tsx — 616 Zeilen (God Object) -- **Datei:** frontend/src/components/contacts/ContactFolderTree.tsx -- **Problem:** 616 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-473: MessageSidebar.tsx — 671 Zeilen (God Object) -- **Datei:** frontend/src/components/layout/MessageSidebar.tsx -- **Problem:** 671 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-474: FilterPanel.tsx — 641 Zeilen (God Object) -- **Datei:** frontend/src/components/contacts/FilterPanel.tsx -- **Problem:** 641 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-475: ContactDetail.tsx — 588 Zeilen (God Object) -- **Datei:** frontend/src/components/contacts/ContactDetail.tsx -- **Problem:** 588 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-476: AgentDashboard.tsx — TODO P2-F25 hardcoded commonModels -- **Datei:** frontend/src/pages/AgentDashboard.tsx:3 -- **Problem:** `// TODO: P2-F25 — Replace hardcoded commonModels with /ai/providers API` — hardcoded Model-Liste. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-477: AISettings.tsx — Hardcoded deutscher String -- **Datei:** frontend/src/pages/AISettings.tsx:300 -- **Problem:** `'KI Assistent Einstellungen'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-478: AgentsPlaceholder.tsx — Hardcoded deutsche Strings -- **Datei:** frontend/src/pages/agents/AgentsPlaceholder.tsx:8 -- **Problem:** `'Agenten'`, `'Diese Seite wird gerade erstellt...'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-479: AutomationOverview.tsx — Hardcoded deutsche Strings -- **Datei:** frontend/src/pages/automation/AutomationOverview.tsx:5 -- **Problem:** `'Automation Übersicht'`, `'Erstellen und verwalten Sie...'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-480: AutomationPlaceholder.tsx — Hardcoded deutsche Strings -- **Datei:** frontend/src/pages/automation/AutomationPlaceholder.tsx:8 -- **Problem:** `'Automation'`, `'Diese Seite wird gerade erstellt...'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-481: CustomFields.tsx — TODO P2-T21 hardcoded ENTITY_OPTIONS -- **Datei:** frontend/src/pages/CustomFields.tsx:3 -- **Problem:** `// TODO: P2-T21 — Replace hardcoded ENTITY_OPTIONS with backend config` — hardcoded Entity-Optionen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-482: GlobalSearchResults.tsx — TODO P2-F5 hardcoded TYPE_LABELS -- **Datei:** frontend/src/pages/GlobalSearchResults.tsx:3 -- **Problem:** `// TODO: P2-F5 — Replace hardcoded TYPE_LABELS with shared constant` — hardcoded Type-Labels. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-483: DmsTrash.tsx — TODO P3-F29 DMS trash endpoint nicht implementiert -- **Datei:** frontend/src/pages/DmsTrash.tsx:2 -- **Problem:** `// TODO: P3-F29 — Implement DMS trash endpoint` — DMS Trash Endpoint fehlt. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-484: GuestContacts.tsx — Hardcoded deutscher String -- **Datei:** frontend/src/pages/GuestContacts.tsx:15 -- **Problem:** `'Weiterleitung zu Kontakten...'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-485: GuestLogin.tsx — Hardcoded deutscher String -- **Datei:** frontend/src/pages/GuestLogin.tsx:15 -- **Problem:** `'Weiterleitung zum Login...'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-486: Help pages — Alle hardcoded deutsch ohne i18n -- **Datei:** frontend/src/pages/help/HelpApiDocs.tsx, HelpContacts.tsx, HelpLogin.tsx, HelpMailSetup.tsx, HelpNavigation.tsx -- **Problem:** Alle Help-Seiten haben hardcoded deutsche Strings ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-487: AgentDashboard.tsx — 832 Zeilen (God Object) -- **Datei:** frontend/src/pages/AgentDashboard.tsx -- **Problem:** 832 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-488: AutomationDashboard.tsx — 778 Zeilen (God Object) -- **Datei:** frontend/src/pages/AutomationDashboard.tsx -- **Problem:** 778 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-489: Calendar.tsx — 759 Zeilen (God Object) -- **Datei:** frontend/src/pages/Calendar.tsx -- **Problem:** 759 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-490: Dms.tsx — 746 Zeilen (God Object) -- **Datei:** frontend/src/pages/Dms.tsx -- **Problem:** 746 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-491: ContactsList.tsx — 787 Zeilen (God Object) -- **Datei:** frontend/src/pages/ContactsList.tsx -- **Problem:** 787 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-492: Communication.tsx — 894 Zeilen (God Object) -- **Datei:** frontend/src/pages/Communication.tsx -- **Problem:** 894 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-493: CustomFields.tsx — 521 Zeilen (God Object) -- **Datei:** frontend/src/pages/CustomFields.tsx -- **Problem:** 521 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-494: ComplianceTab.tsx — 463 Zeilen (God Object) -- **Datei:** frontend/src/pages/ComplianceTab.tsx -- **Problem:** 463 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-495: ProactiveAISettings.tsx — TODO P2-T20 hardcoded categoryLabels/modelOptions -- **Datei:** frontend/src/pages/ProactiveAISettings.tsx:3 -- **Problem:** `// TODO: P2-T20 — Replace hardcoded categoryLabels/modelOptions with backend config` — hardcoded Labels und Model-Optionen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-496: SettingsMenuOrder.tsx — TODO P2-F23 hardcoded DEFAULT_ORDER -- **Datei:** frontend/src/pages/SettingsMenuOrder.tsx:3 -- **Problem:** `// TODO: P2-F23 — Replace hardcoded DEFAULT_ORDER with backend config` — hardcoded Default-Menü-Reihenfolge. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-497: SettingsRechte.tsx — TODO P2-T19 hardcoded PermissionLevelBadge/PrincipalTypeBadge -- **Datei:** frontend/src/pages/SettingsRechte.tsx:4 -- **Problem:** `// TODO: P2-T19 — Replace hardcoded PermissionLevelBadge/PrincipalTypeBadge with i18n` — hardcoded Badges ohne i18n. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-498: SettingsUsers.tsx — TODO P2-F22 hardcoded LEGACY_ROLES -- **Datei:** frontend/src/pages/SettingsUsers.tsx:3 -- **Problem:** `// TODO: P2-F22 — Replace hardcoded LEGACY_ROLES with /roles API` — hardcoded Legacy-Rollen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-499: SettingsWebhooks.tsx — TODO P2-F20 hardcoded AVAILABLE_EVENTS -- **Datei:** frontend/src/pages/SettingsWebhooks.tsx:2 -- **Problem:** `// TODO: P2-F20 — Replace hardcoded AVAILABLE_EVENTS with backend config` — hardcoded verfügbare Webhook-Events. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-500: Trash.tsx — TODO P2-F24 hardcoded ENTITY_TYPES -- **Datei:** frontend/src/pages/Trash.tsx:2 -- **Problem:** `// TODO: P2-F24 — Replace hardcoded ENTITY_TYPES with dynamic config` — hardcoded Entity-Typen. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-501: Mail.tsx — 1098 Zeilen (God Object) -- **Datei:** frontend/src/pages/Mail.tsx -- **Problem:** 1098 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-502: SettingsBackup.tsx — 797 Zeilen (God Object) -- **Datei:** frontend/src/pages/SettingsBackup.tsx -- **Problem:** 797 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-503: SettingsGroups.tsx — 696 Zeilen (God Object) -- **Datei:** frontend/src/pages/SettingsGroups.tsx -- **Problem:** 696 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-504: Tags.tsx — 594 Zeilen (God Object) -- **Datei:** frontend/src/pages/Tags.tsx -- **Problem:** 594 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-505: SettingsRoles.tsx — 532 Zeilen (God Object) -- **Datei:** frontend/src/pages/SettingsRoles.tsx -- **Problem:** 532 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-506: SettingsStammdaten.tsx — 477 Zeilen (God Object) -- **Datei:** frontend/src/pages/SettingsStammdaten.tsx -- **Problem:** 477 Zeilen — God Object. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-507: NoAccessPage.tsx — Hardcoded deutsche Strings -- **Datei:** frontend/src/pages/NoAccessPage.tsx:10 -- **Problem:** `'Kein Zugriff'`, `'Sie haben keine Berechtigung...'`, `'Zum Dashboard'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-508: LogsOverview.tsx — Hardcoded deutsche Strings -- **Datei:** frontend/src/pages/logs/LogsOverview.tsx:5 -- **Problem:** `'Logs Übersicht'`, `'System- und Audit-Logs einsehen...'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-509: LogsPlaceholder.tsx — Hardcoded deutsche Strings -- **Datei:** frontend/src/pages/logs/LogsPlaceholder.tsx:8 -- **Problem:** `'Logs'`, `'Diese Seite wird gerade erstellt...'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-510: HelpPlaceholder.tsx — Hardcoded deutsche Strings -- **Datei:** frontend/src/pages/help/HelpPlaceholder.tsx:8 -- **Problem:** `'Hilfe'`, `'Diese Hilfeseite...'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-511: HelpWelcome.tsx — Hardcoded deutsche Strings -- **Datei:** frontend/src/pages/help/HelpWelcome.tsx:5 -- **Problem:** `'Willkommen bei LeoCRM'`, `'LeoCRM ist ein selbst-gehostetes CRM-System...'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-512: contacts.ts — TODO P2-F9 Dual API Clients -- **Datei:** frontend/src/api/contacts.ts:2 -- **Problem:** `// TODO: P2-F9 — Consolidate dual API clients` — contacts.ts und unifiedContacts.ts existieren parallel. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-513: unifiedContacts.ts — TODO P2-F9 Dual API Clients -- **Datei:** frontend/src/api/unifiedContacts.ts:2 -- **Problem:** `// TODO: P2-F9 — Consolidate dual API clients` — gleiche Dual-Architektur wie contacts.ts. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-514: search.ts — TODO P2-F3 hardcoded ENTITY_URL_MAP -- **Datei:** frontend/src/api/search.ts:2 -- **Problem:** `// TODO: P2-F3 — Replace hardcoded ENTITY_URL_MAP with dynamic backend config` — hardcoded Entity-URL-Mapping. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-515: types.ts — TODO P2-F19 Contact interface nicht mit Backend aligned -- **Datei:** frontend/src/api/types.ts:2 -- **Problem:** `// TODO: P2-F19 — Align Contact interface with backend field names (firstname/surname)` — Contact Interface Feldnamen nicht mit Backend synchronisiert. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-516: mail.ts — 688 Zeilen (God Object) -- **Datei:** frontend/src/api/mail.ts -- **Problem:** 688 Zeilen — God Object. Sollte aufgeteilt werden. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-517: customFields.ts — hardcoded Contact/Company Entity -- **Datei:** frontend/src/api/customFields.ts:15 -- **Problem:** Custom Fields API ist auf Contacts beschränkt (`variables.contactId`). Sollte generisch für alle Entities funktionieren. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-518: errorTypes.ts — Hardcoded deutsche Strings in categorizeError -- **Datei:** frontend/src/utils/errorTypes.ts:50 -- **Problem:** `'Netzwerkfehler'`, `'Nicht authentifiziert'`, `'Keine Berechtigung'`, `'Validierungsfehler'`, `'Serverfehler'`, `'Unbekannter Fehler'` — hardcoded deutsch ohne i18n. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-519: date.ts — Hardcoded German locale -- **Datei:** frontend/src/utils/date.ts:2 -- **Problem:** `import { de } from 'date-fns/locale'` — hardcoded German locale. Sollte dynamisch basierend auf i18n language sein. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-520: App.tsx — Hardcoded deutscher String 'Zum Hauptinhalt springen' -- **Datei:** frontend/src/App.tsx:79 -- **Problem:** `'Zum Hauptinhalt springen'` — hardcoded deutsch ohne t(). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-521: main.tsx — window.__AUTH_STORE__ in Dev Mode -- **Datei:** frontend/src/main.tsx:22 -- **Problem:** `(window as any).__AUTH_STORE__ = useAuthStore` — Auth Store wird global in Dev Mode exposed. Kann in Production leaks verursachen wenn DEV-Flag nicht korrekt gesetzt ist. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-522: index.html — PWA manifest.json noch verlinkt -- **Datei:** frontend/index.html:8 -- **Problem:** `` — PWA Manifest ist noch verlinkt obwohl PWA deaktiviert wurde. Service Worker werden in main.tsx unregistriert aber Manifest ist noch da. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-523: index.html — Hardcoded lang="de" -- **Datei:** frontend/index.html:2 -- **Problem:** `` — hardcoded German. Sollte dynamisch basierend auf i18n language sein. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-524: tsconfig.json — noUnusedLocals: false -- **Datei:** frontend/tsconfig.json:15 -- **Problem:** `"noUnusedLocals": false` — TypeScript erlaubt ungenutzte lokale Variablen. Sollte `true` sein für strikte Code-Qualität. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-525: tsconfig.json — noUnusedParameters: false -- **Datei:** frontend/tsconfig.json:16 -- **Problem:** `"noUnusedParameters": false` — TypeScript erlaubt ungenutzte Parameter. Sollte `true` sein. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-526: package.json — vite-plugin-pwa noch als Dependency -- **Datei:** frontend/package.json:65 -- **Problem:** `"vite-plugin-pwa": "^1.2.0"` — PWA Plugin noch als Dependency obwohl PWA deaktiviert wurde. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-527: package.json — workbox-build noch als Dependency -- **Datei:** frontend/package.json:77 -- **Problem:** `"workbox-build": "^7.4.1"` — Workbox (PWA Service Worker) noch als Dependency obwohl PWA deaktiviert wurde. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-528: .env.example — ADMIN_PASSWORD hardcoded -- **Datei:** .env.example:137 -- **Problem:** `ADMIN_PASSWORD=Admin123!` — hardcoded Admin-Password in .env.example. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-529: .env.docker.example — ADMIN_PASSWORD hardcoded -- **Datei:** .env.docker.example:60 -- **Problem:** `ADMIN_PASSWORD=Admin123!` — hardcoded Admin-Password in .env.docker.example. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-530: prestart.sh — SQL injection risk in GRANT statements -- **Datei:** prestart.sh:60-80 -- **Problem:** `GRANT` statements use string interpolation for table names. While currently safe (table names are hardcoded), the pattern is risky if extended. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-531: prestart.sh — DB_PASSWORD used for ALL roles -- **Datei:** prestart.sh:40-50 -- **Problem:** Same `DB_PASSWORD` env var is used for crm_api, crm_auth, crm_worker, crm_migration. Each role should have its own password. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-532: Dockerfile — No .dockerignore mentioned -- **Datei:** Dockerfile -- **Problem:** No `.dockerignore` file found. Build context may include node_modules, .git, .env, test-results, etc. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-533: docker-compose.yaml — No resource limits on crm_app -- **Datei:** docker-compose.yaml -- **Problem:** crm_app service has no mem_limit or cpus limit, unlike redis (256m, 0.5 cpus). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-534: requirements.txt — No version pinning for some packages -- **Datei:** requirements.txt -- **Problem:** Some packages use `>=` without upper bound (e.g. `httpx>=0.27`, `redis>=5.0`, `arq>=0.25`). Can lead to incompatible updates. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-535: pyproject.toml — disallow_untyped_defs: false -- **Datei:** pyproject.toml:55 -- **Problem:** `disallow_untyped_defs = false` — mypy erlaubt untypisierte Funktionen. Sollte `true` sein für strikte Type-Checking. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-536: .pre-commit-cross-plugin.yaml — stages: [commit] deprecated -- **Datei:** .pre-commit-cross-plugin.yaml:13 -- **Problem:** `stages: [commit]` is deprecated in pre-commit. Should use `pre-commit` or remove stages. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-537: seed_admin.py — Hardcoded Admin Password -- **Datei:** scripts/seed_admin.py:15 -- **Problem:** `admin@media-on.de / Admin123!` — hardcoded Admin-Credentials im Script. -- **Schweregrad:** Medium -- **Status:** ⏳ Nicht gefixt - -### ARCH-538: deploy.py — 905 Zeilen (God Object) -- **Datei:** scripts/deploy.py -- **Problem:** 905 Zeilen — God Object. Sollte aufgeteilt werden. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-539: spike_e_benchmark.py — 713 Zeilen (God Object) -- **Datei:** scripts/spike_e_benchmark.py -- **Problem:** 713 Zeilen — God Object. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-540: ai_run_tests.py — 519 Zeilen (God Object) -- **Datei:** scripts/ai_run_tests.py -- **Problem:** 519 Zeilen — God Object. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-541: ai_deploy.py — 442 Zeilen (God Object) -- **Datei:** scripts/ai_deploy.py -- **Problem:** 442 Zeilen — God Object. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-542: backup.py — 445 Zeilen (God Object) -- **Datei:** scripts/backup.py -- **Problem:** 445 Zeilen — God Object. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-543: test_suite/marathon.py — False Positive Bug Counting -- **Datei:** scripts/test_suite/marathon.py -- **Problem:** Marathon zählt issues aus JSON-Dateien die 0 issues haben als >0 (trace_stores, trace_hooks, trace_functions). Bug im Marathon-Script selbst. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-544: test_suite/trace_api_contracts.py — String-Matching statt Path-Matching -- **Datei:** scripts/test_suite/trace_api_contracts.py -- **Problem:** Vergleicht Frontend API-Calls mit Backend Routes per String-Matching. `/webhooks/{id}` vs `/webhooks/{webhook_id}` wird als Mismatch erkannt obwohl es der selbe Endpoint ist. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-545: test_suite/trace_plugins.py — Sucht manifest.py statt plugin.py -- **Datei:** scripts/test_suite/trace_plugins.py -- **Problem:** Trace-Script sucht nach `manifest.py` aber alle Plugins haben `plugin.py` mit Metadaten. 27 false positive issues. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-546: INSTALL.md — Veraltete Commit/Alembic-Head Referenzen -- **Datei:** docs/INSTALL.md:5 -- **Problem:** `Commit: 72e3756, Alembic-Head: 0136` — veraltete Referenzen. Aktueller Head ist 0140. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-547: INSTALL.md — Widersprüchliche Stand-Angaben -- **Datei:** docs/INSTALL.md:520 -- **Problem:** `Stand: Commit be20a85, Alembic-Head 0090` am Ende der Datei — widerspricht Zeile 5 (Commit 72e3756, Head 0136). -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-548: api-documentation.md — Veraltete Endpoint-Zahl -- **Datei:** docs/api-documentation.md:4 -- **Problem:** `554+ endpoints` — aktuelle Zahl ist 556. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-549: plugin-development-guide.md — 2549 Zeilen (God Object) -- **Datei:** docs/plugin-development-guide.md -- **Problem:** 2549 Zeilen — extrem langes Dokument. Sollte aufgeteilt werden. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-550: 0136_fix_rls_tenant_id.py — Downgrade verwendet app.tenant_id statt app.current_tenant_id -- **Datei:** alembic/versions/0136_fix_rls_tenant_id.py:40 -- **Problem:** Downgrade erstellt RLS policies mit `app.tenant_id` (der fehlerhafte alte Wert) statt `app.current_tenant_id`. Downgrade würde den Bug wieder einführen. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-551: 0137_drop_ai_chat_tables.py — Downgrade macht nichts -- **Datei:** alembic/versions/0137_drop_ai_chat_tables.py:30 -- **Problem:** `def downgrade(): pass` — Tabellen können nicht wiederhergestellt werden. Das ist dokumentiert aber ein Risiko. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt - -### ARCH-552: 0004_ai_workflows.py — Erstellt ai_conversations/ai_messages die später gedropped wurden -- **Datei:** alembic/versions/0004_ai_workflows.py -- **Problem:** Erstellt Tabellen die in Migration 0137 gedropped wurden. Verschwendete Migration. -- **Schweregrad:** Low -- **Status:** ⏳ Nicht gefixt (historisch)