Files
meeting-assistant/tools/ci/MacOsNativeDiagnostic.cs
T

1985 lines
173 KiB
C#

#:property PublishAot=false
using System.Diagnostics;
using System.Buffers.Binary;
using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Xml;
using System.Xml.Linq;
// .NET 10 file-based CI diagnostic. See docs/macos-native-diagnostic.md.
return await NativeDiagnostic.Execute(args);
static class NativeDiagnostic
{
const string DockurCommit = "16a5b470cdd601bae8b05b02d748d7edfb36c12e";
const string Profile = "tcg-skylake-sonoma";
const string CpuModel = "Skylake-Client-v4";
const string CpuFlags = "Skylake-Client-v4,l3-cache=on,+hypervisor,vendor=GenuineIntel,vmx=off,vmware-cpuid-freq=on,-pdpe1gb,-spec-ctrl,-pcid,-invpcid,-tsc-deadline,-xsavec,-xsaves,+ssse3,+sse4.2,+popcnt,+avx,+avx2,+aes,+fma,+bmi1,+bmi2,+smep,+xsave,+xsaveopt,+xgetbv1,+movbe,+rdrand,enforce=on";
const string OpenCoreTemplateHash = "287328995d4198f1b05166f087d85bf7ef66bedafe150d17ad112ac8de60051d";
const string UdifChecksumBindingHash = "6109d04619e800c483fdac363d593cd1cd69f34131d2521417334e11d41c8bfa";
const string OwnerLabel = "org.meeting-assistant.native-diagnostic";
const long GuestDiskBytes = 64L * 1024 * 1024 * 1024;
const long ContainerMemoryBytes = 6L * 1024 * 1024 * 1024;
const int MaximumCapturedCharacters = 8 * 1024 * 1024;
const string SdkVersion = "10.0.401";
const string SdkSha512 = "33401b4a2da8554e3306db6072ea8569d9fcc608509c271e0aa4b39e7cc432da3631f14e7e1e2445d67d72550d18ce44a8bbd2382a756867ad2edab6b1c963c0";
const string FullState = "/storage/14/ci-state";
const string NativeVersionSource = "/System/Library/CoreServices/SystemVersion.plist";
const string NativeVersionMethod = "guest-file/host-xml";
const int MaximumDiskStackBytes = 512 * 1024;
const string ProbeSourceHash = "38acf83b05694f9931c41ff1749e9b6b836f04c740b7f1a1c60e32332678cb1f";
const string ProbeDriverHash = "d9d87415c12398f29b35697109f18d9b16f121dae969a4a05d0ec6a8cb874d25";
const string ProbeBinaryHash = "b8d54e2945eeefb3e0c22468feb7aef7efa50813909058b1e4b40144dd7e3d3e";
const string ProbeManifestHash = "9e71d39e2dd65ab83d0827a467e85893f410ef03e34fb72e08daa27e74861ba3";
static readonly JsonSerializerOptions JsonOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true };
const string OriginalBootstrap = "[ ! -e /tmp/m ]&&{ /sbin/mount_9p installstate >/dev/null 2>&1;exec /Volumes/installstate/launch.sh;};: >/tmp/m\n";
const string MountOnlyBootstrap = "[ ! -e /tmp/m ]&& /sbin/mount_9p installstate >/dev/null 2>&1; : >/tmp/m\n";
static readonly string OriginalDaemon = """
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
\t<key>Label</key>
\t<string>com.apple.recoveryosd</string>
\t<key>OnDemand</key>
\t<false/>
\t<key>ProcessType</key>
\t<string>App</string>
\t<key>EnablePressuredExit</key>
\t<false/>
\t<key>ProgramArguments</key>
\t<array>
\t\t<string>/usr/libexec/recoveryosd</string>
\t</array>
</dict>
</plist>
""".Replace("\\t", "\t", StringComparison.Ordinal);
static readonly string DiagnosticDaemon = (OriginalDaemon + "\n")
.Replace("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n", "", StringComparison.Ordinal)
.Replace("\t\t<string>/usr/libexec/recoveryosd</string>", "\t\t<string>/bin/bash</string>\n\t\t<string>/Volumes/installstate/launch.sh</string>", StringComparison.Ordinal);
// Exact XML framing read from the Apple 13 comparison download, not an assertion
// about the unretained bytes downloaded by run 4173.
static readonly string OriginalDaemon13 = ReplaceOnce(OriginalDaemon + "\n", "<string>App</string>", "<string>Interactive</string>");
static readonly string DiagnosticDaemon13 = ReplaceOnce(DiagnosticDaemon, "<string>App</string>", "<string>Interactive</string>");
public static async Task<int> Execute(string[] args)
{
if (args.Length == 0 || args.Contains("--help"))
{
Console.WriteLine("dotnet run --file tools/ci/MacOsNativeDiagnostic.cs -- --run|--cleanup|--validate [--full] [--output artifacts/native-macos] [--source existing-dockur-clone] [--compression-chunk readonly-qualified-chunk]");
return 0;
}
var output = Path.GetFullPath(Option(args, "--output") ?? "artifacts/native-macos");
var full = args.Contains("--full");
if (args.Contains("--validate"))
{
ValidateContracts();
ValidateBootProgress();
ValidateDiskStackCapture(output);
ValidateProbeAssetFixtures(output);
await ValidateNativeSystemVersion(output);
if (full) ValidateFullContracts();
if (Option(args, "--source") is { } source)
{
await PrepareSource(Path.GetFullPath(source), output, full ? new string('0', 32) : "validation", false, CancellationToken.None, full);
await ValidateResourceRetention(output);
await ValidateRecoveryPatch(output);
await ValidateTcgPreflight(output, CancellationToken.None);
if (full) await ValidateDiskSerialParser(output);
Save(Path.Combine(output, "validation.json"), new
{
success = true, profile = Profile, mode = full ? "full" : "readiness",
helperSha256 = Hash(File.ReadAllBytes(Path.Combine("tools", "ci", "MacOsNativeDiagnostic.cs"))),
readinessSourceSha256 = Hash(File.ReadAllBytes(Path.Combine("tools", "ci", "macos-native-readiness.sh"))),
udifChecksumBindingSha256 = Hash(File.ReadAllBytes(Path.Combine("tools", "ci", "macos-native-udif-checksums.py"))),
baselineReadinessNormalized = true, readinessDiagnosticBlocksExcluded = 7,
nativeVersionGetterBlocksExcluded = 2, nativeVersionGetterSequenceRestored = true,
nativeVersionMethod = NativeVersionMethod, nativeVersionSource = NativeVersionSource,
nativeVersionMaximumBytes = 4096, nativeVersionResponseRequired = false,
nativeVersionCandidateIsQualifiedReadiness = false, nativeVersionBindingRequiredBeforePermit = true,
nativeVersionFixtures = "native-system-version-fixtures.json", nativeProductVersionCommandRemoved = true,
diskReadinessAttemptLimit = 1, diskCommandLimitSeconds = 600, diskCommandExtendedForDiagnosticObservation = true,
diskObservationCommandLimitSeconds = 60, stackSamplingRequested = true, stackSamplingDurationSeconds = 1,
stackSamplingIntervalMilliseconds = 100, stackSamplingMayDie = false, stackSamplingRuntimeSucceeded = false,
nativeProcessProbeBeforeAndAfter = true, nativeProcessProbeObservationPauseSeconds = 180, sampleUsageControlLimitSeconds = 45,
nativeProcessProbeSourceSha256 = ProbeSourceHash, nativeProcessProbeDriverSha256 = ProbeDriverHash,
nativeProcessProbeBinarySha256 = ProbeBinaryHash, nativeProcessProbeManifestSha256 = ProbeManifestHash,
nativeProcessProbeRecoveryPermissionProven = false, nativeProcessProbeAssetNegativeCases = 4,
nativeProcessProbePrivateApiWeakImported = true, nativeProcessProbeStagingFixtureVerified = true,
stackObservationIsQualifiedReadiness = false, diskStackMaximumCapturedBytes = MaximumDiskStackBytes,
diskManagementDiagnosticLabel = "com.apple.storagekitd", diskStackCaptureFixtureCases = 4,
resultNegativeCases = 6, containerNegativeCases = 11, recoveryPositiveCases = 4, recoveryNegativeCases = 12,
independentFixtureCrc32Readback = true, resourceSnapshotRetention = true, cpuProfileSourceContractsVerified = true,
preflightGateFixtureCases = 8, qemuRuntimePreflightExecuted = false, templateIsoDownloaded = false,
bootProgressParserFixtureCases = 6, recoveryRepeatGuardBeforePermit = true,
fullResultContractsVerified = full, fullBootstrapFixtureCases = full ? 12 : 0,
installerGuardFixtureCases = full ? 10 : 0, firstbootEvidenceFixtureCases = full ? 4 : 0, ownedDiskSerialFixtureCases = full ? 6 : 0,
sourceModified = false, dockerExecuted = false, guestExecuted = false, completedUtc = DateTimeOffset.UtcNow
});
}
if (full && Option(args, "--source") is null) await ValidateDiskSerialParser(output);
if (Option(args, "--compression-chunk") is { } chunk) await ValidateCompression(Path.GetFullPath(chunk), output);
Console.WriteLine("Source patch contracts and diagnostic result validation passed; no Docker or guest execution occurred.");
return 0;
}
if (args.Contains("--cleanup"))
return await Cleanup(output) ? 0 : 1;
if (!args.Contains("--run")) throw new ArgumentException("Choose --run, --cleanup or --validate.");
Directory.CreateDirectory(output);
var statePath = Path.Combine(output, "owned-resources.json");
if (File.Exists(statePath)) throw new InvalidOperationException("Output already contains a run identity; choose a fresh directory or clean up its run first.");
var token = Guid.NewGuid().ToString("N");
var work = Path.Combine(Environment.GetEnvironmentVariable("RUNNER_TEMP") ?? Path.GetTempPath(), "meeting-assistant-native-" + token);
var state = new OwnedResources(token, "meeting-assistant-native-" + token, "meeting-assistant-native-diagnostic:" + token, work);
Save(statePath, state);
Directory.CreateDirectory(work);
File.WriteAllText(Path.Combine(work, "run.owner"), token);
// Full leaves eight minutes within the existing three-hour job for capture/cleanup.
var deadlineMinutes = full ? 172 : 90;
using var deadline = new CancellationTokenSource(TimeSpan.FromMinutes(deadlineMinutes));
using var signal = OperatingSystem.IsLinux() ? PosixSignalRegistration.Create(PosixSignal.SIGTERM, context => { context.Cancel = true; deadline.Cancel(); }) : null;
ConsoleCancelEventHandler cancelHandler = (_, context) => { context.Cancel = true; deadline.Cancel(); };
Console.CancelKeyPress += cancelHandler;
var outcome = "failed";
string? error = null;
try
{
if (!OperatingSystem.IsLinux() || RuntimeInformation.ProcessArchitecture != Architecture.X64)
throw new InvalidOperationException("This diagnostic runs on the existing Linux/x64 runner only.");
ValidateContracts();
var sourceCommit = (await Command("git", ["rev-parse", "HEAD"], output, "candidate-commit", deadline.Token)).Output.Trim();
Save(Path.Combine(output, "run-metadata.json"), new { token, startedUtc = DateTimeOffset.UtcNow, sourceCommit, dockurCommit = DockurCommit, profile = Profile, causalSingleVariableTest = false, kvm = false, cpuModel = CpuModel, recoveryMajor = 14, cpuFlags = CpuFlags, runId = Environment.GetEnvironmentVariable("GITHUB_RUN_ID"), server = Environment.GetEnvironmentVariable("GITHUB_SERVER_URL"), architecture = RuntimeInformation.ProcessArchitecture.ToString(), deadlineMinutes, mode = full ? "full" : "readiness" });
var info = await Command("docker", ["info", "--format", "{{json .}}"], output, "docker-info", deadline.Token);
using (var document = JsonDocument.Parse(info.Output))
{
var data = document.RootElement;
if (data.GetProperty("OSType").GetString() != "linux" || data.GetProperty("Architecture").GetString() is not ("x86_64" or "amd64"))
throw new InvalidOperationException("The existing Docker daemon is not Linux/x64; this diagnostic does not reconfigure it.");
if (data.GetProperty("NCPU").GetInt32() < 2 || data.GetProperty("MemTotal").GetInt64() < ContainerMemoryBytes)
throw new InvalidOperationException("Existing Docker resources cannot fit this bounded 2-CPU/6-GiB diagnostic; no infrastructure change was requested.");
}
await Command("sh", ["-c", "cat /proc/meminfo; printf '\n[cgroup]\n'; cat /sys/fs/cgroup/memory.max /sys/fs/cgroup/cpu.max 2>/dev/null || true; printf '\n[workspace disk]\n'; df -Pk ."], output, "runner-resources", deadline.Token);
var available = System.Text.RegularExpressions.Regex.Match(File.ReadAllText("/proc/meminfo"), @"(?m)^MemAvailable:\s+(\d+) kB$");
if (!available.Success || long.Parse(available.Groups[1].Value) < 5L * 1024 * 1024)
throw new InvalidOperationException("Existing runner memory has less than the 5-GiB available diagnostic budget; no infrastructure change was requested.");
var source = Path.Combine(work, "dockur");
await Command("git", ["clone", "--no-checkout", "https://github.com/dockur/macos.git", source], output, "dockur-clone", deadline.Token);
await Command("git", ["-C", source, "checkout", "--detach", DockurCommit], output, "dockur-checkout", deadline.Token);
var actualCommit = (await Command("git", ["-C", source, "rev-parse", "HEAD"], output, "dockur-commit", deadline.Token)).Output.Trim();
if (actualCommit != DockurCommit) throw new InvalidOperationException("Dockur source pin mismatch.");
if (full) await PreparePayload(source, output, token, sourceCommit, deadline.Token);
await PrepareSource(source, output, token, true, deadline.Token, full);
await Command("docker", ["build", "--platform", "linux/amd64", "--label", OwnerLabel + "=" + token, "--tag", state.ImageTag, source], output, "docker-build", deadline.Token, echo: true);
var imageInspect = await Command("docker", ["image", "inspect", state.ImageTag], output, "image-inspect", deadline.Token);
using (var image = JsonDocument.Parse(imageInspect.Output))
state = state with { ImageId = image.RootElement[0].GetProperty("Id").GetString() };
Save(statePath, state);
List<string> createArguments = ["create", "--name", state.ContainerName, "--label", OwnerLabel + "=" + token, "--memory", "6g", "--memory-swap", "6g", "--cpus", "2", "--shm-size", "512m", "--log-opt", "max-size=8m", "--log-opt", "max-file=1", "--env", "KVM=N", "--env", "CPU_MODEL=" + CpuModel, "--env", "NETWORK=slirp", "--env", "DISPLAY=web", "--env", "MANUAL=N", "--env", "VERSION=14", "--env", "RAM_SIZE=4G", "--env", "CPU_CORES=2", "--env", "DISK_SIZE=64G", "--env", "DISK_TYPE=sata", "--env", "ARGUMENTS=-object iothread,id=io2"];
if (full) createArguments.AddRange(["--env", "ALLOCATE=N", "--env", "DISK_OPTIONS=serial=" + DiskSerial(token)]);
createArguments.Add(state.ImageTag);
var create = await Command("docker", createArguments.ToArray(), output, "docker-create", deadline.Token);
var id = create.Output.Trim();
if (!System.Text.RegularExpressions.Regex.IsMatch(id, "^[0-9a-f]{64}$")) throw new InvalidOperationException("Docker did not return a container identity.");
state = state with { ContainerId = id };
Save(statePath, state);
await Command("docker", ["inspect", id], output, "container-created", deadline.Token);
AssertContainer(File.ReadAllText(Path.Combine(output, "container-created.stdout.log")), token);
await Command("docker", ["start", id], output, "docker-start", deadline.Token);
await CapturePressure(id, output, "before", deadline.Token);
Console.WriteLine(full ? "The owned unprivileged TCG/Skylake macOS 14 guest is starting. Installation requires fresh native readiness and an owned-disk permit; success requires all 577 tests with zero skips." : "The owned unprivileged TCG/Skylake macOS 14 guest is starting. Success requires native macOS 14+/x86_64 and a writable 64-GiB disk; no installer will run.");
var phaseStarted = Stopwatch.StartNew();
var phase = "recovery";
var phaseBudget = TimeSpan.FromMinutes(90);
var permitted = false;
var heartbeat = Stopwatch.StartNew();
var diskPressureCaptured = false;
while (true)
{
deadline.Token.ThrowIfCancellationRequested();
await CaptureGuest(id, output, deadline.Token, full, token: token);
if (!permitted) CheckRecoveryBootProgress(output);
if (full && phaseStarted.Elapsed > phaseBudget)
throw new InvalidOperationException("The bounded native " + phase + " phase exceeded " + phaseBudget.TotalMinutes + " minutes.");
var proofPath = Path.Combine(output, "guest-proof.log");
if (!diskPressureCaptured && File.Exists(proofPath) && File.ReadAllText(proofPath).Contains("[proof-start] disks", StringComparison.Ordinal))
{
diskPressureCaptured = true;
await CapturePressure(id, output, "during", deadline.Token);
}
var resultPath = Path.Combine(output, "guest-result.json");
if (File.Exists(resultPath) && !permitted)
{
var result = File.ReadAllText(resultPath);
ValidateResult(result, token);
ValidateNativeVersionBinding(output, token, result);
if (full)
{
await PermitInstallation(id, output, token, sourceCommit, result, deadline.Token);
permitted = true;
phase = "installation";
phaseBudget = TimeSpan.FromMinutes(80);
phaseStarted.Restart();
}
else
{
Console.WriteLine("Native Recovery readiness passed. This run has not installed macOS, .NET, CLT, or run Meeting Assistant tests.");
outcome = "readiness-passed";
break;
}
}
if (full)
{
var phasePath = Path.Combine(output, "guest-phase.json");
if (File.Exists(phasePath))
{
using var nativePhase = JsonDocument.Parse(File.ReadAllText(phasePath));
if (nativePhase.RootElement.GetProperty("token").GetString() != token) throw new InvalidOperationException("Stale native phase receipt.");
var current = nativePhase.RootElement.GetProperty("phase").GetString();
var next = !permitted ? phase : current == "toolchain-installing" ? "toolchain" : current is "tests-running" or "tests-passed" ? "tests" : phase;
if (next != phase) { phase = next; phaseBudget = TimeSpan.FromMinutes(next == "toolchain" ? 30 : 25); phaseStarted.Restart(); Console.WriteLine("[native-diagnostic] phase: " + phase); }
if (current is "tests-failed" or "bootstrap-failed" or "installation-failed") throw new InvalidOperationException("Guest phase failed: " + current);
}
var fullResult = Path.Combine(output, "full-result.json");
if (permitted && File.Exists(fullResult))
{
ValidateFullResult(File.ReadAllText(fullResult), token, sourceCommit, File.ReadAllText(Path.Combine(output, "archive.sha256")).Trim());
ValidateTrx(File.ReadAllBytes(Path.Combine(output, "native.trx")), File.ReadAllText(fullResult));
outcome = "native-tests-passed";
Console.WriteLine("Native macOS 577/577 tests passed, including all five native tests, with fresh Mach-O/x86_64 and codesign evidence.");
break;
}
}
var running = await Command("docker", ["inspect", "--format", "{{.State.Running}}", id], output, "container-running", deadline.Token);
if (running.Output.Trim() != "true") throw new InvalidOperationException("Guest container exited before a native readiness result.");
if (heartbeat.Elapsed >= TimeSpan.FromSeconds(60))
{
Console.WriteLine($"[native-diagnostic] phase={phase}; elapsed={phaseStarted.Elapsed.TotalMinutes:F1}/{phaseBudget.TotalMinutes:F0} minutes; container=running; readiness={(permitted ? "passed" : "pending")}");
heartbeat.Restart();
}
await Task.Delay(TimeSpan.FromSeconds(20), deadline.Token);
}
}
catch (Exception exception)
{
error = exception is OperationCanceledException ? $"The explicit {deadlineMinutes}-minute diagnostic deadline or cancellation was reached." : exception.Message;
Console.Error.WriteLine(error);
}
finally
{
Console.CancelKeyPress -= cancelHandler;
using var captureDeadline = new CancellationTokenSource(TimeSpan.FromSeconds(45));
try { await CaptureGuest(state.ContainerId ?? state.ContainerName, output, captureDeadline.Token, full, true, state.Token); } catch (Exception exception) { Console.Error.WriteLine("Final evidence capture: " + exception.Message); }
await CapturePressure(state.ContainerId ?? state.ContainerName, output, "after", captureDeadline.Token);
try { PrintGuestProof(output, state.Token); } catch (Exception exception) { Console.Error.WriteLine("Native proof output: " + exception.Message); }
if (full) try { PrintFullProof(output, state.Token); } catch (Exception exception) { Console.Error.WriteLine("Full native proof output: " + exception.Message); }
var clean = await Cleanup(output);
if (!clean) { outcome = "failed"; error = (error ?? "") + " Owned-resource cleanup failed; inspect cleanup evidence."; }
Save(Path.Combine(output, "outcome.json"), new { token, outcome, error, completedUtc = DateTimeOffset.UtcNow });
}
return outcome is "readiness-passed" or "native-tests-passed" ? 0 : 1;
}
static string? Option(string[] args, string name)
{
var index = Array.IndexOf(args, name);
return index < 0 ? null : index + 1 < args.Length ? args[index + 1] : throw new ArgumentException("Missing value for " + name);
}
static void ValidateContracts()
{
var readiness = File.ReadAllText(Path.Combine("tools", "ci", "macos-native-readiness.sh"));
var baseline = NormalizeReadinessDiagnostics(readiness);
baseline = ReplaceOnce(baseline, "while (( attempt < 1 && SECONDS - readiness_start < 600 )); do", "while (( SECONDS - readiness_start < 600 )); do");
if (Hash(Encoding.UTF8.GetBytes(baseline)) != "4d428f594dac14eff64ed87b172c81ecf85ac91da8c5460cd6ec4b1d310800c3")
throw new InvalidOperationException("Outside seven explicit diagnostic blocks, two explicit native SystemVersion getter blocks and one-attempt limit, baseline identity/service/disk gates and watchdogs must remain identical.");
foreach (var required in new[] { "command_limit=600; fi", "run_command sample_usage /usr/bin/sample", "run_command management_before /bin/launchctl print system/com.apple.storagekitd", "observe_live_command storagekit-live /bin/launchctl print system/com.apple.storagekitd", "observe_command diskutil-stack /usr/bin/sample \"$disk_process\" 1 100 -file \"$stack_output\"", "observe_live_command diskutil-native-before \"$STATE_DIR/native-process-probe-x86_64\" \"$disk_process\" \"$$\"", "observe_live_command diskutil-native-after \"$STATE_DIR/native-process-probe-x86_64\" \"$disk_process\" \"$$\"", "read -r -t 180 -u 9", "stack_output=\"$STATE_DIR/diskutil-stack.txt\"", "read -r -t 60 -u 9", "\"$BASH_VERSION\"" })
if (!readiness.Contains(required, StringComparison.Ordinal)) throw new InvalidOperationException("Owned optional disk observation contract changed: " + required);
if (readiness.Contains("PENDING_OUTPUTS+=(\"$stack_output\")", StringComparison.Ordinal)) throw new InvalidOperationException("Stack reports must be bounded directly by the Linux host, without another guest copy.");
ReadProbeAssets();
if (Hash(File.ReadAllBytes(Path.Combine("tools", "ci", "macos-native-bootstrap.sh"))) != "94f069e116fdc7685a4d233cab6fa50df9f39274386bb82157674061e74fadb5")
throw new InvalidOperationException("Compatibility profile must preserve the baseline Apple recoveryosd wrapper.");
if (Hash(Encoding.UTF8.GetBytes(OriginalDaemon13)) != "af9d7f6c1948079bd4384d27b6882678d6fb4e338fcf6a8be8f84fceef174ad6") throw new InvalidOperationException("macOS 13 allowlist bytes differ from the independently read comparison plist.");
foreach (var variant in new[] { (OriginalDaemon + "\n", DiagnosticDaemon, "App"), (OriginalDaemon13, DiagnosticDaemon13, "Interactive") })
{
ValidateDaemon(variant.Item1, variant.Item3, false);
ValidateDaemon(variant.Item2, variant.Item3, true);
if (Encoding.UTF8.GetByteCount(variant.Item2) > Encoding.UTF8.GetByteCount(variant.Item1)) throw new InvalidOperationException("Daemon replacement exceeds original file.");
}
var good = JsonSerializer.Serialize(new { token = "validation", success = true, osVersion = "14.6.1", architecture = "x86_64", uid = 0, disk = "/dev/disk1", diskBytes = GuestDiskBytes, readOnly = false, systemExit = 0, diskArbitrationExit = 0, recoveryExit = 0, diskListExit = 0 });
ValidateResult(good, "validation");
foreach (var invalid in new[] { good.Replace("14.6.1", "13.6.1"), good.Replace("x86_64", "arm64"), good.Replace("\"readOnly\":false", "\"readOnly\":true"), good.Replace("\"success\":true", "\"success\":false"), good.Replace("68719476736", "17179869184"), good.Replace("validation", "stale") })
{
try { ValidateResult(invalid, "validation"); } catch (InvalidOperationException) { continue; }
throw new InvalidOperationException("Diagnostic validator accepted an invalid/stale result.");
}
var boundary = """
[{"Config":{"Labels":{"org.meeting-assistant.native-diagnostic":"validation"},"Env":["KVM=N","CPU_MODEL=Skylake-Client-v4","VERSION=14"]},"HostConfig":{"Privileged":false,"NetworkMode":"default","Memory":6442450944,"MemorySwap":6442450944,"NanoCpus":2000000000,"ShmSize":536870912,"CapAdd":null,"DeviceRequests":null,"Binds":null,"PortBindings":{},"DeviceCgroupRules":null,"Tmpfs":null,"Devices":[]},"Mounts":[{"Type":"volume","Destination":"/storage","RW":true}]}]
""";
AssertContainer(boundary, "validation");
foreach (var invalid in new[] { boundary.Replace("\"Privileged\":false", "\"Privileged\":true"), boundary.Replace("\"Devices\":[]", "\"Devices\":[{\"PathOnHost\":\"/dev/kvm\",\"PathInContainer\":\"/dev/kvm\",\"CgroupPermissions\":\"rw\"}]"), boundary.Replace("KVM=N", "KVM=Y"), boundary.Replace("CPU_MODEL=Skylake-Client-v4", "CPU_MODEL=host"), boundary.Replace("VERSION=14", "VERSION=13"), boundary.Replace("6442450944", "8589934592"), boundary.Replace("\"NetworkMode\":\"default\"", "\"NetworkMode\":\"host\""), boundary.Replace("\"CapAdd\":null", "\"CapAdd\":[\"NET_ADMIN\"]"), boundary.Replace("\"Type\":\"volume\"", "\"Type\":\"bind\""), boundary.Replace("/storage", "/host"), boundary.Replace("\"NanoCpus\":2000000000", "\"NanoCpus\":4000000000") })
{
try { AssertContainer(invalid, "validation"); } catch (InvalidOperationException) { continue; }
throw new InvalidOperationException("Diagnostic validator accepted an excessive/wrong-profile container boundary.");
}
}
static string NormalizeReadinessDiagnostics(string source)
{
const string start = "# BEGIN disk IPC diagnostic\n";
const string end = "# END disk IPC diagnostic\n";
var blocks = 0;
while (source.IndexOf(start, StringComparison.Ordinal) is var from && from >= 0)
{
var to = source.IndexOf(end, from + start.Length, StringComparison.Ordinal);
if (to < 0 || source.IndexOf(start, from + start.Length, to - from - start.Length, StringComparison.Ordinal) >= 0)
throw new InvalidOperationException("Readiness diagnostic blocks are unbalanced or nested.");
source = source.Remove(from, to + end.Length - from);
blocks++;
}
if (blocks != 7 || source.Contains(end, StringComparison.Ordinal))
throw new InvalidOperationException("Readiness must contain exactly seven explicit disk IPC diagnostic blocks.");
source = RestoreVersionBlock(source, "native SystemVersion plist request helpers", "");
source = RestoreVersionBlock(source, "native SystemVersion plist getter", OriginalVersionGetter + "\n");
return source;
}
// Only this getter is restored for the baseline comparison. Native uname/id,
// launchd exits, writable-disk gates and every command watchdog stay intact.
const string OriginalVersionGetter = """
run_command platform /usr/bin/sw_vers
platform_exit="$LAST_EXIT"
flush_outputs || finish false diagnostic_log_budget_exceeded
if (( platform_exit != 0 )); then
run_command system /bin/launchctl print system
system_exit="$LAST_EXIT"
run_command arbitration /bin/launchctl print system/com.apple.diskarbitrationd
arbitration_exit="$LAST_EXIT"
run_command recovery /bin/launchctl print system/com.apple.recoveryosd
recovery_exit="$LAST_EXIT"
printf '[proof-retry] sw_vers once after native service context; same 45-second deadline\n' >&3
run_command platform-warm /usr/bin/sw_vers
platform_exit="$LAST_EXIT"
fi
(( platform_exit == 0 )) || fail_probe sw_vers_failed
run_command version /usr/bin/sw_vers -productVersion
(( LAST_EXIT == 0 )) || fail_probe product_version_failed
read_scalar || fail_probe product_version_invalid
""";
static string RestoreVersionBlock(string source, string name, string originalSequence)
{
var start = "# BEGIN " + name + "\n";
var end = "# END " + name + "\n";
if (source.Split(start, StringSplitOptions.None).Length != 2 || source.Split(end, StringSplitOptions.None).Length != 2)
throw new InvalidOperationException("Readiness requires exactly one named version marker pair: " + name);
var from = source.IndexOf(start, StringComparison.Ordinal);
var to = source.IndexOf(end, StringComparison.Ordinal);
if (to < from + start.Length) throw new InvalidOperationException("Readiness version markers are reversed: " + name);
return source.Remove(from, to + end.Length - from).Insert(from, originalSequence);
}
static async Task PrepareSource(string source, string output, string token, bool writeSource, CancellationToken cancellation, bool full = false)
{
Directory.CreateDirectory(output);
var probe = ReadProbeAssets();
File.WriteAllBytes(Path.Combine(output, "native-process-probe-x86_64"), probe.Binary);
File.WriteAllBytes(Path.Combine(output, "native-process-probe-manifest.json"), probe.Manifest);
Save(Path.Combine(output, "native-process-probe-input-hashes.json"), new { sourceSha256 = ProbeSourceHash, driverSha256 = ProbeDriverHash, binarySha256 = ProbeBinaryHash, manifestSha256 = ProbeManifestHash, compilerExecutedInCI = false, qualifiedReadiness = false, recoveryPermissionProven = false });
var patchPath = Path.Combine(source, "src/install/recovery/patch.py");
var originalPatch = File.ReadAllText(patchPath);
if (Hash(Encoding.UTF8.GetBytes(originalPatch)) != "84f13db88c02edbf5ce21a39571fe58f12bebf5b0886c2d012f16ddbaed45323") throw new InvalidOperationException("Pinned Recovery patcher hash mismatch.");
var daemon = OriginalDaemon + "\n";
var patch = PrepareRecoveryPatch(originalPatch);
var checksumBinding = File.ReadAllText(Path.Combine("tools", "ci", "macos-native-udif-checksums.py"));
if (Hash(Encoding.UTF8.GetBytes(checksumBinding)) != UdifChecksumBindingHash) throw new InvalidOperationException("Recovery UDIF checksum binding hash mismatch.");
File.WriteAllText(Path.Combine(output, "udif_checksums.py"), checksumBinding, new UTF8Encoding(false));
var dockerPath = Path.Combine(source, "Dockerfile");
if (Hash(File.ReadAllBytes(dockerPath)) != "a0e804235967400eb70e755d63eff8a33a7761922ddd6e9723faa8e828fd8aa3") throw new InvalidOperationException("Pinned Dockerfile hash mismatch.");
// The existing runner's BuildKit cannot checksum dangling manpage links during COPY /.
// This pinned filesystem image has an empty Config; FROM preserves the same runtime defaults.
var dockerfile = ReplaceOnce(File.ReadAllText(dockerPath), "FROM scratch AS base\nCOPY --from=qemux/qemu:7.50 --exclude=usr/bin/qemu-system-x86_64 / /\n", "FROM qemux/qemu:7.50@sha256:e7f6fda52503a546fd649670ba46e4bc23dc6dcef275bc3fac48877fbbc430df AS base\n");
dockerfile = ReplaceAllExact(dockerfile, "--from=qemux/qemu-macos:latest ", "--from=qemux/qemu-macos:latest@sha256:af64297171228f27d5f616249e18f6ad5e2fbc79c1cc517252521e8bcd8eadaa ", 2);
dockerfile = ReplaceOnce(dockerfile, "ADD $REPO_KVM_OPENCORE/releases/download/v$VERSION_KVM_OPENCORE/LongQT-OpenCore-v$VERSION_KVM_OPENCORE.iso /opencore.iso", "ADD --checksum=sha256:" + OpenCoreTemplateHash + " $REPO_KVM_OPENCORE/releases/download/v$VERSION_KVM_OPENCORE/LongQT-OpenCore-v$VERSION_KVM_OPENCORE.iso /opencore.iso");
dockerfile = ReplaceOnce(dockerfile, " gzip \\\n", " gzip \\\n nasm \\\n");
dockerfile = ReplaceOnce(dockerfile, "COPY --chmod=755 ./assets /assets/\n", "COPY --chmod=755 ./assets /assets/\nRUN nasm -f bin /assets/ci-cpu-preflight.asm -o /assets/ci-cpu-preflight.bin && test \"$(stat -c%s /assets/ci-cpu-preflight.bin)\" = 65536\n");
var boot = PrepareTcgBoot(source);
var cpuPath = Path.Combine(source, "src/cpu.sh");
var cpu = File.ReadAllText(cpuPath);
if (Hash(Encoding.UTF8.GetBytes(cpu)) != "0f3e4b4e1c3e17743d3a8d27b77a76424ceebb576b269283d612c489bc70993e") throw new InvalidOperationException("Pinned CPU composition script hash mismatch.");
cpu = ReplaceOnce(cpu, ",+movbe,+rdrand,check\"", ",+movbe,+rdrand,enforce=on\"");
// Explicit CPU_MODEL bypasses upstream selection, so restore its TCG mitigation mask.
cpu = ReplaceOnce(cpu, " DEFAULT_FLAGS+=\",-pcid,-invpcid,-tsc-deadline,-xsavec,-xsaves\"", " DEFAULT_FLAGS+=\",-spec-ctrl,-pcid,-invpcid,-tsc-deadline,-xsavec,-xsaves\"");
var preflight = File.ReadAllText(Path.Combine("tools", "ci", "macos-tcg-cpu-preflight.asm"));
var entryPath = Path.Combine(source, "src/entry.sh");
var entry = ReplaceOnce(File.ReadAllText(entryPath), "set -Eeuo pipefail\n", "set -Eeuo pipefail\n\n# Diagnostic budget: inspect existing Docker storage before Recovery download/boot.\ndf -Pk /storage\nfree_kib=$(df -Pk /storage | awk 'NR==2 {print $4}')\n[[ \"$free_kib\" =~ ^[0-9]+$ ]] && (( free_kib >= 8 * 1024 * 1024 )) || { echo 'Existing Docker storage has less than the 8-GiB diagnostic budget.' >&2; exit 1; }\n");
entry = ReplaceOnce(entry, ". cpu.sh # Configure CPU model\n", "");
entry = ReplaceOnce(entry, ". proc.sh # Initialize processor\n", "");
entry = ReplaceOnce(entry, ". init.sh # Initialize system\n", ". init.sh # Initialize system\n. cpu.sh # Compose the exact guest CPU before any Apple download\n. proc.sh # Compose the actual accelerator/CPU_FLAGS once\n" + TcgPreflight + "\n");
entry = ReplaceOnce(entry, "trap - ERR\n", "[[ \"$KVM_OPTS\" == ' -accel tcg,thread=multi' && \"$CPU_FLAGS\" == '" + CpuFlags + "' && \"$CPU_OPTS\" == \"-cpu $CPU_FLAGS -smp $SMP\" ]] || { error 'Supported profile refuses a CPU/accelerator fallback.'; exit 1; }\ninfo '[supported-profile] accelerator=tcg cpu=Skylake-Client-v4 recovery=14; AVX/AVX2 preflight passed; native guest gates still pending'\n\nprintf '%s\\n' '[supported-profile] accelerator=tcg cpu=Skylake-Client-v4 recovery=14; AVX/AVX2 preflight passed; native guest gates still pending' >> \"$QEMU_DIR/native-stage.log\"\ntrap - ERR\n");
// Retain sparse boot markers without enabling verbose kernel/exception output.
entry = ReplaceOnce(entry, " -e 's/failed to load Boot/skipped Boot/g' \\\n", " -e 's/failed to load Boot/skipped Boot/g' \\\n -e '/^#\\[EB|LOG:HANDOFF TO XNU\\] /w /run/shm/kernel-handoffs.log' \\\n");
var hookPath = Path.Combine("tools", "ci", "macos-native-readiness.sh");
var hook = ReplaceOnce(File.ReadAllText(hookPath), "@@PROOF_TOKEN@@", token);
var wrapper = File.ReadAllText(Path.Combine("tools", "ci", full ? "macos-native-full-bootstrap.sh" : "macos-native-bootstrap.sh"));
if (full) wrapper = ReplaceOnce(wrapper, "@@PROOF_TOKEN@@", token);
var imagePath = Path.Combine(source, "src", "image.sh");
var originalImage = File.ReadAllText(imagePath);
if (Hash(Encoding.UTF8.GetBytes(originalImage)) != "c08bf9436fb8b72ea82fdf0e677641ab2fc42a0a59e2cf0309c00df519884c5c") throw new InvalidOperationException("Pinned Recovery staging script hash mismatch.");
var image = ReplaceOnce(originalImage, " if ! cp -f \"$IMAGE_TOOLS/recovery/launch.sh\" \"$script\"; then\n", " if ! cp -f \"$IMAGE_TOOLS/recovery/launch.sh\" \"$script\" ||\n ! cp -f \"$IMAGE_TOOLS/recovery/readiness.sh\" \"${script%/*}/readiness.sh\" ||\n ! cp -f \"$IMAGE_ASSETS/native-process-probe/native-process-probe-x86_64\" \"${script%/*}/native-process-probe-x86_64\" ||\n ! cp -f \"$IMAGE_ASSETS/native-process-probe/build-manifest.json\" \"${script%/*}/native-process-probe-manifest.json\"; then\n");
image = ReplaceOnce(image, " chmod 0755 \"$script\"\n", " chmod 0755 \"$script\" \"${script%/*}/native-process-probe-x86_64\"\n printf '%s\\n' '" + token + "' > \"${script%/*}/run.owner\" || return 1\n");
image = ReplaceOnce(image, " if ! cmp -s \"$IMAGE_TOOLS/recovery/launch.sh\" \"$script\" ||\n", " if ! cmp -s \"$IMAGE_TOOLS/recovery/launch.sh\" \"$script\" ||\n ! cmp -s \"$IMAGE_TOOLS/recovery/readiness.sh\" \"$state/readiness.sh\" ||\n ! cmp -s \"$IMAGE_ASSETS/native-process-probe/native-process-probe-x86_64\" \"$state/native-process-probe-x86_64\" ||\n ! cmp -s \"$IMAGE_ASSETS/native-process-probe/build-manifest.json\" \"$state/native-process-probe-manifest.json\" ||\n");
image = ReplaceOnce(image, " if ! result=$(python3 \"$IMAGE_TOOLS/recovery/patch.py\" \"$image\"); then\n", " info \"[recovery-original] bytes=$(stat -c%s -- \"$image\") sha256=$(sha256sum \"$image\" | awk '{print $1}')\"\n if ! result=$(python3 \"$IMAGE_TOOLS/recovery/patch.py\" \"$image\"); then\n");
if (full)
{
await PrepareFullSource(source, output, token, writeSource, cancellation);
hook = CreateFullReadiness(hook);
dockerfile += "\n# Payload stays inside this image and its owned anonymous storage volume.\nCOPY ci-payload/ /assets/ci-payload/\n";
entry = ReplaceOnce(entry, "free_kib >= 8 * 1024 * 1024", "free_kib >= 32 * 1024 * 1024").Replace("8-GiB diagnostic budget", "32-GiB full-run budget", StringComparison.Ordinal);
}
foreach (var pair in new[] { ("recovery-patch.py", patch), ("Dockerfile.patched", dockerfile), ("container-entry.sh", entry), ("guest-launch.sh", wrapper), ("guest-readiness.sh", hook), ("image.sh.patched", image), ("recoveryosd-original.plist", daemon), ("recoveryosd-diagnostic.plist", DiagnosticDaemon), ("recoveryosd-13-original.plist", OriginalDaemon13), ("recoveryosd-13-diagnostic.plist", DiagnosticDaemon13), ("early-bootstrap.sh", MountOnlyBootstrap), ("boot.sh.patched", boot), ("opencore-config.plist", File.ReadAllText(Path.Combine(source, "assets/config.plist"))), ("cpu.sh.patched", cpu), ("ci-cpu-preflight.asm", preflight) })
File.WriteAllText(Path.Combine(output, pair.Item1), pair.Item2, new UTF8Encoding(false));
Save(Path.Combine(output, "source-hashes.json"), Directory.GetFiles(output).Where(path => Path.GetFileName(path) is "recovery-patch.py" or "udif_checksums.py" or "Dockerfile.patched" or "container-entry.sh" or "guest-launch.sh" or "guest-readiness.sh" or "image.sh.patched" or "recoveryosd-original.plist" or "recoveryosd-diagnostic.plist" or "recoveryosd-13-original.plist" or "recoveryosd-13-diagnostic.plist" or "early-bootstrap.sh" or "boot.sh.patched" or "opencore-config.plist" or "cpu.sh.patched" or "ci-cpu-preflight.asm").ToDictionary(path => Path.GetFileName(path)!, path => Hash(File.ReadAllBytes(path))));
Save(Path.Combine(output, "cpu-preflight-source.json"), new { profile = Profile, cpuModel = CpuModel, cpuFlags = CpuFlags, expectedExitCode = 33, instructionProbeExecuted = false, qemuBinaryExecuted = false, sourceSha256 = Hash(Encoding.UTF8.GetBytes(preflight)) });
await Command("bash", ["-n", Path.Combine(output, "guest-launch.sh")], output, "guest-hook-syntax", cancellation);
await Command("bash", ["-n", Path.Combine(output, "guest-readiness.sh")], output, "guest-readiness-syntax", cancellation);
await Command("bash", ["-n", Path.Combine(output, "image.sh.patched")], output, "guest-staging-syntax", cancellation);
await Command("bash", ["-n", Path.Combine(output, "container-entry.sh")], output, "entry-syntax", cancellation);
await Command("bash", ["-n", Path.Combine(output, "boot.sh.patched")], output, "boot-staging-syntax", cancellation);
await Command("bash", ["-n", Path.Combine(output, "cpu.sh.patched")], output, "cpu-composition-syntax", cancellation);
if (!writeSource) await ValidateProbeStaging(image, output, probe.Binary, probe.Manifest, cancellation);
if (full && !writeSource) await ValidateFullBootstrap(wrapper, output, token, cancellation);
if (!writeSource) return;
File.WriteAllText(patchPath, patch, new UTF8Encoding(false));
File.WriteAllText(Path.Combine(source, "src/install/recovery/udif_checksums.py"), checksumBinding, new UTF8Encoding(false));
File.WriteAllText(dockerPath, dockerfile, new UTF8Encoding(false));
File.WriteAllText(entryPath, entry, new UTF8Encoding(false));
File.WriteAllText(imagePath, image, new UTF8Encoding(false));
File.WriteAllText(Path.Combine(source, "src/install/recovery/launch.sh"), wrapper, new UTF8Encoding(false));
File.WriteAllText(Path.Combine(source, "src/install/recovery/readiness.sh"), hook, new UTF8Encoding(false));
File.WriteAllText(Path.Combine(source, "src/boot.sh"), boot, new UTF8Encoding(false));
File.WriteAllText(cpuPath, cpu, new UTF8Encoding(false));
File.WriteAllText(Path.Combine(source, "assets/ci-cpu-preflight.asm"), preflight, new UTF8Encoding(false));
var probeAssets = Path.Combine(source, "assets/install/native-process-probe");
Directory.CreateDirectory(probeAssets);
File.WriteAllBytes(Path.Combine(probeAssets, "native-process-probe-x86_64"), probe.Binary);
File.WriteAllBytes(Path.Combine(probeAssets, "build-manifest.json"), probe.Manifest);
}
static (byte[] Binary, byte[] Manifest) ReadProbeAssets()
{
var folder = Path.Combine("tools", "ci", "native-process-probe");
var source = File.ReadAllBytes(Path.Combine(folder, "NativeProcessProbe.c"));
var driver = File.ReadAllBytes(Path.Combine(folder, "ProbeDriver.cs"));
var binary = File.ReadAllBytes(Path.Combine(folder, "native-process-probe-x86_64"));
var manifest = File.ReadAllBytes(Path.Combine(folder, "build-manifest.json"));
ValidateProbeAssets(source, driver, binary, manifest);
return (binary, manifest);
}
static void ValidateProbeAssets(byte[] source, byte[] driver, byte[] binary, byte[] manifest)
{
if (Hash(source) != ProbeSourceHash || Hash(driver) != ProbeDriverHash || Hash(binary) != ProbeBinaryHash || Hash(manifest) != ProbeManifestHash)
throw new InvalidOperationException("Disposable native diagnostic asset differs from its reviewed source/driver/binary/manifest pin.");
using var document = JsonDocument.Parse(manifest); var value = document.RootElement;
if (value.GetProperty("sourceSha256").GetString() != ProbeSourceHash || value.GetProperty("driverSha256").GetString() != ProbeDriverHash || value.GetProperty("binarySha256").GetString() != ProbeBinaryHash
|| value.GetProperty("architecture").GetString() != "x86_64" || value.GetProperty("minimumMacOS").GetString() != "14.0" || value.GetProperty("sdkVersion").GetString() != "27.0"
|| !value.GetProperty("importedLibraries").EnumerateArray().Select(item => item.GetString()).SequenceEqual(new[] { "/usr/lib/libSystem.B.dylib" })
|| value.GetProperty("signature").GetString() != "ad-hoc" || value.GetProperty("entitlements").GetBoolean() || !value.GetProperty("offlineVerified").GetBoolean()
|| !value.GetProperty("targetAndExpectedParentMandatory").GetBoolean() || !value.GetProperty("readOnlyTaskPortOnly").GetBoolean()
|| !value.GetProperty("taskReadWeakImportVerified").GetBoolean()
|| value.GetProperty("taskReadReturnContract").GetString() != "BSD int/errno" || value.GetProperty("outputMaximumBytes").GetInt32() != 32768
|| value.GetProperty("recoveryPermissionsProven").GetBoolean() || value.GetProperty("qualifiedReadiness").GetBoolean())
throw new InvalidOperationException("Disposable native diagnostic manifest claims another runtime, permissions or readiness.");
}
static void ValidateProbeAssetFixtures(string output)
{
ReadProbeAssets(); var folder = Path.Combine("tools", "ci", "native-process-probe");
var source = File.ReadAllBytes(Path.Combine(folder, "NativeProcessProbe.c")); var driver = File.ReadAllBytes(Path.Combine(folder, "ProbeDriver.cs"));
var binary = File.ReadAllBytes(Path.Combine(folder, "native-process-probe-x86_64")); var manifest = File.ReadAllBytes(Path.Combine(folder, "build-manifest.json"));
byte[] Changed(byte[] bytes) { var copy = bytes.ToArray(); copy[0] ^= 1; return copy; }
var cases = new[] { ("wrong-source", Changed(source), driver, binary, manifest), ("wrong-driver", source, Changed(driver), binary, manifest), ("wrong-binary", source, driver, Changed(binary), manifest), ("wrong-manifest-field", source, driver, binary, Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(manifest).Replace("\"recoveryPermissionsProven\": false", "\"recoveryPermissionsProven\": true", StringComparison.Ordinal))) };
foreach (var test in cases)
{
try { ValidateProbeAssets(test.Item2, test.Item3, test.Item4, test.Item5); }
catch (InvalidOperationException) { continue; }
throw new InvalidOperationException("Disposable native asset validator accepted " + test.Item1);
}
Directory.CreateDirectory(output);
Save(Path.Combine(output, "native-process-probe-assets-validation.json"), new { success = true, negativeCases = cases.Select(test => test.Item1), sourceSha256 = ProbeSourceHash, driverSha256 = ProbeDriverHash, binarySha256 = ProbeBinaryHash, manifestSha256 = ProbeManifestHash, nativeCompilerExecuted = false, nativeProbeExecuted = false, qualifiedReadiness = false });
}
static async Task ValidateProbeStaging(string image, string output, byte[] binary, byte[] manifest, CancellationToken cancellation)
{
var fixture = Path.Combine(output, "validation-probe-staging");
var tools = Path.Combine(fixture, "tools/recovery"); var assets = Path.Combine(fixture, "assets/install"); var state = Path.Combine(fixture, "state");
Directory.CreateDirectory(tools); Directory.CreateDirectory(Path.Combine(assets, "native-process-probe")); Directory.CreateDirectory(state);
File.WriteAllText(Path.Combine(tools, "launch.sh"), "# owned harmless wrapper fixture\n"); File.WriteAllText(Path.Combine(tools, "readiness.sh"), "# owned harmless readiness fixture\n");
File.WriteAllBytes(Path.Combine(assets, "native-process-probe/native-process-probe-x86_64"), binary);
File.WriteAllBytes(Path.Combine(assets, "native-process-probe/build-manifest.json"), manifest);
var begin = image.IndexOf("createAutomatedInstallationFiles() {", StringComparison.Ordinal); var end = image.IndexOf("prepareInstallationState() {", begin, StringComparison.Ordinal);
if (begin < 0 || end < 0) throw new InvalidOperationException("Actual staging producer missing.");
var script = "IMAGE_TOOLS=\"$1/tools\"\nIMAGE_ASSETS=\"$1/assets/install\"\nerror() { printf '%s\\n' \"$*\" >&2; }\n" + image[begin..end] + "\ncreateAutomatedInstallationFiles \"$1/state/launch.sh\"\n";
await Command("bash", ["-c", script, "diagnostic-staging-fixture", fixture], output, "native-probe-staging", cancellation);
if (Hash(File.ReadAllBytes(Path.Combine(state, "native-process-probe-x86_64"))) != ProbeBinaryHash || Hash(File.ReadAllBytes(Path.Combine(state, "native-process-probe-manifest.json"))) != ProbeManifestHash
|| Directory.GetFiles(state).Length != 5 || (File.GetUnixFileMode(Path.Combine(state, "native-process-probe-x86_64")) & UnixFileMode.UserExecute) == 0)
throw new InvalidOperationException("Actual staging paths/bytes/executable mode differ; C/driver must not be staged.");
Save(Path.Combine(fixture, "validation.json"), new { success = true, actualProducerSha256 = Hash(Encoding.UTF8.GetBytes(image[begin..end])), sourceAndDriverStaged = false, binarySha256 = ProbeBinaryHash, manifestSha256 = ProbeManifestHash, executable = true, nativeProbeExecuted = false, qualifiedReadiness = false });
}
static void ValidateDaemon(string xml, string processType, bool patched)
{
var pairs = XDocument.Parse(xml).Root!.Element("dict")!.Elements().ToArray();
if (pairs.Length != 10 || !pairs.Where((_, index) => index % 2 == 0).Select(element => element.Value).SequenceEqual(new[] { "Label", "OnDemand", "ProcessType", "EnablePressuredExit", "ProgramArguments" })) throw new InvalidOperationException("Recovery daemon fields changed.");
if (pairs[1].Value != "com.apple.recoveryosd" || pairs[3].Name != "false" || pairs[5].Value != processType || pairs[7].Name != "false" || pairs[9].Name != "array" || !pairs[9].Elements().Select(element => element.Value).SequenceEqual(patched ? new[] { "/bin/bash", "/Volumes/installstate/launch.sh" } : new[] { "/usr/libexec/recoveryosd" })) throw new InvalidOperationException("Recovery daemon identity/arguments changed.");
}
static string PrepareRecoveryPatch(string original)
{
var patch = ReplaceOnce(original, OriginalBootstrap, MountOnlyBootstrap);
patch = ReplaceOnce(patch, "import zlib\n", "import zlib\nfrom udif_checksums import ChecksumPlan\n");
var constants = "RECOVERY_13_ORIGINAL = b'''" + OriginalDaemon13 + "'''\nRECOVERY_13_REPLACEMENT = b'''" + DiagnosticDaemon13 + "'''.ljust(len(RECOVERY_13_ORIGINAL), b\" \")\nRECOVERY_14_ORIGINAL = b'''" + OriginalDaemon + "\n'''\nRECOVERY_14_REPLACEMENT = b'''" + DiagnosticDaemon + "'''.ljust(len(RECOVERY_14_ORIGINAL), b\" \")\nRECOVERY_LABEL = b'<string>com.apple.recoveryosd</string>'";
patch = ReplaceOnce(patch, "RECOVERY_ORIGINAL = b\"/usr/libexec/recoveryosd\"\nRECOVERY_REPLACEMENT = b\"/private/etc/rc.cdrom.sh\"", constants);
patch = ReplaceOnce(patch, " if len(RECOVERY_REPLACEMENT) != len(RECOVERY_ORIGINAL):\n raise RuntimeError(\"recoveryosd launch-path replacement length mismatch\")", " if len(RECOVERY_13_REPLACEMENT) != len(RECOVERY_13_ORIGINAL) or len(RECOVERY_14_REPLACEMENT) != len(RECOVERY_14_ORIGINAL):\n raise RuntimeError(\"recoveryosd launch-path replacement length mismatch\")");
patch = ReplaceOnce(patch, " (\"recoveryosd launch path\", RECOVERY_ORIGINAL, RECOVERY_REPLACEMENT),", " (\"recoveryosd macOS 13 launch path\", RECOVERY_13_ORIGINAL, RECOVERY_13_REPLACEMENT),\n (\"recoveryosd macOS 14 launch path\", RECOVERY_14_ORIGINAL, RECOVERY_14_REPLACEMENT),");
patch = ReplaceOnce(patch, " chunks = {}\n", " chunks = {}\n recovery_label_count = 0\n");
patch = ReplaceOnce(patch, " plist = plistlib.loads(image.read(xml_length))\n", " plist = plistlib.loads(image.read(xml_length))\n checksums = ChecksumPlan(image, koly, plist, xml_offset, xml_length, size)\n");
patch = ReplaceOnce(patch, " key = (blkx_index, run_index)\n", " recovery_label_count += decoded.count(RECOVERY_LABEL)\n key = (blkx_index, run_index)\n");
var variantValidation = """
if len(matches[patches[0][0]]) != 1:
raise RuntimeError("Expected exactly one rc.cdrom.sh bootstrap")
variants = [item for item in patches[1:] if matches[item[0]]]
if recovery_label_count != 1 or len(variants) != 1 or len(matches[variants[0][0]]) != 1:
raise RuntimeError("Expected exactly one known recoveryosd plist and launch path")
patches = (patches[0], variants[0])
print("[recovery-daemon] " + variants[0][0])
""";
patch = ReplaceOnce(patch, " for name, _, _ in patches:\n count = len(matches[name])\n if count != 1:\n raise RuntimeError(f\"Expected exactly one {name}, found {count}\")", IndentPython(variantValidation, 8));
// Plan all recompressed chunks before the first image write. A later
// compression failure must not leave an earlier chunk patched.
patch = ReplaceOnce(patch, " for key, chunk in chunks.items():\n patched = bytearray", " planned = []\n for key, chunk in chunks.items():\n patched = bytearray");
patch = ReplaceOnce(patch, " image.seek(chunk[\"physical_offset\"])\n image.write(stored)", " planned.append((chunk[\"physical_offset\"], stored))\n\n checksum_xml, checksum_koly = checksums.prepare(planned)\n for physical_offset, stored in planned:\n image.seek(physical_offset)\n image.write(stored)\n image.seek(xml_offset)\n image.write(checksum_xml)\n image.seek(size - 512)\n image.write(checksum_koly)");
patch = ReplaceOnce(patch, " image.flush()\n", " image.flush()\n checksums.verify()\n");
return patch;
}
static string IndentPython(string text, int spaces)
{
var lines = text.Split('\n');
var common = lines.Where(line => line.Length > 0).Min(line => line.TakeWhile(character => character == ' ').Count());
return string.Join("\n", lines.Select(line => new string(' ', spaces) + (line.Length > 0 ? line[common..] : "")));
}
static string PrepareTcgBoot(string source)
{
var boot = File.ReadAllText(Path.Combine(source, "src", "boot.sh"));
var config = File.ReadAllText(Path.Combine(source, "assets", "config.plist"));
if (Hash(Encoding.UTF8.GetBytes(boot)) != "82b56525707a8f586e040f56108b5034c02e7fecfea071f1857e596cba10cbed" || Hash(Encoding.UTF8.GetBytes(config)) != "3b0ec58b693cfa0fadf3e3f952486e87af8c27d504f9545d1e90ae2dc3777096") throw new InvalidOperationException("Pinned OpenCore staging/config hashes mismatch.");
var document = XDocument.Parse(config, LoadOptions.PreserveWhitespace);
var add = PlistValue(PlistValue(document.Root!.Element("dict")!, "Kernel"), "Add");
var expected = new[] { "Lilu.kext", "VMHide.kext", "VirtualSMC.kext", "WhateverGreen.kext", "VoodooPS2Controller.kext", "VoodooPS2Controller.kext/Contents/PlugIns/VoodooPS2Keyboard.kext", "AppleMCEReporterDisabler.kext" };
if (!add.Elements("dict").Select(dict => PlistValue(dict, "BundlePath").Value).SequenceEqual(expected) || add.Elements("dict").Any(dict => PlistValue(dict, "Enabled").Name != "true")) throw new InvalidOperationException("Pinned Kernel.Add order/enabled contract mismatch.");
boot = ReplaceOnce(boot, " PLIST=\"/assets/config.plist\"\n", " [ ! -e /custom.plist ] || { error 'Supported profile refuses an unverified custom OpenCore config!'; exit 12; }\n PLIST=\"/assets/config.plist\"\n");
boot = ReplaceOnce(boot, " if [ -s \"$target\" ] && [ \"$previous\" = \"$current\" ]; then\n IMG=\"$target\"\n return 0\n fi\n", " # This owned compatibility probe always rebuilds; never trust a cached boot.img.\n");
boot = ReplaceOnce(boot, " echo \"VMHIDE=$vmhide\"\n", " echo \"VMHIDE=$vmhide\"\n echo \"PROFILE=tcg-skylake-sonoma\"\n");
return boot;
}
static XElement PlistValue(XElement dictionary, string key)
{
var keys = dictionary.Elements("key").Where(element => element.Value == key).ToArray();
if (keys.Length != 1 || keys[0].ElementsAfterSelf().FirstOrDefault() is not { } value) throw new InvalidOperationException("Missing/duplicate plist key: " + key);
return value;
}
static readonly string TcgPreflight = """
# Realize this exact TCG model and execute AVX/AVX2 before Apple downloads.
disabled "$KVM" && [[ "$ARCH" == amd64 && "$CPU_MODEL" == Skylake-Client-v4 && "$VERSION" == 14 && "$CPU_FLAGS" == '@@CPU_FLAGS@@' ]] || { error 'Supported probe requires the exact TCG/Skylake/macOS 14 profile.'; exit 1; }
[[ "$(qemu-system-x86_64 --version | head -n 1)" == 'QEMU emulator version 11.1.1 (Reims 11.1.3)' ]] || { error 'Pinned QEMU runtime version mismatch.'; exit 1; }
printf '%s %s\n' c32746122cc68f3ed642aa46c21b677f803c58f0d4ff665841723fcc5625f549 /assets/ci-cpu-preflight.bin | sha256sum -c - || { error 'Compiled AVX/AVX2 preflight ROM hash mismatch.'; exit 1; }
probeTcgInstructions() {
/usr/bin/timeout --signal=TERM --kill-after=2 10 qemu-system-x86_64 \
-machine q35 -accel tcg,thread=multi -cpu "$1" -smp 2 -m 64 -bios /assets/ci-cpu-preflight.bin \
-nodefaults -display none -serial none -monitor none -nographic -no-reboot \
-device isa-debug-exit,iobase=0xf4,iosize=0x04
}
if probeTcgInstructions "$CPU_FLAGS" > "$QEMU_DIR/cpu-preflight-positive.log" 2>&1; then positive=0; else positive=$?; fi
cat "$QEMU_DIR/cpu-preflight-positive.log"
(( positive == 33 )) || { error "Actual TCG AVX/AVX2 instruction preflight failed: exit=$positive"; exit 1; }
if probeTcgInstructions "$CPU_FLAGS,-avx2" > "$QEMU_DIR/cpu-preflight-negative.log" 2>&1; then negative=0; else negative=$?; fi
cat "$QEMU_DIR/cpu-preflight-negative.log"
(( negative != 33 )) || { error 'AVX2-disabled negative control unexpectedly passed.'; exit 1; }
info "[cpu-preflight] positive=$positive negative=$negative cpu=$CPU_FLAGS; actual AVX/AVX2 executed before Apple download"
printf '[cpu-preflight] positive=%s negative=%s cpu=%s; actual AVX/AVX2 executed before Apple download\n' "$positive" "$negative" "$CPU_FLAGS" > "$QEMU_DIR/native-stage.log"
""".Replace("@@CPU_FLAGS@@", CpuFlags, StringComparison.Ordinal);
static async Task ValidateTcgPreflight(string output, CancellationToken cancellation)
{
var fixture = Path.Combine(output, "validation-cpu-preflight-gate");
Directory.CreateDirectory(fixture);
var entry = File.ReadAllText(Path.Combine(output, "container-entry.sh"));
if (entry.IndexOf(TcgPreflight, StringComparison.Ordinal) >= entry.IndexOf(". download.sh", StringComparison.Ordinal)
|| entry.Split(". cpu.sh", StringSplitOptions.None).Length != 2
|| entry.Split(". proc.sh", StringSplitOptions.None).Length != 2)
throw new InvalidOperationException("Actual composed CPU preflight must execute once before any Apple download.");
var cases = new[]
{
("positive-negative-exit", 33, 0, "14", CpuFlags, true, true),
("positive-negative-timeout", 33, 124, "14", CpuFlags, true, true),
("positive-normal-exit", 0, 0, "14", CpuFlags, true, false),
("positive-timeout", 124, 0, "14", CpuFlags, true, false),
("negative-passed", 33, 33, "14", CpuFlags, true, false),
("wrong-recovery", 33, 0, "13", CpuFlags, true, false),
("wrong-cpu-flags", 33, 0, "14", CpuFlags.Replace("enforce=on", "check"), true, false),
("wrong-rom-hash", 33, 0, "14", CpuFlags, false, false)
};
foreach (var item in cases)
{
var work = Path.Combine(fixture, item.Item1);
Directory.CreateDirectory(work);
var script = """
set -euo pipefail
disabled() { [ "$1" = N ]; }
error() { printf '%s\n' "$*" >&2; }
info() { printf '%s\n' "$*"; }
qemu-system-x86_64() { printf '%s\n' 'QEMU emulator version 11.1.1 (Reims 11.1.3)'; }
sha256sum() { cat >/dev/null; return "@@HASH_EXIT@@"; }
mock_timeout() {
printf '[fixture-command] %s\n' "$*"
case "$*" in *,-avx2*) return @@NEGATIVE@@ ;; *) return @@POSITIVE@@ ;; esac
}
KVM=N; ARCH=amd64; CPU_MODEL=Skylake-Client-v4; VERSION='@@VERSION@@'
CPU_FLAGS='@@FLAGS@@'; QEMU_DIR='@@WORK@@'
""".Replace("@@HASH_EXIT@@", item.Item6 ? "0" : "1", StringComparison.Ordinal)
.Replace("@@NEGATIVE@@", item.Item3.ToString(), StringComparison.Ordinal)
.Replace("@@POSITIVE@@", item.Item2.ToString(), StringComparison.Ordinal)
.Replace("@@VERSION@@", item.Item4, StringComparison.Ordinal)
.Replace("@@FLAGS@@", item.Item5, StringComparison.Ordinal)
.Replace("@@WORK@@", work.Replace("'", "'\\''", StringComparison.Ordinal), StringComparison.Ordinal)
+ "\n" + TcgPreflight.Replace("/usr/bin/timeout", "mock_timeout", StringComparison.Ordinal)
+ "\nprintf '[fixture] Apple download reached after gate\\n'\n";
var path = Path.Combine(work, "fixture.sh");
File.WriteAllText(path, script, new UTF8Encoding(false));
var result = await Command("bash", [path], work, "gate", cancellation, requireSuccess: false);
var reached = result.Output.Contains("Apple download reached after gate", StringComparison.Ordinal);
Save(Path.Combine(work, "receipt.json"), new { success = (result.ExitCode == 0) == item.Item7 && reached == item.Item7, result.ExitCode, reachedAppleDownloadSeam = reached, qemuExecuted = false });
if ((result.ExitCode == 0) != item.Item7 || reached != item.Item7)
throw new InvalidOperationException("Actual TCG preflight gate fixture failed: " + item.Item1);
}
}
static string ReplaceOnce(string text, string oldValue, string newValue) => ReplaceAllExact(text, oldValue, newValue, 1);
static string DiskSerial(string token) => token[..20];
static async Task ValidateFullBootstrap(string wrapper, string output, string token, CancellationToken cancellation)
{
// Execute the complete generated shell with only its external filesystem,
// Apple daemon and probe-process boundaries mapped to harmless fixtures.
const string commit = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
var ownMarker = token + ":" + commit + "\n";
var cases = new[]
{
(Name: "restart", Initial: (string?)null, ChildExit: 0, WriteFailure: false, Children: 1, Failure: false, MountAfter: 0, Owner: (string?)token),
(Name: "already-owned", Initial: ownMarker, ChildExit: 0, WriteFailure: false, Children: 0, Failure: false, MountAfter: 0, Owner: (string?)token),
(Name: "foreign-token", Initial: ownMarker.Replace(token, new string('f', 32)), ChildExit: 0, WriteFailure: false, Children: 0, Failure: true, MountAfter: 0, Owner: (string?)token),
(Name: "foreign-commit", Initial: ownMarker.Replace(commit, new string('f', 40)), ChildExit: 0, WriteFailure: false, Children: 0, Failure: true, MountAfter: 0, Owner: (string?)token),
(Name: "empty", Initial: "", ChildExit: 0, WriteFailure: false, Children: 0, Failure: true, MountAfter: 0, Owner: (string?)token),
(Name: "extra-record", Initial: ownMarker + ownMarker, ChildExit: 0, WriteFailure: false, Children: 0, Failure: true, MountAfter: 0, Owner: (string?)token),
(Name: "unterminated", Initial: ownMarker.TrimEnd('\n'), ChildExit: 0, WriteFailure: false, Children: 0, Failure: true, MountAfter: 0, Owner: (string?)token),
(Name: "write-failure", Initial: (string?)null, ChildExit: 0, WriteFailure: true, Children: 0, Failure: true, MountAfter: 0, Owner: (string?)token),
(Name: "first-child-failure", Initial: (string?)null, ChildExit: 1, WriteFailure: false, Children: 1, Failure: true, MountAfter: 0, Owner: (string?)token),
(Name: "delayed-share", Initial: (string?)null, ChildExit: 0, WriteFailure: false, Children: 1, Failure: false, MountAfter: 3, Owner: (string?)token),
(Name: "missing-share", Initial: (string?)null, ChildExit: 0, WriteFailure: false, Children: 0, Failure: true, MountAfter: -1, Owner: (string?)null),
(Name: "foreign-owner", Initial: (string?)null, ChildExit: 0, WriteFailure: false, Children: 0, Failure: true, MountAfter: 0, Owner: (string?)new string('f', 32))
};
foreach (var test in cases)
{
var state = Path.Combine(output, "full-bootstrap-" + test.Name + "-fixture");
if (Directory.Exists(state)) throw new InvalidOperationException("Full bootstrap fixtures require fresh validation output: " + state);
Directory.CreateDirectory(state);
if (test.MountAfter == 0 && test.Owner is not null) File.WriteAllText(Path.Combine(state, "run.owner"), test.Owner + "\n");
File.WriteAllText(Path.Combine(state, "source.commit"), commit + "\n");
var active = JsonSerializer.Serialize(new { token, phase = "installation" });
File.WriteAllText(Path.Combine(state, "guest-phase.json"), active);
var marker = Path.Combine(state, "probe.started");
if (test.Initial is not null) File.WriteAllText(marker, test.Initial);
var mapped = wrapper.Replace("/Volumes/installstate", state, StringComparison.Ordinal);
if (test.WriteFailure) mapped = ReplaceOnce(mapped, "MARKER=\"$STATE_DIR/probe.started\"", "MARKER=\"$STATE_DIR/absent-parent/probe.started\"");
var script = """
STATE_TEST="$1"; export STATE_TEST
CHILD_EXIT="$2"; export CHILD_EXIT
MOUNT_AFTER="$3"; MOUNT_OWNER="$4"; MOUNT_COMMIT="$5"
/sbin/mount_9p() {
local attempts=0
[ ! -f "$STATE_TEST/mount-attempts" ] || attempts=$(cat "$STATE_TEST/mount-attempts")
attempts=$((attempts + 1)); printf '%s\n' "$attempts" > "$STATE_TEST/mount-attempts"
if (( MOUNT_AFTER > 0 && attempts >= MOUNT_AFTER )); then
printf '%s\n' "$MOUNT_OWNER" > "$STATE_TEST/run.owner"
printf '%s\n' "$MOUNT_COMMIT" > "$STATE_TEST/source.commit"
return 0
fi
return 1
}
sleep() { [ "$1" = 1 ] || return 1; printf 'sleep\n' >> "$STATE_TEST/mount-sleeps.log"; }
/bin/bash() { cat "$STATE_TEST/probe.started" >> "$STATE_TEST/child-marker.log"; printf 'child\n' >> "$STATE_TEST/children.log"; return "$CHILD_EXIT"; }
exec() { cat "$STATE_TEST/probe.started" >> "$STATE_TEST/apple-marker.log" 2>/dev/null || :; printf '%s\n' "$*" >> "$STATE_TEST/apple-exec.log"; return 0; }
""" + "\n" + mapped + "\nwait\n";
var errors = "";
for (var start = 0; start < 2; start++)
errors += (await Command("bash", ["-c", script, "full-bootstrap-contract", state, test.ChildExit.ToString(), test.MountAfter.ToString(), test.Owner ?? "", commit], output, "full-bootstrap-" + test.Name + "-start-" + start, cancellation)).Error;
var childLog = Path.Combine(state, "children.log");
var children = File.Exists(childLog) ? File.ReadAllLines(childLog).Length : 0;
var appleExecutions = File.ReadAllLines(Path.Combine(state, "apple-exec.log"));
var phase = File.ReadAllText(Path.Combine(state, "guest-phase.json"));
var phaseUnchanged = phase == active;
using var receipt = JsonDocument.Parse(phase);
var realFailure = receipt.RootElement.GetProperty("token").GetString() == token && receipt.RootElement.GetProperty("phase").GetString() == "bootstrap-failed";
var markerPreserved = test.Initial is not null ? File.ReadAllText(marker) == test.Initial : test.Children == 0 ? !File.Exists(marker) : File.Exists(marker) && File.ReadAllText(marker) == ownMarker;
var completeBeforeExec = test.Initial is null && test.Children == 1 ? File.Exists(Path.Combine(state, "child-marker.log")) && File.ReadAllText(Path.Combine(state, "apple-marker.log")) == ownMarker + ownMarker && File.ReadAllText(Path.Combine(state, "child-marker.log")) == ownMarker : true;
var mountAttemptsPath = Path.Combine(state, "mount-attempts");
var mountAttempts = File.Exists(mountAttemptsPath) ? int.Parse(File.ReadAllText(mountAttemptsPath)) : 0;
var sleepPath = Path.Combine(state, "mount-sleeps.log");
var mountSleeps = File.Exists(sleepPath) ? File.ReadAllLines(sleepPath).Length : 0;
var expectedMounts = test.MountAfter < 0 ? 240 : test.MountAfter;
var failureReported = test.Owner == token ? realFailure : phaseUnchanged && errors.Contains("[full-bootstrap] ERROR:", StringComparison.Ordinal);
Save(Path.Combine(output, "full-bootstrap-" + test.Name + ".json"), new { children, appleExecutions = appleExecutions.Length, phaseUnchanged, realFailure, failureReported, markerPreserved, completeBeforeExec, mountAttempts, mountSleeps });
if (children != test.Children || appleExecutions.Length != 2 || appleExecutions.Any(value => value != "/usr/libexec/recoveryosd") || test.Failure && !failureReported || !test.Failure && !phaseUnchanged || !markerPreserved || !completeBeforeExec || mountAttempts != expectedMounts || mountSleeps != expectedMounts)
throw new InvalidOperationException($"Full bootstrap contract failed ({test.Name}): children={children}, appleExecutions={appleExecutions.Length}, phaseUnchanged={phaseUnchanged}, failureReported={failureReported}, markerPreserved={markerPreserved}, completeBeforeExec={completeBeforeExec}, mountAttempts={mountAttempts}, mountSleeps={mountSleeps}.");
}
}
static async Task PreparePayload(string source, string output, string token, string commit, CancellationToken cancellation)
{
if (!System.Text.RegularExpressions.Regex.IsMatch(commit, "^[0-9a-f]{40}$")) throw new InvalidOperationException("Candidate commit is not an exact Git SHA.");
var status = await Command("git", ["status", "--porcelain", "--untracked-files=all"], output, "source-cleanliness", cancellation);
if (!string.IsNullOrEmpty(status.Output)) throw new InvalidOperationException("Full CI requires a clean exact HEAD; commit the reviewable candidate before running it.");
var payload = Path.Combine(source, "ci-payload");
Directory.CreateDirectory(payload);
var archive = Path.Combine(payload, "source.tar");
await Command("git", ["archive", "--format=tar", "--output", archive, commit], output, "source-archive", cancellation);
var archiveHash = Hash(File.ReadAllBytes(archive));
File.WriteAllText(Path.Combine(output, "archive.sha256"), archiveHash + "\n");
File.WriteAllText(Path.Combine(payload, "source.commit"), commit + "\n");
Save(Path.Combine(payload, "payload.json"), new { runToken = token, sourceCommit = commit, archiveSha256 = archiveHash, sdkVersion = SdkVersion, sdkSha512 = SdkSha512, expectedTests = 577 });
File.Copy(Path.Combine(payload, "payload.json"), Path.Combine(output, "payload.json"));
foreach (var pair in new[] { ("MacOsNativeGuest.cs", "MacOsNativeGuest.cs"), ("macos-native-firstboot.sh", "native-firstboot-bootstrap.sh"), ("macos-native-disk-guard.sh", "macos-native-disk-guard.sh") })
File.Copy(Path.Combine("tools", "ci", pair.Item1), Path.Combine(payload, pair.Item2));
Console.WriteLine("[native-diagnostic] pinned-sdk-download");
using var downloadDeadline = CancellationTokenSource.CreateLinkedTokenSource(cancellation);
downloadDeadline.CancelAfter(TimeSpan.FromMinutes(15));
using var client = new HttpClient { Timeout = Timeout.InfiniteTimeSpan };
using var response = await client.GetAsync($"https://builds.dotnet.microsoft.com/dotnet/Sdk/{SdkVersion}/dotnet-sdk-{SdkVersion}-osx-x64.tar.gz", HttpCompletionOption.ResponseHeadersRead, downloadDeadline.Token);
response.EnsureSuccessStatusCode();
var sdkPath = Path.Combine(payload, "sdk.tar.gz");
await using (var sdk = File.Create(sdkPath))
await using (var stream = await response.Content.ReadAsStreamAsync(downloadDeadline.Token))
await stream.CopyToAsync(sdk, downloadDeadline.Token);
await using (var sdk = File.OpenRead(sdkPath))
if (Convert.ToHexStringLower(await SHA512.HashDataAsync(sdk, downloadDeadline.Token)) != SdkSha512) throw new InvalidOperationException("Official macOS/x64 SDK SHA-512 mismatch.");
Save(Path.Combine(output, "payload-hashes.json"), Directory.GetFiles(payload).ToDictionary(path => Path.GetFileName(path)!, path => Hash(File.ReadAllBytes(path))));
}
static string ReadPinned(string source, string path, string expected)
{
var bytes = File.ReadAllBytes(Path.Combine(source, path));
if (Hash(bytes) != expected) throw new InvalidOperationException("Pinned full-install source hash mismatch: " + path);
return Encoding.UTF8.GetString(bytes);
}
static string CreateFullReadiness(string hook) => ReplaceOnce(hook,
" # Keep the service alive for the bounded host diagnostic to capture evidence.\n while :; do sleep 60; done",
"""
# Full mode waits for the host's independently validated fresh owned-disk permit.
if [ "$success" = true ]; then
permit_start=$SECONDS
while (( SECONDS - permit_start < 300 )); do
if [ -s "$STATE_DIR/install.permit" ]; then
exec /bin/bash "$STATE_DIR/full-install.sh"
fi
sleep 1
done
printf '[full-install] host permit was not received in five minutes\n' >> "$PROOF_LOG"
fi
while :; do sleep 60; done
""");
static async Task PrepareFullSource(string source, string output, string token, bool writeSource, CancellationToken cancellation)
{
var installer = ReadPinned(source, "src/install/recovery/launch.sh", "b44309d1056bbd0321251cc9f04a52cf6ad68209586f263b9619339bf7146b6c");
var selectorStart = installer.IndexOf("select_target_disk() {", StringComparison.Ordinal);
var selectorEnd = installer.IndexOf("find_startosinstall() {", StringComparison.Ordinal);
if (selectorStart < 0 || selectorEnd <= selectorStart) throw new InvalidOperationException("Pinned installer selector boundaries changed.");
var selector = """
select_target_disk() {
local permit_token permit_disk permit_commit extra
{ IFS= read -r permit_token; IFS= read -r permit_disk; IFS= read -r permit_commit; IFS= read -r extra || :; } < "$STATE_DIR/install.permit" || return 1
[ "$permit_token" = "$PROOF_TOKEN" ] && [ -z "${extra:-}" ] || return 1
[ "$permit_commit" = "$(cat "$STATE_DIR/source.commit")" ] || return 1
[[ "$permit_commit" =~ ^[0-9a-f]{40}$ ]] || return 1
. "$STATE_DIR/macos-native-disk-guard.sh"
verify_owned_disk "$permit_disk" "$STATE_DIR" "$PROOF_TOKEN" >&2 || return 1
printf '%s\n' "$permit_disk"
}
""" + "\n";
installer = ReplaceOnce(installer, installer[selectorStart..selectorEnd], selector);
installer = ReplaceOnce(installer, "MIN_TARGET_SIZE=$((16 * 1024 * 1024 * 1024))", "# Target policy is exclusively the own writable 64-GiB emulated disk.");
installer = ReplaceOnce(installer, "no writable installation disk of at least 16 GiB was found", "the run-owned writable 64-GiB installation disk was not proved");
installer = ReplaceOnce(installer, " local message=\"$1\"\n\n echo \"[log] ERROR: $message\"", " local message=\"$1\"\n\n mark_installation_failed || :\n echo \"[log] ERROR: $message\"");
installer = ReplaceOnce(installer, "if (( rc != 0 )); then\n", "if (( rc != 0 )); then\n mark_installation_failed || :\n");
installer = ReplaceAllExact(installer, "rm -f \"$STARTED\"", ": # Keep the owned erase guard on failure; never erase again.", 2);
installer = ReplaceOnce(installer, "select_target_disk() {", """
owns_started_guard() {
local permit_token permit_disk permit_commit extra record
[ -f "$STARTED" ] && [ ! -L "$STARTED" ] || return 1
[ "$(cat "$STATE_DIR/run.owner" 2>/dev/null)" = "$PROOF_TOKEN" ] || return 1
{ IFS= read -r permit_token; IFS= read -r permit_disk; IFS= read -r permit_commit; IFS= read -r extra || :; } < "$STATE_DIR/install.permit" || return 1
[ "$permit_token" = "$PROOF_TOKEN" ] && [ -z "${extra:-}" ] || return 1
[[ "$permit_commit" =~ ^[0-9a-f]{40}$ && "$permit_disk" =~ ^/dev/disk[0-9]+$ ]] || return 1
[ "$permit_commit" = "$(cat "$STATE_DIR/source.commit")" ] || return 1
[ -z "${TARGET_DISK:-}" ] || [ "$TARGET_DISK" = "$permit_disk" ] || return 1
{
IFS= read -r record || return 1
if IFS= read -r extra || [ -n "$extra" ]; then return 1; fi
} < "$STARTED"
[ "$record" = "$PROOF_TOKEN:$permit_commit:$permit_disk" ]
}
select_target_disk() {
""");
installer = ReplaceOnce(installer, " echo \"[log] installation was already started; refusing to erase the target disk again\"\n exec /usr/libexec/recoveryosd\n exit 1", " owns_started_guard || fail \"existing installation guard is not owned by this token, commit and disk\"\n echo \"[log] owned installation is already running; duplicate child exits without changing its phase\"\n exit 0");
installer = ReplaceOnce(installer, ": > \"$STARTED\" || fail \"failed to create installation guard\"", """
if ! ( set -o noclobber; printf '%s:%s:%s\n' "$PROOF_TOKEN" "$(cat "$STATE_DIR/source.commit")" "$TARGET_DISK" > "$STARTED" ); then
if owns_started_guard; then
echo "[log] another owned child claimed installation; duplicate exits without changing its phase"
exit 0
fi
fail "failed to create the exclusive owned installation guard"
fi
""");
// The Full bootstrap wrapper keeps Apple's original daemon running.
// An installer child must terminate rather than launch another copy.
installer = ReplaceAllExact(installer, " exec /usr/libexec/recoveryosd\n", "", 2);
installer = ReplaceOnce(installer, "set -u\n", "set -u\nPROOF_TOKEN=\"" + token + "\"\n" + """
mark_installation_failed() {
local state="${STATE_DIR:-/Volumes/installstate}" temporary
[ "$(cat "$state/run.owner" 2>/dev/null)" = "$PROOF_TOKEN" ] || return 1
temporary="$state/guest-phase.install.$$.tmp"
printf '{"token":"%s","phase":"installation-failed"}\n' "$PROOF_TOKEN" > "$temporary" &&
/bin/mv -f "$temporary" "$state/guest-phase.json"
}
installer_parent=$$
# Installer watchdog: 80 minutes, also bounded by the host's 172-minute total.
(
trap 'kill "$sleeper" 2>/dev/null || :; exit 0' TERM INT
sleep 4800 & sleeper=$!; wait "$sleeper"; kill -TERM "$installer_parent" 2>/dev/null || :
) & install_watchdog=$!
trap 'kill -TERM "$install_watchdog" 2>/dev/null || :; wait "$install_watchdog" 2>/dev/null || :' EXIT
trap 'kill "${STARTOSINSTALL_PID:-}" "${BOOTSTRAPPER_PID:-}" 2>/dev/null || :; mark_installation_failed || :; exit 1' TERM INT
""" + "\n");
var firstboot = ReadPinned(source, "src/install/firstboot/launch.sh", "d6b29bb42ffe99edda6b3be3faf6009c4e0b34e5b8bba6eb0855cf24a0c24307");
firstboot = ReplaceOnce(firstboot, "LOG=\"/var/log/macos-unattended-firstboot.log\"\n", "LOG=\"/var/log/macos-unattended-firstboot.log\"\n" + FirstbootEvidence.Replace("@@OWNER@@", token, StringComparison.Ordinal) + "\n");
firstboot = ReplaceOnce(firstboot, " printf '%s\\n' \"[firstboot] $1\" >> \"$LOG\" 2>/dev/null || :\n", " printf '%s\\n' \"[firstboot] $1\" >> \"$LOG\" 2>/dev/null || :\n publish_firstboot_log || :\n");
firstboot = ReplaceOnce(firstboot, "log \"prebuilt account package installed successfully\"\n", "log \"prebuilt account package installed successfully\"\n/bin/bash /Volumes/installstate/native-firstboot-bootstrap.sh \"" + token + "\" || fail \"native CI bootstrap or tests failed\"\n");
ReadPinned(source, "src/install/firstboot/com.dockur.macos.firstboot.plist", "29ef05388d962c236bdb87b2911e3b42e08c600035cfccf440d35ba64011c3d3");
ReadPinned(source, "src/image.sh", "c08bf9436fb8b72ea82fdf0e677641ab2fc42a0a59e2cf0309c00df519884c5c");
var initialize = ReadPinned(source, "src/install.sh", "19b4b27187de85148ad1de1c40d75a54738eb9890f02dbb9445155bb5ec44f90");
initialize = ReplaceOnce(initialize, "INSTALL_STATE_DIR=\"$QEMU_DIR/installstate\"\nrm -rf \"$INSTALL_STATE_DIR\"", "INSTALL_STATE_DIR=\"$STORAGE/ci-state\"\n# Full CI preserves the own-volume erase guard and evidence across starts.");
initialize = ReplaceOnce(initialize, " if ! prepareInstallationState \"$INSTALL_STATE_DIR\"; then\n exit 34\n fi", """
if [ -e "$INSTALL_STATE_DIR/run.owner" ]; then
[ "$(cat "$INSTALL_STATE_DIR/run.owner")" = "@@OWNER@@" ] || { error "CI storage belongs to another run."; exit 34; }
else
prepareInstallationState "$INSTALL_STATE_DIR" || exit 34
cp -f /assets/ci-payload/* "$INSTALL_STATE_DIR/" || exit 34
cp -f "$IMAGE_TOOLS/recovery/full-install.sh" "$INSTALL_STATE_DIR/full-install.sh" || exit 34
cmp -s "$IMAGE_TOOLS/recovery/full-install.sh" "$INSTALL_STATE_DIR/full-install.sh" || exit 34
for file in /assets/ci-payload/*; do cmp -s "$file" "$INSTALL_STATE_DIR/${file##*/}" || exit 34; done
chmod 0755 "$INSTALL_STATE_DIR/full-install.sh" "$INSTALL_STATE_DIR/native-firstboot-bootstrap.sh" || exit 34
printf '%s\n' '@@OWNER@@' > "$INSTALL_STATE_DIR/run.owner" || exit 34
fi
""".Replace("@@OWNER@@", token, StringComparison.Ordinal));
foreach (var pair in new[] { ("full-install.sh", installer), ("full-firstboot.sh", firstboot), ("full-state-source.sh", initialize) })
{
File.WriteAllText(Path.Combine(output, pair.Item1), pair.Item2, new UTF8Encoding(false));
await Command("bash", ["-n", Path.Combine(output, pair.Item1)], output, pair.Item1 + "-syntax", cancellation);
}
foreach (var name in new[] { "macos-native-firstboot.sh", "macos-native-disk-guard.sh" })
await Command("bash", ["-n", Path.Combine("tools", "ci", name)], output, name + "-syntax", cancellation);
Save(Path.Combine(output, "full-source-hashes.json"), new Dictionary<string, string> { ["full-install.sh"] = Hash(Encoding.UTF8.GetBytes(installer)), ["full-firstboot.sh"] = Hash(Encoding.UTF8.GetBytes(firstboot)), ["full-state-source.sh"] = Hash(Encoding.UTF8.GetBytes(initialize)), ["MacOsNativeGuest.cs"] = Hash(File.ReadAllBytes("tools/ci/MacOsNativeGuest.cs")), ["macos-native-firstboot.sh"] = Hash(File.ReadAllBytes("tools/ci/macos-native-firstboot.sh")), ["macos-native-disk-guard.sh"] = Hash(File.ReadAllBytes("tools/ci/macos-native-disk-guard.sh")) });
if (!writeSource)
{
await ValidateInstallerFailureReceipt(installer, output, token, cancellation);
await ValidateInstallGuardChild(installer, output, token, cancellation);
await ValidateFirstbootEvidence(firstboot, output, token, cancellation);
return;
}
File.WriteAllText(Path.Combine(source, "src/install/recovery/full-install.sh"), installer, new UTF8Encoding(false));
File.WriteAllText(Path.Combine(source, "src/install/firstboot/launch.sh"), firstboot, new UTF8Encoding(false));
File.WriteAllText(Path.Combine(source, "src/install.sh"), initialize, new UTF8Encoding(false));
}
const string FirstbootEvidence = """
# Mount and verify only this run's state before account setup can fail.
PROOF_TOKEN="@@OWNER@@"
STATE_DIR="/Volumes/installstate"
owns_firstboot_state() {
[ -f "$STATE_DIR/run.owner" ] && [ ! -L "$STATE_DIR/run.owner" ] &&
[ "$(cat "$STATE_DIR/run.owner" 2>/dev/null)" = "$PROOF_TOKEN" ]
}
publish_firstboot_log() {
owns_firstboot_state && [ -f "$LOG" ] || return 1
local temporary="$STATE_DIR/unattended-firstboot.$$.tmp"
/usr/bin/tail -c 1048576 "$LOG" > "$temporary" &&
/bin/mv -f "$temporary" "$STATE_DIR/unattended-firstboot.log"
}
publish_firstboot_failure() {
owns_firstboot_state || return 1
local temporary="$STATE_DIR/guest-phase.firstboot.$$.tmp"
printf '{"token":"%s","phase":"bootstrap-failed","stage":"account-firstboot"}\n' "$PROOF_TOKEN" > "$temporary" &&
/bin/mv -f "$temporary" "$STATE_DIR/guest-phase.json"
}
trap 'firstboot_status=$?; publish_firstboot_log || :; (( firstboot_status == 0 )) || publish_firstboot_failure || :' EXIT
count=0
while ! owns_firstboot_state && (( count < 120 )); do
if [ -e "$STATE_DIR/run.owner" ] || [ -L "$STATE_DIR/run.owner" ]; then
printf '[firstboot] ERROR: foreign CI state owner\n' >> "$LOG"; exit 1
fi
/sbin/mount_9p installstate >/dev/null 2>&1 || :
count=$((count + 1)); sleep 1
done
owns_firstboot_state || { printf '[firstboot] ERROR: owned CI state share did not mount\n' >> "$LOG"; exit 1; }
""";
static async Task ValidateFirstbootEvidence(string firstboot, string output, string token, CancellationToken cancellation)
{
foreach (var test in new[] { ("missing-package", true, false, false), ("installer-failure", true, true, false), ("foreign-state", false, false, false), ("bounded-log", true, false, true) })
{
var work = Path.Combine(output, "firstboot-evidence-" + test.Item1);
var state = Path.Combine(work, "state");
var account = Path.Combine(work, "account");
Directory.CreateDirectory(state); Directory.CreateDirectory(account);
File.WriteAllText(Path.Combine(state, "run.owner"), test.Item2 ? token : new string('f', 32));
var initial = JsonSerializer.Serialize(new { token, phase = "installation" });
File.WriteAllText(Path.Combine(state, "guest-phase.json"), initial);
if (test.Item3) File.WriteAllText(Path.Combine(account, "admin.pkg"), "owned harmless package fixture");
Directory.CreateDirectory(Path.Combine(account, "users"));
File.WriteAllText(Path.Combine(account, "admin.plist"), "owned harmless admin fixture");
var log = Path.Combine(work, "local-firstboot.log");
if (test.Item4) File.WriteAllText(log, new string('x', 1024 * 1024 + 512) + "\n");
var mapped = firstboot.Replace("/Volumes/installstate", state, StringComparison.Ordinal)
.Replace("/Library/Application Support/macos-unattended", account, StringComparison.Ordinal)
.Replace("/private/var/db/dslocal/nodes/Default/users", Path.Combine(account, "users"), StringComparison.Ordinal)
.Replace("/private/var/db/dslocal/nodes/Default/groups/admin.plist", Path.Combine(account, "admin.plist"), StringComparison.Ordinal)
.Replace("/var/log/macos-unattended-firstboot.log", log, StringComparison.Ordinal)
.Replace("[ -x /usr/sbin/installer ]", "true", StringComparison.Ordinal);
var fixture = """
/sbin/mount_9p() { return 1; }
/usr/sbin/installer() { printf '%s\n' 'synthetic owned installer failure'; return 17; }
sleep() { return 0; }
""" + "\n" + mapped;
var path = Path.Combine(work, "fixture.sh");
File.WriteAllText(path, fixture, new UTF8Encoding(false));
var result = await Command("bash", [path], work, "firstboot", cancellation, requireSuccess: false);
var mirror = Path.Combine(state, "unattended-firstboot.log");
var evidence = File.Exists(mirror) ? File.ReadAllText(mirror) : "";
var phase = File.ReadAllText(Path.Combine(state, "guest-phase.json"));
using var receipt = JsonDocument.Parse(phase);
var published = receipt.RootElement.GetProperty("token").GetString() == token && receipt.RootElement.GetProperty("phase").GetString() == "bootstrap-failed";
var message = test.Item3 ? "synthetic owned installer failure" : "prebuilt account package is missing";
var bounded = !File.Exists(mirror) || new FileInfo(mirror).Length <= 1024 * 1024;
var success = result.ExitCode != 0 && (test.Item2 ? published && evidence.Contains(message, StringComparison.Ordinal) && bounded : phase == initial && !File.Exists(mirror));
Save(Path.Combine(work, "receipt.json"), new { success, result.ExitCode, failurePhasePublished = published, mirroredLogBytes = File.Exists(mirror) ? new FileInfo(mirror).Length : 0, bounded, nativeCommandsExecuted = false });
if (!success) throw new InvalidOperationException("Firstboot account-stage evidence fixture failed: " + test.Item1);
}
}
static async Task ValidateInstallerFailureReceipt(string installer, string output, string token, CancellationToken cancellation)
{
const string start = "mark_installation_failed() {";
const string end = "\n}\ninstaller_parent=$$";
var begin = installer.IndexOf(start, StringComparison.Ordinal);
var finish = begin < 0 ? -1 : installer.IndexOf(end, begin, StringComparison.Ordinal);
if (begin < 0 || finish < begin || installer.Split("mark_installation_failed || :", StringSplitOptions.None).Length != 4)
throw new InvalidOperationException("Pinned installer must publish its terminal failure phase from fail(), nonzero startosinstall and TERM/INT.");
var function = installer[begin..(finish + 2)];
var state = Path.Combine(output, "installer-failure-fixture");
Directory.CreateDirectory(state);
File.WriteAllText(Path.Combine(state, "run.owner"), token);
var command = "set -u\n" + function + "\nPROOF_TOKEN=\"$1\"; STATE_DIR=\"$2\"; mark_installation_failed";
await Command("bash", ["-c", command, "installer-failure-validation", token, state], output, "installer-terminal-failure", cancellation);
var receipt = File.ReadAllText(Path.Combine(state, "guest-phase.json"));
using var json = JsonDocument.Parse(receipt);
if (json.RootElement.GetProperty("token").GetString() != token || json.RootElement.GetProperty("phase").GetString() != "installation-failed" || Directory.GetFiles(state, "*.tmp").Length != 0)
throw new InvalidOperationException("Installer failed to publish a complete atomic terminal phase.");
File.WriteAllText(Path.Combine(state, "run.owner"), "foreign");
var foreign = await Command("bash", ["-c", command, "installer-failure-validation", token, state], output, "installer-foreign-failure", cancellation, requireSuccess: false);
if (foreign.ExitCode == 0 || File.ReadAllText(Path.Combine(state, "guest-phase.json")) != receipt)
throw new InvalidOperationException("Installer terminal phase overwrote foreign run-owned state.");
}
static async Task ValidateInstallGuardChild(string installer, string output, string token, CancellationToken cancellation)
{
// Exercise the generated Recovery shell's actual pre-erase control path.
// Apple exec and rolling log snapshots are external boundaries; no VM,
// native disk command, installer, daemon or application is invoked here.
static string Between(string text, string start, string end)
{
var first = text.IndexOf(start, StringComparison.Ordinal);
var last = first < 0 ? -1 : text.IndexOf(end, first, StringComparison.Ordinal);
if (first < 0 || last <= first) throw new InvalidOperationException("Generated installer guard validation boundary changed: " + start);
return text[first..last];
}
var functions = Between(installer, "mark_installation_failed() {", "installer_parent=$$") +
Between(installer, "fail() {", "select_target_disk() {");
var existing = Between(installer, "if [ -e \"$STARTED\" ]; then", "[ -s \"$ADMIN_PACKAGE\" ]");
var claim = Between(installer, "# Everything needed for the unattended install", "if ! /usr/sbin/diskutil eraseDisk");
const string commit = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
const string disk = "/dev/disk1";
var ownGuard = token + ":" + commit + ":" + disk + "\n";
var cases = new[]
{
(Name: "race", Initial: (string?)null, Race: true, WriteFailure: false, Success: true, Erase: false),
(Name: "fresh-winner", Initial: (string?)null, Race: false, WriteFailure: false, Success: true, Erase: true),
(Name: "already-owned", Initial: ownGuard, Race: false, WriteFailure: false, Success: true, Erase: false),
(Name: "foreign-token", Initial: ownGuard.Replace(token, new string('f', 32)), Race: false, WriteFailure: false, Success: false, Erase: false),
(Name: "foreign-commit", Initial: ownGuard.Replace(commit, new string('f', 40)), Race: false, WriteFailure: false, Success: false, Erase: false),
(Name: "foreign-disk", Initial: ownGuard.Replace(disk, "/dev/disk2"), Race: false, WriteFailure: false, Success: false, Erase: false),
(Name: "empty", Initial: "", Race: false, WriteFailure: false, Success: false, Erase: false),
(Name: "extra-record", Initial: ownGuard + ownGuard, Race: false, WriteFailure: false, Success: false, Erase: false),
(Name: "unterminated", Initial: ownGuard.TrimEnd('\n'), Race: false, WriteFailure: false, Success: false, Erase: false),
(Name: "write-failure", Initial: (string?)null, Race: false, WriteFailure: true, Success: false, Erase: false)
};
foreach (var test in cases)
{
var state = Path.Combine(output, "installer-guard-" + test.Name + "-fixture");
if (Directory.Exists(state)) throw new InvalidOperationException("Install-guard fixtures require a fresh validation output: " + state);
Directory.CreateDirectory(state);
File.WriteAllText(Path.Combine(state, "run.owner"), token + "\n");
File.WriteAllText(Path.Combine(state, "source.commit"), commit + "\n");
File.WriteAllText(Path.Combine(state, "install.permit"), token + "\n" + disk + "\n" + commit + "\n");
var active = JsonSerializer.Serialize(new { token, phase = "installation" });
File.WriteAllText(Path.Combine(state, "guest-phase.json"), active);
var guard = Path.Combine(state, test.WriteFailure ? "absent-parent/started" : "started");
if (test.Initial is not null) File.WriteAllText(guard, test.Initial);
var script = """
set -u
STATE_DIR="$1"; PROOF_TOKEN="$2"; TARGET_DISK="$3"
STARTED="$4"; LOCAL_LOG="$STATE_DIR/local.log"
STATE_LOG="$STATE_DIR/install.log"; STATE_LOG_LIMIT=1024
APPLE_INSTALL_LOG="$STATE_DIR/apple.log"; APPLE_INSTALL_LOG_LIMIT=1024
snapshot_log() { :; }
exec() { printf '%s\n' "$*" >> "$STATE_DIR/apple-exec.log"; return 0; }
""" + "\n" + functions + "\n" + existing + "\n" +
// Publish another child's complete guard after the initial check.
(test.Race ? "printf '%s:%s:%s\\n' \"$PROOF_TOKEN\" \"$(cat \"$STATE_DIR/source.commit\")\" \"$TARGET_DISK\" > \"$STARTED\"\n" : "") + claim +
"printf 'guard-acquired\\n' > \"$STATE_DIR/erase-boundary-reached\"\n";
var command = await Command("bash", ["-c", script, "generated-install-guard-validation", state, token, disk, guard], output, "installer-guard-" + test.Name, cancellation, requireSuccess: false);
var phase = File.ReadAllText(Path.Combine(state, "guest-phase.json"));
var phaseUnchanged = phase == active;
using var receipt = JsonDocument.Parse(phase);
var realFailure = receipt.RootElement.GetProperty("token").GetString() == token && receipt.RootElement.GetProperty("phase").GetString() == "installation-failed";
var appleExec = File.Exists(Path.Combine(state, "apple-exec.log"));
var eraseReached = File.Exists(Path.Combine(state, "erase-boundary-reached"));
var guardPreserved = test.Initial is not null ? File.ReadAllText(guard) == test.Initial : test.WriteFailure ? !File.Exists(guard) : File.ReadAllText(guard) == ownGuard;
Save(Path.Combine(output, "installer-guard-" + test.Name + ".json"), new { command.ExitCode, phaseUnchanged, realFailure, appleExec, eraseReached, guardPreserved });
if ((command.ExitCode == 0) != test.Success || test.Success && !phaseUnchanged || !test.Success && !realFailure || appleExec || eraseReached != test.Erase || !guardPreserved)
throw new InvalidOperationException($"Generated install child contract failed ({test.Name}): exit={command.ExitCode}, phaseUnchanged={phaseUnchanged}, realFailure={realFailure}, appleExec={appleExec}, eraseReached={eraseReached}, guardPreserved={guardPreserved}.");
}
}
static async Task PermitInstallation(string id, string output, string token, string commit, string readiness, CancellationToken cancellation)
{
await Command("docker", ["inspect", id], output, "full-container-boundary", cancellation);
AssertContainer(File.ReadAllText(Path.Combine(output, "full-container-boundary.stdout.log")), token);
using (var document = JsonDocument.Parse(File.ReadAllText(Path.Combine(output, "full-container-boundary.stdout.log"))))
{
var mounts = document.RootElement[0].GetProperty("Mounts").EnumerateArray().ToArray();
if (mounts.Length != 1 || mounts[0].GetProperty("Type").GetString() != "volume" || mounts[0].GetProperty("Destination").GetString() != "/storage" || !mounts[0].GetProperty("RW").GetBoolean()) throw new InvalidOperationException("Full installer requires only the newly owned anonymous /storage volume.");
}
var drive = await Command("docker", ["exec", id, "qemu-img", "info", "--force-share", "--output=json", "/storage/14/data.img"], output, "owned-raw-disk", cancellation);
using (var document = JsonDocument.Parse(drive.Output))
if (document.RootElement.GetProperty("format").GetString() != "raw" || document.RootElement.GetProperty("virtual-size").GetInt64() != GuestDiskBytes) throw new InvalidOperationException("Owned VM raw-disk capacity/format mismatch.");
var attachment = await Command("docker", ["exec", id, "sh", "-c", "qemu_pid=$(cat /dev/shm/qemu.pid); tr '\\0' '\\n' < /proc/\"$qemu_pid\"/cmdline | sed -n '/^file=\\/storage\\/14\\/data\\.img,/p; /^ide-hd,drive=data3,/p; /^local,id=installstatefs,/p'"], output, "owned-disk-attachment", cancellation);
var lines = attachment.Output.Split('\n', StringSplitOptions.RemoveEmptyEntries);
if (lines.Length != 3 || !lines.Any(line => line.StartsWith("file=/storage/14/data.img,id=data3,format=raw,", StringComparison.Ordinal) && !line.Contains("readonly=on", StringComparison.Ordinal)) || !lines.Any(line => line.StartsWith("ide-hd,drive=data3,", StringComparison.Ordinal) && line.Contains("serial=" + DiskSerial(token), StringComparison.Ordinal)) || !lines.Contains("local,id=installstatefs,path=" + FullState + ",security_model=none")) throw new InvalidOperationException("QEMU did not attach the exact owned raw disk/serial and persistent state share.");
var owner = await Command("docker", ["exec", id, "cat", FullState + "/run.owner"], output, "full-share-owner", cancellation);
if (owner.Output.Trim() != token) throw new InvalidOperationException("Native state owner mismatch.");
using var receipt = JsonDocument.Parse(readiness);
var disk = receipt.RootElement.GetProperty("disk").GetString();
var permit = Path.Combine(output, "install.permit");
File.WriteAllText(permit, token + "\n" + disk + "\n" + commit + "\n");
await Command("docker", ["cp", permit, id + ":" + FullState + "/install.permit.tmp"], output, "stage-owned-install-permit", cancellation);
await Command("docker", ["exec", id, "mv", FullState + "/install.permit.tmp", FullState + "/install.permit"], output, "authorize-owned-guest-installation", cancellation);
}
static readonly string[] NativeFacts = [
"MeetingAssistant.Tests.MacOsMeetingAudioSourceTests.NativeAudioCaptureIsPackagedAsSignedMacOsAppForPersistentPrivacyGrant",
"MeetingAssistant.Tests.MacOsMeetingIntegrationTests.MacOsCapabilityEndpointReportsEnabledRealProviders",
"MeetingAssistant.Tests.MacOsMeetingIntegrationTests.NativeHelperAdvertisesCalendarPromptAndScreenshotFeatures",
"MeetingAssistant.Tests.MacOsMeetingIntegrationTests.NativeHelperCropsPngUsingOcrPixelCoordinates",
"MeetingAssistant.Tests.MacOsMeetingIntegrationTests.CalendarClientFallsBackToCalendarAutomationWhenEventKitIsDenied"];
static readonly string[] NativeArtifacts = ["MeetingAssistantAudioCapture.app/Contents/MacOS/macos-meeting-audio-capture", "macos-desktop-controls", "macos-meeting-integrations", "macos-meeting-assistant-launcher"];
static void ValidateFullResult(string json, string token, string commit, string archiveHash)
{
using var document = JsonDocument.Parse(json);
var result = document.RootElement;
if (result.GetProperty("token").GetString() != token || !result.GetProperty("success").GetBoolean() || result.GetProperty("sourceCommit").GetString() != commit || result.GetProperty("archiveSha256").GetString() != archiveHash || result.GetProperty("sdkVersion").GetString() != SdkVersion || !Version.TryParse(result.GetProperty("osVersion").GetString(), out var version) || version.Major < 14 || result.GetProperty("architecture").GetString() != "x86_64" || new[] { "expectedTests", "total", "executed", "passed" }.Any(key => result.GetProperty(key).GetInt32() != 577) || new[] { "failed", "notExecuted", "audioCodeSignExit" }.Any(key => result.GetProperty(key).GetInt32() != 0) || !result.GetProperty("nativeTests").EnumerateArray().Select(value => value.GetString()).Order().SequenceEqual(NativeFacts.Order())) throw new InvalidOperationException("Native full receipt did not prove exact-source 577/577 with all five native tests and zero skips.");
var artifacts = result.GetProperty("nativeArtifacts").EnumerateArray().ToArray();
if (artifacts.Length != 4 || !artifacts.Select(item => item.GetProperty("name").GetString()).Order().SequenceEqual(NativeArtifacts.Order()) || artifacts.Any(item => item.GetProperty("architecture").GetString() != "x86_64" || !System.Text.RegularExpressions.Regex.IsMatch(item.GetProperty("sha256").GetString() ?? "", "^[0-9a-f]{64}$"))) throw new InvalidOperationException("Native Mach-O/x86_64 helper manifest is incomplete.");
}
static void ValidateTrx(byte[] bytes, string json)
{
using var receipt = JsonDocument.Parse(json);
if (Hash(bytes) != receipt.RootElement.GetProperty("trxSha256").GetString()) throw new InvalidOperationException("Returned native TRX SHA-256 mismatch.");
var document = XDocument.Load(new MemoryStream(bytes));
var counters = document.Descendants().Single(item => item.Name.LocalName == "Counters");
foreach (var key in new[] { "total", "executed", "passed" }) if ((int?)counters.Attribute(key) != 577) throw new InvalidOperationException("Native TRX count mismatch: " + key);
foreach (var key in new[] { "failed", "notExecuted" }) if ((int?)counters.Attribute(key) != 0) throw new InvalidOperationException("Native TRX failure/skip counter: " + key);
var results = document.Descendants().Where(item => item.Name.LocalName == "UnitTestResult").ToArray();
if (results.Length != 577 || results.Any(item => (string?)item.Attribute("outcome") != "Passed")) throw new InvalidOperationException("Native TRX contains missing, failed or skipped results.");
var identities = document.Descendants().Where(item => item.Name.LocalName == "UnitTest").ToDictionary(item => (string)item.Attribute("id")!, item => { var method = item.Elements().Single(child => child.Name.LocalName == "TestMethod"); var className = ((string?)method.Attribute("className"))?.Split(',')[0].Trim() ?? ""; var name = (string?)method.Attribute("name") ?? ""; return name.StartsWith(className + ".", StringComparison.Ordinal) ? name : className + "." + name; });
var passed = results.Select(item => identities[(string)item.Attribute("testId")!]).ToHashSet();
if (NativeFacts.Any(name => !passed.Contains(name))) throw new InvalidOperationException("Native TRX does not explicitly pass every required macOS fact.");
}
static void ValidateFullContracts()
{
var token = new string('a', 32); var commit = new string('b', 40); var hash = new string('c', 64);
var trx = "<TestRun><TestDefinitions>" + string.Concat(Enumerable.Range(0, 577).Select(index => { var identity = index < 5 ? NativeFacts[index] : "MeetingAssistant.Tests.Validation.Test" + index; var split = identity.LastIndexOf('.'); return $"<UnitTest id='t{index}'><TestMethod className='{identity[..split]}' name='{identity[(split + 1)..]}' /></UnitTest>"; })) + "</TestDefinitions><Results>" + string.Concat(Enumerable.Range(0, 577).Select(index => $"<UnitTestResult testId='t{index}' outcome='Passed' />")) + "</Results><ResultSummary><Counters total='577' executed='577' passed='577' failed='0' notExecuted='0' /></ResultSummary></TestRun>";
var good = JsonSerializer.Serialize(new { token, success = true, sourceCommit = commit, archiveSha256 = hash, sdkVersion = SdkVersion, osVersion = "14.6.1", architecture = "x86_64", expectedTests = 577, total = 577, executed = 577, passed = 577, failed = 0, notExecuted = 0, nativeTests = NativeFacts, nativeArtifacts = NativeArtifacts.Select(name => new { name, sha256 = hash, architecture = "x86_64" }), audioCodeSignExit = 0, trxSha256 = Hash(Encoding.UTF8.GetBytes(trx)) });
ValidateFullResult(good, token, commit, hash); ValidateTrx(Encoding.UTF8.GetBytes(trx), good);
byte[] bomTrx = [0xef, 0xbb, 0xbf, .. Encoding.UTF8.GetBytes(trx)];
ValidateTrx(bomTrx, good.Replace(Hash(Encoding.UTF8.GetBytes(trx)), Hash(bomTrx), StringComparison.Ordinal));
var qualifiedTrx = trx;
foreach (var name in NativeFacts) qualifiedTrx = qualifiedTrx.Replace("name='" + name[(name.LastIndexOf('.') + 1)..] + "'", "name='" + name + "'", StringComparison.Ordinal);
ValidateTrx(Encoding.UTF8.GetBytes(qualifiedTrx), good.Replace(Hash(Encoding.UTF8.GetBytes(trx)), Hash(Encoding.UTF8.GetBytes(qualifiedTrx)), StringComparison.Ordinal));
foreach (var invalid in new[] { good.Replace("\"success\":true", "\"success\":false"), good.Replace("\"passed\":577", "\"passed\":572"), good.Replace("\"notExecuted\":0", "\"notExecuted\":5"), good.Replace("\"audioCodeSignExit\":0", "\"audioCodeSignExit\":1"), good.Replace("14.6.1", "13.6.1"), good.Replace("x86_64", "arm64"), good.Replace(token, new string('d', 32)), good.Replace(commit, new string('e', 40)), good.Replace("NativeHelperAdvertisesCalendarPromptAndScreenshotFeatures", "UnrelatedTest") })
{
try { ValidateFullResult(invalid, token, commit, hash); } catch (InvalidOperationException) { continue; }
throw new InvalidOperationException("Full native validator accepted an incomplete or stale proof.");
}
try { ValidateTrx(Encoding.UTF8.GetBytes(trx.Replace("outcome='Passed'", "outcome='NotExecuted'")), good); } catch (InvalidOperationException) { return; }
throw new InvalidOperationException("Full native validator accepted changed TRX bytes.");
}
static async Task ValidateCompression(string chunk, string output)
{
Directory.CreateDirectory(output);
var bytes = File.ReadAllBytes(chunk);
if (Hash(bytes) != "2770f06fe51f19ddc040cfad4ab870d7227f540d1ba4190a9ce631145c12fae0") throw new InvalidOperationException("Readonly retained Recovery qualification chunk hash mismatch.");
var text = Encoding.Latin1.GetString(bytes);
if (text.Split(DiagnosticDaemon, StringSplitOptions.None).Length != 2 || text.Split(MountOnlyBootstrap, StringSplitOptions.None).Length != 2) throw new InvalidOperationException("Qualification chunk does not contain this exact Recovery LaunchDaemon and mount-only patch.");
// Upstream UDIF recompression uses Python zlib; .NET's compressor differs even on baseline.
await Command("python3", ["-c", "import json,pathlib,sys,zlib; b=pathlib.Path(sys.argv[1]).read_bytes(); n=len(zlib.compress(b,9)); print(json.dumps({'runtime':zlib.ZLIB_RUNTIME_VERSION,'compressedBytes':n,'slotBytes':43266,'fits':n<=43266})); sys.exit(0 if n<=43266 else 1)", chunk], output, "readonly-recovery-compression", CancellationToken.None);
}
static async Task ValidateDiskSerialParser(string output)
{
Directory.CreateDirectory(output);
var guard = File.ReadAllText("tools/ci/macos-native-disk-guard.sh");
const string start = "-v disk=\"${disk#/dev/}\" '\n";
const string end = " ' \"$state/disk-ownership-ioreg.log\")";
var program = guard[(guard.IndexOf(start, StringComparison.Ordinal) + start.Length)..guard.IndexOf(end, StringComparison.Ordinal)];
var serial = new string('0', 20);
var own = "+-o QEMU HARDDISK <class IOAHCIBlockStorageDevice>\n | \"Device Characteristics\" = {\"Serial Number\"=\"" + serial + "\"}\n +-o Media <class IOMedia>\n \"BSD Name\" = \"disk1\"\n";
var reversed = "+-o QEMU HARDDISK <class IOAHCIBlockStorageDevice>\n +-o Media <class IOMedia>\n \"BSD Name\" = \"disk1\"\n | \"Device Characteristics\" = {\"Serial Number\"=\"" + serial + "\"}\n";
var splitRoots = "+-o QEMU HARDDISK <class IOAHCIBlockStorageDevice>\n | \"Device Characteristics\" = {\"Serial Number\"=\"" + serial + "\"}\n+-o Other <class IOAHCIBlockStorageDevice>\n +-o Media <class IOMedia>\n \"BSD Name\" = \"disk1\"\n";
foreach (var test in new[] { ("own", own, "1"), ("reversed-properties", reversed, "1"), ("split-roots", splitRoots, "0"), ("foreign-serial", own.Replace(serial, new string('a', 20)), "0"), ("foreign-disk", own.Replace("disk1", "disk2"), "0"), ("ambiguous", own + own, "2") })
{
var path = Path.Combine(output, "ioreg-" + test.Item1 + ".fixture");
File.WriteAllText(path, test.Item2);
var result = await Command("awk", ["-v", "expected=" + serial, "-v", "disk=disk1", program, path], output, "disk-serial-" + test.Item1, CancellationToken.None);
if (result.Output.Trim() != test.Item3) throw new InvalidOperationException("Actual boot-seam IORegistry parser fixture failed: " + test.Item1);
}
}
static string ReplaceAllExact(string text, string oldValue, string newValue, int expected)
{
var count = text.Split(oldValue, StringSplitOptions.None).Length - 1;
if (count != expected) throw new InvalidOperationException($"Pinned source contract expected {expected} match(es), found {count}: {oldValue.Split('\n')[0]}");
return text.Replace(oldValue, newValue, StringComparison.Ordinal);
}
static void ValidateResult(string json, string token)
{
using var document = JsonDocument.Parse(json);
var result = document.RootElement;
if (result.GetProperty("token").GetString() != token || !result.GetProperty("success").GetBoolean() || !Version.TryParse(result.GetProperty("osVersion").GetString(), out var version) || version.Major < 14 || result.GetProperty("architecture").GetString() != "x86_64" || result.GetProperty("uid").GetInt32() != 0 || !System.Text.RegularExpressions.Regex.IsMatch(result.GetProperty("disk").GetString() ?? "", "^/dev/disk[0-9]+$") || result.GetProperty("diskBytes").GetInt64() != GuestDiskBytes || result.GetProperty("readOnly").GetBoolean() || new[] { "systemExit", "diskArbitrationExit", "recoveryExit", "diskListExit" }.Any(key => result.GetProperty(key).GetInt32() != 0))
throw new InvalidOperationException("The fresh guest receipt did not prove native macOS 14+/x86_64, service readiness and the writable 64-GiB disk.");
}
static void AssertContainer(string json, string token)
{
using var document = JsonDocument.Parse(json);
var container = document.RootElement[0];
var config = container.GetProperty("HostConfig");
var devices = config.GetProperty("Devices");
var mounts = container.GetProperty("Mounts");
var environment = container.GetProperty("Config").GetProperty("Env").EnumerateArray().Select(value => value.GetString()).ToArray();
if (container.GetProperty("Config").GetProperty("Labels").GetProperty(OwnerLabel).GetString() != token
|| config.GetProperty("Privileged").GetBoolean()
|| config.GetProperty("NetworkMode").GetString() is not ("default" or "bridge")
|| config.GetProperty("Memory").GetInt64() != ContainerMemoryBytes
|| config.GetProperty("MemorySwap").GetInt64() != ContainerMemoryBytes
|| config.GetProperty("NanoCpus").GetInt64() != 2000000000
|| config.GetProperty("ShmSize").GetInt64() != 536870912
|| new[] { "CapAdd", "DeviceRequests", "Binds", "PortBindings", "DeviceCgroupRules", "Tmpfs" }.Any(key =>
config.TryGetProperty(key, out var value) && value.ValueKind != JsonValueKind.Null
&& (value.ValueKind == JsonValueKind.Array ? value.GetArrayLength() != 0 : value.EnumerateObject().Any()))
|| devices.GetArrayLength() != 0
|| mounts.GetArrayLength() != 1
|| mounts[0].GetProperty("Type").GetString() != "volume"
|| mounts[0].GetProperty("Destination").GetString() != "/storage"
|| !mounts[0].GetProperty("RW").GetBoolean()
|| new[] { "KVM=N", "CPU_MODEL=" + CpuModel, "VERSION=14" }.Any(expected =>
environment.Count(value => value is not null && value.StartsWith(expected.Split('=')[0] + "=", StringComparison.Ordinal)) != 1
|| !environment.Contains(expected)))
throw new InvalidOperationException("Created container exceeds the owned unprivileged TCG/Skylake/macOS 14 boundary.");
}
static async Task CaptureGuest(string id, string output, CancellationToken cancellation, bool full = false, bool final = false, string? token = null)
{
if (final && token is not null) await CaptureMonitor(id, output, token, cancellation);
var logs = await Command("docker", ["logs", "--tail", "3000", id], output, "container", cancellation, requireSuccess: false);
var stage = await Command("docker", ["exec", id, "cat", "/run/shm/native-stage.log"], output, "capture-native-stage", cancellation, requireSuccess: false);
ReportCpuPreflight(output, stage.ExitCode == 0 ? stage.Output : logs.Output);
await Command("docker", ["exec", id, "head", "-c", "4096", "/run/shm/kernel-handoffs.log"], output, "capture-kernel-handoffs", cancellation, requireSuccess: false, retainSuccessful: true);
if (token is not null) await CaptureNativeSystemVersion(id, output, token, full, cancellation);
if (token is not null) await CaptureDiskStack(id, output, token, full, final, cancellation);
var files = new List<(string, string)> { ("proof.log", "guest-proof.log"), ("result.json", "guest-result.json") };
if (full) files.AddRange([("guest-phase.json", "guest-phase.json"), ("full-result.json", "full-result.json"), ("firstboot.log", "firstboot.log"), ("unattended-firstboot.log", "unattended-firstboot.log"), ("install.log", "install.log"), ("apple.log", "apple.log"), ("disk-ownership-ioreg.log", "disk-ownership-ioreg.log"), ("installed-root.plist", "installed-root.plist"), ("apfs-containers.plist", "apfs-containers.plist"), ("physical-store.plist", "physical-store.plist"), ("clt-catalog.log", "clt-catalog.log"), ("clt-install.log", "clt-install.log"), ("clt-sdk.log", "clt-sdk.log")]);
foreach (var file in files)
{
var result = await Command("docker", ["exec", id, "cat", (full ? FullState : "/dev/shm/installstate") + "/" + file.Item1], output, "capture-" + file.Item1.Replace('/', '-'), cancellation, requireSuccess: false);
if (result.ExitCode == 0 && !string.IsNullOrWhiteSpace(result.Output)) File.WriteAllText(Path.Combine(output, file.Item2), result.Output);
}
if (full)
{
var trx = await Command("docker", ["cp", id + ":" + FullState + "/test-results/native.trx", Path.Combine(output, "native.trx.tmp")], output, "capture-native-trx", cancellation, requireSuccess: false);
if (trx.ExitCode == 0) File.Move(Path.Combine(output, "native.trx.tmp"), Path.Combine(output, "native.trx"), overwrite: true);
if (final || File.Exists(Path.Combine(output, "full-result.json")))
{
Directory.CreateDirectory(Path.Combine(output, "guest-logs"));
await Command("docker", ["cp", id + ":" + FullState + "/guest-logs/.", Path.Combine(output, "guest-logs")], output, "capture-guest-logs", cancellation, requireSuccess: false);
}
}
// The immutable Recovery image is complete only after this staging marker.
// Hash it once instead of rereading the image on every twenty-second poll.
if ((logs.Output + stage.Output).Contains("[supported-profile] accelerator=tcg", StringComparison.Ordinal)
&& !File.Exists(Path.Combine(output, "guest-container-resources.last-success.json")))
await Command("docker", ["exec", id, "sh", "-c", "printf '[qemu]\n'; qemu-system-x86_64 --version | head -n 1; printf '[Recovery hash]\n'; test -f /storage/14/setup.dmg && sha256sum /storage/14/setup.dmg || exit 1; printf '[resources]\n'; df -Pk /storage; cat /sys/fs/cgroup/memory.max /sys/fs/cgroup/cpu.max 2>/dev/null || true"], output, "guest-container-resources", cancellation, requireSuccess: false, retainSuccessful: true);
}
static async Task CaptureDiskStack(string id, string output, string token, bool full, bool final, CancellationToken cancellation)
{
var sourcePath = (full ? FullState : "/dev/shm/installstate") + "/diskutil-stack.txt";
// The sample writes directly through 9p. Capture changing bytes with Linux
// coreutils; absence/empty output must never suppress a later or final read.
var capture = await Command("docker", ["exec", id, "bash", "-o", "pipefail", "-c", "head -c 524289 '" + sourcePath + "' | base64 -w 0"], output, "capture-diskutil-stack", cancellation, requireSuccess: false);
if (capture.ExitCode != 0 || string.IsNullOrEmpty(capture.Output)) return;
SaveDiskStackObservation(output, token, sourcePath, Convert.FromBase64String(capture.Output), final);
}
static void SaveDiskStackObservation(string output, string token, string sourcePath, byte[] raw, bool final)
{
if (raw.Length == 0) return;
if (raw.Length > MaximumDiskStackBytes + 1) throw new InvalidOperationException("Disk stack transport exceeded its one-byte sentinel.");
var truncated = raw.Length > MaximumDiskStackBytes;
var bounded = truncated ? raw[..MaximumDiskStackBytes] : raw;
File.WriteAllBytes(Path.Combine(output, "diskutil-stack.txt"), bounded);
Save(Path.Combine(output, "diskutil-stack-capture.json"), new { token, sourcePath, capturedBytes = bounded.Length, sha256 = Hash(bounded), maximumCapturedBytes = MaximumDiskStackBytes, truncated, finalCapture = final, snapshotOnly = true, sampleCompletionVerified = false, qualifiedReadiness = false, sampleExitAndTimeoutEvidence = "guest-proof.log", capturedUtc = DateTimeOffset.UtcNow });
}
static void ValidateDiskStackCapture(string output)
{
var fixture = Path.Combine(output, "validation-disk-stack-capture");
Directory.CreateDirectory(fixture);
var cases = new List<object>();
foreach (var size in new[] { 0, 64, MaximumDiskStackBytes, MaximumDiskStackBytes + 1 })
{
var folder = Path.Combine(fixture, size.ToString());
Directory.CreateDirectory(folder);
var raw = Enumerable.Repeat((byte)'s', size).ToArray();
SaveDiskStackObservation(folder, "fixture", FullState + "/diskutil-stack.txt", raw, false);
if (size == 0)
{
if (Directory.EnumerateFiles(folder).Any()) throw new InvalidOperationException("Empty stack capture was finalized.");
}
else
{
var retained = File.ReadAllBytes(Path.Combine(folder, "diskutil-stack.txt"));
using var receipt = JsonDocument.Parse(File.ReadAllText(Path.Combine(folder, "diskutil-stack-capture.json")));
if (retained.Length != Math.Min(size, MaximumDiskStackBytes) || !retained.AsSpan().SequenceEqual(raw.AsSpan(0, retained.Length))
|| receipt.RootElement.GetProperty("truncated").GetBoolean() != (size > MaximumDiskStackBytes)
|| receipt.RootElement.GetProperty("sampleCompletionVerified").GetBoolean() || receipt.RootElement.GetProperty("qualifiedReadiness").GetBoolean())
throw new InvalidOperationException("Stack capture changed bytes/bounds or qualified an observation.");
}
cases.Add(new { size, success = true });
}
Save(Path.Combine(fixture, "validation.json"), new { success = true, cases, emptyCaptureFinalized = false, maximumCapturedBytes = MaximumDiskStackBytes, qualifiedReadiness = false, guestExecuted = false });
}
static int NativeVersionRequestLength(string request, string token)
{
var fields = request.Split('\n');
if (request.Length > 256 || request.Contains('\0') || fields.Length != 5 || fields[3] != "ready:" + token || fields[4] != ""
|| fields[0] != token || fields[1] != NativeVersionSource
|| !System.Text.RegularExpressions.Regex.IsMatch(fields[2], @"\A[0-9]{1,4}\z")
|| !int.TryParse(fields[2], out var length) || length is < 1 or > 4096)
throw new InvalidOperationException("Native SystemVersion request token/path/length/EOF is invalid.");
return length;
}
static string ParseNativeSystemVersion(byte[] raw, string request, string token)
{
if (raw.Length != NativeVersionRequestLength(request, token) || raw.Length is < 1 or > 4096 || raw.Contains((byte)0))
throw new InvalidOperationException("Native SystemVersion raw bytes are missing, binary, overbound or differ from the request.");
var xml = new UTF8Encoding(false, true).GetString(raw);
using var reader = XmlReader.Create(new StringReader(xml), new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, XmlResolver = null, MaxCharactersInDocument = 4096 });
var document = XDocument.Load(reader);
var root = document.Root;
if (root is null || root.Name != "plist" || root.Attribute("version")?.Value != "1.0" || root.Attributes().Count() != 1 || root.Elements().Count() != 1 || root.Elements().Single().Name != "dict" || root.Nodes().OfType<XText>().Any(text => !string.IsNullOrWhiteSpace(text.Value)))
throw new InvalidOperationException("Native SystemVersion requires one top-level plist/dict.");
var dict = root.Elements().Single();
var values = dict.Elements().ToArray();
if (dict.HasAttributes || dict.Nodes().OfType<XText>().Any(text => !string.IsNullOrWhiteSpace(text.Value)) || values.Length % 2 != 0 || dict.Descendants("key").Count(key => key.Value == "ProductVersion") != 1)
throw new InvalidOperationException("Native SystemVersion requires exactly one direct ProductVersion key.");
string? versionText = null;
for (var index = 0; index < values.Length; index += 2)
{
var key = values[index]; var value = values[index + 1];
if (key.Name != "key" || key.HasElements || key.HasAttributes) throw new InvalidOperationException("Native SystemVersion has an invalid dict key/value pair.");
if (value.Name != "string" || value.HasElements || value.HasAttributes) throw new InvalidOperationException("Native SystemVersion requires scalar string values.");
if (key.Value != "ProductVersion") continue;
versionText = value.Value;
}
if (versionText is null || !System.Text.RegularExpressions.Regex.IsMatch(versionText, @"\A[0-9]+\.[0-9]+(?:\.[0-9]+)?\z") || !Version.TryParse(versionText, out var version) || version.Major < 14)
throw new InvalidOperationException("Native ProductVersion is invalid or below macOS 14.");
return versionText;
}
static async Task CaptureNativeSystemVersion(string id, string output, string token, bool full, CancellationToken cancellation)
{
var evidencePath = Path.Combine(output, "native-system-version.json");
if (File.Exists(evidencePath)) return;
var state = full ? FullState : "/dev/shm/installstate";
var ready = await Command("docker", ["exec", id, "head", "-c", "257", state + "/native-system-version.request"], output, "capture-native-version-request", cancellation, requireSuccess: false);
if (ready.ExitCode != 0 || string.IsNullOrEmpty(ready.Output)) return;
// The built-in producer publishes the final marker after closing raw bytes.
// A still incomplete marker remains pending within the outer Recovery deadline.
var requestFields = ready.Output.Split('\n');
if (ready.Output.Length <= 256 && (!ready.Output.EndsWith('\n') || requestFields.Length < 5 || !requestFields[^2].StartsWith("ready:", StringComparison.Ordinal))) return;
File.WriteAllText(Path.Combine(output, "native-system-version.request"), ready.Output, new UTF8Encoding(false));
var owner = await Command("docker", ["exec", id, "head", "-c", "81", state + "/run.owner"], output, "capture-native-version-owner", cancellation, requireSuccess: false);
if (owner.ExitCode != 0 || owner.Output != token + "\n") throw new InvalidOperationException("Native SystemVersion exchange has no current owned state.");
var started = Stopwatch.StartNew();
byte[] raw = []; string? version = null; string? error = null;
try
{
NativeVersionRequestLength(ready.Output, token);
// Linux coreutils transport preserves bytes; guest pre-SDK work uses only read/printf.
var capture = await Command("docker", ["exec", id, "bash", "-o", "pipefail", "-c", "head -c 4097 '" + state + "/native-system-version.plist' | base64 -w 0"], output, "capture-native-version-bytes", cancellation);
raw = Convert.FromBase64String(capture.Output);
File.WriteAllBytes(Path.Combine(output, "native-system-version.plist"), raw);
version = ParseNativeSystemVersion(raw, ready.Output, token);
}
catch (Exception exception) when (exception is InvalidOperationException or XmlException or DecoderFallbackException or FormatException)
{
error = exception.Message;
}
Save(evidencePath, new NativeVersionEvidence(token, NativeVersionSource, raw.Length, Hash(raw), NativeVersionMethod, version, error is null, started.Elapsed.TotalMilliseconds, DateTimeOffset.UtcNow, error));
Console.WriteLine(error is null ? "[native-version] method=" + NativeVersionMethod + " source=" + NativeVersionSource + " version=" + version : "[native-version] method=" + NativeVersionMethod + " source=" + NativeVersionSource + " failed: invalid native file/request; see raw evidence.");
if (error is not null) throw new InvalidOperationException("Native guest-file XML evidence failed; no installation permit: " + error);
}
static void ValidateNativeVersionBinding(string output, string token, string readiness)
{
if (new[] { "native-system-version.json", "native-system-version.plist", "native-system-version.request" }.Any(name => !File.Exists(Path.Combine(output, name))))
throw new InvalidOperationException("Native guest-file evidence is incomplete; no installation permit.");
using var evidence = JsonDocument.Parse(File.ReadAllText(Path.Combine(output, "native-system-version.json")));
using var result = JsonDocument.Parse(readiness);
var raw = File.ReadAllBytes(Path.Combine(output, "native-system-version.plist"));
var version = ParseNativeSystemVersion(raw, File.ReadAllText(Path.Combine(output, "native-system-version.request")), token);
var recorded = evidence.RootElement;
if (!recorded.GetProperty("success").GetBoolean() || recorded.GetProperty("token").GetString() != token
|| recorded.GetProperty("sourcePath").GetString() != NativeVersionSource || recorded.GetProperty("method").GetString() != NativeVersionMethod
|| recorded.GetProperty("byteLength").GetInt32() != raw.Length || recorded.GetProperty("sha256").GetString() != Hash(raw)
|| recorded.GetProperty("version").GetString() != version || result.RootElement.GetProperty("token").GetString() != token || result.RootElement.GetProperty("osVersion").GetString() != version)
throw new InvalidOperationException("Readiness version does not match the current token/path/length/SHA native guest-file evidence.");
}
sealed record NativeVersionEvidence(string Token, string SourcePath, int ByteLength, string Sha256, string Method, string? Version, bool Success, double ElapsedMilliseconds, DateTimeOffset CapturedUtc, string? Error);
static async Task ValidateNativeSystemVersion(string output)
{
Directory.CreateDirectory(output);
var fixture = Path.Combine(output, "validation-native-system-version");
Directory.CreateDirectory(fixture);
const string token = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
var canonical = Encoding.UTF8.GetBytes("""
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
\t<key>BuildID</key>
\t<string>5B24CC0E-5244-11EF-A61B-8668C9DC12C6</string>
\t<key>ProductBuildVersion</key>
\t<string>23G93</string>
\t<key>ProductCopyright</key>
\t<string>1983-2024 Apple Inc.</string>
\t<key>ProductName</key>
\t<string>macOS</string>
\t<key>ProductUserVisibleVersion</key>
\t<string>14.6.1</string>
\t<key>ProductVersion</key>
\t<string>14.6.1</string>
\t<key>iOSSupportVersion</key>
\t<string>17.6</string>
</dict>
</plist>
""".Replace("\\t", "\t", StringComparison.Ordinal) + "\n");
if (canonical.Length != 603 || Hash(canonical) != "0a652705e311f0346f7570007651bc13f4c98670950d376ddc21e3a567016b2b") throw new InvalidOperationException("Actual run4192 canonical SystemVersion fixture bytes differ.");
var valid = Encoding.UTF8.GetBytes("<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"><plist version=\"1.0\"><dict><key>ProductName</key><string>macOS</string><key>ProductVersion</key><string>14.6</string></dict></plist>\n");
string Request(byte[] raw) => token + "\n" + NativeVersionSource + "\n" + raw.Length + "\nready:" + token + "\n";
byte[] Changed(string from, string to) => Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(valid).Replace(from, to, StringComparison.Ordinal));
var duplicate = Changed("</dict>", "<key>ProductVersion</key><string>14.6</string></dict>");
var nested = Changed("<key>ProductVersion</key><string>14.6</string>", "<key>Nested</key><dict><key>ProductVersion</key><string>14.6</string></dict>");
var entity = Encoding.UTF8.GetBytes("<!DOCTYPE plist [<!ENTITY version SYSTEM 'file:///must-never-be-read'>]><plist version='1.0'><dict><key>ProductVersion</key><string>&version;</string></dict></plist>");
(string Name, byte[] Raw, string Request, string? Version)[] parserCases =
{
("actual-canonical603", canonical, Request(canonical), (string?)"14.6.1"),
(Name: "valid14", Raw: valid, Request: Request(valid), Version: (string?)"14.6"),
("valid14patch", Changed("14.6", "14.6.1"), Request(Changed("14.6", "14.6.1")), (string?)"14.6.1"),
("duplicate", duplicate, Request(duplicate), (string?)null),
("nested", nested, Request(nested), (string?)null),
("binary-plist", "bplist00"u8.ToArray(), Request("bplist00"u8.ToArray()), (string?)null),
("nul", valid.Concat(new byte[] { 0 }).ToArray(), Request(valid.Concat(new byte[] { 0 }).ToArray()), (string?)null),
("invalid-utf8", new byte[] { 0xff }, Request(new byte[] { 0xff }), (string?)null),
("oversize", new byte[4097], Request(new byte[4097]), (string?)null),
("entity", entity, Request(entity), (string?)null),
("invalid-version", Changed("14.6", "14.6junk"), Request(Changed("14.6", "14.6junk")), (string?)null),
("below14", Changed("14.6", "13.6"), Request(Changed("14.6", "13.6")), (string?)null),
("bad-eof", valid, Request(valid).TrimEnd('\n'), (string?)null),
("stale-token", valid, Request(valid).Replace(token, new string('b', 32), StringComparison.Ordinal), (string?)null),
("wrong-path", valid, Request(valid).Replace(NativeVersionSource, "/metadata/VERSION", StringComparison.Ordinal), (string?)null),
("length-mismatch", valid, Request(valid).Replace("\n" + valid.Length + "\n", "\n" + (valid.Length + 1) + "\n", StringComparison.Ordinal), (string?)null),
("dict-garbage", Changed("</dict>", "garbage</dict>"), Request(Changed("</dict>", "garbage</dict>")), (string?)null),
("bogus-value", Changed("<string>macOS</string>", "<bogus/>"), Request(Changed("<string>macOS</string>", "<bogus/>")), (string?)null),
("key-in-value-position", Changed("<string>macOS</string>", "<key>macOS</key>"), Request(Changed("<string>macOS</string>", "<key>macOS</key>")), (string?)null)
};
var parserReceipts = new List<object>();
foreach (var test in parserCases)
{
string? actual = null;
try { actual = ParseNativeSystemVersion(test.Raw, test.Request, token); }
catch (Exception exception) when (exception is InvalidOperationException or XmlException or DecoderFallbackException) { }
File.WriteAllBytes(Path.Combine(fixture, test.Name + ".plist"), test.Raw);
parserReceipts.Add(new { test.Name, accepted = actual is not null, version = actual, expectedVersion = test.Version });
if (actual != test.Version) throw new InvalidOperationException("Native SystemVersion XML/request fixture failed: " + test.Name);
}
var bindingState = Path.Combine(fixture, "binding");
Directory.CreateDirectory(bindingState);
var goodEvidence = new NativeVersionEvidence(token, NativeVersionSource, valid.Length, Hash(valid), NativeVersionMethod, "14.6", true, 0, DateTimeOffset.UtcNow, null);
var goodResult = JsonSerializer.Serialize(new { token, osVersion = "14.6" });
File.WriteAllBytes(Path.Combine(bindingState, "native-system-version.plist"), valid);
File.WriteAllText(Path.Combine(bindingState, "native-system-version.request"), Request(valid));
Save(Path.Combine(bindingState, "native-system-version.json"), goodEvidence);
ValidateNativeVersionBinding(bindingState, token, goodResult);
var bindingCases = new[]
{
goodEvidence with { Token = new string('b', 32) }, goodEvidence with { SourcePath = "/metadata/VERSION" },
goodEvidence with { ByteLength = valid.Length + 1 }, goodEvidence with { Sha256 = new string('f', 64) },
goodEvidence with { Method = "environment" }, goodEvidence with { Version = "14.6.1" }, goodEvidence with { Success = false }
};
foreach (var invalid in bindingCases)
{
Save(Path.Combine(bindingState, "native-system-version.json"), invalid);
try { ValidateNativeVersionBinding(bindingState, token, goodResult); }
catch (InvalidOperationException) { continue; }
throw new InvalidOperationException("Native SystemVersion binding accepted changed evidence.");
}
Save(Path.Combine(bindingState, "native-system-version.json"), goodEvidence);
try { ValidateNativeVersionBinding(bindingState, token, goodResult.Replace("14.6", "14.6.1", StringComparison.Ordinal)); throw new Exception("Readiness version mismatch accepted."); }
catch (InvalidOperationException) { }
var readiness = File.ReadAllText(Path.Combine("tools", "ci", "macos-native-readiness.sh"));
const string begin = "# BEGIN native SystemVersion plist request helpers\n";
const string end = "# END native SystemVersion plist request helpers\n";
var from = readiness.IndexOf(begin, StringComparison.Ordinal) + begin.Length;
var to = readiness.IndexOf(end, from, StringComparison.Ordinal);
var producer = readiness[from..to];
var mapped = ReplaceOnce(ReplaceOnce(producer, "[ -f \"$source\" ]", "[ -f \"$SYSTEM_VERSION_FIXTURE\" ]"), "< \"$source\"", "< \"$SYSTEM_VERSION_FIXTURE\"");
var gateStart = readiness.IndexOf("# END native SystemVersion plist getter\n", StringComparison.Ordinal) + "# END native SystemVersion plist getter\n".Length;
var candidateGate = readiness[gateStart..readiness.IndexOf("flush_outputs || finish false diagnostic_log_budget_exceeded", gateStart, StringComparison.Ordinal)];
var disagreement = Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(canonical).Replace("<dict>", "<dict><!--<key>ProductVersion</key><string>14.6</string>-->", StringComparison.Ordinal));
(string Name, byte[]? Raw, string Owner, string Existing, string? Candidate, bool Readonly, bool Request, bool Permit)[] shellCases =
{
("actual-canonical603", canonical, token, "", "14.6.1", true, true, true),
("valid-minified14", valid, token, "", "14.6", true, true, true),
("missing", null, token, "", null, false, false, false),
("nul", valid.Concat(new byte[] { 0 }).ToArray(), token, "", null, false, false, false),
("control-binary", valid.Concat(new byte[] { 1 }).ToArray(), token, "", null, false, false, false),
("oversize", Enumerable.Repeat((byte)'x', 4097).ToArray(), token, "", null, false, false, false),
("stale-owner", valid, new string('b', 32), "", null, false, false, false),
("stale-request", valid, token, "request", null, false, false, false),
("stale-raw", valid, token, "plist", null, false, false, false),
("numeric-duplicate", duplicate, token, "", "14.6", true, true, false),
("numeric-nested", nested, token, "", "14.6", true, true, false),
("numeric-bogus", Changed("<string>macOS</string>", "<bogus/>"), token, "", "14.6", true, true, false),
("version-disagreement", disagreement, token, "", "14.6", true, true, false),
("below14", Changed("14.6", "13.6"), token, "", "13.6", false, true, false),
("candidate-invalid", Changed("14.6", "14.6junk"), token, "", null, false, true, false),
("binary-plist", "bplist00"u8.ToArray(), token, "", null, false, true, false)
};
bool Eligible(string state, string candidate)
{
var result = JsonSerializer.Serialize(new { token, success = true, osVersion = candidate, architecture = "x86_64", uid = 0, disk = "/dev/disk1", diskBytes = GuestDiskBytes, readOnly = false, systemExit = 0, diskArbitrationExit = 0, recoveryExit = 0, diskListExit = 0 });
try { ValidateResult(result, token); ValidateNativeVersionBinding(state, token, result); return true; }
catch (Exception exception) when (exception is InvalidOperationException or XmlException or DecoderFallbackException) { return false; }
}
if (Eligible(Path.Combine(fixture, "absent-evidence"), "14.6")) throw new InvalidOperationException("Early numeric readiness result bypassed missing evidence.");
var shellReceipts = new List<object>();
foreach (var test in shellCases)
{
var state = Path.Combine(fixture, "producer-" + test.Name);
Directory.CreateDirectory(state);
var raw = Path.Combine(state, "source.plist");
if (test.Raw is not null) File.WriteAllBytes(raw, test.Raw);
File.WriteAllText(Path.Combine(state, "run.owner"), test.Owner + "\n");
if (test.Existing != "") File.WriteAllText(Path.Combine(state, "native-system-version." + test.Existing), "stale\n");
var script = "set -u\nSTATE_DIR=\"$1\"; SYSTEM_VERSION_FIXTURE=\"$2\"; PROOF_TOKEN=\"$3\"; SCALAR=\"\"\nexec 3> \"$STATE_DIR/proof.log\"\nfail_probe() { printf 'failed:%s\\n' \"$1\"; exit 1; }\n" + mapped + "\nif read_native_system_version; then printf '%s\\n' \"$SCALAR\" > \"$STATE_DIR/candidate\"\n" + candidateGate + "printf 'readonly-boundary\\n' > \"$STATE_DIR/readonly-boundary\"; exit 0; else printf 'failed:%s\\n' \"$NATIVE_VERSION_ERROR\"; exit 1; fi\n";
File.WriteAllText(Path.Combine(state, "producer.sh"), script);
using var deadline = new CancellationTokenSource(TimeSpan.FromSeconds(20));
var result = await Command("/bin/bash", ["-c", script, "native-version-producer-fixture", state, raw, token], output, "native-version-producer-" + test.Name, deadline.Token, requireSuccess: false);
var requestFile = Path.Combine(state, "native-system-version.request");
string? request = null;
if (File.Exists(requestFile) && File.ReadAllText(requestFile).EndsWith("\nready:" + token + "\n", StringComparison.Ordinal)) request = File.ReadAllText(requestFile);
var published = request is not null;
var readonlyReached = File.Exists(Path.Combine(state, "readonly-boundary"));
var candidateFile = Path.Combine(state, "candidate");
var candidate = File.Exists(candidateFile) ? File.ReadAllText(candidateFile).TrimEnd('\n') : null;
if ((result.ExitCode == 0) != test.Readonly || readonlyReached != test.Readonly || candidate != test.Candidate || published != test.Request)
throw new InvalidOperationException("Native SystemVersion exact Bash candidate fixture failed: " + test.Name);
if (published && !File.ReadAllBytes(Path.Combine(state, "native-system-version.plist")).SequenceEqual(test.Raw!)) throw new InvalidOperationException("Native version producer did not preserve exact bytes.");
string? qualifiedVersion = null; string? qualificationError = null;
if (published)
{
try { qualifiedVersion = ParseNativeSystemVersion(test.Raw!, request!, token); }
catch (Exception exception) when (exception is InvalidOperationException or XmlException or DecoderFallbackException) { qualificationError = exception.Message; }
Save(Path.Combine(state, "native-system-version.json"), new NativeVersionEvidence(token, NativeVersionSource, test.Raw!.Length, Hash(test.Raw!), NativeVersionMethod, qualifiedVersion, qualificationError is null, 0, DateTimeOffset.UtcNow, qualificationError));
}
var eligible = Eligible(state, candidate ?? "14.6");
if (eligible != test.Permit) throw new InvalidOperationException("Bash candidate bypassed mandatory host qualification: " + test.Name);
shellReceipts.Add(new { test.Name, result.ExitCode, requestPublished = published, readonlyReached, candidate, qualifiedVersion, permitEligible = eligible });
}
Save(Path.Combine(output, "native-system-version-fixtures.json"), new { success = true, parserCases = parserReceipts, bindingPositiveCases = 1, bindingNegativeCases = bindingCases.Length + 1, earlyResultWithoutEvidenceRejected = true, producerCases = shellReceipts, sourceBoundHashes = new { controller = Hash(File.ReadAllBytes("tools/ci/MacOsNativeDiagnostic.cs")), readiness = Hash(Encoding.UTF8.GetBytes(readiness)), producer = Hash(Encoding.UTF8.GetBytes(producer)), actualCanonical603 = Hash(canonical) }, sourcePathMappedOnlyForFixtureRead = true, actualBash = "/bin/bash", candidateIsQualifiedReadiness = false, hostBindingRequiredBeforePermit = true, responseRequired = false, requestCommitLineRequired = true, dockerExecuted = false, guestExecuted = false });
}
static void ReportCpuPreflight(string output, string logs)
{
var receipt = Path.Combine(output, "cpu-preflight-runtime.json");
if (File.Exists(receipt)) return;
var expectedSuffix = " cpu=" + CpuFlags + "; actual AVX/AVX2 executed before Apple download";
foreach (var line in logs.Split('\n'))
{
var match = System.Text.RegularExpressions.Regex.Match(line, @"\[cpu-preflight\] positive=33 negative=([0-9]{1,3})");
if (!match.Success || match.Groups[1].Value == "33" || !line[(match.Index + match.Length)..].StartsWith(expectedSuffix, StringComparison.Ordinal)) continue;
var sourceMarker = match.Value + expectedSuffix;
var marker = "[cpu-preflight] positive=33 negative=" + match.Groups[1].Value + " accelerator=tcg cpu=" + CpuModel + " instructions=AVX/AVX2";
Console.WriteLine(marker);
Save(receipt, new { marker, markerSha256 = Hash(Encoding.UTF8.GetBytes(sourceMarker)), capturedUtc = DateTimeOffset.UtcNow, readinessGateSatisfied = false });
return;
}
}
static int KernelHandoffs(string logs) => logs.Split('\n').Count(line => line.Trim().StartsWith("#[EB|LOG:HANDOFF TO XNU] ", StringComparison.Ordinal));
static void ValidateBootProgress()
{
const string handoff = "#[EB|LOG:HANDOFF TO XNU] _\r\n";
foreach (var (logs, count) in new[] { ("", 0), ("BdsDxe: starting Boot0002\n", 0), (handoff, 1), (handoff + handoff, 2), ("source says \"" + handoff, 0), ("#[EB|LOG:HANDOFF TO XNU-ish] _\n", 0) })
if (KernelHandoffs(logs) != count) throw new InvalidOperationException("Recovery boot-progress parser accepted missing, quoted or malformed markers.");
}
static void CheckRecoveryBootProgress(string output)
{
var retained = Path.Combine(output, "capture-kernel-handoffs.last-success.stdout.log");
var count = KernelHandoffs(File.ReadAllText(File.Exists(retained) ? retained : Path.Combine(output, "container.stdout.log")));
Save(Path.Combine(output, "recovery-boot-progress.json"), new { kernelHandoffs = count, unexpectedRepeat = count >= 2, capturedUtc = DateTimeOffset.UtcNow });
if (count >= 2) throw new InvalidOperationException("Recovery returned to kernel boot before readiness; repeated handoff detected. This does not identify the reset cause.");
}
static async Task CapturePressure(string id, string output, string phase, CancellationToken cancellation)
{
using var snapshotDeadline = CancellationTokenSource.CreateLinkedTokenSource(cancellation);
snapshotDeadline.CancelAfter(TimeSpan.FromSeconds(20));
const string snapshot = """
printf '[snapshot UTC]\n'; date -u '+%Y-%m-%dT%H:%M:%SZ'
for path in /proc/meminfo /proc/loadavg /proc/pressure/cpu /proc/pressure/memory /proc/pressure/io \
/sys/fs/cgroup/cpu.max /sys/fs/cgroup/cpu.stat /sys/fs/cgroup/cpu.pressure \
/sys/fs/cgroup/memory.max /sys/fs/cgroup/memory.current /sys/fs/cgroup/memory.peak \
/sys/fs/cgroup/memory.events /sys/fs/cgroup/memory.stat /sys/fs/cgroup/memory.pressure \
/sys/fs/cgroup/memory.swap.current /sys/fs/cgroup/io.stat /sys/fs/cgroup/io.pressure; do
printf '\n[%s]\n' "$path"
if [ -r "$path" ]; then cat "$path"; else printf 'unavailable\n'; fi
done
printf '\n[host paging counters]\n'
awk '/^(pgmajfault|pswpin|pswpout) / {print}' /proc/vmstat
printf '\n[owned QEMU process snapshot; counters are raw]\n'
qemu_pid=$(head -c 16 /run/shm/qemu.pid 2>/dev/null || true)
case "$qemu_pid" in ''|*[!0-9]*|0|1) printf 'owned QEMU PID unavailable\n' ;;
*)
qemu_exe=$(readlink "/proc/$qemu_pid/exe" 2>/dev/null || true)
if [ "$qemu_exe" = /usr/bin/qemu-system-x86_64 ]; then
printf 'pid=%s executable=%s\n' "$qemu_pid" "$qemu_exe"
for file in cmdline stat status; do
printf '\n[/proc/%s/%s]\n' "$qemu_pid" "$file"
head -c 4096 "/proc/$qemu_pid/$file" 2>/dev/null | tr '\000' '\n' || true
done
task_count=0
for file in /proc/"$qemu_pid"/task/*/stat; do
[ -r "$file" ] || continue
[ "$task_count" -lt 32 ] || { printf '[remaining own QEMU threads omitted]\n'; break; }
printf '\n[%s]\n' "$file"; head -c 4096 "$file" 2>/dev/null || true
task_count=$((task_count + 1))
done
else
printf 'owned QEMU executable identity unavailable; no process files read\n'
fi ;;
esac
""";
try
{
await Command("docker", ["exec", id, "sh", "-c", snapshot], output, "capture-pressure-" + phase, snapshotDeadline.Token, requireSuccess: false, retainSuccessful: true);
}
catch (Exception exception)
{
// Optional evidence must not replace the guest outcome or prevent cleanup.
try { Save(Path.Combine(output, "capture-pressure-" + phase + ".unavailable.json"), new { phase, error = exception.Message, capturedUtc = DateTimeOffset.UtcNow }); }
catch (Exception evidenceError) { Console.Error.WriteLine("Optional pressure evidence: " + evidenceError.Message); }
}
}
static async Task CaptureMonitor(string id, string output, string token, CancellationToken cancellation)
{
using var deadline = CancellationTokenSource.CreateLinkedTokenSource(cancellation);
deadline.CancelAfter(TimeSpan.FromSeconds(10));
int? monitorExit = null, copyExit = null;
string? error = null;
try
{
if (!System.Text.RegularExpressions.Regex.IsMatch(id, "^[0-9a-f]{64}$") || !System.Text.RegularExpressions.Regex.IsMatch(token, "^[0-9a-f]{32}$")) throw new InvalidOperationException("No saved owned container identity for the optional monitor capture.");
var inspection = await Command("docker", ["inspect", id], output, "capture-monitor-container", deadline.Token);
AssertContainer(inspection.Output, token);
using (var document = JsonDocument.Parse(inspection.Output))
if (document.RootElement[0].GetProperty("Id").GetString() != id || !document.RootElement[0].GetProperty("State").GetProperty("Running").GetBoolean()) throw new InvalidOperationException("Owned guest container is no longer running for the optional monitor capture.");
var screen = "/tmp/native-diagnostic-screen-" + token + ".ppm";
var monitor = await Command("docker", ["exec", id, "sh", "-c", """
test -S /run/shm/monitor.sock || exit 1
rm -f -- "$1" || exit 1
printf 'info kvm\ninfo status\nscreendump %s\n' "$1" | /usr/bin/timeout -s KILL 5 /usr/bin/nc.openbsd -q 1 -w 2 -U /run/shm/monitor.sock
monitor_exit=$?
printf '\n[monitor-exit] %s\n' "$monitor_exit"
[ "$monitor_exit" -eq 0 ] || exit "$monitor_exit"
bytes=$(stat -c%s "$1") || exit 1
[ "$bytes" -gt 0 ] && [ "$bytes" -le 8388608 ] || exit 1
printf '[screen-bytes] %s\n' "$bytes"
""", "native-monitor", screen], output, "capture-monitor", deadline.Token, requireSuccess: false);
monitorExit = monitor.ExitCode;
if (monitorExit != 0) throw new InvalidOperationException("Optional monitor status/screenshot command exited " + monitorExit + ".");
var copy = await Command("docker", ["cp", id + ":" + screen, Path.Combine(output, "guest-screen-" + token + ".ppm")], output, "capture-monitor-screen", deadline.Token, requireSuccess: false);
copyExit = copy.ExitCode;
if (copyExit != 0) throw new InvalidOperationException("Optional monitor screenshot copy exited " + copyExit + ".");
}
catch (Exception exception) { error = exception.Message; Console.Error.WriteLine("Optional final monitor capture: " + error); }
finally { Save(Path.Combine(output, "monitor-capture.json"), new { token, monitorExit, copyExit, success = error is null, error, capturedUtc = DateTimeOffset.UtcNow }); }
}
static async Task<bool> Cleanup(string output)
{
var path = Path.Combine(output, "owned-resources.json");
if (!File.Exists(path)) return true;
var state = JsonSerializer.Deserialize<OwnedResources>(File.ReadAllText(path), JsonOptions) ?? throw new InvalidOperationException("Invalid owned-resource receipt.");
if (!System.Text.RegularExpressions.Regex.IsMatch(state.Token, "^[0-9a-f]{32}$") || state.ContainerName != "meeting-assistant-native-" + state.Token || state.ImageTag != "meeting-assistant-native-diagnostic:" + state.Token) throw new InvalidOperationException("Invalid cleanup ownership identity.");
using var deadline = new CancellationTokenSource(TimeSpan.FromSeconds(90));
try
{
foreach (var kind in new[] { "container", "image" })
{
var name = kind == "container" ? state.ContainerName : state.ImageTag;
var inspect = await Command("docker", [kind, "inspect", name], output, "cleanup-" + kind + "-inspect", deadline.Token, requireSuccess: false);
if (inspect.ExitCode != 0)
{
if (inspect.Error.Contains("No such object", StringComparison.Ordinal) || inspect.Error.Contains("No such container", StringComparison.Ordinal) || inspect.Error.Contains("No such image", StringComparison.Ordinal)) continue;
throw new InvalidOperationException("Cannot establish owned " + kind + " absence: " + inspect.Error);
}
using var document = JsonDocument.Parse(inspect.Output);
var resource = document.RootElement[0];
if (resource.GetProperty("Config").GetProperty("Labels").GetProperty(OwnerLabel).GetString() != state.Token) throw new InvalidOperationException("Cleanup refuses a resource without this run's exact ownership label.");
var id = resource.GetProperty("Id").GetString()!;
var expectedId = kind == "container" ? state.ContainerId : state.ImageId;
if (expectedId is not null && expectedId != id) throw new InvalidOperationException("Cleanup refuses a resource whose ID changed after creation.");
await Command("docker", kind == "container" ? ["rm", "--force", "--volumes", id] : ["image", "rm", id], output, "cleanup-" + kind + "-remove", deadline.Token);
}
if (Path.GetFileName(state.WorkDirectory) == "meeting-assistant-native-" + state.Token && File.Exists(Path.Combine(state.WorkDirectory, "run.owner")) && File.ReadAllText(Path.Combine(state.WorkDirectory, "run.owner")) == state.Token) Directory.Delete(state.WorkDirectory, true);
Save(Path.Combine(output, "cleanup.json"), new { state.Token, success = true, completedUtc = DateTimeOffset.UtcNow });
return true;
}
catch (Exception exception)
{
Save(Path.Combine(output, "cleanup.json"), new { state.Token, success = false, error = exception.Message, completedUtc = DateTimeOffset.UtcNow });
Console.Error.WriteLine("Owned diagnostic cleanup failed: " + exception.Message);
return false;
}
}
static async Task ValidateRecoveryPatch(string output)
{
if (Crc32(Encoding.ASCII.GetBytes("123456789")) != 0xcbf43926) throw new InvalidOperationException("Independent C# CRC32 known vector failed.");
var fixture = Path.Combine(output, "validation-recovery-patch");
Directory.CreateDirectory(fixture);
var patch = File.ReadAllText(Path.Combine(output, "recovery-patch.py"));
const string marker = "SCRIPT_ORIGINAL = b'''";
var start = patch.IndexOf(marker, StringComparison.Ordinal) + marker.Length;
var end = patch.IndexOf("'''", start, StringComparison.Ordinal);
var bootstrap = patch[start..end];
var cases = new[] {
("13-zlib", OriginalDaemon13, true, true), ("14-zlib", OriginalDaemon + "\n", true, true),
("13-raw", OriginalDaemon13, false, true), ("14-raw", OriginalDaemon + "\n", false, true),
("unknown", OriginalDaemon13.Replace("Interactive", "Unknown"), true, false),
("duplicate", OriginalDaemon13 + OriginalDaemon + "\n", true, false),
("duplicate-unknown", OriginalDaemon13 + OriginalDaemon13.Replace("Interactive", "Unknown"), true, false),
("malformed", OriginalDaemon13.Replace("</array>", "</broken>"), true, false),
("wrong-arguments", OriginalDaemon13.Replace("/usr/libexec/recoveryosd", "/usr/libexec/wrongdaemon"), true, false),
("duplicate-arguments", OriginalDaemon13.Replace("</array>", "<string>/usr/libexec/recoveryosd</string></array>"), true, false),
("corrupt-data-crc", OriginalDaemon13, true, false), ("unsupported-crc", OriginalDaemon13, true, false),
("xml-boundary", OriginalDaemon13, true, false), ("physical-boundary", OriginalDaemon13, true, false),
("unknown-zero-run", OriginalDaemon13, true, false), ("logical-boundary", OriginalDaemon13, false, false)
};
foreach (var item in cases)
{
var path = Path.Combine(fixture, item.Item1 + ".dmg");
CreateRecoveryFixture(path, bootstrap, item.Item2, item.Item3);
if (item.Item1 is "corrupt-data-crc" or "unsupported-crc" or "xml-boundary" or "physical-boundary" or "unknown-zero-run" or "logical-boundary")
{
var corrupt = File.ReadAllBytes(path);
var trailer = corrupt.Length - 512;
if (item.Item1 == "corrupt-data-crc") corrupt[trailer + 88] ^= 1;
else if (item.Item1 == "unsupported-crc") BinaryPrimitives.WriteUInt32BigEndian(corrupt.AsSpan(trailer + 80), 3);
else if (item.Item1 == "xml-boundary") BinaryPrimitives.WriteUInt64BigEndian(corrupt.AsSpan(trailer + 224), (ulong)corrupt.Length);
else if (item.Item1 == "logical-boundary") BinaryPrimitives.WriteUInt64BigEndian(corrupt.AsSpan(trailer + 492), 1);
else
{
var xmlOffset = checked((int)BinaryPrimitives.ReadUInt64BigEndian(corrupt.AsSpan(trailer + 216)));
var xmlLength = checked((int)BinaryPrimitives.ReadUInt64BigEndian(corrupt.AsSpan(trailer + 224)));
var xmlText = Encoding.UTF8.GetString(corrupt, xmlOffset, xmlLength);
var data = XDocument.Parse(xmlText).Descendants("data").Single().Value;
var mish = Convert.FromBase64String(data);
if (item.Item1 == "physical-boundary") BinaryPrimitives.WriteUInt64BigEndian(mish.AsSpan(236), (ulong)corrupt.Length);
else BinaryPrimitives.WriteUInt32BigEndian(mish.AsSpan(204), 0);
var replacement = Encoding.UTF8.GetBytes(ReplaceOnce(xmlText, data, Convert.ToBase64String(mish)));
replacement.CopyTo(corrupt, xmlOffset);
}
File.WriteAllBytes(path, corrupt);
}
var before = File.ReadAllBytes(path);
var result = await Command("python3", ["-B", Path.Combine(output, "recovery-patch.py"), path], fixture, item.Item1, CancellationToken.None, requireSuccess: false);
var after = File.ReadAllBytes(path);
if ((result.ExitCode == 0) != item.Item4) throw new InvalidOperationException("Recovery fixture result mismatch: " + item.Item1 + ": " + result.Error);
if (!item.Item4 && !before.SequenceEqual(after)) throw new InvalidOperationException("Rejected Recovery fixture was modified: " + item.Item1);
if (item.Item4)
{
var decoded = DecodeRecoveryFixture(after, item.Item3);
var original = Encoding.UTF8.GetBytes(item.Item2);
var expectedText = item.Item1.StartsWith("13", StringComparison.Ordinal) ? DiagnosticDaemon13 : DiagnosticDaemon;
var expected = Encoding.UTF8.GetBytes(expectedText.PadRight(item.Item2.Length, ' '));
if (before.Length != after.Length || !decoded.AsSpan(4096, original.Length).SequenceEqual(expected)) throw new InvalidOperationException("Recovery fixture changed byte extent or daemon fields: " + item.Item1);
ValidateDaemon(expectedText, item.Item1.StartsWith("13", StringComparison.Ordinal) ? "Interactive" : "App", true);
VerifyRecoveryFixtureChecksums(after, decoded);
}
}
Save(Path.Combine(fixture, "receipt.json"), new { success = true, positiveCases = 4, negativeCases = 12, rejectedImagesUnmodified = true, knownDaemonFieldsPreserved = true, readBackCrc32IndependentlyVerified = true, syntheticUdifFixtures = true, guestExecuted = false });
}
static uint Crc32(ReadOnlySpan<byte> bytes)
{
var crc = uint.MaxValue;
foreach (var value in bytes)
{
crc ^= value;
for (var bit = 0; bit < 8; bit++) crc = (crc >> 1) ^ ((crc & 1) != 0 ? 0xedb88320u : 0);
}
return ~crc;
}
static void CreateRecoveryFixture(string path, string bootstrap, string daemon, bool compressed)
{
var decoded = new byte[16384];
Encoding.UTF8.GetBytes(bootstrap).CopyTo(decoded, 64);
Encoding.UTF8.GetBytes(daemon).CopyTo(decoded, 4096);
byte[] stored;
if (compressed)
{
using var memory = new MemoryStream();
using (var zipper = new ZLibStream(memory, CompressionLevel.Fastest, true)) zipper.Write(decoded);
stored = memory.ToArray();
}
else stored = decoded;
var mish = new byte[284];
Encoding.ASCII.GetBytes("mish").CopyTo(mish, 0);
BinaryPrimitives.WriteUInt32BigEndian(mish.AsSpan(4), 1);
BinaryPrimitives.WriteUInt64BigEndian(mish.AsSpan(16), 32);
BinaryPrimitives.WriteUInt32BigEndian(mish.AsSpan(64), 2);
BinaryPrimitives.WriteUInt32BigEndian(mish.AsSpan(68), 32);
BinaryPrimitives.WriteUInt32BigEndian(mish.AsSpan(72), Crc32(decoded));
BinaryPrimitives.WriteUInt32BigEndian(mish.AsSpan(200), 2);
BinaryPrimitives.WriteUInt32BigEndian(mish.AsSpan(204), compressed ? 0x80000005u : 1u);
BinaryPrimitives.WriteUInt64BigEndian(mish.AsSpan(220), 32);
BinaryPrimitives.WriteUInt64BigEndian(mish.AsSpan(236), (ulong)stored.Length);
BinaryPrimitives.WriteUInt32BigEndian(mish.AsSpan(244), 0xffffffff);
var xml = Encoding.UTF8.GetBytes("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<plist version=\"1.0\"><dict><key>resource-fork</key><dict><key>blkx</key><array><dict><key>Data</key><data>" + Convert.ToBase64String(mish) + "</data></dict></array></dict></dict></plist>\n");
var koly = new byte[512];
Encoding.ASCII.GetBytes("koly").CopyTo(koly, 0);
BinaryPrimitives.WriteUInt32BigEndian(koly.AsSpan(4), 4);
BinaryPrimitives.WriteUInt32BigEndian(koly.AsSpan(8), 512);
BinaryPrimitives.WriteUInt32BigEndian(koly.AsSpan(12), 1);
BinaryPrimitives.WriteUInt64BigEndian(koly.AsSpan(32), (ulong)stored.Length);
BinaryPrimitives.WriteUInt32BigEndian(koly.AsSpan(80), 2);
BinaryPrimitives.WriteUInt32BigEndian(koly.AsSpan(84), 32);
BinaryPrimitives.WriteUInt32BigEndian(koly.AsSpan(88), Crc32(stored));
BinaryPrimitives.WriteUInt64BigEndian(koly.AsSpan(216), (ulong)stored.Length);
BinaryPrimitives.WriteUInt64BigEndian(koly.AsSpan(224), (ulong)xml.Length);
BinaryPrimitives.WriteUInt32BigEndian(koly.AsSpan(352), 2);
BinaryPrimitives.WriteUInt32BigEndian(koly.AsSpan(356), 32);
BinaryPrimitives.WriteUInt32BigEndian(koly.AsSpan(360), Crc32(mish.AsSpan(72, 4)));
BinaryPrimitives.WriteUInt64BigEndian(koly.AsSpan(492), 32);
File.WriteAllBytes(path, stored.Concat(xml).Concat(koly).ToArray());
}
static byte[] DecodeRecoveryFixture(byte[] image, bool compressed)
{
var length = checked((int)BinaryPrimitives.ReadUInt64BigEndian(image.AsSpan(image.Length - 512 + 32)));
if (!compressed) return image[..length];
using var input = new MemoryStream(image, 0, length);
using var decoder = new ZLibStream(input, CompressionMode.Decompress);
using var output = new MemoryStream();
decoder.CopyTo(output);
return output.ToArray();
}
static void VerifyRecoveryFixtureChecksums(byte[] image, byte[] decoded)
{
var trailer = image.Length - 512;
var length = checked((int)BinaryPrimitives.ReadUInt64BigEndian(image.AsSpan(trailer + 32)));
var xmlLength = checked((int)BinaryPrimitives.ReadUInt64BigEndian(image.AsSpan(trailer + 224)));
var xml = XDocument.Parse(Encoding.UTF8.GetString(image, length, xmlLength));
var mish = Convert.FromBase64String(xml.Descendants("data").Single().Value);
if (Crc32(image.AsSpan(0, length)) != BinaryPrimitives.ReadUInt32BigEndian(image.AsSpan(trailer + 88)) || Crc32(decoded) != BinaryPrimitives.ReadUInt32BigEndian(mish.AsSpan(72)) || Crc32(mish.AsSpan(72, 4)) != BinaryPrimitives.ReadUInt32BigEndian(image.AsSpan(trailer + 360))) throw new InvalidOperationException("Independent C# fixture CRC32 readback failed.");
}
static async Task ValidateResourceRetention(string output)
{
var fixture = Path.Combine(output, "validation-resource-retention");
Directory.CreateDirectory(fixture);
const string label = "capture-resource-fixture";
const string successful = "Successful snapshot before stopped-container capture.\n";
await Command("bash", ["-c", "printf '%s\\n' 'Successful snapshot before stopped-container capture.'"], fixture, label, CancellationToken.None, retainSuccessful: true);
await Command("bash", ["-c", "printf '%s\\n' 'Container is not running.' >&2; exit 1"], fixture, label, CancellationToken.None, requireSuccess: false, retainSuccessful: true);
var retained = Path.Combine(fixture, label + ".last-success.stdout.log");
if (!File.Exists(retained) || File.ReadAllText(retained) != successful || File.ReadAllText(Path.Combine(fixture, label + ".stdout.log")) != "" || !File.ReadAllText(Path.Combine(fixture, label + ".stderr.log")).Contains("Container is not running."))
throw new InvalidOperationException("A failed final capture lost the last successful resource snapshot.");
using var receipt = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture, label + ".last-success.json")));
if (receipt.RootElement.GetProperty("stdoutSha256").GetString() != Hash(Encoding.UTF8.GetBytes(successful)) || receipt.RootElement.GetProperty("exitCode").GetInt32() != 0) throw new InvalidOperationException("Last successful snapshot receipt does not identify the retained bytes.");
}
static async Task<CommandResult> Command(string executable, string[] arguments, string output, string label, CancellationToken cancellation, bool requireSuccess = true, bool echo = false, bool retainSuccessful = false)
{
if (!label.StartsWith("capture-", StringComparison.Ordinal) && label is not "container" and not "container-running" and not "guest-container-resources")
Console.WriteLine("[native-diagnostic] " + label);
using var commandCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellation);
var commandToken = commandCancellation.Token;
var start = new ProcessStartInfo(executable) { RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false };
foreach (var argument in arguments) start.ArgumentList.Add(argument);
start.Environment["GIT_TERMINAL_PROMPT"] = "0";
using var process = Process.Start(start) ?? throw new InvalidOperationException("Cannot start " + executable);
async Task<string> Read(StreamReader reader, string stream)
{
var captured = new StringBuilder();
var buffer = new char[8192];
using var log = new StreamWriter(Path.Combine(output, label + "." + stream + ".log"), false, new UTF8Encoding(false));
while (true)
{
var count = await reader.ReadAsync(buffer.AsMemory(), commandToken);
if (count == 0) break;
if (captured.Length + count > MaximumCapturedCharacters)
{
commandCancellation.Cancel();
throw new InvalidOperationException(label + " exceeded its bounded diagnostic log size.");
}
captured.Append(buffer, 0, count);
await log.WriteAsync(buffer.AsMemory(0, count), commandToken);
await log.FlushAsync(commandToken);
if (echo) Console.Write(new string(buffer, 0, count));
}
return captured.ToString();
}
var stdout = Read(process.StandardOutput, "stdout");
var stderr = Read(process.StandardError, "stderr");
try
{
await Task.WhenAll(stdout, stderr, process.WaitForExitAsync(commandToken));
var result = new CommandResult(process.ExitCode, await stdout, await stderr);
if (retainSuccessful && result.ExitCode == 0 && !string.IsNullOrWhiteSpace(result.Output))
{
File.WriteAllText(Path.Combine(output, label + ".last-success.stdout.log"), result.Output, new UTF8Encoding(false));
Save(Path.Combine(output, label + ".last-success.json"), new { exitCode = result.ExitCode, stdoutSha256 = Hash(Encoding.UTF8.GetBytes(result.Output)), capturedUtc = DateTimeOffset.UtcNow });
}
if (requireSuccess && result.ExitCode != 0) throw new InvalidOperationException($"{label} exited {result.ExitCode}: {result.Error[..Math.Min(result.Error.Length, 1500)]}");
return result;
}
catch
{
try { if (!process.HasExited) process.Kill(entireProcessTree: true); } catch (InvalidOperationException) { }
throw;
}
}
static string Hash(byte[] bytes) => Convert.ToHexStringLower(SHA256.HashData(bytes));
static void PrintGuestProof(string output, string token)
{
var path = Path.Combine(output, "guest-proof.log");
if (!File.Exists(path)) { Console.WriteLine("[native-diagnostic] No native guest proof was captured."); return; }
var proof = File.ReadAllText(path).Replace(token, "<run-id>", StringComparison.Ordinal);
const int budget = 512 * 1024;
if (proof.Length > budget)
proof = proof[..(64 * 1024)] + "\n[native-diagnostic] Middle of proof omitted from CI stdout; complete bounded proof is retained in the artifact.\n" + proof[^((budget - 64 * 1024))..];
Console.WriteLine("[native-diagnostic] Final native guest proof:");
Console.Write(proof);
}
static void PrintFullProof(string output, string token)
{
foreach (var name in new[] { "full-result.json", "firstboot.log", "guest-logs/build.stdout.log", "guest-logs/build.stderr.log", "guest-logs/test.stdout.log", "guest-logs/test.stderr.log" })
{
var path = Path.Combine(output, name);
if (!File.Exists(path)) continue;
var proof = File.ReadAllText(path).Replace(token, "<run-id>", StringComparison.Ordinal);
if (proof.Length > 64 * 1024) proof = "[earlier output retained in artifact]\n" + proof[^(64 * 1024)..];
Console.WriteLine("[native-diagnostic] Final native evidence: " + name);
Console.WriteLine(proof);
}
}
static void Save(string path, object value)
{
var temporary = path + ".tmp";
File.WriteAllText(temporary, JsonSerializer.Serialize(value, JsonOptions), new UTF8Encoding(false));
File.Move(temporary, path, overwrite: true);
}
sealed record OwnedResources(string Token, string ContainerName, string ImageTag, string WorkDirectory, string? ContainerId = null, string? ImageId = null);
sealed record CommandResult(int ExitCode, string Output, string Error);
}