/** * generate-secrets.mjs — FamilySync bootstrap secret generator (SETUP-03 / D-05). * * Generates all secrets required for a first-time FamilySync deployment: * - SESSION_SECRET (AES-256-GCM session signing key, 32 random bytes / 64 hex chars) * - APP_PASSWORD_ENCRYPTION_KEY (AES-256-GCM encryption key, 32 random bytes / 64 hex chars) * - VAPID_PUBLIC_KEY (EC P-256 public key, base64url, ~87 chars) * - VAPID_PRIVATE_KEY (EC P-256 private scalar, base64url, ~43 chars) * * Security contract (SC-3): * - Prints to stdout ONLY — never writes any file, never touches the DB, never calls any API. * - The operator is responsible for pasting the output into docker-compose.yml and keeping it safe. * - These values CANNOT be recovered if lost (VAPID key rotation invalidates push subscriptions). * * Usage: * node scripts/generate-secrets.mjs * # or via pnpm script: * pnpm generate-secrets */ // web-push is a CommonJS module — import via default then destructure. // Resolve from apps/api/node_modules to avoid a root-level dependency. import webpush from '../apps/api/node_modules/web-push/src/index.js'; const { generateVAPIDKeys } = webpush; import { randomBytes } from 'node:crypto'; const sessionSecret = randomBytes(32).toString('hex'); const encKey = randomBytes(32).toString('hex'); const vapid = generateVAPIDKeys(); console.log(`# FamilySync Bootstrap Secrets — generated ${new Date().toISOString()} # Paste into your docker-compose.yml environment block under the 'api' service. # Keep this output safe — these values cannot be recovered if lost. # VAPID key rotation will invalidate all existing push subscriptions. SESSION_SECRET=${sessionSecret} APP_PASSWORD_ENCRYPTION_KEY=${encKey} VAPID_PUBLIC_KEY=${vapid.publicKey} VAPID_PRIVATE_KEY=${vapid.privateKey} `);