/** * Runs the encryption key check once per process at boot and records the * verdict for the request path (`./key-mismatch-state.ts`). * * Returns true when the process must refuse: the caller then starts neither * the queue producer nor the worker, because a process holding the wrong key * must never write. The process keeps running so `/api/health` and the * explanation page can say why; a crash loop would hide the reason in a log * that the people most likely to hit this (a NAS app catalog install) never * open. */ import { checkEncryptionKeyCanaries, keyMismatchLogBlock, type CanaryClient, type InconclusiveReason, } from "@/lib/crypto/canary"; import { setKeyMismatchState } from "./key-mismatch-state"; const INCONCLUSIVE_EXPLANATION: Record = { "single-value": "the only stored value found under that id did not open.", mixed: "the oldest stored values under that id do not open, newer ones do. " + "That is what a wrong key that served for a while leaves behind; check " + "that this is the key the database was first written with.", unsampled: "the values stored under that id are too large to probe at start-up.", incomplete: "the probe of the stored data did not finish in time or a table could " + "not be read.", }; export async function runBootKeyCheck(client: CanaryClient): Promise { const outcome = await checkEncryptionKeyCanaries(client); if (outcome.state === "mismatch") { setKeyMismatchState({ keyIds: outcome.keyIds, detectedAt: new Date().toISOString(), }); console.error(keyMismatchLogBlock(outcome.keyIds)); return true; } setKeyMismatchState(null); if (outcome.state === "error") { // The check could not run. The loaders and the database each have their // own loud signal for that; serving stays on. console.warn( `[boot] Encryption key check skipped: ${outcome.message.slice(0, 300)}`, ); } else { for (const { keyId, reason } of outcome.inconclusive) { console.warn( `[boot] Encryption key check inconclusive for key id ${keyId}: ` + `${INCONCLUSIVE_EXPLANATION[reason]} Serving; no key recorded; ` + "the check runs again at the next start.", ); } if (outcome.written.length > 0) { console.info( `[boot] Encryption key check: recorded key id(s) ${outcome.written.join(", ")}`, ); } } return false; }