BUG: Plugin-Lifecycle Runtime-Cleanup tot — was_already_active/inactive erst NACH registry-Aufruf berechnet #355

Closed
opened 2026-08-27 11:32:21 +00:00 by Leopoldadmin · 1 comment
Owner

Live gemessen 2026-08-27 (tests/test_plugin_lifecycle_service.py, roter TDD-Lauf):

P1: In plugin_service.activate_plugin()/deactivate_plugin() wurde was_already_active/was_already_inactive aus dem Record berechnet, den registry.activate()/deactivate() ZURÜCKGIBT — dieser spiegelt immer den NEUEN Zustand. Ergebnis: Beide Flags konstant falsch → der komplette Zweig für Runtime-Deregistrierung beim Deactivate war toter Code (stale _active_plugins-Gate-Eintrag + Phantom-Permissions + verwaiste ENTITY_MODELS nach jeder echten Deaktivierung).

Realer Prod-Schaden heute: KI-Chat 403 plugin_inactive trotz DB=active (Registry-Zustand divergierte von DB — dieselbe Diskrepanzklasse).

P3: registry.activate() rief sync_notification_types() VOR dem Statusupdate auf → Notification Types des frisch aktivierten Plugins wurden nie gesynct.

Fix (b50a933-Nachfolger): Vorher-Status VOR dem Registry-Aufruf cachen; sync hinter den Flush verschoben. Beweis: neuer echter Integrationstest tests/test_plugin_lifecycle_service.py (install→activate×2→deactivate×2→re-activate über PluginService) rot→grün; Regressionssuite 93 passed (nur bekannter #354-Vorbestand rot).

Live gemessen 2026-08-27 (`tests/test_plugin_lifecycle_service.py`, roter TDD-Lauf): **P1:** In `plugin_service.activate_plugin()`/`deactivate_plugin()` wurde `was_already_active`/`was_already_inactive` aus dem Record berechnet, den `registry.activate()/deactivate()` ZURÜCKGIBT — dieser spiegelt immer den NEUEN Zustand. Ergebnis: Beide Flags konstant falsch → der komplette Zweig für Runtime-Deregistrierung beim Deactivate war toter Code (stale `_active_plugins`-Gate-Eintrag + Phantom-Permissions + verwaiste ENTITY_MODELS nach jeder echten Deaktivierung). **Realer Prod-Schaden heute:** KI-Chat 403 `plugin_inactive` trotz DB=active (Registry-Zustand divergierte von DB — dieselbe Diskrepanzklasse). **P3:** `registry.activate()` rief `sync_notification_types()` VOR dem Statusupdate auf → Notification Types des frisch aktivierten Plugins wurden nie gesynct. **Fix (b50a933-Nachfolger):** Vorher-Status VOR dem Registry-Aufruf cachen; sync hinter den Flush verschoben. Beweis: neuer echter Integrationstest `tests/test_plugin_lifecycle_service.py` (install→activate×2→deactivate×2→re-activate über PluginService) rot→grün; Regressionssuite 93 passed (nur bekannter #354-Vorbestand rot).
Leopoldadmin added the bugcritical labels 2026-08-27 11:32:21 +00:00
Author
Owner

Gefixt in Commit 385521e — deployed und live verifiziert (2026-08-27 13:38):

Fix

  1. Vorher-Status VOR der Mutation: activate_plugin()/deactivate_plugin() lesen den Record jetzt via _get_plugin_record() bevor sie registry.activate()/deactivate() aufrufen. Die Flags waren vorher konstant falsch (Record nach Aufruf spiegelt immer den neuen Zustand).
  2. sync_notification_types Reihenfolge: in registry.activate() hinter DB-Statusupdate+Flush verschoben.

Verifikation (Live-Messung)

  • Neuer echter Integrationstest tests/test_plugin_lifecycle_service.py: install → activate ×2 → deactivate ×2 → re-activate über PluginService
    • Roter Lauf vor Fix: beide Tests failed exakt an was_already_active ("Plugin is already active" statt "activated successfully")
    • Grüner Lauf nach Fix: 2/2 passed — beweist Permissions ×1 registriert/entfernt, Gate-Eintrag (_active_plugins) gesetzt/entfernt, ENTITY_MODELS on/off, Notification-Type synced/entfernt, on_activate/on_deactivate je genau 1×
  • Regression: tests/plugins + marketplace + contacts_lifecycle + route_order + detail = 93 passed (nur dokumentierter #354-Vorbestand rot)
  • ruff modified-files grün · Full Deploy SUCCESS · Health healthy · Alembic 0142 OK
**Gefixt in Commit `385521e` — deployed und live verifiziert (2026-08-27 13:38):** ## Fix 1. **Vorher-Status VOR der Mutation:** `activate_plugin()`/`deactivate_plugin()` lesen den Record jetzt via `_get_plugin_record()` bevor sie `registry.activate()/deactivate()` aufrufen. Die Flags waren vorher konstant falsch (Record nach Aufruf spiegelt immer den neuen Zustand). 2. **sync_notification_types Reihenfolge:** in `registry.activate()` hinter DB-Statusupdate+Flush verschoben. ## Verifikation (Live-Messung) - Neuer echter Integrationstest `tests/test_plugin_lifecycle_service.py`: install → activate ×2 → deactivate ×2 → re-activate über PluginService - Roter Lauf vor Fix: beide Tests failed exakt an `was_already_active` ("Plugin is already active" statt "activated successfully") - Grüner Lauf nach Fix: **2/2 passed** — beweist Permissions ×1 registriert/entfernt, Gate-Eintrag (`_active_plugins`) gesetzt/entfernt, ENTITY_MODELS on/off, Notification-Type synced/entfernt, on_activate/on_deactivate je genau 1× - Regression: tests/plugins + marketplace + contacts_lifecycle + route_order + detail = **93 passed** (nur dokumentierter #354-Vorbestand rot) - ruff modified-files grün · Full Deploy SUCCESS · Health healthy · Alembic 0142 OK
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Leopoldadmin/leocrm#355