const std = @import("std");const builtin = @import("builtin");const diff_mod = @import("../output/diff.zig");const file_mutation_contract = @import("file_mutation_contract.zig");const io_mod = @import("../shared/io.zig");const pathing = @import("../workspace/pathing.zig");const text_utils = @import("../shared/text_utils.zig");const types = @import("../shared/types.zig"); const testing_permissions = if (builtin.is_test) @import("../permissions/permissions.zig")else struct {};const testing_builtin_tools = if (builtin.is_test) @import("../../builtins/tools.zig")else struct {};const testing_write_file = if (builtin.is_test) @import("../../tools/filesystem/write_file.zig")else struct {};const testing_edit_file = if (builtin.is_test) @import("../../tools/filesystem/edit_file.zig")else struct {}; const Allocator = std.mem.Allocator;const PreparedFileMutation = file_mutation_contract.PreparedFileMutation;const PolicyEvaluatedFileTargets = file_mutation_contract.PolicyEvaluatedFileTargets; const max_content_bytes: usize = 4 * 1024 * 1024;const max_total_content_bytes: usize = 8 * 1024 * 1024; pub const ParentCleanupResidueReason = enum { not_empty, identity_changed, remove_failed,}; pub const CreatedParentResidue = struct { component_index: usize, path_end: usize, permission_target_index: usize, created_identity: file_mutation_contract.FileIdentity, observed_identity: ?file_mutation_contract.FileIdentity, reason: ParentCleanupResidueReason,}; pub const ApplyRejectionReason = enum { binding_mismatch, stale_preimage, cancelled, traversal_changed, staged_source_changed, io_failure,}; pub const ApplyRejection = struct { reason: ApplyRejectionReason, created_parent_residue: []const CreatedParentResidue,}; pub const ChangeTrackerHandoff = struct { kind: file_mutation_contract.Kind, raw_path: []const u8, previous_content: ?[]const u8, committed_at_ms: i64,}; pub const FullViewSnapshot = struct { after_content: []const u8, lifecycle_id: types.ToolLifecycleId,}; pub const CommittedFileHandoff = struct { preview: diff_mod.FileChangePreview, tracker: ChangeTrackerHandoff, full_view: ?FullViewSnapshot = null, pub fn init( preview: diff_mod.FileChangePreview, tracker: ChangeTrackerHandoff, ) CommittedFileHandoff { return .{ .preview = preview, .tracker = tracker, }; } pub fn deinit(self: CommittedFileHandoff, alloc: Allocator) void { alloc.free(@constCast(self.preview.path)); for (self.preview.lines) |line| alloc.free(@constCast(line.text)); alloc.free(@constCast(self.preview.lines)); alloc.free(@constCast(self.tracker.raw_path)); if (self.tracker.previous_content) |content| { alloc.free(@constCast(content)); } if (self.full_view) |full_view| { alloc.free(@constCast(full_view.after_content)); alloc.free(@constCast(full_view.lifecycle_id.call_id)); } } pub fn attachFullView( self: *CommittedFileHandoff, alloc: Allocator, after_content: []const u8, lifecycle_id: types.ToolLifecycleId, ) Allocator.Error!void { const owned_after_content = try alloc.dupe(u8, after_content); errdefer alloc.free(owned_after_content); const owned_call_id = try alloc.dupe(u8, lifecycle_id.call_id); errdefer alloc.free(owned_call_id); self.full_view = .{ .after_content = owned_after_content, .lifecycle_id = .{ .turn_id = lifecycle_id.turn_id, .call_id = owned_call_id, }, }; }}; pub const ApplyResult = union(enum) { rejected: ApplyRejection, committed: CommittedFileHandoff,}; const target_mismatch_message = "file mutation preparation failed: approved target no longer matches the call";const identity_changed_message = "file mutation preparation failed: approved filesystem identity changed";const preview_too_large_message = "file mutation preparation failed: diff preview exceeds preparation limits";const total_content_too_large_message = "file mutation preparation failed: content proof exceeds the 8 MiB preparation limit"; const FileMutationPrepareError = error{ OutOfMemory, Canceled, Unexpected, SystemResources, ProcessFdQuotaExceeded, SystemFdQuotaExceeded,}; const FileMutationApplyError = error{ OutOfMemory, ResultContractViolation,}; const PreimageResult = union(enum) { preimage: file_mutation_contract.Preimage, semantic_failure: []const u8,}; const PostimageResult = union(enum) { content: []const u8, semantic_failure: []const u8,}; const PreviewResult = union(enum) { preview: diff_mod.FileChangePreview, semantic_failure: []const u8,}; const CommitClaim = struct { claimed: std.atomic.Value(bool) = .init(false),}; var target_resolution_check_count: usize = 0; pub fn resetTargetResolutionCheckCountForTest() void { if (builtin.is_test) target_resolution_check_count = 0;} pub fn targetResolutionCheckCountForTest() usize { return if (builtin.is_test) target_resolution_check_count else 0;} pub fn prepare( call_alloc: std.mem.Allocator, call: types.ToolCall, input: file_mutation_contract.FileMutationInput, policy_targets: file_mutation_contract.PolicyEvaluatedFileTargets,) FileMutationPrepareError!file_mutation_contract.PrepareResult { return prepareInternal(call_alloc, call, input, policy_targets, true);} /// Prepares a mutation whose decoded input and canonical target proof were/// produced together by tool admission. Identity, proof, preimage, and diff/// validation remain unchanged; only duplicate canonical resolution is skipped.pub fn prepareResolvedTarget( call_alloc: std.mem.Allocator, call: types.ToolCall, input: file_mutation_contract.FileMutationInput, policy_targets: file_mutation_contract.PolicyEvaluatedFileTargets,) FileMutationPrepareError!file_mutation_contract.PrepareResult { return prepareInternal(call_alloc, call, input, policy_targets, false);} fn prepareInternal( call_alloc: std.mem.Allocator, call: types.ToolCall, input: file_mutation_contract.FileMutationInput, policy_targets: file_mutation_contract.PolicyEvaluatedFileTargets, verify_target_resolution: bool,) FileMutationPrepareError!file_mutation_contract.PrepareResult { if (policyIdentityBindingMismatch(policy_targets)) { return .{ .semantic_failure = identity_changed_message }; } if (!policy_targets.proofValid()) { return .{ .semantic_failure = target_mismatch_message }; } if (verify_target_resolution and !try resolvedTargetMatches(input, policy_targets)) { return .{ .semantic_failure = target_mismatch_message }; } const preimage_result = try verifyAndReadPreimage(call_alloc, input, policy_targets); const preimage = switch (preimage_result) { .preimage => |preimage| preimage, .semantic_failure => |message| return .{ .semantic_failure = message }, }; const postimage_result = try derivePostimage(call_alloc, input, preimage); const after_content = switch (postimage_result) { .content => |content| content, .semantic_failure => |message| return .{ .semantic_failure = message }, }; const before_content = switch (preimage) { .absent => "", .present => |present| present.content, }; const total_content_bytes = std.math.add( usize, before_content.len, after_content.len, ) catch return .{ .semantic_failure = total_content_too_large_message }; if (total_content_bytes > max_total_content_bytes) { return .{ .semantic_failure = total_content_too_large_message }; } // External anchors show the resolved target so a symlink redirect cannot look local. const approval_path = switch (policy_targets.anchor.scope) { .external => policy_targets.canonical_target_path, .workspace => input.path(), }; const encoded_path = text_utils.encodeTerminalSafePathTail( call_alloc, approval_path, diff_mod.max_encoded_path_bytes, ) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.PathBasenameTooLong => return .{ .semantic_failure = preview_too_large_message, }, }; const preview_result = try buildPreview( call_alloc, encoded_path, preimage, before_content, after_content, ); const preview = switch (preview_result) { .preview => |preview| preview, .semantic_failure => |message| return .{ .semantic_failure = message }, }; const review = diff_mod.FileReview.init( call_alloc, before_content, after_content, ) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ArithmeticOverflow => return .{ .semantic_failure = preview_too_large_message, }, }; var arguments_hasher = std.crypto.hash.sha2.Sha256.init(.{}); arguments_hasher.update(call.arguments_json); const commit_claim = try call_alloc.create(CommitClaim); commit_claim.* = .{}; return .{ .prepared = .{ .call_id = call.id, .tool_name = call.name, .arguments_hash = arguments_hasher.finalResult(), .target_path = policy_targets.canonical_target_path, .display_path = encoded_path.bytes, .policy_targets = policy_targets, .kind = std.meta.activeTag(input), .preimage = preimage, .after_content = after_content, .preview = preview, .review = review, .commit_token = commit_claim, } };} const ApplyTestControls = struct { ctx: ?*anyopaque = null, after_write_chunk: ?*const fn (?*anyopaque, usize) anyerror!void = null, after_stage: ?*const fn (?*anyopaque, std.Io.Dir, []const u8) anyerror!void = null, after_final_preimage_read: ?*const fn (?*anyopaque, std.Io.Dir, []const u8) anyerror!void = null, after_final_validation: ?*const fn (?*anyopaque) anyerror!void = null,}; const CreatedParentRecord = struct { component_index: usize, path_end: usize, permission_target_index: usize, identity: file_mutation_contract.FileIdentity,}; const PreimageValidation = union(enum) { valid: ?std.Io.File.Permissions, stale, io_failure,}; const TraversalValidation = union(enum) { parent: std.Io.Dir, changed, io_failure,}; const StagedSourceValidation = enum { valid, changed, io_failure,}; const TargetEntryValidation = enum { valid, changed, io_failure,}; const StagedWriteError = error{ Canceled, IoFailure,}; const ApplyResources = struct { policy: PolicyEvaluatedFileTargets, created: *[file_mutation_contract.max_file_target_components]CreatedParentRecord, realized: *[file_mutation_contract.max_file_target_components]file_mutation_contract.FileIdentity, residue_storage: []CreatedParentResidue, created_count: usize = 0, parent: ?std.Io.Dir = null, temp_name: ?[]const u8 = null, temp_identity: ?file_mutation_contract.FileIdentity = null, fn closeParent(self: *ApplyResources) void { if (self.parent) |parent| parent.close(io_mod.getIo()); self.parent = null; } fn reject( self: *ApplyResources, reason: ApplyRejectionReason, ) ApplyResult { self.cleanupTemp(); self.closeParent(); const residues = self.cleanupCreatedParents(); return .{ .rejected = .{ .reason = reason, .created_parent_residue = residues, } }; } fn cleanupTemp(self: *ApplyResources) void { const parent = self.parent orelse return; const temp_name = self.temp_name orelse return; const expected_identity = self.temp_identity orelse return; const actual_identity = observedFileIdentity(parent, temp_name) orelse return; if (!identityEql(actual_identity, expected_identity)) return; parent.deleteFile(io_mod.getIo(), temp_name) catch return; self.temp_name = null; self.temp_identity = null; } fn cleanupCreatedParents( self: *ApplyResources, ) []const CreatedParentResidue { var residue_count: usize = 0; var index = self.created_count; while (index > 0) { index -= 1; const created = self.created[index]; if (cleanupCreatedParent(self.policy, self.realized, created)) |residue| { self.residue_storage[residue_count] = residue; residue_count += 1; } } return self.residue_storage[0..residue_count]; }}; pub fn apply( call_alloc: std.mem.Allocator, result_alloc: std.mem.Allocator, call: types.ToolCall, authorization: file_mutation_contract.FileExecutionAuthorization, cancel_flag: *std.atomic.Value(bool),) FileMutationApplyError!ApplyResult { return applyWithTestControls( call_alloc, result_alloc, call, authorization, cancel_flag, .{}, );} fn applyWithTestControls( call_alloc: std.mem.Allocator, result_alloc: std.mem.Allocator, call: types.ToolCall, authorization: file_mutation_contract.FileExecutionAuthorization, cancel_flag: *std.atomic.Value(bool), test_controls: ApplyTestControls,) FileMutationApplyError!ApplyResult { const prepared = authorization.prepared orelse { return rejectedWithoutResidue(.binding_mismatch); }; if (!applyBindingValid(call, authorization.policy_targets, prepared)) { return rejectedWithoutResidue(.binding_mismatch); } const commit_claim = preparedCommitClaim(prepared); if (commit_claim.claimed.load(.seq_cst)) { return error.ResultContractViolation; } if (cancel_flag.load(.seq_cst)) return rejectedWithoutResidue(.cancelled); const residue_storage = try call_alloc.alloc( CreatedParentResidue, prepared.policy_targets.traversal_directories.len, ); const previous_content = switch (prepared.preimage) { .absent => null, .present => |present| present.content, }; var handoff = try dupeCommittedFileHandoff( result_alloc, prepared.preview, prepared.kind, prepared.target_path, previous_content, ); var handoff_owned = true; defer if (handoff_owned) handoff.deinit(result_alloc); var created: [file_mutation_contract.max_file_target_components]CreatedParentRecord = undefined; var realized: [file_mutation_contract.max_file_target_components]file_mutation_contract.FileIdentity = undefined; var resources: ApplyResources = .{ .policy = prepared.policy_targets, .created = &created, .realized = &realized, .residue_storage = residue_storage, }; defer resources.closeParent(); io_mod.e2eFailIfDurableMutationAttempted(); if (realizeTraversal(&resources)) |reason| return resources.reject(reason); const parent = resources.parent.?; const target_name = prepared.policy_targets.component( prepared.policy_targets.anchor.relative_components[ prepared.policy_targets.anchor.relative_components.len - 1 ], ); const initial_preimage = validatePreimage( parent, target_name, prepared, null, null, null, ); const destination_permissions = switch (initial_preimage) { .valid => |permissions| permissions, .stale => return resources.reject(.stale_preimage), .io_failure => return resources.reject(.io_failure), }; var random_bytes: [16]u8 = undefined; io_mod.getIo().random(&random_bytes); const suffix = std.fmt.bytesToHex(random_bytes, .lower); var temp_name_buffer: [".fx-stage-".len + suffix.len]u8 = undefined; @memcpy(temp_name_buffer[0..".fx-stage-".len], ".fx-stage-"); @memcpy(temp_name_buffer[".fx-stage-".len..], suffix[0..]); const temp_name = temp_name_buffer[0..]; var stage = parent.createFile(io_mod.getIo(), temp_name, .{ .read = true,Lines 1–500 of 3376. Load more
const std = @import("std"); const builtin = @import("builtin"); const diff_mod = @import("../output/diff.zig"); const file_mutation_contract = @import("file_mutation_contract.zig"); const io_mod = @import("../shared/io.zig"); const pathing = @import("../workspace/pathing.zig"); const text_utils = @import("../shared/text_utils.zig"); const types = @import("../shared/types.zig"); const testing_permissions = if (builtin.is_test) @import("../permissions/permissions.zig") else struct {}; const testing_builtin_tools = if (builtin.is_test) @import("../../builtins/tools.zig") else struct {}; const testing_write_file = if (builtin.is_test) @import("../../tools/filesystem/write_file.zig") else struct {}; const testing_edit_file = if (builtin.is_test) @import("../../tools/filesystem/edit_file.zig") else struct {}; const Allocator = std.mem.Allocator; const PreparedFileMutation = file_mutation_contract.PreparedFileMutation; const PolicyEvaluatedFileTargets = file_mutation_contract.PolicyEvaluatedFileTargets; const max_content_bytes: usize = 4 * 1024 * 1024; const max_total_content_bytes: usize = 8 * 1024 * 1024; pub const ParentCleanupResidueReason = enum { not_empty, identity_changed, remove_failed, }; pub const CreatedParentResidue = struct { component_index: usize, path_end: usize, permission_target_index: usize, created_identity: file_mutation_contract.FileIdentity, observed_identity: ?file_mutation_contract.FileIdentity, reason: ParentCleanupResidueReason, }; pub const ApplyRejectionReason = enum { binding_mismatch, stale_preimage, cancelled, traversal_changed, staged_source_changed, io_failure, }; pub const ApplyRejection = struct { reason: ApplyRejectionReason, created_parent_residue: []const CreatedParentResidue, }; pub const ChangeTrackerHandoff = struct { kind: file_mutation_contract.Kind, raw_path: []const u8, previous_content: ?[]const u8, committed_at_ms: i64, }; pub const FullViewSnapshot = struct { after_content: []const u8, lifecycle_id: types.ToolLifecycleId, }; pub const CommittedFileHandoff = struct { preview: diff_mod.FileChangePreview, tracker: ChangeTrackerHandoff, full_view: ?FullViewSnapshot = null, pub fn init( preview: diff_mod.FileChangePreview, tracker: ChangeTrackerHandoff, ) CommittedFileHandoff { return .{ .preview = preview, .tracker = tracker, }; } pub fn deinit(self: CommittedFileHandoff, alloc: Allocator) void { alloc.free(@constCast(self.preview.path)); for (self.preview.lines) |line| alloc.free(@constCast(line.text)); alloc.free(@constCast(self.preview.lines)); alloc.free(@constCast(self.tracker.raw_path)); if (self.tracker.previous_content) |content| { alloc.free(@constCast(content)); } if (self.full_view) |full_view| { alloc.free(@constCast(full_view.after_content)); alloc.free(@constCast(full_view.lifecycle_id.call_id)); } } pub fn attachFullView( self: *CommittedFileHandoff, alloc: Allocator, after_content: []const u8, lifecycle_id: types.ToolLifecycleId, ) Allocator.Error!void { const owned_after_content = try alloc.dupe(u8, after_content); errdefer alloc.free(owned_after_content); const owned_call_id = try alloc.dupe(u8, lifecycle_id.call_id); errdefer alloc.free(owned_call_id); self.full_view = .{ .after_content = owned_after_content, .lifecycle_id = .{ .turn_id = lifecycle_id.turn_id, .call_id = owned_call_id, }, }; } }; pub const ApplyResult = union(enum) { rejected: ApplyRejection, committed: CommittedFileHandoff, }; const target_mismatch_message = "file mutation preparation failed: approved target no longer matches the call"; const identity_changed_message = "file mutation preparation failed: approved filesystem identity changed"; const preview_too_large_message = "file mutation preparation failed: diff preview exceeds preparation limits"; const total_content_too_large_message = "file mutation preparation failed: content proof exceeds the 8 MiB preparation limit"; const FileMutationPrepareError = error{ OutOfMemory, Canceled, Unexpected, SystemResources, ProcessFdQuotaExceeded, SystemFdQuotaExceeded, }; const FileMutationApplyError = error{ OutOfMemory, ResultContractViolation, }; const PreimageResult = union(enum) { preimage: file_mutation_contract.Preimage, semantic_failure: []const u8, }; const PostimageResult = union(enum) { content: []const u8, semantic_failure: []const u8, }; const PreviewResult = union(enum) { preview: diff_mod.FileChangePreview, semantic_failure: []const u8, }; const CommitClaim = struct { claimed: std.atomic.Value(bool) = .init(false), }; var target_resolution_check_count: usize = 0; pub fn resetTargetResolutionCheckCountForTest() void { if (builtin.is_test) target_resolution_check_count = 0; } pub fn targetResolutionCheckCountForTest() usize { return if (builtin.is_test) target_resolution_check_count else 0; } pub fn prepare( call_alloc: std.mem.Allocator, call: types.ToolCall, input: file_mutation_contract.FileMutationInput, policy_targets: file_mutation_contract.PolicyEvaluatedFileTargets, ) FileMutationPrepareError!file_mutation_contract.PrepareResult { return prepareInternal(call_alloc, call, input, policy_targets, true); } /// Prepares a mutation whose decoded input and canonical target proof were /// produced together by tool admission. Identity, proof, preimage, and diff /// validation remain unchanged; only duplicate canonical resolution is skipped. pub fn prepareResolvedTarget( call_alloc: std.mem.Allocator, call: types.ToolCall, input: file_mutation_contract.FileMutationInput, policy_targets: file_mutation_contract.PolicyEvaluatedFileTargets, ) FileMutationPrepareError!file_mutation_contract.PrepareResult { return prepareInternal(call_alloc, call, input, policy_targets, false); } fn prepareInternal( call_alloc: std.mem.Allocator, call: types.ToolCall, input: file_mutation_contract.FileMutationInput, policy_targets: file_mutation_contract.PolicyEvaluatedFileTargets, verify_target_resolution: bool, ) FileMutationPrepareError!file_mutation_contract.PrepareResult { if (policyIdentityBindingMismatch(policy_targets)) { return .{ .semantic_failure = identity_changed_message }; } if (!policy_targets.proofValid()) { return .{ .semantic_failure = target_mismatch_message }; } if (verify_target_resolution and !try resolvedTargetMatches(input, policy_targets)) { return .{ .semantic_failure = target_mismatch_message }; } const preimage_result = try verifyAndReadPreimage(call_alloc, input, policy_targets); const preimage = switch (preimage_result) { .preimage => |preimage| preimage, .semantic_failure => |message| return .{ .semantic_failure = message }, }; const postimage_result = try derivePostimage(call_alloc, input, preimage); const after_content = switch (postimage_result) { .content => |content| content, .semantic_failure => |message| return .{ .semantic_failure = message }, }; const before_content = switch (preimage) { .absent => "", .present => |present| present.content, }; const total_content_bytes = std.math.add( usize, before_content.len, after_content.len, ) catch return .{ .semantic_failure = total_content_too_large_message }; if (total_content_bytes > max_total_content_bytes) { return .{ .semantic_failure = total_content_too_large_message }; } // External anchors show the resolved target so a symlink redirect cannot look local. const approval_path = switch (policy_targets.anchor.scope) { .external => policy_targets.canonical_target_path, .workspace => input.path(), }; const encoded_path = text_utils.encodeTerminalSafePathTail( call_alloc, approval_path, diff_mod.max_encoded_path_bytes, ) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.PathBasenameTooLong => return .{ .semantic_failure = preview_too_large_message, }, }; const preview_result = try buildPreview( call_alloc, encoded_path, preimage, before_content, after_content, ); const preview = switch (preview_result) { .preview => |preview| preview, .semantic_failure => |message| return .{ .semantic_failure = message }, }; const review = diff_mod.FileReview.init( call_alloc, before_content, after_content, ) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ArithmeticOverflow => return .{ .semantic_failure = preview_too_large_message, }, }; var arguments_hasher = std.crypto.hash.sha2.Sha256.init(.{}); arguments_hasher.update(call.arguments_json); const commit_claim = try call_alloc.create(CommitClaim); commit_claim.* = .{}; return .{ .prepared = .{ .call_id = call.id, .tool_name = call.name, .arguments_hash = arguments_hasher.finalResult(), .target_path = policy_targets.canonical_target_path, .display_path = encoded_path.bytes, .policy_targets = policy_targets, .kind = std.meta.activeTag(input), .preimage = preimage, .after_content = after_content, .preview = preview, .review = review, .commit_token = commit_claim, } }; } const ApplyTestControls = struct { ctx: ?*anyopaque = null, after_write_chunk: ?*const fn (?*anyopaque, usize) anyerror!void = null, after_stage: ?*const fn (?*anyopaque, std.Io.Dir, []const u8) anyerror!void = null, after_final_preimage_read: ?*const fn (?*anyopaque, std.Io.Dir, []const u8) anyerror!void = null, after_final_validation: ?*const fn (?*anyopaque) anyerror!void = null, }; const CreatedParentRecord = struct { component_index: usize, path_end: usize, permission_target_index: usize, identity: file_mutation_contract.FileIdentity, }; const PreimageValidation = union(enum) { valid: ?std.Io.File.Permissions, stale, io_failure, }; const TraversalValidation = union(enum) { parent: std.Io.Dir, changed, io_failure, }; const StagedSourceValidation = enum { valid, changed, io_failure, }; const TargetEntryValidation = enum { valid, changed, io_failure, }; const StagedWriteError = error{ Canceled, IoFailure, }; const ApplyResources = struct { policy: PolicyEvaluatedFileTargets, created: *[file_mutation_contract.max_file_target_components]CreatedParentRecord, realized: *[file_mutation_contract.max_file_target_components]file_mutation_contract.FileIdentity, residue_storage: []CreatedParentResidue, created_count: usize = 0, parent: ?std.Io.Dir = null, temp_name: ?[]const u8 = null, temp_identity: ?file_mutation_contract.FileIdentity = null, fn closeParent(self: *ApplyResources) void { if (self.parent) |parent| parent.close(io_mod.getIo()); self.parent = null; } fn reject( self: *ApplyResources, reason: ApplyRejectionReason, ) ApplyResult { self.cleanupTemp(); self.closeParent(); const residues = self.cleanupCreatedParents(); return .{ .rejected = .{ .reason = reason, .created_parent_residue = residues, } }; } fn cleanupTemp(self: *ApplyResources) void { const parent = self.parent orelse return; const temp_name = self.temp_name orelse return; const expected_identity = self.temp_identity orelse return; const actual_identity = observedFileIdentity(parent, temp_name) orelse return; if (!identityEql(actual_identity, expected_identity)) return; parent.deleteFile(io_mod.getIo(), temp_name) catch return; self.temp_name = null; self.temp_identity = null; } fn cleanupCreatedParents( self: *ApplyResources, ) []const CreatedParentResidue { var residue_count: usize = 0; var index = self.created_count; while (index > 0) { index -= 1; const created = self.created[index]; if (cleanupCreatedParent(self.policy, self.realized, created)) |residue| { self.residue_storage[residue_count] = residue; residue_count += 1; } } return self.residue_storage[0..residue_count]; } }; pub fn apply( call_alloc: std.mem.Allocator, result_alloc: std.mem.Allocator, call: types.ToolCall, authorization: file_mutation_contract.FileExecutionAuthorization, cancel_flag: *std.atomic.Value(bool), ) FileMutationApplyError!ApplyResult { return applyWithTestControls( call_alloc, result_alloc, call, authorization, cancel_flag, .{}, ); } fn applyWithTestControls( call_alloc: std.mem.Allocator, result_alloc: std.mem.Allocator, call: types.ToolCall, authorization: file_mutation_contract.FileExecutionAuthorization, cancel_flag: *std.atomic.Value(bool), test_controls: ApplyTestControls, ) FileMutationApplyError!ApplyResult { const prepared = authorization.prepared orelse { return rejectedWithoutResidue(.binding_mismatch); }; if (!applyBindingValid(call, authorization.policy_targets, prepared)) { return rejectedWithoutResidue(.binding_mismatch); } const commit_claim = preparedCommitClaim(prepared); if (commit_claim.claimed.load(.seq_cst)) { return error.ResultContractViolation; } if (cancel_flag.load(.seq_cst)) return rejectedWithoutResidue(.cancelled); const residue_storage = try call_alloc.alloc( CreatedParentResidue, prepared.policy_targets.traversal_directories.len, ); const previous_content = switch (prepared.preimage) { .absent => null, .present => |present| present.content, }; var handoff = try dupeCommittedFileHandoff( result_alloc, prepared.preview, prepared.kind, prepared.target_path, previous_content, ); var handoff_owned = true; defer if (handoff_owned) handoff.deinit(result_alloc); var created: [file_mutation_contract.max_file_target_components]CreatedParentRecord = undefined; var realized: [file_mutation_contract.max_file_target_components]file_mutation_contract.FileIdentity = undefined; var resources: ApplyResources = .{ .policy = prepared.policy_targets, .created = &created, .realized = &realized, .residue_storage = residue_storage, }; defer resources.closeParent(); io_mod.e2eFailIfDurableMutationAttempted(); if (realizeTraversal(&resources)) |reason| return resources.reject(reason); const parent = resources.parent.?; const target_name = prepared.policy_targets.component( prepared.policy_targets.anchor.relative_components[ prepared.policy_targets.anchor.relative_components.len - 1 ], ); const initial_preimage = validatePreimage( parent, target_name, prepared, null, null, null, ); const destination_permissions = switch (initial_preimage) { .valid => |permissions| permissions, .stale => return resources.reject(.stale_preimage), .io_failure => return resources.reject(.io_failure), }; var random_bytes: [16]u8 = undefined; io_mod.getIo().random(&random_bytes); const suffix = std.fmt.bytesToHex(random_bytes, .lower); var temp_name_buffer: [".fx-stage-".len + suffix.len]u8 = undefined; @memcpy(temp_name_buffer[0..".fx-stage-".len], ".fx-stage-"); @memcpy(temp_name_buffer[".fx-stage-".len..], suffix[0..]); const temp_name = temp_name_buffer[0..]; var stage = parent.createFile(io_mod.getIo(), temp_name, .{ .read = true,