docs: 349 Architektur-Fehler durch Code-Review dokumentiert (Routes+Services komplett gelesen)
This commit is contained in:
@@ -2108,3 +2108,795 @@ Playwright E2E: 10 passed, 24 failed (BUG-011/012/013 — Mock-Daten und data-te
|
||||
- **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
|
||||
|
||||
Reference in New Issue
Block a user