feat(install): macOS launchd installer + Install/Uninstall routing (VA-89) #138
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/VA-89-macos-launchd-installer"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Part of VA-89. The agent had no macOS install path -
install.rsis systemd-only andmain.rsroutedInstall/Uninstallfor Linux and Windows only. This adds the launchd analog.New
install_macosmodule (mirrors the systemd installer)/Library/LaunchDaemons/run.a8n.vervain-agent.plist, binary at/usr/local/sbin/vervain-agent, databases under/Library/Application Support/vervain-agent/{config,data}.~/Library/LaunchAgents/, binary at~/.local/bin/, databases under~/Library/Application Support/vervain-agent/.Both consume the one-time
bootstrap.json, write the four enrollment PEMs into the data dir (mode 600), generate a freshVERVAIN_DB_KEY, and render a plist whoseEnvironmentVariablesdict carries the DB key +VERVAIN_SERVER_DOMAIN+VERVAIN_*_FILEpointers (plist mode 600).RunAtLoad+KeepAlive{SuccessfulExit:false}matches systemdRestart=on-failure. Uninstall reverses each step;uninstall_full/uninstall_full_selfwipe identity + state for the VA-87 remote-uninstall path (wired into dispatch'sperform_full_uninstall).main.rsgains macOSInstall/Uninstallsubcommands (sharedInstallTypesystem/user) and a macOS routing block;read_bundle,InstallType, and theValueEnumimport extend to macOS.Testing
Plist rendering + layout are pure and unit-tested (required keys, XML escaping, home-relative user paths, LaunchDaemon path). The module is compiled under
testviacfg(any(target_os = "macos", test)), so those 5 tests run on the Linux CI, and the whole module (bar thegeteuidline) compile-checks on Linux. 406 lib tests pass; clippy--all-targets+ fmt clean.The
launchctl load/unloadcalls, the macOS-onlymain.rsrouting block, and the real install/uninstall need a Mac to verify (VA-90 runner or manual). Apple codesign/notarization is a separate follow-up (VA-128); macOS KVM is VA-7.Scope: x86_64-apple-darwin (
AgentId::MacOsx64=16) only; no protocol change.The agent had no macOS install path: install.rs was systemd-only and main.rs routed Install/Uninstall for Linux (systemd) and Windows (SCM) only. Add the launchd analog so a Mac agent can be installed as a managed service. New install_macos module mirrors the systemd installer: a system mode (root LaunchDaemon at /Library/LaunchDaemons/run.a8n.vervain-agent.plist, binary at /usr/local/sbin, databases under /Library/Application Support/vervain-agent) and a per-user mode (LaunchAgent under ~/Library/LaunchAgents, binary at ~/.local/bin, databases under ~/Library/Application Support). Both take the one-time bootstrap.json, write the four enrollment PEMs into the data dir (mode 600), generate a fresh VERVAIN_DB_KEY, and render a plist whose EnvironmentVariables dict carries the DB key + VERVAIN_SERVER_DOMAIN + VERVAIN_*_FILE pointers (plist mode 600). RunAtLoad + KeepAlive{SuccessfulExit:false} matches systemd Restart=on-failure. Uninstall reverses each step; uninstall_full/uninstall_full_self wipe identity + state for the VA-87 remote-uninstall path (wired into dispatch's perform_full_uninstall). main.rs gains macOS Install/Uninstall subcommands (shared InstallType system/user) and a macOS routing block; read_bundle, InstallType, and the ValueEnum import extend to macOS. The plist rendering + layout logic is pure and unit-tested; the module is compiled under `test` (via cfg(any(target_os = "macos", test))) so those tests run on the Linux CI, not only the mac runner. The launchctl load/unload calls and the actual install need a Mac to verify (VA-90 runner / manual). Apple codesign/notarization stays a separate follow-up (VA-128); macOS KVM is VA-7. Part of VA-89. Only x86_64-apple-darwin (AgentId::MacOsx64=16) is targeted; no protocol change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BFsMi3Vmf3pCc7mBdhZqoV