#:property PublishAot=false using System.Diagnostics; using System.IO.Compression; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using System.Text.Json; 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 CryptexUrl = "https://github.com/acidanthera/CryptexFixup/releases/download/1.0.5/CryptexFixup-1.0.5-RELEASE.zip"; const string CryptexHash = "25041d94a0fe9a0261caf0ba89b36dfcb21682bf3c697a34bcaddc839576ab30"; const string OpenCoreTemplateHash = "287328995d4198f1b05166f087d85bf7ef66bedafe150d17ad112ac8de60051d"; 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/13/ci-state"; 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 = """ \tLabel \tcom.apple.recoveryosd \tOnDemand \t \tProcessType \tApp \tEnablePressuredExit \t \tProgramArguments \t \t\t/usr/libexec/recoveryosd \t """.Replace("\\t", "\t", StringComparison.Ordinal); static readonly string DiagnosticDaemon = (OriginalDaemon + "\n") .Replace("\n", "", StringComparison.Ordinal) .Replace("\t\t/usr/libexec/recoveryosd", "\t\t/bin/bash\n\t\t/Volumes/installstate/launch.sh", StringComparison.Ordinal); public static async Task 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] [--cryptex-archive verified-release.zip] [--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(); 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, Option(args, "--cryptex-archive")); if (full) 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 execution leaves eight minutes within the existing 180-minute job for evidence/cleanup. var deadlineMinutes = full ? 172 : 40; 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 = "kvm-host-ventura-cryptex", causalSingleVariableTest = false, kvm = true, cpuModel = "host", recoveryMajor = 13, cryptexVersion = "1.0.5", liluVersion = "1.7.1", 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, Option(args, "--cryptex-archive")); 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 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", "--device", "/dev/kvm:/dev/kvm:rw", "--env", "KVM=Y", "--env", "CPU_MODEL=host", "--env", "NETWORK=slirp", "--env", "DISPLAY=web", "--env", "MANUAL=N", "--env", "VERSION=13", "--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); Console.WriteLine(full ? "The owned restricted KVM/host-CPU macOS 13 guest is starting. Installation requires fresh native readiness and an owned-disk permit; success requires all 577 tests with zero skips." : "The owned restricted KVM/host-CPU macOS 13 guest is starting. Success requires native macOS 13+/x86_64 and a writable 64-GiB disk; no installer will run."); var phaseStarted = Stopwatch.StartNew(); var phase = "recovery"; var phaseBudget = TimeSpan.FromMinutes(40); var heartbeat = Stopwatch.StartNew(); var permitted = false; while (true) { deadline.Token.ThrowIfCancellationRequested(); await CaptureGuest(id, output, deadline.Token, full); if (full && phaseStarted.Elapsed > phaseBudget) throw new InvalidOperationException("The bounded native " + phase + " phase exceeded " + phaseBudget.TotalMinutes + " minutes."); var resultPath = Path.Combine(output, "guest-result.json"); if (File.Exists(resultPath) && !permitted) { var result = File.ReadAllText(resultPath); ValidateResult(result, token); 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); } 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 = ReplaceOnce(readiness, "(( ${os_version%%.*} >= 13 ))", "(( ${os_version%%.*} >= 14 ))"); if (Hash(Encoding.UTF8.GetBytes(baseline)) != "4d428f594dac14eff64ed87b172c81ecf85ac91da8c5460cd6ec4b1d310800c3") throw new InvalidOperationException("Compatibility readiness may change only the baseline's macOS minimum to 13; identity, services, disk and limits must remain identical."); 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."); XDocument.Parse(DiagnosticDaemon); if (Encoding.UTF8.GetByteCount(DiagnosticDaemon) > Encoding.UTF8.GetByteCount(OriginalDaemon + "\n")) throw new InvalidOperationException("Daemon replacement exceeds original file."); var good = JsonSerializer.Serialize(new { token = "validation", success = true, osVersion = "13.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("13.6.1", "12.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=Y","CPU_MODEL=host","VERSION=13"]},"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":[{"PathOnHost":"/dev/kvm","PathInContainer":"/dev/kvm","CgroupPermissions":"rw"}]},"Mounts":[{"Type":"volume","Destination":"/storage","RW":true}]}] """; AssertContainer(boundary, "validation"); foreach (var invalid in new[] { boundary.Replace("\"Privileged\":false", "\"Privileged\":true"), boundary.Replace("\"CgroupPermissions\":\"rw\"", "\"CgroupPermissions\":\"rwm\""), boundary.Replace("/dev/kvm", "/dev/other"), boundary.Replace("KVM=Y", "KVM=N"), boundary.Replace("CPU_MODEL=host", "CPU_MODEL=Skylake-Client-v4"), boundary.Replace("VERSION=13", "VERSION=14"), 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") }) { try { AssertContainer(invalid, "validation"); } catch (InvalidOperationException) { continue; } throw new InvalidOperationException("Diagnostic validator accepted an excessive/wrong-profile container boundary."); } } static async Task PrepareSource(string source, string output, string token, bool writeSource, CancellationToken cancellation, bool full = false, string? cryptexArchive = null) { Directory.CreateDirectory(output); 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 patch = ReplaceOnce(originalPatch, OriginalBootstrap, MountOnlyBootstrap); var oldConstants = "RECOVERY_ORIGINAL = b\"/usr/libexec/recoveryosd\"\nRECOVERY_REPLACEMENT = b\"/private/etc/rc.cdrom.sh\""; var daemon = OriginalDaemon + "\n"; var constants = "RECOVERY_ORIGINAL = b'''" + daemon + "'''\nRECOVERY_REPLACEMENT = b'''" + DiagnosticDaemon + "'''.ljust(len(RECOVERY_ORIGINAL), b\" \")"; patch = ReplaceOnce(patch, oldConstants, constants); 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"); var compatibility = await PrepareCompatibility(source, output, cryptexArchive, cancellation); 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, ". init.sh # Initialize system\n", ". init.sh # Initialize system\n# Fail before Apple downloads if the existing daemon cannot retain this profile.\nenabled \"$KVM\" && [[ \"$CPU_MODEL\" == host && \"$VERSION\" == 13 ]] && grep -Eq '^vendor_id[[:space:]]*:[[:space:]]*GenuineIntel$' /proc/cpuinfo || { error 'Compatibility probe requires existing Intel KVM and the exact host/13 profile.'; exit 1; }\n"); entry = ReplaceOnce(entry, "trap - ERR\n", "[[ \"$KVM_OPTS\" == *'accel=kvm'* || \"$KVM_OPTS\" == *'-accel kvm'* ]] && [[ \"$KVM_OPTS\" != *tcg* && \"$CPU_MODEL\" == host ]] || { error 'Compatibility profile refuses a TCG/CPU fallback.'; exit 1; }\ninfo '[compatibility-profile] accelerator=kvm cpu=host recovery=13; actual guest gates still pending'\n\ntrap - ERR\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"); // Read immutable staging source before PrepareFullSource can write any seam. var originalImage = ReadPinned(source, "src/image.sh", "c08bf9436fb8b72ea82fdf0e677641ab2fc42a0a59e2cf0309c00df519884c5c"); 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\"; then\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"); 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), ("early-bootstrap.sh", MountOnlyBootstrap), ("boot.sh.patched", compatibility.Boot), ("opencore-config.plist", compatibility.Config) }) 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 "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 "early-bootstrap.sh" or "boot.sh.patched" or "opencore-config.plist" or "compatibility-boot-assets.json").ToDictionary(path => Path.GetFileName(path)!, path => Hash(File.ReadAllBytes(path)))); 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); if (full && !writeSource) await ValidateFullBootstrap(wrapper, output, token, cancellation); if (!writeSource) return; File.WriteAllText(patchPath, patch, 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"), compatibility.Boot, new UTF8Encoding(false)); File.WriteAllText(Path.Combine(source, "assets/config.plist"), compatibility.Config, new UTF8Encoding(false)); var target = Path.Combine(source, "assets", "native-compatibility"); if (Directory.Exists(target)) throw new InvalidOperationException("Refusing an existing compatibility asset overlay."); foreach (var file in Directory.GetFiles(compatibility.Assets, "*", SearchOption.AllDirectories)) { var destination = Path.Combine(target, Path.GetRelativePath(compatibility.Assets, file)); Directory.CreateDirectory(Path.GetDirectoryName(destination)!); File.Copy(file, destination, false); } } static async Task<(string Boot, string Config, string Assets)> PrepareCompatibility(string source, string output, string? archivePath, CancellationToken cancellation) { 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."); byte[] bytes; if (archivePath is not null) bytes = await File.ReadAllBytesAsync(archivePath, cancellation); else { using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30), MaxResponseContentBufferSize = 2 * 1024 * 1024 }; bytes = await client.GetByteArrayAsync(CryptexUrl, cancellation); } if (bytes.Length != 69703 || Hash(bytes) != CryptexHash) throw new InvalidOperationException("Official CryptexFixup release size/hash mismatch."); File.WriteAllBytes(Path.Combine(output, "CryptexFixup-1.0.5-RELEASE.zip"), bytes); var assets = Path.Combine(output, "compatibility-assets"); if (Directory.Exists(assets)) throw new InvalidOperationException("Compatibility validation requires a fresh output directory."); Directory.CreateDirectory(assets); using var archive = new ZipArchive(new MemoryStream(bytes), ZipArchiveMode.Read); var required = new[] { "CryptexFixup.kext/Contents/Info.plist", "CryptexFixup.kext/Contents/MacOS/CryptexFixup" }; var entries = archive.Entries.Where(entry => entry.FullName.StartsWith("CryptexFixup.kext/", StringComparison.Ordinal) && !entry.FullName.EndsWith('/')).ToArray(); if (entries.Length != 2 || required.Any(name => entries.Count(entry => entry.FullName == name) != 1)) throw new InvalidOperationException("Cryptex bundle has an unexpected file layout."); foreach (var entry in entries) { if (entry.Length <= 0 || entry.Length > 1024 * 1024) throw new InvalidOperationException("Cryptex bundle file exceeded the staging bound."); var destination = Path.Combine(assets, entry.FullName); Directory.CreateDirectory(Path.GetDirectoryName(destination)!); entry.ExtractToFile(destination, false); } var info = XDocument.Load(Path.Combine(assets, required[0])).Root!.Element("dict")!; if (PlistValue(info, "CFBundleIdentifier").Value != "com.khronokernel.CryptexFixup" || PlistValue(info, "CFBundleVersion").Value != "1.0.5" || PlistValue(info, "CFBundleExecutable").Value != "CryptexFixup" || PlistValue(PlistValue(info, "OSBundleLibraries"), "as.vit9696.Lilu").Value != "1.4.7") throw new InvalidOperationException("Cryptex bundle identity/version/Lilu dependency mismatch."); var fileHashes = required.ToDictionary(name => name, name => Hash(File.ReadAllBytes(Path.Combine(assets, name)))); File.WriteAllText(Path.Combine(assets, "SHA256SUMS"), string.Concat(fileHashes.Select(pair => pair.Value + " " + pair.Key + "\n")), new UTF8Encoding(false)); Save(Path.Combine(output, "compatibility-boot-assets.json"), new { cryptexUrl = CryptexUrl, cryptexSha256 = CryptexHash, cryptexBytes = bytes.Length, cryptexFiles = fileHashes, templateUrl = "https://github.com/LongQT-sea/OpenCore-ISO/releases/download/v0.7/LongQT-OpenCore-v0.7.iso", templateSha256 = OpenCoreTemplateHash, templateBytes = 15884288, liluVersion = "1.7.1", liluBinarySha256 = "0c016d93cfe40c7fa3965813175c1b991a76f3d295efd5be66ae712b4a3ffb52", liluBinaryBytes = 526984, liluInfoSha256 = "fc885f3319f326e3af60e7965a5216b671772d39d40993ec695758bb43d6ea3a", causalSingleVariableTest = false }); 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."); var cryptex = XElement.Parse("Archx86_64BundlePathCryptexFixup.kextCommentOfficial CryptexFixup 1.0.5; owned compatibility guest onlyEnabledExecutablePathContents/MacOS/CryptexFixupMaxKernelMinKernel22.0.0PlistPathContents/Info.plist"); add.Elements("dict").First().AddAfterSelf(cryptex); var bootArguments = PlistValue(PlistValue(PlistValue(PlistValue(document.Root.Element("dict")!, "NVRAM"), "Add"), "7C436110-AB2A-4BBB-A880-FE41995C9F82"), "boot-args").Value.Split(' ', StringSplitOptions.RemoveEmptyEntries); if (bootArguments.Intersect(new[] { "-cryptoff", "-liluoff", "-crypt_allow_hash_validation", "-crypt_force_avx", "-cryptbeta", "-lilubetaall" }).Any()) throw new InvalidOperationException("Unexpected Cryptex/Lilu disabling or forcing boot argument."); boot = ReplaceOnce(boot, " cp -a \"$template/OC/Resources\" \"$EFI_DIR/OC/\"\n", " cp -a \"$template/OC/Resources\" \"$EFI_DIR/OC/\"\n" + CompatibilityStaging + "\n"); boot = ReplaceOnce(boot, " PLIST=\"/assets/config.plist\"\n", " [ ! -e /custom.plist ] || { error 'Compatibility profile refuses an unverified custom OpenCore config!'; exit 12; }\n PLIST=\"/assets/config.plist\"\n"); boot = ReplaceOnce(boot, " checkOpenCoreConfig\n addVmHideKext\n", " checkOpenCoreConfig\n" + CompatibilityConfigCheck + "\n addVmHideKext\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 \"COMPATIBILITY=kvm-host-ventura-cryptex\"\n sha256sum /assets/native-compatibility/SHA256SUMS\n"); return (boot, document.ToString(), assets); } 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; } const string CompatibilityStaging = """ # Only the freshly extracted, owned guest EFI is changed; never the host. local lilu="$EFI_DIR/OC/Kexts/Lilu.kext/Contents" printf '%s %s\n' \ fc885f3319f326e3af60e7965a5216b671772d39d40993ec695758bb43d6ea3a "$lilu/Info.plist" \ 0c016d93cfe40c7fa3965813175c1b991a76f3d295efd5be66ae712b4a3ffb52 "$lilu/MacOS/Lilu" | sha256sum -c - || { error "Pinned active Lilu files mismatch!"; exit 12; } [ "$(xmlstarlet sel -T -t -v '/plist/dict/key[.="CFBundleVersion"]/following-sibling::string[1]' "$lilu/Info.plist")" = 1.7.1 ] || { error "Active Lilu version mismatch!"; exit 12; } [ ! -e "$EFI_DIR/OC/Kexts/CryptexFixup.kext" ] || { error "Unexpected pre-existing Cryptex kext!"; exit 12; } (cd /assets/native-compatibility && sha256sum -c SHA256SUMS) || { error "Pinned Cryptex staging files mismatch!"; exit 12; } cp -a /assets/native-compatibility/CryptexFixup.kext "$EFI_DIR/OC/Kexts/" (cd "$EFI_DIR/OC/Kexts" && sha256sum -c /assets/native-compatibility/SHA256SUMS) || { error "Active Cryptex copy mismatch!"; exit 12; } info "[compatibility-boot] Lilu=1.7.1 CryptexFixup=1.0.5 files=verified; guest injection and Recovery readiness remain unproved" """; const string CompatibilityConfigCheck = """ local kernel='/plist/dict/key[.="Kernel"]/following-sibling::dict[1]/key[.="Add"]/following-sibling::array[1]' local actual expected actual=$(xmlstarlet sel -T -t -m "$kernel/dict" -v 'key[.="BundlePath"]/following-sibling::string[1]' -n "$CFG") || exit 12 expected=$(printf '%s\n' Lilu.kext CryptexFixup.kext VMHide.kext VirtualSMC.kext WhateverGreen.kext VoodooPS2Controller.kext VoodooPS2Controller.kext/Contents/PlugIns/VoodooPS2Keyboard.kext AppleMCEReporterDisabler.kext) [ "$actual" = "$expected" ] || { error "Active Kernel.Add order mismatch!"; exit 12; } [ "$(xmlstarlet sel -T -t -v "name($kernel/dict[1]/key[.='Enabled']/following-sibling::*[1])" -v "name($kernel/dict[2]/key[.='Enabled']/following-sibling::*[1])" "$CFG")" = truetrue ] || { error "Active Lilu/Cryptex must both be enabled!"; exit 12; } actual=$(xmlstarlet sel -T -t -m "$kernel/dict[2]" -v 'key[.="Arch"]/following-sibling::string[1]' -n -v 'key[.="ExecutablePath"]/following-sibling::string[1]' -n -v 'key[.="PlistPath"]/following-sibling::string[1]' -n -v 'key[.="MinKernel"]/following-sibling::string[1]' -n -v 'key[.="MaxKernel"]/following-sibling::string[1]' "$CFG") || exit 12 expected=$(printf '%s\n' x86_64 Contents/MacOS/CryptexFixup Contents/Info.plist 22.0.0 '') [ "$actual" = "$expected" ] || { error "Active Cryptex Kernel.Add paths/architecture/Darwin bounds mismatch!"; exit 12; } info "[compatibility-config] Kernel.Add=Lilu,CryptexFixup before remaining baseline kexts; MinKernel=22.0.0 MaxKernel=empty" """; 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 \"prebuilt account package installed successfully\"\n", "log \"prebuilt account package installed successfully\"\n" + """ count=0 while [ ! -d /Volumes/installstate ] && (( count < 120 )); do /sbin/mount_9p installstate >/dev/null 2>&1 || : count=$((count + 1)); sleep 1 done [ -d /Volumes/installstate ] || fail "native CI state share did not mount" """ + "\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 { ["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); 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)); } 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/13/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\\/13\\/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/13/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 < 13 || 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 = "" + string.Concat(Enumerable.Range(0, 577).Select(index => { var identity = index < 5 ? NativeFacts[index] : "MeetingAssistant.Tests.Validation.Test" + index; var split = identity.LastIndexOf('.'); return $""; })) + "" + string.Concat(Enumerable.Range(0, 577).Select(index => $"")) + ""; var good = JsonSerializer.Serialize(new { token, success = true, sourceCommit = commit, archiveSha256 = hash, sdkVersion = SdkVersion, osVersion = "13.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("13.6.1", "12.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 \n | \"Device Characteristics\" = {\"Serial Number\"=\"" + serial + "\"}\n +-o Media \n \"BSD Name\" = \"disk1\"\n"; var reversed = "+-o QEMU HARDDISK \n +-o Media \n \"BSD Name\" = \"disk1\"\n | \"Device Characteristics\" = {\"Serial Number\"=\"" + serial + "\"}\n"; var splitRoots = "+-o QEMU HARDDISK \n | \"Device Characteristics\" = {\"Serial Number\"=\"" + serial + "\"}\n+-o Other \n +-o Media \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 < 13 || 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 13+/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() != 1 || devices[0].GetProperty("PathOnHost").GetString() != "/dev/kvm" || devices[0].GetProperty("PathInContainer").GetString() != "/dev/kvm" || devices[0].GetProperty("CgroupPermissions").GetString() != "rw" || mounts.GetArrayLength() != 1 || mounts[0].GetProperty("Type").GetString() != "volume" || mounts[0].GetProperty("Destination").GetString() != "/storage" || !mounts[0].GetProperty("RW").GetBoolean() || new[] { "KVM=Y", "CPU_MODEL=host", "VERSION=13" }.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 restricted KVM/host-CPU compatibility 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 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"), ("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")]); if (full) files.Add(("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) { // Copy only this owned guest's diagnostic logs; no host paths or credentials. 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); } } 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/13/setup.dmg || sha256sum /storage/13/setup.dmg; 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); } 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 Cleanup(string output) { var path = Path.Combine(output, "owned-resources.json"); if (!File.Exists(path)) return true; var state = JsonSerializer.Deserialize(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 Command(string executable, string[] arguments, string output, string label, CancellationToken cancellation, bool requireSuccess = true, bool echo = 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 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 (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, "", 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, "", 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); }