feat(housekeeping): correlate command audit evidence

This commit is contained in:
Simo committed 2026-08-26 21:56:51 +02:00
1 parent 7c93d3e766
commit 89dec9da05
4 files changed
+226 -4

No files matched your search

@@ -0,0 +1,99 @@
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,
);
});
});
@@ -0,0 +1,44 @@
import type {
AuditEntry,
HousekeepingAuditTransaction,
HousekeepingAuditWriter,
} from "@/lib/services/audit";
type AuditOutcome = Exclude<NonNullable<AuditEntry["outcome"]>, "intent">;
export async function writeIntent(
writer: HousekeepingAuditWriter,
entry: AuditEntry,
transaction?: HousekeepingAuditTransaction,
): Promise<void> {
await writer.write({ ...entry, outcome: "intent" }, transaction);
}
export async function writeOutcome(
writer: HousekeepingAuditWriter,
entry: AuditEntry,
outcome: AuditOutcome,
transaction?: HousekeepingAuditTransaction,
): Promise<void> {
await writer.write({ ...entry, outcome }, transaction);
}
export async function runWithAuditIntent<T>(
writer: HousekeepingAuditWriter,
entry: AuditEntry,
operation: () => Promise<T>,
transaction?: HousekeepingAuditTransaction,
): Promise<T> {
await writeIntent(writer, entry, transaction);
let result: T;
try {
result = await operation();
} catch (error) {
await writeOutcome(writer, entry, "failure", transaction);
throw error;
}
await writeOutcome(writer, entry, "success", transaction);
return result;
}