feat(FN-4637): complete Step 2 — add bubblewrap policy adapter

Fusion-Task-Id: FN-4637
Fusion-Task-Lineage: 564c5692-3aaf-4396-9306-a395703cf365
This commit is contained in:
Fusion
2026-05-15 10:34:48 -07:00
committed by gsxdsm
parent 063977e23e
commit b755553bd6
2 changed files with 200 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
import { describe, expect, it } from "vitest";
import { SandboxPolicyError, fusionWorktreePreset, policyToBwrapArgs, type BubblewrapPolicyContext } from "../../sandbox/bubblewrap-policy.js";
function baseCtx(overrides: Partial<BubblewrapPolicyContext> = {}): BubblewrapPolicyContext {
return {
worktreePath: "/repo/.worktrees/fn-1",
repoRootPath: "/repo",
pnpmStorePath: "/home/u/.pnpm-store",
nodeBinPath: "/usr/bin/node",
homeDir: "/home/u",
pathExists: (path) => !path.includes("missing"),
envSource: {
PATH: "/usr/bin",
HOME: "/home/u",
USER: "u",
LANG: "en_US.UTF-8",
FUSION_RUN_ID: "run-1",
SECRET_TOKEN: "hidden",
},
...overrides,
};
}
describe("policyToBwrapArgs", () => {
it.each([
{ allowNetwork: true, expected: false },
{ allowNetwork: false, expected: true },
])("maps allowNetwork=$allowNetwork to --unshare-net=$expected", ({ allowNetwork, expected }) => {
const args = policyToBwrapArgs({ allowNetwork }, baseCtx());
expect(args.includes("--unshare-net")).toBe(expected);
});
it("includes defaults for writable mounts and env allowlist", () => {
const args = policyToBwrapArgs({ allowNetwork: true }, baseCtx());
expect(args).toContain("--bind");
expect(args).toContain("/repo/.worktrees/fn-1");
expect(args).toContain("/home/u/.pnpm-store");
expect(args).toContain("--tmpfs");
expect(args).toContain("/tmp");
expect(args).toContain("--setenv");
expect(args.join(" ")).toContain("FUSION_RUN_ID run-1");
expect(args.join(" ")).not.toContain("SECRET_TOKEN");
});
it("supports additional writable paths and skips missing readonly sources", () => {
const args = policyToBwrapArgs(
{
allowNetwork: true,
allowedWritePaths: ["/custom/write"],
allowedReadPaths: ["/missing/readonly", "/custom/ro"],
},
baseCtx(),
);
expect(args.join(" ")).toContain("--bind /custom/write /custom/write");
expect(args.join(" ")).toContain("--ro-bind /custom/ro /custom/ro");
expect(args.join(" ")).not.toContain("/missing/readonly");
});
it("guards port 4040 unless explicitly overridden", () => {
expect(() =>
policyToBwrapArgs({ allowNetwork: true, allowedPorts: [4040] }, baseCtx()),
).toThrow(SandboxPolicyError);
expect(() =>
policyToBwrapArgs({ allowNetwork: true, allowedPorts: [4040], allowPort4040Override: true }, baseCtx()),
).not.toThrow();
});
it("fusionWorktreePreset includes worktree and pnpm store but not .fusion db path", () => {
const preset = fusionWorktreePreset(baseCtx());
expect(preset.allowedWritePaths).toContain("/repo/.worktrees/fn-1");
expect(preset.allowedWritePaths).toContain("/home/u/.pnpm-store");
expect((preset.allowedWritePaths ?? []).some((path) => path.includes(".fusion"))).toBe(false);
});
});