const std = @import("std"); const command_admission = @import("../permissions/command_admission.zig");const direct_command = @import("../permissions/direct_command.zig");const sandbox = @import("../permissions/sandbox.zig");const command_effect = @import("../shell_command/command_effect.zig"); pub const RouteKind = enum { direct_read_only, approved_shell,}; /// An admitted foreground command prepared for local execution.////// The direct plan owns its allocations. The caller must call `deinit`.pub const PreparedCommand = union(enum) { direct_read_only: command_effect.DirectReadOnlyPlan, approved_shell: struct { command_ctx: command_admission.CommandContext, reason: command_effect.ApprovalReason, source: command_admission.ShellAuthorizationSource, }, pub fn deinit(self: *PreparedCommand, alloc: std.mem.Allocator) void { switch (self.*) { .direct_read_only => |*plan| plan.deinit(alloc), .approved_shell => {}, } self.* = undefined; }}; pub const CommandResult = struct { route: RouteKind, result: sandbox.CommandExecutionResult,}; /// Upper bound for raw callback bytes that can still be represented by the/// command's ordinary foreground result. Above this bound execution either/// rejects output or promotes it to an unordered command artifact.pub fn foregroundResultComparisonLimit( command: PreparedCommand, approved_shell_limit: usize,) usize { return switch (command) { .direct_read_only => direct_command.direct_output_limit_bytes, .approved_shell => approved_shell_limit, };} /// Executes a prepared foreground command without taking ownership of it.pub fn executePreparedCommand( cfg: sandbox.Config, alloc: std.mem.Allocator, command: PreparedCommand,) !CommandResult { return switch (command) { .direct_read_only => |plan| .{ .route = .direct_read_only, .result = try direct_command.executeDirectReadOnly(cfg, alloc, plan), }, .approved_shell => |shell| .{ .route = .approved_shell, .result = try sandbox.executeCommandInEnvironment( cfg, alloc, shell.command_ctx.command, shell.command_ctx.resolved_cwd, shell.command_ctx.environment, ), }, };} test "local executor keeps route-specific foreground result limits" { const direct = PreparedCommand{ .direct_read_only = .{ .command = "", .cwd = "", .stages = &.{}, } }; try std.testing.expectEqual( direct_command.direct_output_limit_bytes, foregroundResultComparisonLimit(direct, 1), ); const approved = PreparedCommand{ .approved_shell = .{ .command_ctx = .{ .command = "", .resolved_cwd = "", .background = false, .resolved_backend = .none, .target_os = @import("builtin").os.tag, }, .reason = .process_or_system, .source = .interactive_once, } }; try std.testing.expectEqual( @as(usize, 1024), foregroundResultComparisonLimit(approved, 1024), );} test "local executor runs an approved shell command with its admitted context" { var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena_state.deinit(); const arena = arena_state.allocator(); const command = PreparedCommand{ .approved_shell = .{ .command_ctx = .{ .command = "printf local-executor", .resolved_cwd = "/tmp", .background = false, .resolved_backend = .none, .target_os = @import("builtin").os.tag, }, .reason = .process_or_system, .source = .interactive_once, } }; const executed = try executePreparedCommand(.{ .backend = .none, .workspace_root = "/tmp", .max_command_output_bytes = 1024, }, arena, command); try std.testing.expectEqual(RouteKind.approved_shell, executed.route); try std.testing.expect(std.mem.find( u8, executed.result.output, "<stdout>\nlocal-executor\n</stdout>", ) != null); const foreground = executed.result.command_result.?.foreground; try std.testing.expectEqualStrings(command.approved_shell.command_ctx.command, foreground.command); try std.testing.expectEqualStrings(command.approved_shell.command_ctx.resolved_cwd, foreground.cwd); try std.testing.expectEqual(@as(?i64, 0), foreground.exit_code);}
const std = @import("std");
const command_admission = @import("../permissions/command_admission.zig");
const direct_command = @import("../permissions/direct_command.zig");
const sandbox = @import("../permissions/sandbox.zig");
const command_effect = @import("../shell_command/command_effect.zig");
pub const RouteKind = enum {
direct_read_only,
approved_shell,
};
/// An admitted foreground command prepared for local execution.
///
/// The direct plan owns its allocations. The caller must call `deinit`.
pub const PreparedCommand = union(enum) {
direct_read_only: command_effect.DirectReadOnlyPlan,
approved_shell: struct {
command_ctx: command_admission.CommandContext,
reason: command_effect.ApprovalReason,
source: command_admission.ShellAuthorizationSource,
},
pub fn deinit(self: *PreparedCommand, alloc: std.mem.Allocator) void {
switch (self.*) {
.direct_read_only => |*plan| plan.deinit(alloc),
.approved_shell => {},
}
self.* = undefined;
}
};
pub const CommandResult = struct {
route: RouteKind,
result: sandbox.CommandExecutionResult,
};
/// Upper bound for raw callback bytes that can still be represented by the
/// command's ordinary foreground result. Above this bound execution either
/// rejects output or promotes it to an unordered command artifact.
pub fn foregroundResultComparisonLimit(
command: PreparedCommand,
approved_shell_limit: usize,
) usize {
return switch (command) {
.direct_read_only => direct_command.direct_output_limit_bytes,
.approved_shell => approved_shell_limit,
};
}
/// Executes a prepared foreground command without taking ownership of it.
pub fn executePreparedCommand(
cfg: sandbox.Config,
alloc: std.mem.Allocator,
command: PreparedCommand,
) !CommandResult {
return switch (command) {
.direct_read_only => |plan| .{
.route = .direct_read_only,
.result = try direct_command.executeDirectReadOnly(cfg, alloc, plan),
},
.approved_shell => |shell| .{
.route = .approved_shell,
.result = try sandbox.executeCommandInEnvironment(
cfg,
alloc,
shell.command_ctx.command,
shell.command_ctx.resolved_cwd,
shell.command_ctx.environment,
),
},
};
}
test "local executor keeps route-specific foreground result limits" {
const direct = PreparedCommand{ .direct_read_only = .{
.command = "",
.cwd = "",
.stages = &.{},
} };
try std.testing.expectEqual(
direct_command.direct_output_limit_bytes,
foregroundResultComparisonLimit(direct, 1),
);
const approved = PreparedCommand{ .approved_shell = .{
.command_ctx = .{
.command = "",
.resolved_cwd = "",
.background = false,
.resolved_backend = .none,
.target_os = @import("builtin").os.tag,
},
.reason = .process_or_system,
.source = .interactive_once,
} };
try std.testing.expectEqual(
@as(usize, 1024),
foregroundResultComparisonLimit(approved, 1024),
);
}
test "local executor runs an approved shell command with its admitted context" {
var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);
defer arena_state.deinit();
const arena = arena_state.allocator();
const command = PreparedCommand{ .approved_shell = .{
.command_ctx = .{
.command = "printf local-executor",
.resolved_cwd = "/tmp",
.background = false,
.resolved_backend = .none,
.target_os = @import("builtin").os.tag,
},
.reason = .process_or_system,
.source = .interactive_once,
} };
const executed = try executePreparedCommand(.{
.backend = .none,
.workspace_root = "/tmp",
.max_command_output_bytes = 1024,
}, arena, command);
try std.testing.expectEqual(RouteKind.approved_shell, executed.route);
try std.testing.expect(std.mem.find(
u8,
executed.result.output,
"<stdout>\nlocal-executor\n</stdout>",
) != null);
const foreground = executed.result.command_result.?.foreground;
try std.testing.expectEqualStrings(command.approved_shell.command_ctx.command, foreground.command);
try std.testing.expectEqualStrings(command.approved_shell.command_ctx.resolved_cwd, foreground.cwd);
try std.testing.expectEqual(@as(?i64, 0), foreground.exit_code);
}