← back to Nas Setup
scripts/install-optionB-launcher.sh
85 lines
#!/bin/bash
# install-optionB-launcher.sh — TK-10547 Option B finalizer, ONE-PASTE run as root:
# sudo bash /Users/macstudio3/Projects/nas-setup/scripts/install-optionB-launcher.sh
#
# Faithful mechanization of the approved memo's Step 1 + Step 2 (Option B):
# - installs BOTH backup root-daemon plists from the repo (already repointed at the
# stable ad-hoc-signed launcher /usr/local/bin/nas-backup-sh) into /Library/LaunchDaemons
# - bootout + bootstrap both daemons so the new ProgramArguments[0] takes effect
# - kickstart both to test the FDA-granted launcher immediately
# - tail pull.log so you see [Henry] PASS (or the WARN if the FDA click hasn't landed yet)
#
# PRECONDITION (do FIRST, in System Settings — TCC is GUI-only, cannot be scripted):
# Privacy & Security > Full Disk Access > "+" > /usr/local/bin/nas-backup-sh (toggle ON)
# (Cmd-Shift-G in the file picker, paste the path.)
#
# This script does NOT touch /opt/homebrew/bin/bash, does NOT re-sign the launcher
# (already adhoc-signed by cycle 8), and is idempotent — safe to re-run.
#
# NOTE: intentionally NO `pipefail` — every guard below is `cmd | grep -q ...` where the
# TRUTH we want is grep's match, not the upstream exit code. Under root, `codesign -dv`
# exits non-zero even on a valid signature; with pipefail that non-zero poisons the
# pipeline and turns a matched grep into a false FATAL. `set -u` stays for unbound-var safety.
set -u
USER_HOME=/Users/macstudio3
NAS=$USER_HOME/Projects/nas-setup
LAUNCHER=/usr/local/bin/nas-backup-sh
say(){ printf '\n=== %s ===\n' "$1"; }
if [ "$(id -u)" -ne 0 ]; then echo "must run as root: sudo bash $0"; exit 1; fi
# ── 0. sanity: launcher present + signed ──
say "0. launcher preflight"
if [ ! -x "$LAUNCHER" ]; then echo "FATAL: $LAUNCHER missing/not executable — run memo Step 0 (cp+codesign) first."; exit 1; fi
# exit-code-based (robust under root), with an output-parse fallback; a failure here is a
# WARN, not a hard stop — the signature was independently proven present, and the REAL gate
# is whether Henry gets a verified write in step 3.
if codesign --verify --strict "$LAUNCHER" 2>/dev/null; then
echo "OK — $LAUNCHER signature verifies (--verify)"
elif codesign -dvv "$LAUNCHER" 2>&1 | grep -qi 'adhoc'; then
echo "OK — $LAUNCHER is ad-hoc signed (-dvv)"
else
echo "WARN — codesign could not confirm the signature in this context; proceeding anyway"
echo " (memo Step 0 already ad-hoc-signed it; if the Henry write below is TCC-denied,"
echo " re-sign with: sudo codesign -s - -f $LAUNCHER)"
fi
# ── 1. install + reload both root daemons ──
for LABEL in com.steve.nas-dwdump-mirror-root com.steve.nas-realestate-dump-mirror-root; do
SRC=$NAS/launchd/$LABEL.plist
DST=/Library/LaunchDaemons/$LABEL.plist
say "1. install + bootstrap $LABEL"
# confirm the repo plist really points at the launcher (Option B invariant)
# capture-then-compare (pipefail-immune) instead of a piped grep guard
PA0=$(/usr/libexec/PlistBuddy -c 'Print :ProgramArguments:0' "$SRC" 2>/dev/null || true)
if [ "$PA0" != "$LAUNCHER" ]; then
echo "FATAL: $SRC ProgramArguments[0] is '$PA0', not $LAUNCHER — repo plist not repointed. Aborting."; exit 1
fi
install -m 644 -o root -g wheel "$SRC" "$DST" && echo "installed $DST"
launchctl bootout system/$LABEL 2>/dev/null && echo "booted out old $LABEL" || echo "(was not loaded)"
launchctl bootstrap system "$DST" && echo "bootstrapped $LABEL" || echo "WARN: bootstrap returned non-zero"
# verify the LOADED job now invokes the launcher, not brew bash
LOADED=$(launchctl print system/$LABEL 2>/dev/null | grep -m1 -oE '/usr/local/bin/nas-backup-sh|/opt/homebrew/bin/bash')
echo "loaded ProgramArguments[0] = ${LOADED:-<unknown>}"
done
# ── 2. kickstart both (tests the FDA-granted launcher NOW) ──
say "2. kickstart both daemons (immediate FDA test)"
launchctl kickstart -k system/com.steve.nas-dwdump-mirror-root && echo "kicked dwdump"
launchctl kickstart -k system/com.steve.nas-realestate-dump-mirror-root && echo "kicked realestate"
echo "waiting 20s for the pulls to finish..."; sleep 20
# ── 3. verdict ──
say "3. result (pull.log tail)"
tail -20 "$NAS/data/pull.log"
echo
if tail -40 "$NAS/data/pull.log" | grep -q '\[Henry\] PASS'; then
echo ">>> OPTION B SUCCESS — [Henry] PASS present. Durability upgrade live."
echo ">>> Next (durability gate): reboot at your convenience, then re-run daemon-health.sh"
echo ">>> to confirm the FDA grant persisted across reboot (memo Step 0 gate)."
else
echo ">>> NO [Henry] PASS yet. Almost always = the Full Disk Access toggle for"
echo ">>> $LAUNCHER is not ON. Add it in System Settings and re-run this script."
fi