import assert from "node:assert/strict"; import { existsSync, readFileSync } from "node:fs"; import test from "node:test"; import { ADMIN_MFA_PROOF_TTL_MS, issueAdminMfaProof, resolveAdminMfaStatus, verifyAdminMfaProof, } from "../src/lib/admin/auth-policy.ts"; const now = 1_786_000_000_000; const context = { userId: "11111111-1111-4111-8111-111111111111", sessionId: "22222222-2222-4222-8222-222222222222", origin: "https://admin.staging.jyotisha.chat", }; const sessionToken = "better-auth-session-token-held-server-side"; const proofSecret = "admin-proof-secret-held-only-by-the-server"; test("MFA proof is server-signed, short-lived, and bound to the current user, session, origin, and session token", () => { const proof = issueAdminMfaProof(context, proofSecret, sessionToken, now); assert.equal(verifyAdminMfaProof(proof, context, proofSecret, sessionToken, now + 1_000), true); assert.equal(verifyAdminMfaProof(proof, { ...context, userId: "other-user" }, proofSecret, sessionToken, now + 1_000), false); assert.equal(verifyAdminMfaProof(proof, { ...context, sessionId: "other-session" }, proofSecret, sessionToken, now + 1_000), false); assert.equal(verifyAdminMfaProof(proof, { ...context, origin: "https://evil.example" }, proofSecret, sessionToken, now + 1_000), false); assert.equal(verifyAdminMfaProof(proof, context, "wrong-server-secret-that-is-long-enough", sessionToken, now + 1_000), false); assert.equal(verifyAdminMfaProof(proof, context, proofSecret, "rotated-session-token", now + 1_000), false); assert.equal(verifyAdminMfaProof(proof, context, proofSecret, sessionToken, now + ADMIN_MFA_PROOF_TTL_MS), false); }); test("MFA status only reports account-level enrollment and current-session verification", () => { assert.deepEqual(resolveAdminMfaStatus(false, false, false), { required: false, enrolled: false, verified: false, }); assert.deepEqual(resolveAdminMfaStatus(true, false, false), { required: true, enrolled: false, verified: false, }); assert.deepEqual(resolveAdminMfaStatus(true, true, false), { required: true, enrolled: true, verified: false, }); assert.deepEqual(resolveAdminMfaStatus(true, true, true), { required: true, enrolled: true, verified: true, }); }); test("MFA API keeps native Better Auth enrollment, recovery, rotation, and proof boundaries", () => { const route = readFileSync(new URL("../src/app/api/admin/mfa/route.ts", import.meta.url), "utf8"); const authFactory = readFileSync(new URL("../src/modules/identity/auth-factory.ts", import.meta.url), "utf8"); const migration = readFileSync(new URL("../db/migrations/20260806070000_admin_mfa.sql", import.meta.url), "utf8"); assert.match(authFactory, /twoFactor\(/); assert.doesNotMatch(authFactory, /skipVerificationOnEnable\s*:\s*true/); assert.match(route, /enableTwoFactor/); assert.match(route, /verifyTOTP/); assert.match(route, /verifyBackupCode/); assert.match(route, /generateBackupCodes/); assert.match(route, /disableTwoFactor/); assert.match(route, /headersAfterNativeResponse/); assert.match(route, /copyNativeCookies\(nativeResponse, response\)/); assert.match(route, /requireVerifiedMfa\(request, session\)/); assert.match(route, /ADMIN_MFA_PROOF_COOKIE/); assert.doesNotMatch(route, /HIGH_RISK_ADMIN_PROOF_COOKIE/); assert.match(route, /adminProofSigningSecret\(\)/); assert.doesNotMatch(route, /console\.|logger|log.*(?:seed|secret|backup|totp)|(?:seed|secret|backup|totp).*log/i); assert.match(migration, /revoke all on table identity\.two_factors[\s\S]*admin_runtime/); assert.match(migration, /grant select, insert, update, delete on table identity\.two_factors[\s\S]*identity_runtime/); }); test("business operation confirmation UI is removed while account MFA remains separate", () => { const http = readFileSync(new URL("../src/lib/admin/http.ts", import.meta.url), "utf8"); assert.equal(existsSync(new URL("../src/components/admin/confirm-action-modal.tsx", import.meta.url)), false); assert.match(http, /requireAdminMutation/); assert.doesNotMatch(http, /requireHighRiskAdminMutation|verifyHighRiskAdminProof/); });