// M5 snapshot-key loud-fail guard (2026-06-25) — RECOMMENDED tier in secret-boot-guard.
//
// AUDIT_SNAPSHOT_SIGNING_KEY gates the M5 audit-chain forgery countermeasure, which is FAIL-SAFE:
// if unset, the platform still boots and runs, the countermeasure is just inactive. That fail-safe
// is correct (so it is NOT in the fatal REQUIRED tier) — but it means M5 can ship SILENTLY OFF. The
// RECOMMENDED tier converts that quiet failure into a loud one: a consequence-carrying boot warning,
// never fatal. This proves BOTH halves of the contract:
//   - unset  -> the key is flagged AND a warning naming the inactive protection fires, boot CONTINUES;
//   - set    -> silence (no warning names the key) so the guard never becomes ignorable noise.
//
// Set SECRET_GUARD_DEV_MODE=warn BEFORE importing the guard so its top-level self-audit of the
// (mostly-unset-in-test) REQUIRED secrets warns instead of throwing. Process-isolated per file.

process.env.SECRET_GUARD_DEV_MODE = "warn";

import { test, describe, before, beforeEach, afterEach } from "node:test";
import assert from "node:assert/strict";

const KEY = "AUDIT_SNAPSHOT_SIGNING_KEY";
const origWarn = console.warn;
let warnings: string[] = [];
let enforceSecretBootGuard: () => { recommendedUnset: string[] };

describe("secret-boot-guard RECOMMENDED tier (M5 snapshot-key loud-fail guard)", () => {
  before(async () => {
    const mod = await import("../server/lib/secret-boot-guard.js");
    enforceSecretBootGuard = mod.enforceSecretBootGuard as any;
  });
  beforeEach(() => { warnings = []; console.warn = (...a: unknown[]) => { warnings.push(a.join(" ")); }; });
  afterEach(() => { console.warn = origWarn; });

  test("fires when unset: key flagged + consequence-carrying warning emitted, and boot is NON-FATAL", () => {
    delete process.env[KEY];
    const result = enforceSecretBootGuard(); // must RETURN, not throw — non-fatal
    assert.ok(result.recommendedUnset.includes(KEY), "an unset key must appear in recommendedUnset");
    const w = warnings.join("\n");
    assert.match(w, new RegExp(KEY), "the warning must name the unset key");
    assert.match(w, /INACTIVE|M5|forgery/i, "the warning must carry the consequence (which protection is off), not just the fact");
  });

  test("silent when set: not flagged and no warning names the key (no cry-wolf)", () => {
    process.env[KEY] = "x".repeat(32);
    const result = enforceSecretBootGuard();
    assert.ok(!result.recommendedUnset.includes(KEY), "a properly-set key must NOT appear in recommendedUnset");
    assert.ok(!warnings.join("\n").includes(KEY), "no warning should name a properly-set key — the guard must stay quiet when satisfied");
    delete process.env[KEY];
  });
});
