feat(12-01): generate-secrets helper — SETUP-03 / D-05
- Add scripts/generate-secrets.mjs: plain ESM script that prints SESSION_SECRET + APP_PASSWORD_ENCRYPTION_KEY (32 random bytes each, hex-encoded) and VAPID_PUBLIC_KEY + VAPID_PRIVATE_KEY from web-push generateVAPIDKeys() — all to stdout only (SC-3: nothing written to disk) - Resolve web-push as CommonJS default import from apps/api/node_modules (avoids a root-level dependency; named-export ESM form not supported) - Wire root package.json "generate-secrets" script: node scripts/generate-secrets.mjs
This commit is contained in:
+2
-1
@@ -13,7 +13,8 @@
|
||||
"typecheck": "pnpm -r typecheck",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"md:lint": "markdownlint-cli2"
|
||||
"md:lint": "markdownlint-cli2",
|
||||
"generate-secrets": "node scripts/generate-secrets.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "9.39.4",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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}
|
||||
`);
|
||||
Reference in New Issue
Block a user