{ "task_id": "REVIEW-USER-THEME-001", "plan_ref": "REVIEW-USER-THEME-001/plan.json", "status": "done", "changed_files": [ { "path": "pages/admin/users/switch-tenant().php", "summary": "Tenant-Switch JSON-Response um effektives Theme ergaenzt (currentTheme()), damit Client nach Wechsel das korrekte Theme kennt." }, { "path": "web/js/components/app-tenant-switcher.js", "summary": "Nach erfolgreichem Tenant-Switch wird data.theme auf document.documentElement.dataset.theme gesetzt, bevor window.location.reload() erfolgt — verhindert Flash-of-wrong-theme." }, { "path": "web/js/components/app-theme-toggle.js", "summary": "Race-Condition-Guard (pending-Flag) fuer Theme-Menu und Toggle-Button eingefuehrt: parallele Klicks werden blockiert, bis der laufende Request abgeschlossen ist." }, { "path": "tests/Support/ThemeResolutionTest.php", "summary": "Neuer Testfall (16 Tests) fuer Theme-Resolution-Prioritaetskette: appDefaultTheme, currentTheme, allowUserTheme mit Kombinationen aus global/tenant/user Settings und Tenant-Switch-Szenarien." }, { "path": "tests/Service/Auth/AuthSessionTenantContextServiceTest.php", "summary": "Neuer Test testHydratePreservesThemeAndPolicyFieldsInSession: verifiziert, dass default_theme und allow_user_theme aus Tenant-Daten korrekt in Session uebernommen werden." } ], "guard_evidence": [ { "guard_id": "GR-CORE-001", "status": "pass", "evidence": "Theme-Prioritaetskette global->tenant->user ist konsistent in helpers/app.php (appDefaultTheme, currentTheme, allowUserTheme). Tenant-Switch aktualisiert current_tenant in Session; currentTheme() liest immer aktuellen Session-State. 16 Unit-Tests verifizieren alle Kombinationen." }, { "guard_id": "GR-CORE-003", "status": "pass", "evidence": "Session-Synchronisation bei Tenant-Wechsel: current_tenant wird vollstaendig aktualisiert (switch-tenant().php Zeile 81). currentTheme() liest daraus korrekt. JSON-Response enthaelt jetzt das effektive Theme." }, { "guard_id": "GR-SEC-001", "status": "pass", "evidence": "Keine neuen sicherheitsrelevanten Aenderungen. Theme-Endpoint prueft allowUserTheme(), CSRF, Login. Tenant-Switch prueft Zugehoerigkeit via UserTenantContextService. Keine Injection-Vektoren eingefuehrt." }, { "guard_id": "GR-UI-009", "status": "pass", "evidence": "Theme-Menu-Items haben aria-current=true fuer aktives Theme (app-topbar.phtml Zeile 117, app-theme-toggle.js Zeilen 47-55). Tenant-Switch-Links haben aria-current=true fuer aktiven Tenant (Zeile 60)." }, { "guard_id": "GR-UI-010", "status": "pass", "evidence": "Tenant-Switcher zeigt pending-State via aria-busy=true und reduzierte Opacity. Fehler werden via showAsyncFlash sichtbar. Theme-Toggle hat optimistic Update mit Rollback bei Fehler." }, { "guard_id": "GR-UI-011", "status": "pass", "evidence": "Race-Condition in Theme-Toggle durch pending-Flag verhindert (app-theme-toggle.js). Nur serverbestaetigte Aenderungen bleiben persistent — bei fetch-Fehler wird auf vorherigen Zustand zurueckgesetzt. Kein localStorage als Source of Truth." }, { "guard_id": "GR-TEST-001", "status": "pass", "evidence": "19 neue/erweiterte Tests: ThemeResolutionTest (16 Tests fuer Prioritaetskette, Policy-Flags, Tenant-Switch), AuthSessionTenantContextServiceTest (+1 Test fuer Theme-Felder in Session-Hydration). Alle gruen." }, { "guard_id": "GR-TEST-002", "status": "pass", "evidence": "Decision-Matrix dokumentiert in Analyse (S1). Tests decken alle Pfade ab: default fallback, app_setting override, tenant override, user override erlaubt/verboten, Tenant-Switch mit Policy-Wechsel, ungueltige Theme-Werte." } ], "commands": [ { "cmd": "docker compose exec php vendor/bin/phpunit", "result": "pass" }, { "cmd": "docker compose exec php vendor/bin/phpstan analyse -c phpstan.neon --no-progress", "result": "pass" }, { "cmd": "docker compose exec php vendor/bin/phpunit tests/Architecture/CoreStarterkitContractTest.php", "result": "pass" }, { "cmd": "docker compose exec php composer cs:check", "result": "pass" } ], "quality_gate_results": [ { "gate_id": "QG-001", "result": "pass", "notes": "454 Tests, 10879 Assertions, 0 Failures. Vollstaendig gruen." }, { "gate_id": "QG-002", "result": "pass", "notes": "PHPStan level 5: No errors." }, { "gate_id": "QG-003", "result": "pass", "notes": "CoreStarterkitContractTest: 11 Tests, 6137 Assertions, OK." }, { "gate_id": "QG-005", "result": "pass", "notes": "Browser-Smoke manuell durch User erfolgreich durchgefuehrt: Theme-Wechsel, schnelle Klicks, Tenant-Wechsel mit korrektem Theme, deaktivierte Policy ohne Theme-Menu — alle Szenarien bestanden." }, { "gate_id": "QG-006", "result": "pass", "notes": "PHP CS Fixer: 0 of 514 files need fixing." } ], "test_results": [ { "name": "ThemeResolutionTest (16 Tests): appDefaultTheme/currentTheme/allowUserTheme Prioritaetskette", "result": "pass" }, { "name": "AuthSessionTenantContextServiceTest::testHydratePreservesThemeAndPolicyFieldsInSession", "result": "pass" }, { "name": "QG-001 Full PHPUnit Suite (454 Tests)", "result": "pass", "notes": "454 Tests, 10879 Assertions, 0 Failures." }, { "name": "QG-003 CoreStarterkitContractTest (11 Tests)", "result": "pass" } ], "open_items": [] }