refactor(exec-approvals): unify system.run binding and generate host env policy

This commit is contained in:
Peter Steinberger
2026-02-26 16:57:29 +01:00
parent baf1c8ea13
commit 4894d907fa
18 changed files with 858 additions and 342 deletions

View File

@@ -11,7 +11,7 @@ import {
validateExecApprovalRequestParams,
validateExecApprovalResolveParams,
} from "../protocol/index.js";
import { buildSystemRunApprovalEnvBinding } from "../system-run-approval-env-binding.js";
import { buildSystemRunApprovalBindingV1 } from "../system-run-approval-binding.js";
import type { GatewayRequestHandlers } from "./types.js";
export function createExecApprovalHandlers(
@@ -70,7 +70,16 @@ export function createExecApprovalHandlers(
const commandArgv = Array.isArray(p.commandArgv)
? p.commandArgv.map((entry) => String(entry))
: undefined;
const envBinding = buildSystemRunApprovalEnvBinding(p.env);
const systemRunBindingV1 =
host === "node" && Array.isArray(commandArgv) && commandArgv.length > 0
? buildSystemRunApprovalBindingV1({
argv: commandArgv,
cwd: p.cwd,
agentId: p.agentId,
sessionKey: p.sessionKey,
env: p.env,
})
: null;
if (host === "node" && !nodeId) {
respond(
false,
@@ -90,8 +99,8 @@ export function createExecApprovalHandlers(
const request = {
command: p.command,
commandArgv,
envHash: envBinding.envHash,
envKeys: envBinding.envKeys.length > 0 ? envBinding.envKeys : undefined,
envKeys: systemRunBindingV1?.envKeys?.length ? systemRunBindingV1.envKeys : undefined,
systemRunBindingV1: systemRunBindingV1?.binding ?? null,
cwd: p.cwd ?? null,
nodeId: host === "node" ? nodeId : null,
host: host || null,

View File

@@ -9,7 +9,7 @@ import { formatZonedTimestamp } from "../../infra/format-time/format-datetime.js
import { resetLogger, setLoggerOverride } from "../../logging.js";
import { ExecApprovalManager } from "../exec-approval-manager.js";
import { validateExecApprovalRequestParams } from "../protocol/index.js";
import { buildSystemRunApprovalEnvBinding } from "../system-run-approval-env-binding.js";
import { buildSystemRunApprovalBindingV1 } from "../system-run-approval-binding.js";
import { waitForAgentJob } from "./agent-job.js";
import { injectTimestamp, timestampOptsFromConfig } from "./agent-timestamp.js";
import { normalizeRpcAttachmentsToChatAttachments } from "./attachment-normalize.js";
@@ -424,13 +424,14 @@ describe("exec approval handlers", () => {
expect(broadcasts.some((entry) => entry.event === "exec.approval.resolved")).toBe(true);
});
it("stores env binding hash and sorted env keys on approval request", async () => {
it("stores versioned system.run binding and sorted env keys on approval request", async () => {
const { handlers, broadcasts, respond, context } = createExecApprovalFixture();
await requestExecApproval({
handlers,
respond,
context,
params: {
commandArgv: ["echo", "ok"],
env: {
Z_VAR: "z",
A_VAR: "a",
@@ -440,12 +441,14 @@ describe("exec approval handlers", () => {
const requested = broadcasts.find((entry) => entry.event === "exec.approval.requested");
expect(requested).toBeTruthy();
const request = (requested?.payload as { request?: Record<string, unknown> })?.request ?? {};
const expected = buildSystemRunApprovalEnvBinding({
A_VAR: "a",
Z_VAR: "z",
});
expect(request["envHash"]).toBe(expected.envHash);
expect(request["envKeys"]).toEqual(["A_VAR", "Z_VAR"]);
expect(request["systemRunBindingV1"]).toEqual(
buildSystemRunApprovalBindingV1({
argv: ["echo", "ok"],
cwd: "/tmp",
env: { A_VAR: "a", Z_VAR: "z" },
}).binding,
);
});
it("accepts resolve during broadcast", async () => {