import { mkdtemp, mkdir, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { describe, expect, it } from "vitest"; import { failureCount, gates, mfaScopeMfaScopeInventoryPatterns, mfaScopeMfaScopeInventoryScanRoots, renderReport, reportPath, runMfaScopeMfaScopeInventory, } from "./verify-mfa-scope-baseline.mjs"; const forbiddenCommandPattern = /playwright|cypress|browser|e2e/i; describe("MFA Scope baseline runner configuration", () => { it("defines the required non-E2E gates and report path", () => { expect(reportPath).toMatch(/\.tc\/baselines\/mfa-scope\/baseline-health\.md$/); expect(gates.map((gate) => gate.id)).toEqual(["typecheck", "lint", "ci-baseline", "mfaScope-mfa-scope-inventory"]); expect(gates.some((gate) => [gate.command, ...(gate.args ?? [])].some((arg) => forbiddenCommandPattern.test(arg)))).toBe(false); expect(mfaScopeMfaScopeInventoryScanRoots).toEqual(["apps/web/app", "prisma/schema", "docs/security", "scripts", "package.json"]); }); it("defines MFA scope inventory term buckets", () => { expect(mfaScopeMfaScopeInventoryPatterns.map(({ id }) => id)).toEqual(["mfa", "totp", "recovery-code", "step-up", "admin-enforcement", "auth-session", "security-doc"]); }); }); describe("MFA Scope baseline runner failure counting", () => { it("returns zero for clean exits and read-only inventory gates", () => { expect(failureCount("typecheck", "warning only", "", 0)).toBe(0); expect(failureCount("mfaScope-mfa-scope-inventory", "total matches: 12", "", 1)).toBe(0); }); it("counts failed shell diagnostics conservatively", () => { expect(failureCount("typecheck", "src/a.ts(1,1): error TS2307: Cannot find module", "", 1)).toBe(1); expect(failureCount("lint", "✖ 4 problems (3 errors, 1 warning)", "", 1)).toBe(3); expect(failureCount("ci-baseline", "Summary: 4 passed, 0 observed, 2 failed", "", 1)).toBe(2); expect(failureCount("ci-baseline", "CI baseline crashed", "", 1)).toBe(1); }); }); describe("MFA Scope MFA scope inventory scan", () => { it("recognizes required MFA inventory roots and security/auth-related matches in the repository", async () => { const inventory = await runMfaScopeMfaScopeInventory(process.cwd()); const allMatches = inventory.matches.join("\n"); expect(inventory.roots).toEqual(expect.arrayContaining(["apps/web/app", "prisma/schema", "docs/security"])); expect(inventory.counts.mfa + inventory.counts.totp + inventory.counts["auth-session"] + inventory.counts["security-doc"]).toBeGreaterThan(0); expect(allMatches).toMatch(/app\//); }); it("scans configured roots, counts MFA terms, and ignores dependency/generated/TC paths", async () => { const root = await mkdtemp(join(tmpdir(), "mfaScope-baseline-inventory-")); await mkdir(join(root, "apps/web/app"), { recursive: true }); await mkdir(join(root, "prisma", "schema"), { recursive: true }); await mkdir(join(root, "docs", "security"), { recursive: true }); await mkdir(join(root, "scripts", "node_modules", "ignored"), { recursive: true }); await mkdir(join(root, "scripts", ".tc"), { recursive: true }); await mkdir(join(root, "scripts", "generated"), { recursive: true }); await writeFile(join(root, "apps/web/app", "auth.ts"), "MFA TOTP recovery code step-up admin enforcement auth session security doc", "utf8"); await writeFile(join(root, "prisma", "schema", "auth.prisma"), "remembered device trusted device mandatory MFA", "utf8"); await writeFile(join(root, "docs", "security", "mfa.md"), "Multi-factor authenticator app backup code reauthentication security checklist", "utf8"); await writeFile(join(root, "scripts", "audit.mjs"), "Require MFA and session token checks", "utf8"); await writeFile(join(root, "package.json"), "{\"description\":\"two-factor security policy\"}", "utf8"); await writeFile(join(root, "scripts", "node_modules", "ignored", "ignored.mjs"), "MFA TOTP recovery code", "utf8"); await writeFile(join(root, "scripts", ".tc", "ignored.mjs"), "MFA TOTP recovery code", "utf8"); await writeFile(join(root, "scripts", "generated", "ignored.mjs"), "MFA TOTP recovery code", "utf8"); const inventory = await runMfaScopeMfaScopeInventory(root); const allMatches = inventory.matches.join("\n"); expect(inventory.roots).toEqual(["apps/web/app", "prisma/schema", "docs/security", "scripts", "package.json"]); expect(inventory.missingRoots).toEqual([]); expect(inventory.filesScanned).toBe(5); expect(inventory.counts).toMatchObject({ mfa: 5, totp: 2, "recovery-code": 2, "step-up": 2, "admin-enforcement": 3, "auth-session": 4, "security-doc": 3, }); expect(inventory.totalMatches).toBe(21); expect(allMatches).toContain("apps/web/app/auth.ts"); expect(allMatches).not.toContain("node_modules/ignored/ignored.mjs"); expect(allMatches).not.toContain(".tc/ignored.mjs"); expect(allMatches).not.toContain("generated/ignored.mjs"); }); it("records absent MFA roots without failing the read-only inventory gate", async () => { const root = await mkdtemp(join(tmpdir(), "mfaScope-baseline-missing-")); const inventory = await runMfaScopeMfaScopeInventory(root); expect(inventory.roots).toEqual([]); expect(inventory.missingRoots).toEqual(mfaScopeMfaScopeInventoryScanRoots); expect(inventory.filesScanned).toBe(0); expect(inventory.totalMatches).toBe(0); }); }); describe("MFA Scope report rendering", () => { it("renders gate metadata, fingerprints, and inventory counts", () => { const report = renderReport([ { id: "typecheck", command: "pnpm run typecheck", exitCode: 2, durationMs: 1500, failureCount: 7, fingerprint: { hash: "abc123def456", excerpt: "error TS2322" } }, { id: "mfaScope-mfa-scope-inventory", command: "read-only MFA Scope MFA scope inventory", exitCode: 0, durationMs: 42, failureCount: 0, inventory: { roots: ["apps/web/app"], missingRoots: ["docs/security"], filesScanned: 1, counts: { mfa: 1, totp: 2 }, totalMatches: 3, matches: [], }, fingerprint: { hash: "fed456abc123", excerpt: "mfa: 1" }, }, ]); expect(report).toContain("# MFA Scope Baseline Health"); expect(report).toContain("non-E2E baseline gates for MFA Scope baseline"); expect(report).toContain("MFA/TOTP/recovery-code/step-up/admin-enforcement/auth-session/security-doc references"); expect(report).toContain("## typecheck"); expect(report).toContain("## mfaScope-mfa-scope-inventory"); expect(report).toContain("- Exitcode: 2"); expect(report).toContain("- Failure Count: 7"); expect(report).toContain("- Output Fingerprint: abc123def456"); expect(report).toContain("- Inventory Roots: apps/web/app"); expect(report).toContain("- Missing Roots Skipped: docs/security"); expect(report).toContain(" - mfa: 1"); expect(report).toContain("- Total Inventory Matches: 3"); }); });