fix(installer): route macOS re-sign through the config-aware signing fixup

install.sh duplicated the raw deep ad-hoc re-sign, so install/repair and
self-update could disagree about the app's signing identity — an update
signed with the stable identity would be clobbered back to a cdhash-only
DR by the next installer repair. Call the shared Python fixup (passing
the shell's publisher-signing decision explicitly), and branch into the
historical xattr + deep ad-hoc repair when the venv helper is missing or
fails so a broken venv never leaves the bundle unlaunchable.

Co-authored-by: cipry0200 <cipry0200@users.noreply.github.com>
Co-authored-by: natebransc <natebransc@users.noreply.github.com>
Co-authored-by: caseyanthony <caseyanthony@users.noreply.github.com>
This commit is contained in:
Brooklyn Nicholson 2026-07-28 17:28:33 -05:00
parent 5d171ffbbe
commit 456818875d

View file

@ -2990,16 +2990,41 @@ install_desktop() {
fi
fi
# macOS: make the locally-built (ad-hoc) app relaunchable after an in-place
# self-update. An ad-hoc bundle has no stable Designated Requirement, so a
# later in-place rebuild (new cdhash) plus the inherited quarantine flag
# trips Gatekeeper's tamper check ("Hermes is damaged and can't be opened").
# Strip quarantine + re-apply a clean deep ad-hoc signature (no
# hardened-runtime flag, which an ad-hoc build can't satisfy). Skipped when a
# real signing identity is configured so a signed build isn't clobbered.
# macOS: route through the same config-aware signing fixup as
# `hermes desktop`, so install/repair and self-update agree about the app's
# identity. The fixup preserves the Electron entitlement plists and signs
# with a stable Designated Requirement (configured keychain identity, else
# identifier-pinned ad-hoc), so macOS TCC grants — Full Disk Access,
# Desktop/Downloads/Documents, Accessibility, microphone — survive the
# rebuild instead of resetting on every update. The shell's
# publisher-signing decision governed the build and is passed explicitly so
# importing Python cannot reverse it by loading HERMES_HOME/.env. If the
# helper is unavailable or fails, branch into the historical quarantine
# strip + deep ad-hoc repair so a broken venv never leaves the bundle
# unsigned/unlaunchable.
if [ "$OS" = "macos" ] && [ -z "${CSC_LINK:-}" ] && [ -z "${APPLE_SIGNING_IDENTITY:-}" ] && command -v codesign >/dev/null 2>&1; then
xattr -cr "$app" 2>/dev/null || true
codesign --force --deep --sign - "$app" >/dev/null 2>&1 || true
local config_python="$INSTALL_DIR/venv/bin/python"
local fixup_ok=""
if [ -x "$config_python" ]; then
if HERMES_HOME="$HERMES_HOME" "$config_python" - "$desktop_dir" <<'PYEOF'
import sys
from pathlib import Path
from hermes_cli.main import _desktop_macos_relaunchable_fixup
ok = _desktop_macos_relaunchable_fixup(
Path(sys.argv[1]), publisher_signing_configured=False
)
sys.exit(0 if ok else 1)
PYEOF
then
fixup_ok=1
else
log_warn "Config-aware macOS signing fixup failed; applying the historical ad-hoc fallback."
fi
fi
if [ -z "$fixup_ok" ]; then
xattr -cr "$app" 2>/dev/null || true
codesign --force --deep --sign - "$app" >/dev/null 2>&1 || true
fi
fi
# `npm install` + `npm run pack` rewrite lockfiles; restore them so the