test(FN-4603): complete Step 3 — cover web fetch network_api gating
Fusion-Task-Id: FN-4603 Fusion-Task-Lineage: c74085e2-d91c-468f-883b-5c33818e53fd
This commit is contained in:
@@ -17,16 +17,42 @@ describe("agent action gate project-default resolution", () => {
|
|||||||
evaluateAgentActionGate({ agentId: "a1", toolName: "bash", args: { command: "git commit -m x" }, permissionPolicy }),
|
evaluateAgentActionGate({ agentId: "a1", toolName: "bash", args: { command: "git commit -m x" }, permissionPolicy }),
|
||||||
evaluateAgentActionGate({ agentId: "a1", toolName: "write", args: { path: "x.ts", content: "x" }, permissionPolicy }),
|
evaluateAgentActionGate({ agentId: "a1", toolName: "write", args: { path: "x.ts", content: "x" }, permissionPolicy }),
|
||||||
evaluateAgentActionGate({ agentId: "a1", toolName: "bash", args: { command: "pnpm test" }, permissionPolicy }),
|
evaluateAgentActionGate({ agentId: "a1", toolName: "bash", args: { command: "pnpm test" }, permissionPolicy }),
|
||||||
evaluateAgentActionGate({ agentId: "a1", toolName: "fn_web_fetch", args: { url: "https://example.com" }, permissionPolicy }),
|
|
||||||
evaluateAgentActionGate({ agentId: "a1", toolName: "fn_task_add_dep", args: { task_id: "FN-1" }, permissionPolicy }),
|
evaluateAgentActionGate({ agentId: "a1", toolName: "fn_task_add_dep", args: { task_id: "FN-1" }, permissionPolicy }),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const decision of decisions) {
|
for (const decision of decisions) {
|
||||||
if (decision.category === "exempt") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
expect(decision.disposition).toBe("require-approval");
|
expect(decision.disposition).toBe("require-approval");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const webFetchDecision = evaluateAgentActionGate({
|
||||||
|
agentId: "a1",
|
||||||
|
toolName: "fn_web_fetch",
|
||||||
|
args: { url: "https://example.com" },
|
||||||
|
permissionPolicy,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(webFetchDecision.category).toBe("network_api");
|
||||||
|
expect(webFetchDecision.disposition).toBe("require-approval");
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
["allow", "allow"],
|
||||||
|
["block", "block"],
|
||||||
|
["require-approval", "require-approval"],
|
||||||
|
] as const)("routes fn_web_fetch through network_api policy (%s)", (networkDisposition, expected) => {
|
||||||
|
const permissionPolicy = resolveEffectiveAgentPermissionPolicy(undefined, {
|
||||||
|
rules: { network_api: networkDisposition },
|
||||||
|
});
|
||||||
|
|
||||||
|
const decision = evaluateAgentActionGate({
|
||||||
|
agentId: "a1",
|
||||||
|
toolName: "fn_web_fetch",
|
||||||
|
args: { url: "https://example.com" },
|
||||||
|
permissionPolicy,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(decision.category).toBe("network_api");
|
||||||
|
expect(decision.disposition).toBe(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("keeps per-agent custom rule over project default", () => {
|
it("keeps per-agent custom rule over project default", () => {
|
||||||
|
|||||||
@@ -106,6 +106,12 @@ describe("gating-classifications parity", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("classifies fn_web_fetch as network_api in both action and permanent sets", () => {
|
||||||
|
expect(ACTION_GATE_NETWORK_API_TOOLS.has("fn_web_fetch")).toBe(true);
|
||||||
|
expect(NETWORK_API_TOOLS.has("fn_web_fetch")).toBe(true);
|
||||||
|
expect(COORDINATION_EXEMPT_TOOLS.includes("fn_web_fetch")).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
it("keeps fn_* category equivalence mappings across gates", () => {
|
it("keeps fn_* category equivalence mappings across gates", () => {
|
||||||
const fnTools = new Set<string>();
|
const fnTools = new Set<string>();
|
||||||
for (const source of [
|
for (const source of [
|
||||||
|
|||||||
Reference in New Issue
Block a user