mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-13 22:03:13 -06:00
A fresh unclaimed player that reconnects (same fingerprint) INSIDE the server's ~5s deferred-offline grace hit a false 'active on another connection' reclaim reject, then collided on UNIQUE(devices.pairing_code) on the fall-through INSERT and wedged unclaimed with no content. Real trial customer (web player) hit it. server/ws/deviceSocket.js: - Fix A (guard): gate the liveConn reclaim reject on !inDeferredOffline (pendingOfflines.has(id)). A device mid-deferred-offline is a zombie, not live, so a same-fingerprint reconnect is a legit reconnect, not a hijack. A genuinely live socket (never disconnected -> no pending-offline) still rejects a cloned fingerprint -> anti-hijack boundary preserved (documented). - Fix B (idempotency): when the unclaimed old row holds the SAME pairing_code the reconnecting player presents, ADOPT/refresh it (mirror the claimed-reclaim path, but no device:paired) instead of INSERT-colliding. Differing-code case unchanged. - deferOffline is NOT shrunk (it exists to prevent transient-blip flapping). server/player/index.html: - The cold-boot flap source: an unfiltered pageshow handler ran verifyLivenessSoon() on every load, opening+registering a socket early, which the boot connect() then tore down and rebuilt (connect->register->disconnect->reconnect). Guard it with ev.persisted (mirror the pagehide guard) so only real bfcache restores trigger it. server/test/pairing-race.test.js: - Forces the race against the real socket server (log-gated reconnect inside the deferred-offline window), asserts no false reject / no UNIQUE collision / single claimable row; + a hijack case asserting a cloned fingerprint on a genuinely-live display is still rejected. Web- and android-shaped fingerprints. Fails 2/4 on pre-fix code, 4/4 with the fix. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| dashboardSocket.js | ||
| deviceSocket.js | ||
| index.js | ||