screentinker/server
screentinker 7c6cfeecfd
Stop database snapshots losing their permissions (#289)
copyFileBytes replaced fs.copyFileSync because copyFileSync does not merely
copy bytes - it fchmods the destination to match the source, and exFAT has no
permission bits, so the pre-migration snapshot failed with EPERM on a player.

The replacement dropped the chmod entirely, which fixed that and introduced a
worse problem everywhere else: the copy landed at the default 0666 & ~umask.
Measured on ext4, a 0600 database file copied to a 0664 snapshot - the whole
database readable by group and other, on every install, not just on a player.

Removing a permission operation to fix a permission error is not a fix.

The mode is now applied as a separate, failure-tolerant step after the bytes
are written. That is the actual difference from copyFileSync: there the chmod
is inseparable from the copy, so a filesystem without modes fails the whole
operation; here the data is already safe and a refusal simply means there were
never permissions to carry across.

Two tests: the source mode survives the copy (fails on the current main), and
a filesystem that refuses fchmod still gets its bytes.


Claude-Session: https://claude.ai/code/session_014kfhrUPit5MCqxeTQyqr56

Co-authored-by: Dan Walters <dan.walters@bytetinker.net>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:24:39 -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 Run the ScreenTinker server on the player it serves (#288) 2026-08-18 15:16:09 -05:00
lib Stop database snapshots losing their permissions (#289) 2026-08-18 15:24:39 -05:00
middleware Merge branch 'fix/recovery-grants' into release/auth-campaign 2026-07-26 16:22:59 -05:00
player Run the ScreenTinker server on the player it serves (#288) 2026-08-18 15:16:09 -05:00
routes Run the ScreenTinker server on the player it serves (#288) 2026-08-18 15:16:09 -05:00
scripts Drop sharp: pure-JS image ops on a worker thread (#263) 2026-08-13 11:40:13 -05:00
services #240: stop the morning wave buying itself a blocking checkpoint 2026-08-06 20:22:21 -05:00
test Stop database snapshots losing their permissions (#289) 2026-08-18 15:24:39 -05:00
ws Run the ScreenTinker server on the player it serves (#288) 2026-08-18 15:16:09 -05:00
.gitignore feat(email): Microsoft Graph send + alert spam protection + preferences UI 2026-05-12 18:16:40 -05:00
config.js SSO: prove domain ownership by DNS, and fix what the second review found 2026-08-10 19:23:46 -05:00
node_modules Merge Japanese localisation (#283) (#285) 2026-08-18 09:23:28 -05:00
package-lock.json Stop shipping a licence we would rather not have to explain (#281) 2026-08-14 14:50:18 -05:00
package.json Stop shipping a licence we would rather not have to explain (#281) 2026-08-14 14:50:18 -05:00
server.js Run the ScreenTinker server on the player it serves (#288) 2026-08-18 15:16:09 -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