# SPA cutover feature flag (`USE_SPA_UI`) ## Formål `USE_SPA_UI` styrer om host/player UI routes serverer Angular SPA shell eller legacy Django templates. ## Miljø-toggle (uden kodeændring) Sæt env var pr. miljø: - `USE_SPA_UI=true` -> `/lobby/ui/host` og `/lobby/ui/player` returnerer SPA shell - `USE_SPA_UI=false` (default) -> legacy template-flow bruges uændret Backward compatibility under cutover: - Hvis `USE_SPA_UI` ikke er sat, bruges `WPP_SPA_ENABLED` som fallback. ## Static asset versioning/cache-busting (hardening) Formål: sikre at browser/proxy/CDN hurtigt henter ny SPA bundle i release-vinduet uden at kræve hard refresh. - `WPP_SPA_ASSET_BASE` peger fortsat på build-output (`/static/frontend/angular/browser`). - `WPP_SPA_ASSET_VERSION` injiceres i SPA shell URLs som query-param (`?v=`). - Anbefalet værdi for `WPP_SPA_ASSET_VERSION`: release-tag eller kort commit SHA. - Ved rollback sættes `WPP_SPA_ASSET_VERSION` til den tidligere kendte stabile release-værdi. Eksempel (staging/prod env): ```env USE_SPA_UI=true WPP_SPA_ASSET_BASE=/static/frontend/angular/browser WPP_SPA_ASSET_VERSION=rel-2026-03-01-bb82357 ``` ## Staging rollout-checkliste (`USE_SPA_UI`) 1. **Baseline (flag OFF)** - Bekræft at staging kører med `USE_SPA_UI=false`. - Kør gameplay smoke på legacy routes (`/lobby/ui/host` + `/lobby/ui/player`). 2. **Smoke-gate før aktivering (skal være grøn)** - Cutover route sanity = PASS for både OFF og ON checks. - Full gameplay round (join/start/round/scoreboard) = PASS. - Next-round/final leaderboard sanity = PASS. - Ingen nye blocker-regressioner i host/player kerneflow. 3. **Kontrolleret aktivering i staging** - Sæt `USE_SPA_UI=true` i staging miljøet. - Kør smoke-flow igen med SPA-route-verifikation. 4. **Post-cutover dokumentation** - Log evidens med commit/head SHA, UTC timestamp og gate-status. ## Rollback playbook (`USE_SPA_UI`) — mål: <10 min Rollback til legacy (`USE_SPA_UI=false`) udføres straks hvis et checkpoint fejler: - Forkert route/shell for valgt flag i cutover route sanity. - Gameplay smoke kan ikke gennemføres til scoreboard/final leaderboard. - Kritisk regression i host/player flow under smoke. Trin-for-trin: 1. Sæt `USE_SPA_UI=false` i deploy-env. 2. Sæt `WPP_SPA_ASSET_VERSION` til sidste stabile release-token. 3. Deploy/reload app-processer. 4. Verificér legacy routes: `/lobby/ui/host` + `/lobby/ui/player`. 5. Kør hurtig smoke sanity (join/start/scoreboard path). 6. Log UTC tid, trigger, release-token og resultat i smoke artifact. Target: rollback + sanity-verifikation inden for 10 minutter. ## Verifikation - Flag OFF: `UiScreenTests.test_legacy_templates_are_used_when_spa_flag_is_off` - Flag ON (host): `UiScreenTests.test_host_screen_can_render_angular_shell_when_feature_flag_enabled` - Flag ON (host deep-link): `UiScreenTests.test_host_screen_deeplink_preserves_spa_path_when_feature_flag_enabled` - Flag ON (player): `UiScreenTests.test_player_screen_can_render_angular_shell_when_feature_flag_enabled` - Smoke-checkliste for cutover paths: `docs/STAGING_GAMEPLAY_SMOKE_ARTIFACT.md` + `docs/UI_SMOKE.md` ## MVP audio policy guardrail (telefon-klient) - Telefon-/player-klienten må ikke starte lydafspilning lokalt i MVP (`primary-device only`). - Policy er bundet til capability-flaget `frontend.capabilities.client_has_no_audio_output=true` i `shared/i18n/lobby.json`. - Brugeradvarsel i player UI leveres via i18n key: `frontend.ui.player.audio_policy_notice`. - Acceptance-spec er dækket i Angular tests (`player-shell.component.spec.ts`), inkl. at init-path ikke kalder original media `play`.