feat(macos): qualify the Tahoe Lume seed and its Mac Studio host - #29
Merged
Merged
Conversation
Phase 8 inputs for the macOS backend, reviewed but never executed: design prerequisite 5 (a dedicated Apple Silicon host in the lab, reachable over SSH) is not satisfied, so no VM, TCC, or clone experiment has run and none may run on a personal workstation. What is verified here: every pin resolves out of pins.lock.yaml and the recipe, the scripts parse, the pin reader fails closed on a renamed key, and the Driver archive digest, bundle id (com.trycua.driver), and signing team (YCK386LBJ7) were measured from the pinned release. The Sequoia IPSW digest is republished by AppleDB, not by Apple, so its pin gate stays open until it is measured on the Mac host. Two findings the host will have to settle: 15.6.1 (24G90) is the last Sequoia release Apple published as a full restore image, so a Sequoia seed sits about a year behind that train's security level, and upstream now calls `tahoe` the verified unattended preset while still warning that `sequoia` can stop on Setup Assistant. Changing trains is the design owner's call. No catalog row is added: the server still answers `platform "mac" is not available yet`, and a catalog entry would advertise an image no instance.create can launch.
Built and gated the seed end to end on studio-1 (Mac Studio M2 Max, macOS 26.6.2) under a dedicated `agentcompute` account, per the owner's amendment to design prerequisite 5. Every value in pins.lock.yaml is now measured locally, not just publisher-verified. Tahoe is the qualified train. Sequoia stays recorded: its last full restore image is 15.6.1 (2025-08-20), a year behind that train's security level, and it clears no gate Tahoe does not. What the spike changed in the recipe, all measured rather than assumed: - The Driver LaunchAgent execs the bundle binary under launchd (com.trycua.cua_driver_daemon). Upstream's `open -g -a CuaDriver --args serve` makes `open` the responsible process and the Driver then refuses to read its own TCC state. - provision.sh raises AccountInfo:FirstLogins in loginwindow's preferences. Lume's offline setup does not complete Setup Assistant, and the documented com.apple.SetupAssistant keys do not suppress it on 26.6.2. - lib.sh composes one shell line per guest command: `lume ssh` joins argv with spaces and the guest re-parses it, so a quoted script arrives mangled. - The display is 1920x1200; at 1440x900 macOS clips Setup Assistant's buttons off-screen, which makes the console pass impossible. - In-guest Screen Sharing is dropped. `launchctl enable system/com.apple.screensharing` fails on macOS 26 and Lume already serves a per-VM VNC console. - verify.sh gained a desktop-session check, `--clone`, and a BSD-correct mktemp template. Clone evidence over four cycles: clone 2-3 s, boot to NAT address 10-11 s, Driver answering with both TCC grants about 30 s, no clone ever asking for consent again. Two findings for the backend are in images/macos/README.md: a clone re-runs Setup Assistant, and Lume's API accepts a third macOS guest with 202 while silently leaving it stopped.
jmgilman
marked this pull request as ready for review
September 15, 2026 08:08
This was referenced Sep 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The macOS backend's image side, built and gated on real hardware.
images/macos/:pins.lock.yaml— Lume 0.5.3, Cua Driver 0.28.1 (darwin-arm64), and both theTahoe and Sequoia IPSWs. Every digest was measured on the host and matched.
provision.sh,verify.sh,lib.sh— shared by every train; per-traindirectories hold only
image.yamlandunattended.yaml.tahoe/desktop/— the qualified train.sequoia/desktop/stays recorded.README.md— operator runbook, measurements, findings.images-validate.ymlparses the scripts and asserts every pin they read.Host:
studio-1(Mac Studio M2 Max, macOS 26.6.2), the owner's amendment todesign prerequisite 5 — an always-on workstation rather than a dedicated Mac
mini, with the backend confined to a dedicated
agentcomputeaccount.Migration to a mini is moving that account's
~/.lumeand re-issuing one key.Evidence
Four clone cycles: clone 2–3 s, boot to NAT address 10–11 s, Driver
answering with both TCC grants ~30 s,
verify.sh6–7 s, ~26.5 GBallocated per clone. No clone ever asked for consent again — that is the
Lume decision criterion, and it is met.
lume create287 s, IPSW fetch 212 s.The seed passes all ten gate checks, including a desktop capture pulled over
scp from the host.
What the spike changed, all measured
(
com.trycua.cua_driver_daemon). Upstream'sopen -g -a CuaDriver --args servemakesopenthe responsible process and the Driver then refuses toread its own TCC state.
AccountInfo:FirstLoginsin loginwindow's preferences is what suppressesmacOS's first-login Setup Assistant. Lume's offline setup does not complete
it, and the documented
com.apple.SetupAssistantkeys do nothing on 26.6.2.lume sshis not argv-safe: it joins argv with spaces and the guestre-parses it, so
lume ssh vm /bin/bash -c '<script>'arrives mangled.lib.shcomposes one shell line and carries the payload as base64.Assistant's buttons off-screen.
launchctl enable system/com.apple.screensharingfails on macOS 26, and Lume already serves aper-VM VNC console.
Findings for the backend
keeps it suppressed across its own reboots; killing it logs the session out.
The Driver is unaffected, so
verify.sh --cloneskips only thedesktop-session check — but an agent handed a clone sees the wizard. Open
defect, documented, not hidden.
POST /lume/vms/<n>/runreturns202 {"status":"pending"}, the VM staysstopped, and onlylume serve's log saysThe number of virtual machines exceeds the limit. The backend must count running guests itself.lume run --detachfails without a controlling terminal (nohup: can't detach from console); start VMs through the HTTP API.loopback-only.
cua-driver status | headpanics the CLI on a broken pipe.Host hardening (owner's conditions)
lume serveruns asagentcomputeand binds127.0.0.1:7777only —verified with
lsofand by failed connects from the LAN and tailnetaddresses.
AllowTcpForwarding local,PermitOpen 127.0.0.1:7777, duplicated root-owned in/etc/ssh/sshd_config.d/110-agentcompute.conf. Proven: command executionrefused,
:7777forward serves the API,:22and:5900forwards rejectedadministratively prohibited, remote forwarding rejected outright.Correction to the spec:
restrictalone does not block commandexecution — without the forced command
ssh host whoamisucceeded.until the host is tagged.
Still not in this PR:
internal/lume, and nocatalog.yamlrow — the serveranswers
platform "mac" is not available yet, so a row would advertise animage nothing can launch.