Harden the server and add a Links page

Security headers, cross-site write refusal, atomic JSON writes, admin backup download, /healthz and Docker health check, OnlyOffice requires a JWT secret, npm test, CI audit, arm64 hub image. New Links tab for personal bookmarks, saved with per-person settings.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-22 07:43:34 -04:00
1 parent b0d3aec811
commit 1f8c9493b7
16 files changed
+147 -25

No files matched your search

+2 -1
View File
@@ -3,6 +3,7 @@
// Everyone else enrols with a one-time invite code the admin creates; a signed-in person can also invite one of their own devices.
const crypto = require('crypto');
const fs = require('fs');
const atomicWrite = require('./atomic');
const path = require('path');
const {
generateRegistrationOptions, verifyRegistrationResponse,
@@ -13,7 +14,7 @@ const users = require('./users');
const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, 'data');
fs.mkdirSync(DATA_DIR, { recursive: true });
const readJson = (f, d) => { try { return JSON.parse(fs.readFileSync(path.join(DATA_DIR, f), 'utf8')); } catch { return d; } };
const writeJson = (f, v) => fs.writeFileSync(path.join(DATA_DIR, f), JSON.stringify(v, null, 2), { mode: 0o600 });
const writeJson = (f, v) => atomicWrite(path.join(DATA_DIR, f), JSON.stringify(v, null, 2), { mode: 0o600 });
// Signing secret for cookies: env wins, otherwise generated once and kept so sessions survive restarts.
let secret = process.env.COOKIE_SECRET;