import { describe, expect, it } from "vitest"; import { z } from "zod"; import type { AuditEntry, HousekeepingAuditWriter } from "@/lib/services/audit"; import type { HousekeepingCapabilityContext } from "../contracts"; import { anyCapability, fail, ok } from "../contracts"; import { dispatchHousekeepingCommand } from "./dispatcher"; import { type HousekeepingCommand, registerHousekeepingCommand, } from "./registry"; const actor = { id: 42, username: "operator", rank: 9 }; function capabilityContext( granted: readonly string[] = ["admin.settings.edit"], ): HousekeepingCapabilityContext { const permissions = new Set(granted); return { actor, isSuperAdmin: false, has: (slug) => permissions.has(slug), hasAny: (...slugs) => slugs.some((slug) => permissions.has(slug)), hasAll: (...slugs) => slugs.every((slug) => permissions.has(slug)), }; } function auditRecorder(events: string[] = []): { entries: AuditEntry[]; writer: HousekeepingAuditWriter; } { const entries: AuditEntry[] = []; return { entries, writer: { write: async (entry) => { entries.push({ ...entry }); events.push(`audit:${entry.outcome}`); }, }, }; } function dependencies(options?: { context?: HousekeepingCapabilityContext; ipAddress?: string; audit?: HousekeepingAuditWriter; rateLimit?: ( key: string, attempts: number, windowMs: number, ) => Promise; }) { return { context: options?.context ?? capabilityContext(), ipAddress: options?.ipAddress ?? "198.51.100.8", audit: options?.audit ?? auditRecorder().writer, rateLimit: options?.rateLimit ?? (async () => true), }; } function register(command: HousekeepingCommand): void { registerHousekeepingCommand(command); } function baseCommand( id: string, overrides: Pick, "input" | "execute"> & Partial< Pick, "risk" | "requiresReason" | "rateLimit"> >, ): HousekeepingCommand { return { id, owner: "system", risk: overrides.risk ?? "safe", capability: anyCapability("admin.settings.edit"), input: overrides.input, requiresReason: overrides.requiresReason ?? false, rateLimit: overrides.rateLimit ?? { attempts: 3, windowMs: 45_000 }, execute: overrides.execute, }; } describe("dispatchHousekeepingCommand", () => { it("returns a typed not-found result for an unknown command", async () => { const result = await dispatchHousekeepingCommand( { commandId: "system.missing", input: {} }, dependencies(), ); expect(result).toMatchObject({ ok: false, error: { code: "NOT_FOUND", messageKey: "errors.housekeeping.notFound", }, }); expect(result.correlationId).toMatch(/^[0-9a-f-]{36}$/i); }); it("rechecks capability without treating actor rank as authorization", async () => { let executed = false; const audit = auditRecorder(); register( baseCommand("system.dispatch.denied", { risk: "sensitive", input: z.object({}), execute: async (context) => { executed = true; return ok(null, context.correlationId); }, }), ); const result = await dispatchHousekeepingCommand( { commandId: "system.dispatch.denied", input: {} }, dependencies({ context: capabilityContext([]), audit: audit.writer }), ); expect(result).toMatchObject({ ok: false, error: { code: "FORBIDDEN" }, }); expect(executed).toBe(false); expect(audit.entries.map((entry) => entry.outcome)).toEqual([ "intent", "denied", ]); expect(audit.entries[0]?.correlationId).toBe(result.correlationId); expect(audit.entries[1]?.correlationId).toBe(result.correlationId); }); it("rejects invalid input before the command can execute", async () => { let executed = false; register( baseCommand("system.dispatch.invalid-input", { input: z.object({ count: z.number().int().positive() }), execute: async (context) => { executed = true; return ok(null, context.correlationId); }, }), ); const result = await dispatchHousekeepingCommand( { commandId: "system.dispatch.invalid-input", input: { count: -1 } }, dependencies(), ); expect(result).toMatchObject({ ok: false, error: { code: "VALIDATION" }, }); expect(executed).toBe(false); }); it("rejects a missing required reason before the command can execute", async () => { let executed = false; const audit = auditRecorder(); register( baseCommand("system.dispatch.reason", { risk: "sensitive", requiresReason: true, input: z.object({}), execute: async (context) => { executed = true; return ok(null, context.correlationId); }, }), ); const result = await dispatchHousekeepingCommand( { commandId: "system.dispatch.reason", input: {}, reason: " " }, dependencies({ audit: audit.writer }), ); expect(result).toMatchObject({ ok: false, error: { code: "VALIDATION", fieldErrors: { reason: ["errors.validation.required"] }, }, }); expect(executed).toBe(false); expect(audit.entries.map((entry) => entry.outcome)).toEqual([ "intent", "denied", ]); }); it("uses actor, IP, command ID, and the approved command limit", async () => { const calls: Array<[string, number, number]> = []; let executed = false; register( baseCommand("system.dispatch.rate-limit", { input: z.object({}), rateLimit: { attempts: 2, windowMs: 90_000 }, execute: async (context) => { executed = true; return ok(null, context.correlationId); }, }), ); const result = await dispatchHousekeepingCommand( { commandId: "system.dispatch.rate-limit", input: {} }, dependencies({ rateLimit: async (key, attempts, windowMs) => { calls.push([key, attempts, windowMs]); return false; }, }), ); expect(calls).toEqual([ [ "housekeeping-command:42:198.51.100.8:system.dispatch.rate-limit", 2, 90_000, ], ]); expect(result).toMatchObject({ ok: false, error: { code: "RATE_LIMITED" }, }); expect(executed).toBe(false); }); it("executes a safe command with parsed input and writes one success outcome", async () => { const audit = auditRecorder(); let receivedCount = 0; register( baseCommand("system.dispatch.safe-success", { input: z.object({ count: z.coerce.number().int().positive() }), execute: async (_context, input) => { receivedCount = input.count; return ok({ doubled: input.count * 2 }, "wrong-command-correlation"); }, }), ); const result = await dispatchHousekeepingCommand( { commandId: "system.dispatch.safe-success", input: { count: "4" } }, dependencies({ audit: audit.writer }), ); expect(receivedCount).toBe(4); expect(result).toMatchObject({ ok: true, data: { doubled: 8 } }); expect(audit.entries.map((entry) => entry.outcome)).toEqual(["success"]); expect(audit.entries[0]?.correlationId).toBe(result.correlationId); expect(result.correlationId).not.toBe("wrong-command-correlation"); }); it("persists sensitive intent before execution and success afterward", async () => { const events: string[] = []; const audit = auditRecorder(events); let executionCorrelation = ""; register( baseCommand("system.dispatch.sensitive-success", { risk: "sensitive", requiresReason: true, input: z.object({ enabled: z.boolean() }), execute: async (context) => { executionCorrelation = context.correlationId; events.push("execute"); return ok({ saved: true }, "untrusted-command-correlation"); }, }), ); const result = await dispatchHousekeepingCommand( { commandId: "system.dispatch.sensitive-success", input: { enabled: true }, reason: " Planned change ", }, dependencies({ audit: audit.writer }), ); expect(events).toEqual(["audit:intent", "execute", "audit:success"]); expect(audit.entries).toMatchObject([ { userId: 42, action: "system.dispatch.sensitive-success", target: "system", domain: "system", reason: "Planned change", ipAddress: "198.51.100.8", outcome: "intent", }, { outcome: "success" }, ]); expect(executionCorrelation).toBe(result.correlationId); expect(audit.entries[0]?.correlationId).toBe(result.correlationId); expect(audit.entries[1]?.correlationId).toBe(result.correlationId); }); it("persists sensitive failure after execution with the same correlation", async () => { const events: string[] = []; const audit = auditRecorder(events); register( baseCommand("system.dispatch.sensitive-failure", { risk: "sensitive", input: z.object({}), execute: async () => { events.push("execute"); return fail( "DEPENDENCY_UNAVAILABLE", "errors.housekeeping.dependencyUnavailable", "wrong-command-correlation", ); }, }), ); const result = await dispatchHousekeepingCommand( { commandId: "system.dispatch.sensitive-failure", input: {} }, dependencies({ audit: audit.writer }), ); expect(events).toEqual(["audit:intent", "execute", "audit:failure"]); expect(result).toMatchObject({ ok: false, error: { code: "DEPENDENCY_UNAVAILABLE" }, }); expect(audit.entries[0]?.correlationId).toBe(result.correlationId); expect(audit.entries[1]?.correlationId).toBe(result.correlationId); }); it("blocks sensitive execution when intent persistence fails", async () => { let executed = false; register( baseCommand("system.dispatch.intent-failure", { risk: "sensitive", input: z.object({}), execute: async (context) => { executed = true; return ok(null, context.correlationId); }, }), ); const result = await dispatchHousekeepingCommand( { commandId: "system.dispatch.intent-failure", input: {} }, dependencies({ audit: { write: async () => { throw new Error("audit credentials exposed"); }, }, }), ); expect(executed).toBe(false); expect(result).toMatchObject({ ok: false, error: { code: "INTERNAL", messageKey: "errors.housekeeping.internal", }, }); }); it("sanitizes unknown exceptions and records a failure outcome", async () => { const audit = auditRecorder(); register( baseCommand("system.dispatch.exception", { risk: "sensitive", input: z.object({}), execute: async () => { throw new Error("database password=hunter2"); }, }), ); const result = await dispatchHousekeepingCommand( { commandId: "system.dispatch.exception", input: {} }, dependencies({ audit: audit.writer }), ); expect(result).toMatchObject({ ok: false, error: { code: "INTERNAL", messageKey: "errors.housekeeping.internal", }, }); expect(JSON.stringify(result)).not.toContain("hunter2"); expect(audit.entries.map((entry) => entry.outcome)).toEqual([ "intent", "failure", ]); expect(audit.entries[1]?.correlationId).toBe(result.correlationId); }); });