import { describe, expect, it, vi } from "vitest"; import type { AuditEntry, HousekeepingAuditWriter } from "@/lib/services/audit"; import { runWithAuditIntent, writeIntent, writeOutcome, } from "./audit-envelope"; const auditEntry: AuditEntry = { userId: 7, action: "maintenance.run", target: "system", correlationId: "corr-command-7", domain: "system", reason: "Scheduled maintenance", }; function createWriter(): HousekeepingAuditWriter { return { write: vi.fn().mockResolvedValue(undefined) }; } describe("audit command envelope", () => { it("writes an intent with the original correlation evidence", async () => { const writer = createWriter(); await writeIntent(writer, auditEntry); expect(writer.write).toHaveBeenCalledWith( { ...auditEntry, outcome: "intent" }, undefined, ); }); it("writes denied and failure outcomes as durable evidence", async () => { const writer = createWriter(); await writeOutcome(writer, auditEntry, "denied"); await writeOutcome(writer, auditEntry, "failure"); expect(writer.write).toHaveBeenNthCalledWith( 1, { ...auditEntry, outcome: "denied" }, undefined, ); expect(writer.write).toHaveBeenNthCalledWith( 2, { ...auditEntry, outcome: "failure" }, undefined, ); }); it("blocks the operation when intent persistence fails", async () => { const writer: HousekeepingAuditWriter = { write: vi.fn().mockRejectedValue(new Error("audit unavailable")), }; const operation = vi.fn().mockResolvedValue("external operation result"); await expect( runWithAuditIntent(writer, auditEntry, operation), ).rejects.toThrow("audit unavailable"); expect(operation).not.toHaveBeenCalled(); }); it("writes a success outcome after the operation completes", async () => { const writer = createWriter(); await expect( runWithAuditIntent(writer, auditEntry, () => Promise.resolve("done")), ).resolves.toBe("done"); expect(writer.write).toHaveBeenNthCalledWith( 1, { ...auditEntry, outcome: "intent" }, undefined, ); expect(writer.write).toHaveBeenNthCalledWith( 2, { ...auditEntry, outcome: "success" }, undefined, ); }); it("writes a failure outcome before rethrowing an operation failure", async () => { const writer = createWriter(); await expect( runWithAuditIntent(writer, auditEntry, () => Promise.reject(new Error("operation failed")), ), ).rejects.toThrow("operation failed"); expect(writer.write).toHaveBeenNthCalledWith( 2, { ...auditEntry, outcome: "failure" }, undefined, ); }); it("preserves the original operation error when failure evidence rejects", async () => { const original = new Error("operation failed"); const auditFailure = new Error("audit failure"); const writer: HousekeepingAuditWriter = { write: vi .fn() .mockResolvedValueOnce(undefined) .mockRejectedValueOnce(auditFailure), }; await expect( runWithAuditIntent(writer, auditEntry, () => Promise.reject(original)), ).rejects.toBe(original); expect( (original as Error & { auditOutcomeError?: unknown }).auditOutcomeError, ).toBe(auditFailure); }); it("throws a completed-operation error when success evidence rejects", async () => { const auditFailure = new Error("audit failure"); const writer: HousekeepingAuditWriter = { write: vi .fn() .mockResolvedValueOnce(undefined) .mockRejectedValueOnce(auditFailure), }; await expect( runWithAuditIntent(writer, auditEntry, () => Promise.resolve("done")), ).rejects.toMatchObject({ operationCompleted: true, operationResult: "done", auditOutcomeError: auditFailure, }); }); it("preserves a frozen operation error when failure evidence rejects", async () => { const original = Object.freeze(new Error("operation failed")); const writer: HousekeepingAuditWriter = { write: vi .fn() .mockResolvedValueOnce(undefined) .mockRejectedValueOnce(new Error("audit failure")), }; await expect( runWithAuditIntent(writer, auditEntry, () => Promise.reject(original)), ).rejects.toBe(original); }); it("preserves a pathological rejection when failure evidence rejects", async () => { const { proxy, revoke } = Proxy.revocable( new Error("operation failed"), {}, ); revoke(); const writer: HousekeepingAuditWriter = { write: vi .fn() .mockResolvedValueOnce(undefined) .mockRejectedValueOnce(new Error("audit failure")), }; let rejected: unknown; try { await runWithAuditIntent(writer, auditEntry, () => Promise.reject(proxy)); } catch (error) { rejected = error; } expect(rejected === proxy).toBe(true); }); });