fix(exec): restore two-phase approval registration flow

This commit is contained in:
Peter Steinberger
2026-02-24 03:16:26 +00:00
parent c6c1e3e7cf
commit 6f0dd61795
5 changed files with 211 additions and 40 deletions

View File

@@ -22,7 +22,13 @@ describe("requestExecApprovalDecision", () => {
});
it("returns string decisions", async () => {
vi.mocked(callGatewayTool).mockResolvedValue({ decision: "allow-once" });
vi.mocked(callGatewayTool)
.mockResolvedValueOnce({
status: "accepted",
id: "approval-id",
expiresAtMs: DEFAULT_APPROVAL_TIMEOUT_MS,
})
.mockResolvedValueOnce({ decision: "allow-once" });
const result = await requestExecApprovalDecision({
id: "approval-id",
@@ -52,12 +58,22 @@ describe("requestExecApprovalDecision", () => {
resolvedPath: "/usr/bin/echo",
sessionKey: "session",
timeoutMs: DEFAULT_APPROVAL_TIMEOUT_MS,
twoPhase: true,
},
{ expectFinal: false },
);
expect(callGatewayTool).toHaveBeenNthCalledWith(
2,
"exec.approval.waitDecision",
{ timeoutMs: DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS },
{ id: "approval-id" },
);
});
it("returns null for missing or non-string decisions", async () => {
vi.mocked(callGatewayTool).mockResolvedValueOnce({});
vi.mocked(callGatewayTool)
.mockResolvedValueOnce({ status: "accepted", id: "approval-id", expiresAtMs: 1234 })
.mockResolvedValueOnce({});
await expect(
requestExecApprovalDecision({
id: "approval-id",
@@ -70,7 +86,9 @@ describe("requestExecApprovalDecision", () => {
}),
).resolves.toBeNull();
vi.mocked(callGatewayTool).mockResolvedValueOnce({ decision: 123 });
vi.mocked(callGatewayTool)
.mockResolvedValueOnce({ status: "accepted", id: "approval-id-2", expiresAtMs: 1234 })
.mockResolvedValueOnce({ decision: 123 });
await expect(
requestExecApprovalDecision({
id: "approval-id-2",
@@ -83,4 +101,20 @@ describe("requestExecApprovalDecision", () => {
}),
).resolves.toBeNull();
});
it("returns final decision directly when gateway already replies with decision", async () => {
vi.mocked(callGatewayTool).mockResolvedValue({ decision: "deny", id: "approval-id" });
const result = await requestExecApprovalDecision({
id: "approval-id",
command: "echo hi",
cwd: "/tmp",
host: "gateway",
security: "allowlist",
ask: "on-miss",
});
expect(result).toBe("deny");
expect(vi.mocked(callGatewayTool).mock.calls).toHaveLength(1);
});
});