const std = @import("std"); // Local v1 guardrails for SSH/iPhone use: visible rows instead of silent stalls. // req: testing/001, testing/002, testing/003, testing/004 pub const max_file_bytes: usize = 1024 * 1024; pub const max_search_rows: usize = 64; pub const process_stdout_limit: usize = 256 * 1024; pub const process_stderr_limit: usize = 256 * 1024; pub fn searchTruncatedRowAlloc(allocator: std.mem.Allocator, shown: usize, limit: usize) ![]u8 { return std.fmt.allocPrint(allocator, "diagnostic:search_truncated:showing_{d}_of_limit_{d}", .{ shown, limit }); } pub fn fileTooLargeRowAlloc(allocator: std.mem.Allocator, bytes: usize, limit: usize) ![]u8 { return std.fmt.allocPrint(allocator, "diagnostic:file_too_large:{d}_bytes_limit_{d}", .{ bytes, limit }); } pub fn unsupportedFileRowAlloc(allocator: std.mem.Allocator, reason: []const u8) ![]u8 { return std.fmt.allocPrint(allocator, "diagnostic:unsupported_file:{s}", .{reason}); } pub fn processLimitRowAlloc(allocator: std.mem.Allocator, kind: []const u8, stdout_limit: usize, stderr_limit: usize) ![]u8 { return std.fmt.allocPrint(allocator, "diagnostic:{s}_limits:stdout_{d}:stderr_{d}", .{ kind, stdout_limit, stderr_limit }); } pub fn saveFailedRowAlloc(allocator: std.mem.Allocator, reason: []const u8) ![]u8 { return std.fmt.allocPrint(allocator, "diagnostic:save_failed:{s}", .{reason}); } pub fn sanitizeReason(reason: []const u8) []const u8 { if (reason.len == 0) return "unknown"; for (reason) |byte| { if (byte <= 0x20 or byte == ':' or byte == '|') return "invalid"; } return reason; } test "regular: diagnostic rows are compact and actionable" { const row = try searchTruncatedRowAlloc(std.testing.allocator, 64, 64); defer std.testing.allocator.free(row); try std.testing.expectEqualStrings("diagnostic:search_truncated:showing_64_of_limit_64", row); } test "adversarial: unsafe diagnostic reasons are sanitized" { try std.testing.expectEqualStrings("invalid", sanitizeReason("two words")); try std.testing.expectEqualStrings("unknown", sanitizeReason("")); try std.testing.expectEqualStrings("spawn_error", sanitizeReason("spawn_error")); }