screentinker/server
ScreenTinker 866e35a2b2 Clear a device's OTA rate state when it proves its identity
The update check is deliberately unauthenticated — every client version has to be
able to ask, including old ones that never learned to send a token — and it keys the
rate breaker on the caller-supplied device_id. Keying on IP is not available either:
the fleet SNATs behind one address, so per-IP would collapse a whole site into a
single bucket.

The result was that the bucket belonged to whoever cited the id rather than to the
device that owns it. A handful of requests naming a panel's UUID left that panel in
rate-backoff, un-updatable for up to half an hour at a time and renewable
indefinitely, while every other device stayed healthy.

Rather than adding auth (which would strand old clients) the state is now
self-healing: when a device registers on the /device socket with a valid device_token
its bucket is cleared. Noise is still possible, but it now lasts until the panel's
next genuine reconnect instead of as long as someone keeps poking.

This is not an escape hatch from the breaker's real job. A device stuck in an update
loop is re-registering legitimately, and clearing its rate state on each genuine
reconnect is what a healthy device looks like; the loop protection that matters is
the download guard. The version-keyed bucket that covers old clients sending only
?version= is a separate namespace and is deliberately not reachable this way.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 22:28:47 -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 feat(auth): self-service password reset 2026-07-27 11:19:39 -05:00
lib Clear a device's OTA rate state when it proves its identity 2026-07-27 22:28:47 -05:00
middleware Merge branch 'fix/recovery-grants' into release/auth-campaign 2026-07-26 16:22:59 -05:00
player fix(widgets): honest webpage-widget note — blocked sites don't work on device (#230) 2026-07-24 19:17:00 -05:00
routes Scope device serialization to what each endpoint actually needs 2026-07-27 20:40:40 -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 feat(auth): self-service password reset 2026-07-27 11:19:39 -05:00
test Clear a device's OTA rate state when it proves its identity 2026-07-27 22:28:47 -05:00
ws Clear a device's OTA rate state when it proves its identity 2026-07-27 22:28:47 -05:00
.gitignore feat(email): Microsoft Graph send + alert spam protection + preferences UI 2026-05-12 18:16:40 -05:00
config.js feat(email): SMTP transport as an alternative to Microsoft Graph [#173] (#179) 2026-07-13 15:56:22 -05:00
package-lock.json chore(release): v1.9.19 2026-07-27 21:18:47 -05:00
package.json chore(release): v1.9.19 2026-07-27 21:18:47 -05:00
server.js Merge branch 'feat/self-service-password-reset' 2026-07-27 11:21:36 -05:00
version.js chore(version): single-source VERSION, env-configurable data paths, bump tooling 2026-06-10 12:56:03 -05:00