Integrate verified Recovery image repair into full native CI candidate

This commit is contained in:
dh
2026-10-03 22:04:31 +02:00
3 changed files with 426 additions and 14 deletions
+10 -4
View File
@@ -26,7 +26,7 @@ dotnet run --file tools/ci/MacOsNativeDiagnostic.cs -- --validate
dotnet run --file tools/ci/MacOsNativeDiagnostic.cs -- --validate --source /path/to/clean/pinned/dockur-clone --cryptex-archive /path/to/CryptexFixup-1.0.5-RELEASE.zip --output /path/to/fresh/validation
~~~
`--validate` checks result/container contracts without Docker. With `--source` it verifies the actual Cryptex ZIP/bundle, source seams, generated OpenCore configuration and staging/checksum contracts, then checks Bash syntax, leaving the supplied source untouched. It does not download/extract the LongQT ISO or execute the active-Lilu runtime checks. The ISO checksum is enforced during the later Docker build; active Lilu and EFI-copy checks execute only during container boot. The optional local Cryptex ZIP must match the release size/hash; omitting it downloads only the public 69,703-byte release. Use a fresh output directory. Dependencies are .NET 10, Git and Bash; manual execution also requires the existing Linux/x64 Docker daemon and its existing KVM device.
`--validate` checks result/container contracts without Docker. With `--source` it verifies the actual Cryptex ZIP/bundle, source seams, generated OpenCore configuration and staging/checksum contracts, checks Bash syntax, then exercises four raw/zlib Recovery fixtures and twelve rejection cases with independent C# CRC32 readback. It also checks preservation of a successful resource snapshot after a later failed capture, leaving the supplied source untouched. It does not download/extract the LongQT ISO, verify a complete Apple Recovery image or execute the active-Lilu runtime checks. The ISO checksum is enforced during the later Docker build; active Lilu and EFI-copy checks execute only during container boot. The optional local Cryptex ZIP must match the release size/hash; omitting it downloads only the public 69,703-byte release. Use a fresh output directory. Dependencies are .NET 10, Git, Bash and Python 3 with its standard library; manual execution also requires the existing Linux/x64 Docker daemon and its existing KVM device.
The manual-only workflow keeps these owned run/cleanup entry points; validation invokes neither:
@@ -37,7 +37,13 @@ dotnet run --file tools/ci/MacOsNativeDiagnostic.cs -- --cleanup --output artifa
## Exact bootasset contract
Dockur stays pinned to `16a5b470cdd601bae8b05b02d748d7edfb36c12e`. Original Recovery patcher/staging, Dockerfile, OpenCore script and active config hashes are verified before edits. Both existing QEMU image digests remain pinned; other existing upstream downloads are observed through image identity.
Dockur stays pinned to `16a5b470cdd601bae8b05b02d748d7edfb36c12e`. Original Recovery patcher/staging, Dockerfile, OpenCore script and active config hashes are verified before edits. Both existing QEMU image digests remain pinned; other existing upstream downloads are observed through image identity. `source-hashes.json` includes the generated Recovery patcher, both original/replacement daemon variants and `udif_checksums.py`, staged from `tools/ci/macos-native-udif-checksums.py`. This small Python module belongs to the existing Linux UDIF runtime; C# supplies orchestration, validation fixtures and an independent CRC32 implementation.
Run 4173 at `45d7bde71f9f5a1f7121585fe3ee9fc81f7c585f` failed before QEMU started: the full macOS 14 plist pattern was absent from the macOS 13 download. The original image's hash was not retained. An independently downloaded comparison for the same board `Mac-4B682C642B45593E` is macOS 13.6/22G120, Apple product 042-23155, 710,918,897 bytes, SHA256 `c19bd12f5cb1651b87b74d04f02a636da762ea46b81c7ebc9f205fa2a976d599`. Its Apple chunklist signature and chunks verified before any changes. It is comparison evidence, not the missing run-4173 image identity.
The HFS+ catalog identifies `/System/Library/LaunchDaemons/com.apple.recoveryosd.plist` as file ID 57231, logical size 465 bytes and one 4,096-byte allocated block. Its exact XML SHA256 is `af9d7f6c1948079bd4384d27b6882678d6fb4e338fcf6a8be8f84fceef174ad6`. This variant has `ProcessType=Interactive`; the previous macOS 14 variant has `App`. The patch accepts only these two exact layouts with exactly one daemon label and original `ProgramArguments=[/usr/libexec/recoveryosd]`. It preserves each variant's fields and process type, removes only the XML doctype to fit the wrapper arguments, and pads to the original file size. Unknown, duplicate, malformed or wrong-argument layouts fail before image writes. The early rc.cdrom hook remains mount-only; both the unchanged read-only wrapper and guarded Full wrapper exec the original Apple daemon.
The checksum binding validates the original flattened UDIF boundaries and CRC32 values, stages every recompressed chunk before writing, then updates only the changed mish CRC32 and koly data-fork/master CRC32. [libdmg-hfsplus](https://github.com/planetbeing/libdmg-hfsplus/blob/master/dmg/dmglib.c) provides the checksum semantics; an independent C# reader matched all eight mish checksums on the unchanged comparison. Raw and inflated zlib bytes enter logical CRCs in run order; observed IGNORE runs are omitted. Unobserved ZERO runs, other compression/checksum types, overlaps and invalid boundaries are rejected. Base64 characters are replaced within the same metadata region, preserving its whitespace, length, partition tables and trailer offsets; the entire modified image is read again to verify CRCs. Apple chunklist authentication applies exclusively to the unchanged input, not the deliberately modified guest image. CRC integrity proves no Apple authenticity or native runtime gate.
The [original LongQT v0.7 template](https://github.com/LongQT-sea/OpenCore-ISO/releases/download/v0.7/LongQT-OpenCore-v0.7.iso), 15,884,288 bytes, is now Docker-ADD-checksummed to SHA256 `287328995d4198f1b05166f087d85bf7ef66bedafe150d17ad112ac8de60051d`. Runtime copies actual `EFI_RELEASE/EFI/OC/Kexts`, including Lilu 1.7.1, even with official OpenCore DEBUG executables. Active Lilu: executable 526,984 bytes, SHA256 `0c016d93cfe40c7fa3965813175c1b991a76f3d295efd5be66ae712b4a3ffb52`; Info.plist SHA256 `fc885f3319f326e3af60e7965a5216b671772d39d40993ec695758bb43d6ea3a`. Staging checks both hashes and bundle version. Cryptex declares Lilu 1.4.7; [Lilu history](https://github.com/acidanthera/Lilu/blob/master/Changelog.md) includes Ventura/Sonoma installer/Recovery support before 1.7.1. Existing Lilu is kept.
@@ -57,7 +63,7 @@ Container profile: `KVM=Y`, `CPU_MODEL=host`, `VERSION=13`, 4-GiB guest, two gue
Only device mapping: exactly `/dev/kvm:/dev/kvm:rw`. Inspection rejects other devices/permissions, added capabilities, device requests/rules, binds, tmpfs overrides, published ports, host networking, privileged mode, wrong limits, unexpected persistent mounts or changed CPU/OS profile. No host modules, infrastructure, secrets, SSH or app lifecycle actions are involved. Guest slirp networking remains.
Evidence retains run/profile identity, source/assets, EFI staging, container/resources, macOS 13 Recovery hash, native proof/result/outcome and cleanup. Optional final Unix HMP capture includes `info kvm`, `info status` and a bounded PPM exported from `/tmp`; capture success passes no native gate.
Evidence retains run/profile identity, source/assets, EFI staging, container/resources, macOS 13 Recovery hash, native proof/result/outcome and cleanup. `[recovery-original]` logs the exact download's size/SHA256 before modifying it, including when patch failure later deletes the source. `guest-container-resources.last-success.stdout.log` and its timestamp/hash receipt preserve the last successful resource snapshot independently of a later failed stopped-container `docker exec`. Optional final Unix HMP capture includes `info kvm`, `info status` and a bounded PPM exported from `/tmp`; capture success passes no native gate.
Both cleanup paths keep exact token/label/ID checks. `docker rm --force --volumes` removes only the owned container and anonymous volume, then its exact image; no unrelated objects or pruning. Evidence stays seven days. Full native CI still needs a subsequent actual installed remote guest to build/sign helpers and pass the full suite, including five native tests without skips.
@@ -88,4 +94,4 @@ The Full outer deadline is 172 minutes; the workflow declares 180 minutes within
Artifacts include source/SDK hashes, pinned boot patches, installer/Apple/firstboot logs, CLT SDK identity, installed-root/disk identity with APFS mapping plists, native tool logs, guest phase and Full-result receipts, helper hashes and binary-preserved TRX. Polling prints a bounded heartbeat each elapsed minute with phase/time/budget, liveness and readiness. Cleanup retains exact saved resource ID/ownership checks through `finally` and workflow `always()`; only the owned container/image/anonymous volume are removed. Installed files disappear with that volume; retained CI evidence remains outside it. Shared Docker build cache is not pruned.
Local `--validate --full` generates source/fixture evidence and executes the generated installer guard and complete Full wrapper with harmless filesystem/mount, child-process and Apple-exec boundary fixtures. It covers owned/foreign/invalid/write-failed installer and probe markers, restart, first-child failure and delayed/missing/foreign-owner shares. It starts no Docker or VM, erases no disk, installs no OS/toolchain, builds no application and runs no native test. Bash syntax, synthetic disk parser and receipt tests do not qualify actual Apple exec, guest storage or native CI. Read-only `--compression-chunk` evidence applies only to its retained Recovery chunk, not the new Full wrapper or a different downloaded macOS image. This remains a locally prepared candidate until actual remote guests satisfy every native gate.
Local `--validate --full` generates source/fixture evidence and executes the generated installer guard and complete Full wrapper with harmless filesystem/mount, child-process and Apple-exec boundary fixtures. It covers owned/foreign/invalid/write-failed installer and probe markers, restart, first-child failure and delayed/missing/foreign-owner shares, plus all four positive/twelve negative Recovery image cases and retained resource-snapshot checks. Its independent C# CRC32 reader validates fixture readback while the existing pinned Python UDIF binding performs the patch. It starts no Docker or VM, erases no disk, installs no OS/toolchain, builds no application and runs no native test. Bash syntax, synthetic disk parser and receipt tests do not qualify actual Apple exec, guest storage or native CI. Read-only `--compression-chunk` evidence applies only to its retained Recovery chunk, not the new Full wrapper or a different downloaded macOS image. This remains a locally prepared candidate until actual remote guests satisfy every native gate.