Observed
Every page load on /beatify/admin, /beatify/dashboard, and /beatify/player logs:
```
[Admin] SW registration failed: SecurityError: Failed to register a ServiceWorker
for scope ('/beatify/') with script ('/beatify/static/sw.js'):
The path of the provided scope ('/beatify/') is not under the max scope
allowed ('/beatify/static/'). Adjust the scope, move the Service Worker
script, or use the Service-Worker-Allowed HTTP header to allow the scope.
```
Root cause
Browsers limit a service worker's scope to its script's own path or deeper. Beatify serves `sw.js` from `/beatify/static/sw.js` but tries to register it at the broader `/beatify/` scope — blocked by the security check.
Three call sites make this same registration:
Impact
The SW never activates. Everything `sw.js` was built to do (Story 18.5) is dead code in production:
- No offline/cache-first asset serving
- `CACHE_VERSION` bumps in `sw.js` do nothing — the cache that version string names doesn't exist
- `PRECACHE_ASSETS` list is never precached
- HTML Network-First fallback to cache on disconnect doesn't kick in
This also means the existing rc1/rc2/rc3 `CACHE_VERSION` bumps haven't been doing what the CHANGELOG notes claim — HTML `?v=` cache-busters are the only force-refresh mechanism that actually works today.
Two fix options
Option A (preferred): serve sw.js from /beatify/sw.js
Add a dedicated view that serves `sw.js` at `/beatify/sw.js` (not under `/static/`). Update the three `serviceWorker.register()` call sites to match. The wider scope is then allowed because the script itself lives at the root of that scope.
Option B: add Service-Worker-Allowed header
Serve `/beatify/static/sw.js` with the response header `Service-Worker-Allowed: /beatify/`. Keeps the file location unchanged; only the HTTP response changes. Requires the HA backend view serving static files to set this header for the `sw.js` path specifically.
Spotted during the #772 wizard UX live-test — unrelated, pre-existing.
Observed
Every page load on
/beatify/admin,/beatify/dashboard, and/beatify/playerlogs:```
[Admin] SW registration failed: SecurityError: Failed to register a ServiceWorker
for scope ('/beatify/') with script ('/beatify/static/sw.js'):
The path of the provided scope ('/beatify/') is not under the max scope
allowed ('/beatify/static/'). Adjust the scope, move the Service Worker
script, or use the Service-Worker-Allowed HTTP header to allow the scope.
```
Root cause
Browsers limit a service worker's scope to its script's own path or deeper. Beatify serves `sw.js` from `/beatify/static/sw.js` but tries to register it at the broader `/beatify/` scope — blocked by the security check.
Three call sites make this same registration:
Impact
The SW never activates. Everything `sw.js` was built to do (Story 18.5) is dead code in production:
This also means the existing rc1/rc2/rc3 `CACHE_VERSION` bumps haven't been doing what the CHANGELOG notes claim — HTML `?v=` cache-busters are the only force-refresh mechanism that actually works today.
Two fix options
Option A (preferred): serve sw.js from /beatify/sw.js
Add a dedicated view that serves `sw.js` at `/beatify/sw.js` (not under `/static/`). Update the three `serviceWorker.register()` call sites to match. The wider scope is then allowed because the script itself lives at the root of that scope.
Option B: add Service-Worker-Allowed header
Serve `/beatify/static/sw.js` with the response header `Service-Worker-Allowed: /beatify/`. Keeps the file location unchanged; only the HTTP response changes. Requires the HA backend view serving static files to set this header for the `sw.js` path specifically.
Spotted during the #772 wizard UX live-test — unrelated, pre-existing.