feat(FN-4641): complete Step 2 — add sandbox provisioning policy resolver

Fusion-Task-Id: FN-4641
Fusion-Task-Lineage: 50ac1fd2-8c88-4a29-9ebb-962a6b5c772c
This commit is contained in:
Fusion (runfusion.ai)
2026-05-15 22:33:06 -07:00
committed by gsxdsm
parent 30f71d399c
commit 9ef00e1197
3 changed files with 254 additions and 0 deletions

View File

@@ -0,0 +1,129 @@
import { describe, expect, it } from "vitest";
import { extractSandboxProvisioningRequest, resolveSandboxProvisioningPolicy } from "../sandbox-provisioning-policy.js";
describe("resolveSandboxProvisioningPolicy", () => {
it("denies missing caller", () => {
const decision = resolveSandboxProvisioningPolicy({
backendId: "bubblewrap",
operation: "install",
caller: undefined,
settings: undefined,
});
expect(decision.decision).toBe("deny");
expect(decision.matchedRule).toBe("missing-caller");
});
it("allows auto-approved backend id", () => {
const decision = resolveSandboxProvisioningPolicy({
backendId: "native",
operation: "prepare",
caller: { id: "agent-1" },
settings: undefined,
});
expect(decision.decision).toBe("allow");
expect(decision.matchedRule).toBe("auto-approve-backend");
});
it("allows privileged caller", () => {
const decision = resolveSandboxProvisioningPolicy({
backendId: "bubblewrap",
operation: "install",
caller: { id: "user-1", isPrivileged: true },
settings: { sandboxProvisioning: { approvalMode: "always" } },
});
expect(decision.decision).toBe("allow");
expect(decision.matchedRule).toBe("privileged-caller");
});
it("allows trusted agent id", () => {
const decision = resolveSandboxProvisioningPolicy({
backendId: "bubblewrap",
operation: "install",
caller: { id: "trusted-id" },
settings: { sandboxProvisioning: { approvalMode: "trusted-only", trustedAgentIds: ["trusted-id"] } },
});
expect(decision.decision).toBe("allow");
expect(decision.matchedRule).toBe("trusted-agent-id");
});
it("allows trusted role", () => {
const decision = resolveSandboxProvisioningPolicy({
backendId: "bubblewrap",
operation: "install",
caller: { id: "agent-1", role: "CEO" },
settings: { sandboxProvisioning: { approvalMode: "trusted-only", trustedRoles: ["ceo"] } },
});
expect(decision.decision).toBe("allow");
expect(decision.matchedRule).toBe("trusted-role");
});
it("requires approval in always mode", () => {
const decision = resolveSandboxProvisioningPolicy({
backendId: "bubblewrap",
operation: "install",
caller: { id: "agent-1" },
settings: { sandboxProvisioning: { approvalMode: "always" } },
});
expect(decision.decision).toBe("require-approval");
expect(decision.matchedRule).toBe("approval-mode-always");
});
it("defaults to always mode", () => {
const decision = resolveSandboxProvisioningPolicy({
backendId: "bubblewrap",
operation: "install",
caller: { id: "agent-1" },
settings: undefined,
});
expect(decision.decision).toBe("require-approval");
expect(decision.effectiveMode).toBe("always");
});
it("allows never mode", () => {
const decision = resolveSandboxProvisioningPolicy({
backendId: "bubblewrap",
operation: "install",
caller: { id: "agent-1" },
settings: { sandboxProvisioning: { approvalMode: "never" } },
});
expect(decision.decision).toBe("allow");
expect(decision.matchedRule).toBe("approval-mode-never");
});
it("supports unknown backend ids by requiring approval", () => {
const decision = resolveSandboxProvisioningPolicy({
backendId: "unknown-backend",
operation: "custom-bootstrap",
caller: { id: "agent-1" },
settings: undefined,
});
expect(decision.decision).toBe("require-approval");
});
});
describe("extractSandboxProvisioningRequest", () => {
it("extracts backendId, operation, and params", () => {
const request: any = {
id: "apr-1",
targetAction: {
category: "sandbox_provisioning",
context: { backendId: "bubblewrap", operation: "install", params: { packageName: "bubblewrap" } },
},
};
expect(extractSandboxProvisioningRequest(request)).toEqual({
backendId: "bubblewrap",
operation: "install",
params: { packageName: "bubblewrap" },
});
});
it("throws on wrong category", () => {
const request: any = { id: "apr-1", targetAction: { category: "agent_provisioning", context: {} } };
expect(() => extractSandboxProvisioningRequest(request)).toThrow("not a sandbox_provisioning request");
});
it("throws for malformed context", () => {
const request: any = { id: "apr-1", targetAction: { category: "sandbox_provisioning", context: {} } };
expect(() => extractSandboxProvisioningRequest(request)).toThrow("invalid provisioning backend id");
});
});

View File

