Protect live race results and shrink cross-browser staleness

Investigated whether two admin browsers open at once can overwrite each
other's changes, per an explicit request to report the risk before
making bigger changes. Found that POST /api/state always replaces the
entire stored document with a client's in-memory copy, with no version
check and no per-field merge - and a browser only ever pushes, never
re-fetching server state after page load except on the Overlay view.
An idle browser's next save, even an unrelated edit, could silently
revert another browser's more recent changes, worst case a live race's
in-progress results.

Two scoped fixes instead of the bigger optimistic-locking rework (that
needs real UX decisions about conflicting saves, deferred separately):

1. server.js now remembers which session results were just written by
   a real live decoder passing (/api/passings) and protects that key
   for 15 seconds against being reverted by a stale full-state save,
   while still applying the rest of that save normally.
2. Every non-Overlay view now quietly refreshes its data in the
   background every 15 seconds (skipped while a local edit is
   pending), without ever calling renderView(), so it can never
   discard an open, unsaved edit form - shrinking how stale a
   browser's next save can be from hours to seconds.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
larssand
2026-09-09 12:56:58 +02:00
parent be9a2de31a
commit 3373f8dddd
8 changed files with 160 additions and 6 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "rc-racecore",
"version": "1.4.2",
"version": "1.4.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "rc-racecore",
"version": "1.4.2",
"version": "1.4.3",
"hasInstallScript": true,
"dependencies": {
"better-sqlite3": "^12.11.1",