Files
fusion/packages/engine/src/sandbox/__tests__/provisioning-gate.test.ts
Fusion (runfusion.ai) 10b73d538d feat(FN-4641): complete Step 4 — integrate sandbox provisioning approvals in dashboard
Fusion-Task-Id: FN-4641
Fusion-Task-Lineage: 50ac1fd2-8c88-4a29-9ebb-962a6b5c772c
2026-05-15 22:56:31 -07:00

153 lines
5.5 KiB
TypeScript

import type { ApprovalRequest } from "@fusion/core";
import { describe, expect, it, vi } from "vitest";
import {
SandboxProvisioningPendingError,
requireSandboxProvisioningApproval,
} from "../provisioning-gate.js";
function makeApproval(id: string, status: ApprovalRequest["status"]): ApprovalRequest {
return {
id,
status,
requester: { actorId: "agent-1", actorType: "agent", actorName: "Executor" },
targetAction: {
category: "sandbox_provisioning",
action: "provision",
summary: "Provision sandbox backend",
resourceType: "command",
resourceId: "install-bubblewrap",
context: { backendId: "bubblewrap", operation: "install-bubblewrap", params: {} },
},
taskId: "FN-4641",
runId: "run-1",
requestedAt: new Date().toISOString(),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
}
describe("requireSandboxProvisioningApproval", () => {
it("allows auto-approved backend", async () => {
const createApprovalRequest = vi.fn();
const result = await requireSandboxProvisioningApproval({
backendId: "native",
operation: "prepare",
description: "Prepare native backend",
context: {
requester: { actorId: "agent-1", actorType: "agent", actorName: "Executor" },
settings: undefined,
createApprovalRequest,
},
});
expect(result).toEqual({ outcome: "allow" });
expect(createApprovalRequest).not.toHaveBeenCalled();
});
it("creates pending request and pauses for approval in default mode", async () => {
const createApprovalRequest = vi.fn(async () => makeApproval("apr-1", "pending"));
const pauseForApproval = vi.fn(async () => undefined);
await expect(
requireSandboxProvisioningApproval({
backendId: "bubblewrap",
operation: "install",
description: "Install bubblewrap",
context: {
taskId: "FN-4641",
requester: { actorId: "agent-1", actorType: "agent", actorName: "Executor" },
settings: undefined,
createApprovalRequest,
pauseForApproval,
},
}),
).rejects.toBeInstanceOf(SandboxProvisioningPendingError);
expect(createApprovalRequest).toHaveBeenCalledTimes(1);
expect(pauseForApproval).toHaveBeenCalledTimes(1);
});
it("returns execute-once-then-complete after approval exists", async () => {
const result = await requireSandboxProvisioningApproval({
backendId: "bubblewrap",
operation: "install",
description: "Install bubblewrap",
context: {
taskId: "FN-4641",
requester: { actorId: "agent-1", actorType: "agent", actorName: "Executor" },
settings: undefined,
createApprovalRequest: vi.fn(async () => null),
findApprovalByDedupeKey: vi.fn(async () => ({ id: "apr-1", status: "approved" as const })),
},
});
expect(result).toEqual({ outcome: "execute-once-then-complete", approvalRequestId: "apr-1" });
});
it("throws block when prior approval was denied", async () => {
await expect(
requireSandboxProvisioningApproval({
backendId: "bubblewrap",
operation: "install",
description: "Install bubblewrap",
context: {
requester: { actorId: "agent-1", actorType: "agent", actorName: "Executor" },
settings: undefined,
createApprovalRequest: vi.fn(async () => null),
findApprovalByDedupeKey: vi.fn(async () => ({ id: "apr-1", status: "denied" as const })),
},
}),
).rejects.toBeInstanceOf(SandboxProvisioningPendingError);
});
it("allows never mode without creating approval", async () => {
const createApprovalRequest = vi.fn(async () => makeApproval("apr-1", "pending"));
const result = await requireSandboxProvisioningApproval({
backendId: "bubblewrap",
operation: "install",
description: "Install bubblewrap",
context: {
requester: { actorId: "agent-1", actorType: "agent", actorName: "Executor" },
settings: { sandboxProvisioning: { approvalMode: "never" } },
createApprovalRequest,
},
});
expect(result).toEqual({ outcome: "allow" });
expect(createApprovalRequest).not.toHaveBeenCalled();
});
it("produces stable dedupe key for identical inputs", async () => {
const createApprovalRequest = vi.fn(async () => makeApproval("apr-1", "pending"));
const first = requireSandboxProvisioningApproval({
backendId: "bubblewrap",
operation: "install",
description: "Install bubblewrap",
context: {
taskId: "FN-4641",
requester: { actorId: "agent-1", actorType: "agent", actorName: "Executor" },
settings: undefined,
createApprovalRequest,
},
}).catch((error) => error as SandboxProvisioningPendingError);
const second = requireSandboxProvisioningApproval({
backendId: "bubblewrap",
operation: "install",
description: "Install bubblewrap",
context: {
taskId: "FN-4641",
requester: { actorId: "agent-1", actorType: "agent", actorName: "Executor" },
settings: undefined,
createApprovalRequest,
},
}).catch((error) => error as SandboxProvisioningPendingError);
const [firstError, secondError] = await Promise.all([first, second]);
expect(firstError).toBeInstanceOf(SandboxProvisioningPendingError);
expect(secondError).toBeInstanceOf(SandboxProvisioningPendingError);
expect((firstError as SandboxProvisioningPendingError).dedupeKey).toBe(
(secondError as SandboxProvisioningPendingError).dedupeKey,
);
});
});