@@ -96,11 +96,19 @@ export {
resolveAgentProvisioningPolicy,
extractAgentProvisioningRequest,
} from "./agent-provisioning-policy.js";
export {
resolveSandboxProvisioningPolicy,
extractSandboxProvisioningRequest,
} from "./sandbox-provisioning-policy.js";
export type {
AgentProvisioningTool,
AgentProvisioningPolicyInput,
AgentProvisioningPolicyDecision,
} from "./agent-provisioning-policy.js";
export type {
SandboxProvisioningPolicyInput,
SandboxProvisioningPolicyDecision,
} from "./sandbox-provisioning-policy.js";
export { TaskStore } from "./store.js";
export { computeRetrySummary, RETRY_STORM_WARNING_RATIO } from "./retry-summary.js";
export { RetryStormError, serializeRetryStormError } from "./retry-storm-error.js";

View File

@@ -0,0 +1,117 @@
import type { ApprovalRequest, ProjectSettings, SandboxProvisioningApprovalMode } from "./types.js";
type SandboxProvisioningSettings = Pick<ProjectSettings, "sandboxProvisioning">;
export interface SandboxProvisioningPolicyInput {
/** Sandbox backend id (for example: native, bubblewrap, sandbox-exec, podman, docker). */
backendId: string;
operation: string;
caller?: { id: string; role?: string; isPrivileged?: boolean };
settings: SandboxProvisioningSettings | undefined;
}
export interface SandboxProvisioningPolicyDecision {
decision: "allow" | "require-approval" | "deny";
reason: string;
matchedRule:
| "auto-approve-backend"
| "privileged-caller"
| "trusted-agent-id"
| "trusted-role"
| "approval-mode-always"
| "approval-mode-trusted-only"
| "approval-mode-never"
| "missing-caller";
effectiveMode: SandboxProvisioningApprovalMode;
}
function normalizeMode(settings: SandboxProvisioningSettings | undefined): SandboxProvisioningApprovalMode {
return settings?.sandboxProvisioning?.approvalMode ?? "always";
}
export function resolveSandboxProvisioningPolicy(
input: SandboxProvisioningPolicyInput,
): SandboxProvisioningPolicyDecision {
const effectiveMode = normalizeMode(input.settings);
const caller = input.caller;
if (!caller) {
return { decision: "deny", reason: "missing caller", matchedRule: "missing-caller", effectiveMode };
}
const autoApproveBackendIds = input.settings?.sandboxProvisioning?.autoApproveBackendIds ?? ["native"];
if (autoApproveBackendIds.includes(input.backendId)) {
return {
decision: "allow",
reason: `backend ${input.backendId} is auto-approved`,
matchedRule: "auto-approve-backend",
effectiveMode,
};
}
if (caller.isPrivileged === true) {
return { decision: "allow", reason: "privileged caller", matchedRule: "privileged-caller", effectiveMode };
}
if (effectiveMode === "never") {
return { decision: "allow", reason: "approval mode never", matchedRule: "approval-mode-never", effectiveMode };
}
const trustedAgentIds = input.settings?.sandboxProvisioning?.trustedAgentIds ?? [];
if (trustedAgentIds.includes(caller.id)) {
return { decision: "allow", reason: "trusted agent id", matchedRule: "trusted-agent-id", effectiveMode };
}
const trustedRoles = (input.settings?.sandboxProvisioning?.trustedRoles ?? []).map((role) => role.toLowerCase());
if (caller.role && trustedRoles.includes(caller.role.toLowerCase())) {
return { decision: "allow", reason: "trusted role", matchedRule: "trusted-role", effectiveMode };
}
if (effectiveMode === "always") {
return {
decision: "require-approval",
reason: "approval mode always",
matchedRule: "approval-mode-always",
effectiveMode,
};
}
return {
decision: "require-approval",
reason: "trusted-only requires trusted caller",
matchedRule: "approval-mode-trusted-only",
effectiveMode,
};
}
export function extractSandboxProvisioningRequest(approvalRequest: ApprovalRequest): {
backendId: string;
operation: string;
params: Record<string, unknown>;
} {
if (approvalRequest.targetAction.category !== "sandbox_provisioning") {
throw new Error(`Approval request ${approvalRequest.id} is not a sandbox_provisioning request`);
}
const context = approvalRequest.targetAction.context;
if (!context || typeof context !== "object") {
throw new Error(`Approval request ${approvalRequest.id} is missing provisioning context`);
}
const backendId = context.backendId;
if (typeof backendId !== "string" || backendId.trim().length === 0) {
throw new Error(`Approval request ${approvalRequest.id} has invalid provisioning backend id`);
}
const operation = context.operation;
if (typeof operation !== "string" || operation.trim().length === 0) {
throw new Error(`Approval request ${approvalRequest.id} has invalid provisioning operation`);
}
const params = context.params;
if (!params || typeof params !== "object") {
throw new Error(`Approval request ${approvalRequest.id} has invalid provisioning params`);
}
return { backendId, operation, params: params as Record<string, unknown> };
}