Merge nucleic/vivid-glass-urchin-xoym into main

This commit is contained in:
2026-08-07 15:41:01 -07:00
parent 6b0c01b74b
commit 902bea5091
11 changed files with 450 additions and 91 deletions
+52 -5
View File
@@ -3,7 +3,8 @@
# Virtualization.framework refuses to start a VM unless the calling process
# carries the `com.apple.security.virtualization` entitlement, and entitlements
# only survive on a signed bundle. So the shipping artifact is not a bare
# executable but a minimal `.app` bundle that we ad-hoc sign. See docs/DESIGN.md
# executable but a minimal `.app` bundle that we sign -- with a Developer ID
# certificate when one is in the keychain, ad-hoc otherwise. See docs/DESIGN.md
# ("Verified Facts", item 10).
SHELL := /bin/bash
@@ -18,8 +19,9 @@ INFO_PLIST := Resources/Info.plist
# The entitlements plist grants exactly one entitlement,
# `com.apple.security.virtualization`. Virtualization.framework refuses to
# create a VM without it, and it is granted by ad-hoc signing
# (`codesign --sign -`) -- no Apple developer account required.
# create a VM without it. It is not a restricted entitlement: ad-hoc signing
# (`codesign --sign -`) grants it, and a Developer ID certificate grants it
# without a provisioning profile.
#
# Deliberately absent: com.apple.vm.networking, which would be needed for a
# bridged network attachment. That one IS restricted and requires an approved
@@ -43,6 +45,31 @@ APP_RESOURCES := Resources/provision.sh \
INSTALL_DIR := $(HOME)/Applications
LINK_PATH := /usr/local/bin/$(BIN_NAME)
# Code signing identity.
#
# A real Developer ID certificate is what makes the bundle's code identity
# *stable across rebuilds*. Its designated requirement is anchored to the team
# ("... and certificate leaf[subject.OU] = L7UDTQ6F5W"), so macOS recognises
# every subsequent build as the same program. An ad-hoc signature has no such
# anchor, so the system falls back to the main executable's Mach-O UUID -- which
# the linker regenerates on essentially every link. Each `make install` then
# presents a program macOS has never seen, and per TN3179 that silently
# withdraws the app's Local Network grant. See docs/troubleshooting.md.
#
# TEAM_ID picks the certificate out of the keychain. When no matching
# "Developer ID Application" identity is present the build still succeeds --
# ad-hoc, with a warning -- because CI runs `make all` inside a throwaway guest
# that has neither a keychain nor a certificate, and that path must keep
# working. Override with `make sign TEAM_ID=...`, or `TEAM_ID=` to force ad-hoc.
TEAM_ID ?= L7UDTQ6F5W
# Hardened runtime plus a trusted timestamp: the pair notarization requires.
# Neither costs anything at runtime here, and having them means the bundle can
# be notarized later without re-signing. `--timestamp` contacts Apple's
# timestamp authority, so signing needs network access. Both are rejected by an
# ad-hoc signature, hence they are only passed on the Developer ID path.
SIGN_OPTS ?= --options runtime --timestamp
# Release by default; `make dev` overrides to debug.
CONFIG ?= release
BIN_PATH = $(BUILD_DIR)/$(CONFIG)/$(BIN_NAME)
@@ -72,11 +99,31 @@ bundle:
cp $(APP_RESOURCES) "$(RES_DIR)/"
chmod +x "$(RES_DIR)/provision.sh"
## sign: ad-hoc sign the bundle with the virtualization entitlement
## sign: sign the bundle (Developer ID when available, else ad-hoc) with the virtualization entitlement
sign:
codesign --sign - --entitlements "$(ENTITLEMENTS)" --force "$(APP_DIR)"
@identity=$$(security find-identity -v -p codesigning 2>/dev/null \
| grep "Developer ID Application" | grep -F "($(TEAM_ID))" \
| head -1 | awk '{print $$2}'); \
if [ -n "$$identity" ]; then \
echo "signing with Developer ID $$identity (team $(TEAM_ID))"; \
codesign --sign "$$identity" $(SIGN_OPTS) \
--entitlements "$(ENTITLEMENTS)" --force "$(APP_DIR)"; \
else \
echo "warning: no 'Developer ID Application' identity for team '$(TEAM_ID)' in the keychain."; \
echo " Falling back to an ad-hoc signature. The bundle runs and the entitlement"; \
echo " works, but its code identity changes on every rebuild, so a macOS Local"; \
echo " Network grant will not survive the next 'make install'."; \
echo " See docs/troubleshooting.md."; \
codesign --sign - --entitlements "$(ENTITLEMENTS)" --force "$(APP_DIR)"; \
fi
@echo "--- entitlements ---"
@codesign -d --entitlements - "$(APP_DIR)" 2>/dev/null || true
@echo "--- identity ---"
@# -dvv, not -dv: the Authority chain is only printed at the second -v.
@# The CodeDirectory line is where `flags=0x10000(runtime)` shows up, which
@# is the only proof the hardened runtime actually landed.
@codesign -dvv "$(APP_DIR)" 2>&1 \
| grep -E "^(Identifier|TeamIdentifier|Authority|Timestamp|CodeDirectory)" || true
## dev: debug build + bundle + sign (fast iteration loop)
dev: