fix(sse): start credential-health sweep at boot so stale web sessions recover (#7689)

The credential-health scheduler (src/lib/credentialHealth/scheduler.ts) auto-inits on
import, but nothing imported it at startup — only the on-demand credentialGate
(open-sse/services/credentialGate.ts) does, lazily on the first gated request. So the
boot-time sweep never ran, and web-session connections whose cookies expired overnight
stayed red/unavailable until a real request re-tripped the failure (the "*-web providers
go red on restart" complaint).

Wire initCredentialHealthCheck() into src/instrumentation-node.ts (the real Next.js
instrumentation startup) right after the runtime-settings restore, in its own try/catch
with a [STARTUP] log line. Idempotent and self-disabling via
OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK; cadence tunable via
CREDENTIAL_HEALTH_CHECK_INTERVAL.

The wiring MUST live in instrumentation-node.ts, NOT the unused src/server-init.ts —
the latter never runs in production, which is why the earlier attempt (closed PR #7432)
was a no-op.

Test: tests/unit/credential-health-boot-wiring.test.ts asserts the boot wiring is present
in instrumentation-node.ts and absent from the dead server-init.ts.

Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
This commit is contained in:
danscMax
2026-07-19 10:20:28 +03:00
committed by GitHub
parent 313cbefda4
commit fbbc695efa
2 changed files with 61 additions and 0 deletions

View File

@@ -379,6 +379,22 @@ export async function registerNodejs(): Promise<void> {
console.warn("[STARTUP] Could not restore runtime settings:", msg);
}
// Proactively start the credential-health sweep at boot so stale web-session
// connections (cookies that expired overnight) get re-probed and recovered on
// startup — instead of staying red until the first real request lazily imports
// the on-demand credentialGate. Idempotent; self-disables via
// OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK and its cadence is tunable via
// CREDENTIAL_HEALTH_CHECK_INTERVAL. NOTE: this MUST live here (the real Next.js
// instrumentation startup), NOT in the unused src/server-init.ts.
try {
const { initCredentialHealthCheck } = await import("@/lib/credentialHealth/scheduler");
initCredentialHealthCheck();
console.log("[STARTUP] Credential health scheduler started");
} catch (err: unknown) {
const msg = err instanceof Error ? err.message : String(err);
console.warn("[STARTUP] Could not start credential health scheduler:", msg);
}
try {
const { initAuditLog, cleanupExpiredLogs } = await import("@/lib/compliance/index");
initAuditLog();

View File

@@ -0,0 +1,45 @@
import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync, existsSync } from "node:fs";
import { fileURLToPath } from "node:url";
// The credential-health sweep re-probes web-session connections and recovers ones
// whose cookies expired (the "*-web providers go red on restart" bug). scheduler.ts
// only auto-inits when something imports it; nothing did at boot, so the sweep never
// ran proactively at startup. This guards that the wiring lives in the REAL startup
// (src/instrumentation-node.ts) and NOT in the unused src/server-init.ts — the exact
// mistake that made the earlier attempt (closed PR #7432) a no-op.
const read = (rel: string) =>
readFileSync(fileURLToPath(new URL(rel, import.meta.url)), "utf8");
const instrumentation = read("../../src/instrumentation-node.ts");
test("credential health scheduler is started from the real Next.js instrumentation startup", () => {
assert.match(
instrumentation,
/import\(["']@\/lib\/credentialHealth\/scheduler["']\)/,
"instrumentation-node.ts must import the scheduler at boot"
);
assert.match(
instrumentation,
/initCredentialHealthCheck\(\)/,
"instrumentation-node.ts must call initCredentialHealthCheck() at boot"
);
assert.match(
instrumentation,
/\[STARTUP\] Credential health scheduler started/,
"a [STARTUP] log line proves the boot wiring ran (grep-able in app.log)"
);
});
test("the wiring is NOT placed in the dead src/server-init.ts (the #7432 no-op)", () => {
const url = new URL("../../src/server-init.ts", import.meta.url);
const p = fileURLToPath(url);
if (!existsSync(p)) return; // file removed upstream → nothing to guard
assert.doesNotMatch(
readFileSync(p, "utf8"),
/initCredentialHealthCheck/,
"server-init.ts is unused in production; wiring there never runs"
);
});