screentinker/server
ScreenTinker 0a888910dc Stop claiming offline cache on a runtime that refuses to run a service worker
Found on alpha after deploying rc4, by comparing what a device advertised
against what it actually requested.

A real BrightSign XT245 has navigator.serviceWorker, passes an
`'serviceWorker' in navigator` check, and then never even fetches sw.js — its
widget runtime refuses the registration. It was declaring offline.cache to the
fleet while unable to cache a single byte, which is precisely the lie the
capability model exists to prevent. The claim is now made on a worker that is
actually IN CONTROL, and a refused registration sets a flag so the negative
sticks on a runtime where it will never succeed.

That failure previously went to console.warn, on a display nobody has a console
for, so a panel that could cache nothing looked identical to one that could. It
now reports app_error/sw_unavailable — as an allow-listed event type, since an
unknown one is dropped by the server and would have been just as invisible.

The cost is that the first load under-reports, before the worker claims the
page. That is the right direction to be wrong in, and it self-corrects: the next
register sends the true set.

Also corrects docs/player-parity.md, which claimed BrightSign simply inherits
the web player's service worker. The failing unit runs BSN's Supervisor rather
than our brightsign/autorun.brs, and Supervisor's widget has no storage_path —
the setting our own host script does configure and the precondition for a widget
having persistent storage. So this is likely a widget config issue rather than a
platform limit, but it is UNVERIFIED on hardware and the doc now says so.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uaeo9MvzKoyXuN6ZsbhtkL
2026-08-05 19:34:52 -05:00
..
config fix(logging): gate CF-Connecting-IP on a Cloudflare peer, not any trusted proxy 2026-07-26 10:23:04 -05:00
db Offline media on every player, and a revision so the cache can still be updated 2026-08-05 15:27:36 -05:00
lib Offline media on every player, and a revision so the cache can still be updated 2026-08-05 15:27:36 -05:00
middleware Merge branch 'fix/recovery-grants' into release/auth-campaign 2026-07-26 16:22:59 -05:00
player Stop claiming offline cache on a runtime that refuses to run a service worker 2026-08-05 19:34:52 -05:00
routes Offline media on every player, and a revision so the cache can still be updated 2026-08-05 15:27:36 -05:00
scripts fix(content+android): rotation-aware media — portrait upright on dashboard AND player (#170) (#172) 2026-07-12 22:05:11 -05:00
services Show only the controls a display can actually honour 2026-08-05 14:24:52 -05:00
test Stop claiming offline cache on a runtime that refuses to run a service worker 2026-08-05 19:34:52 -05:00
ws Offline media on every player, and a revision so the cache can still be updated 2026-08-05 15:27:36 -05:00
.gitignore feat(email): Microsoft Graph send + alert spam protection + preferences UI 2026-05-12 18:16:40 -05:00
config.js Add an operator override for self-update on MDM-managed panels 2026-07-28 23:07:30 -05:00
package-lock.json chore(release): v1.9.29-rc4 2026-08-05 16:32:56 -05:00
package.json chore(release): v1.9.29-rc4 2026-08-05 16:32:56 -05:00
server.js Fix the worker scope that made web offline playback silently inert, and prune superseded assets 2026-08-05 16:30:12 -05:00
smoke-ui.js Keep the smoke test out of npm test, and update the lockfile 2026-07-28 20:34:34 -05:00
version.js chore(version): single-source VERSION, env-configurable data paths, bump tooling 2026-06-10 12:56:03 -05:00