Always revalidate the app's files, tell open pages when a newer version exists, and log why a session is refused
build-container / build (push) Successful in 1m58s

An open page kept running the old version after a deploy (the single page never reloads), so the new
People screens did not appear. Static files are now sent with no-cache + ETag (304 when unchanged), icons
are cached for a week, /api/config reports a build stamp, and the app shows "A new version is available -
Reload" when it comes back into view or every 10 minutes. The service worker cache name is bumped.

The server also logs, at most once a minute per reason, why it refused a session cookie (unknown account,
turned off, signed out everywhere, bad signature, expired) without printing the cookie.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-20 16:55:44 -04:00
1 parent 2d17ee9939
commit 12a1e50a0e
6 files changed
+57 -9

No files matched your search

+7
View File
@@ -49,6 +49,13 @@ const wait = ms => new Promise(r => setTimeout(r, ms));
const raw = await fetch(base + '/api/tasks', { method: 'POST', headers: { cookie, 'content-type': 'application/json' }, body: '{not json' }).then(async r => { await r.text(); return r; }).catch(() => ({ status: -1 }));
ok('malformed JSON gets a clean error, not a crash', raw.status !== 500 && raw.status !== -1 && alive, raw.status);
ok('signed-out requests are refused', await fetch(base + '/api/tasks/lists').then(r => r.status === 401).catch(() => false));
// browsers must always check for a new version of the app's files
const a1 = await fetch(base + '/app.js', { headers: { cookie } }); await a1.text(); const etag = a1.headers.get('etag');
ok('app files are sent with no-cache and an ETag, so a new version is never missed', /no-cache/.test(a1.headers.get('cache-control') || '') && !!etag, [a1.headers.get('cache-control'), etag]);
const a2 = await fetch(base + '/app.js', { headers: { cookie, 'if-none-match': etag } }); await a2.text();
ok('and an unchanged file is answered with a cheap 304', a2.status === 304, a2.status);
const i1 = await fetch(base + '/icons/icon-192.png'); await i1.arrayBuffer(); ok('icons are cached for a week', /max-age=604800/.test(i1.headers.get('cache-control') || ''), i1.headers.get('cache-control'));
const cfg = await (await fetch(base + '/api/config', { headers: { cookie } })).json(); ok('the server reports a build stamp so open pages can tell a newer version exists', /^[0-9a-f]{12}$/.test(cfg.build || ''), cfg.build);
ok('the server is still running after all of that', alive);
child.kill(); fs.rmSync(dir, { recursive: true, force: true });
if (failed) { console.log('\n--- server log ---\n' + log.split('\n').filter(l => /error|Error|not defined/.test(l)).slice(0, 12).join('\n')); }