refactor!: remove versioned system-run approval contract

This commit is contained in:
Peter Steinberger
2026-03-02 01:12:47 +00:00
parent 1636f7ff5f
commit 155118751f
33 changed files with 564 additions and 215 deletions

View File

@@ -626,7 +626,7 @@ function renderQuotedArgv(argv: string[]): string {
return argv.map((token) => shellEscapeSingleArg(token)).join(" ");
}
function resolvePlannedSegmentArgv(segment: ExecCommandSegment): string[] | null {
export function resolvePlannedSegmentArgv(segment: ExecCommandSegment): string[] | null {
if (segment.resolution?.policyBlocked === true) {
return null;
}
@@ -638,7 +638,8 @@ function resolvePlannedSegmentArgv(segment: ExecCommandSegment): string[] | null
return null;
}
const argv = [...baseArgv];
const resolvedExecutable = segment.resolution?.resolvedPath?.trim() ?? "";
const resolvedExecutable =
segment.resolution?.resolvedRealPath?.trim() ?? segment.resolution?.resolvedPath?.trim() ?? "";
if (resolvedExecutable) {
argv[0] = resolvedExecutable;
}

View File

@@ -11,8 +11,7 @@ export type ExecHost = "sandbox" | "gateway" | "node";
export type ExecSecurity = "deny" | "allowlist" | "full";
export type ExecAsk = "off" | "on-miss" | "always";
export type SystemRunApprovalBindingV1 = {
version: 1;
export type SystemRunApprovalBinding = {
argv: string[];
cwd: string | null;
agentId: string | null;
@@ -20,8 +19,7 @@ export type SystemRunApprovalBindingV1 = {
envHash: string | null;
};
export type SystemRunApprovalPlanV2 = {
version: 2;
export type SystemRunApprovalPlan = {
argv: string[];
cwd: string | null;
rawCommand: string | null;
@@ -34,8 +32,8 @@ export type ExecApprovalRequestPayload = {
commandArgv?: string[];
// Optional UI-safe env key preview for approval prompts.
envKeys?: string[];
systemRunBindingV1?: SystemRunApprovalBindingV1 | null;
systemRunPlanV2?: SystemRunApprovalPlanV2 | null;
systemRunBinding?: SystemRunApprovalBinding | null;
systemRunPlan?: SystemRunApprovalPlan | null;
cwd?: string | null;
nodeId?: string | null;
host?: string | null;

View File

@@ -9,6 +9,7 @@ export const DEFAULT_SAFE_BINS = ["jq", "cut", "uniq", "head", "tail", "tr", "wc
export type CommandResolution = {
rawExecutable: string;
resolvedPath?: string;
resolvedRealPath?: string;
executableName: string;
effectiveArgv?: string[];
wrapperChain?: string[];
@@ -86,6 +87,17 @@ function resolveExecutablePath(rawExecutable: string, cwd?: string, env?: NodeJS
return undefined;
}
function tryResolveRealpath(filePath: string | undefined): string | undefined {
if (!filePath) {
return undefined;
}
try {
return fs.realpathSync(filePath);
} catch {
return undefined;
}
}
export function resolveCommandResolution(
command: string,
cwd?: string,
@@ -96,10 +108,12 @@ export function resolveCommandResolution(
return null;
}
const resolvedPath = resolveExecutablePath(rawExecutable, cwd, env);
const resolvedRealPath = tryResolveRealpath(resolvedPath);
const executableName = resolvedPath ? path.basename(resolvedPath) : rawExecutable;
return {
rawExecutable,
resolvedPath,
resolvedRealPath,
executableName,
effectiveArgv: [rawExecutable],
wrapperChain: [],
@@ -119,10 +133,12 @@ export function resolveCommandResolutionFromArgv(
return null;
}
const resolvedPath = resolveExecutablePath(rawExecutable, cwd, env);
const resolvedRealPath = tryResolveRealpath(resolvedPath);
const executableName = resolvedPath ? path.basename(resolvedPath) : rawExecutable;
return {
rawExecutable,
resolvedPath,
resolvedRealPath,
executableName,
effectiveArgv,
wrapperChain: plan.wrappers,

View File

@@ -1,5 +1,5 @@
import crypto from "node:crypto";
import type { SystemRunApprovalBindingV1, SystemRunApprovalPlanV2 } from "./exec-approvals.js";
import type { SystemRunApprovalBinding, SystemRunApprovalPlan } from "./exec-approvals.js";
import { normalizeEnvVarKey } from "./host-env-security.js";
type NormalizedSystemRunEnvEntry = [key: string, value: string];
@@ -16,20 +16,16 @@ function normalizeStringArray(value: unknown): string[] {
return Array.isArray(value) ? value.map((entry) => String(entry)) : [];
}
export function normalizeSystemRunApprovalPlanV2(value: unknown): SystemRunApprovalPlanV2 | null {
export function normalizeSystemRunApprovalPlan(value: unknown): SystemRunApprovalPlan | null {
if (!value || typeof value !== "object" || Array.isArray(value)) {
return null;
}
const candidate = value as Record<string, unknown>;
if (candidate.version !== 2) {
return null;
}
const argv = normalizeStringArray(candidate.argv);
if (argv.length === 0) {
return null;
}
return {
version: 2,
argv,
cwd: normalizeString(candidate.cwd),
rawCommand: normalizeString(candidate.rawCommand),
@@ -75,17 +71,16 @@ export function buildSystemRunApprovalEnvBinding(env: unknown): {
};
}
export function buildSystemRunApprovalBindingV1(params: {
export function buildSystemRunApprovalBinding(params: {
argv: unknown;
cwd?: unknown;
agentId?: unknown;
sessionKey?: unknown;
env?: unknown;
}): { binding: SystemRunApprovalBindingV1; envKeys: string[] } {
}): { binding: SystemRunApprovalBinding; envKeys: string[] } {
const envBinding = buildSystemRunApprovalEnvBinding(params.env);
return {
binding: {
version: 1,
argv: normalizeStringArray(params.argv),
cwd: normalizeString(params.cwd),
agentId: normalizeString(params.agentId),
@@ -161,17 +156,11 @@ export function matchSystemRunApprovalEnvHash(params: {
return { ok: true };
}
export function matchSystemRunApprovalBindingV1(params: {
expected: SystemRunApprovalBindingV1;
actual: SystemRunApprovalBindingV1;
export function matchSystemRunApprovalBinding(params: {
expected: SystemRunApprovalBinding;
actual: SystemRunApprovalBinding;
actualEnvKeys: string[];
}): SystemRunApprovalMatchResult {
if (params.expected.version !== 1 || params.actual.version !== 1) {
return requestMismatch({
expectedVersion: params.expected.version,
actualVersion: params.actual.version,
});
}
if (!argvMatches(params.expected.argv, params.actual.argv)) {
return requestMismatch();
}
@@ -191,11 +180,10 @@ export function matchSystemRunApprovalBindingV1(params: {
});
}
export function missingSystemRunApprovalBindingV1(params: {
export function missingSystemRunApprovalBinding(params: {
actualEnvKeys: string[];
}): SystemRunApprovalMatchResult {
return requestMismatch({
requiredBindingVersion: 1,
envKeys: params.actualEnvKeys,
});
}

View File

@@ -1,14 +1,14 @@
import type { SystemRunApprovalPlanV2 } from "./exec-approvals.js";
import { normalizeSystemRunApprovalPlanV2 } from "./system-run-approval-binding.js";
import type { SystemRunApprovalPlan } from "./exec-approvals.js";
import { normalizeSystemRunApprovalPlan } from "./system-run-approval-binding.js";
import { formatExecCommand, resolveSystemRunCommand } from "./system-run-command.js";
type PreparedRunPayload = {
cmdText: string;
plan: SystemRunApprovalPlanV2;
plan: SystemRunApprovalPlan;
};
type SystemRunApprovalRequestContext = {
planV2: SystemRunApprovalPlanV2 | null;
plan: SystemRunApprovalPlan | null;
commandArgv: string[] | undefined;
commandText: string;
cwd: string | null;
@@ -19,7 +19,7 @@ type SystemRunApprovalRequestContext = {
type SystemRunApprovalRuntimeContext =
| {
ok: true;
planV2: SystemRunApprovalPlanV2 | null;
plan: SystemRunApprovalPlan | null;
argv: string[];
cwd: string | null;
agentId: string | null;
@@ -54,7 +54,7 @@ export function parsePreparedSystemRunPayload(payload: unknown): PreparedRunPayl
}
const raw = payload as { cmdText?: unknown; plan?: unknown };
const cmdText = normalizeString(raw.cmdText);
const plan = normalizeSystemRunApprovalPlanV2(raw.plan);
const plan = normalizeSystemRunApprovalPlan(raw.plan);
if (!cmdText || !plan) {
return null;
}
@@ -65,38 +65,38 @@ export function resolveSystemRunApprovalRequestContext(params: {
host?: unknown;
command?: unknown;
commandArgv?: unknown;
systemRunPlanV2?: unknown;
systemRunPlan?: unknown;
cwd?: unknown;
agentId?: unknown;
sessionKey?: unknown;
}): SystemRunApprovalRequestContext {
const host = normalizeString(params.host) ?? "";
const planV2 = host === "node" ? normalizeSystemRunApprovalPlanV2(params.systemRunPlanV2) : null;
const plan = host === "node" ? normalizeSystemRunApprovalPlan(params.systemRunPlan) : null;
const fallbackArgv = normalizeStringArray(params.commandArgv);
const fallbackCommand = normalizeCommandText(params.command);
return {
planV2,
commandArgv: planV2?.argv ?? (fallbackArgv.length > 0 ? fallbackArgv : undefined),
commandText: planV2 ? (planV2.rawCommand ?? formatExecCommand(planV2.argv)) : fallbackCommand,
cwd: planV2?.cwd ?? normalizeString(params.cwd),
agentId: planV2?.agentId ?? normalizeString(params.agentId),
sessionKey: planV2?.sessionKey ?? normalizeString(params.sessionKey),
plan,
commandArgv: plan?.argv ?? (fallbackArgv.length > 0 ? fallbackArgv : undefined),
commandText: plan ? (plan.rawCommand ?? formatExecCommand(plan.argv)) : fallbackCommand,
cwd: plan?.cwd ?? normalizeString(params.cwd),
agentId: plan?.agentId ?? normalizeString(params.agentId),
sessionKey: plan?.sessionKey ?? normalizeString(params.sessionKey),
};
}
export function resolveSystemRunApprovalRuntimeContext(params: {
planV2?: unknown;
plan?: unknown;
command?: unknown;
rawCommand?: unknown;
cwd?: unknown;
agentId?: unknown;
sessionKey?: unknown;
}): SystemRunApprovalRuntimeContext {
const normalizedPlan = normalizeSystemRunApprovalPlanV2(params.planV2 ?? null);
const normalizedPlan = normalizeSystemRunApprovalPlan(params.plan ?? null);
if (normalizedPlan) {
return {
ok: true,
planV2: normalizedPlan,
plan: normalizedPlan,
argv: [...normalizedPlan.argv],
cwd: normalizedPlan.cwd,
agentId: normalizedPlan.agentId,
@@ -113,7 +113,7 @@ export function resolveSystemRunApprovalRuntimeContext(params: {
}
return {
ok: true,
planV2: null,
plan: null,
argv: command.argv,
cwd: normalizeString(params.cwd),
agentId: normalizeString(params.agentId),