Skip to content
C.W.K.
Lesson 05 of 06 · published

Signed Once, Delivered Everywhere — Without a Single Signal

~15 min · code-signing, deployment, launchd, rollback, stable-identity

Level 0Idle Hands
0 XP0/39 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"The designated requirement is pinned to the certificate, so a copied bundle keeps a Mac's grant across updates." — Tinker architecture

Two Places, Two Jobs

The lab proves behaviour with an unsigned or ad-hoc build. The real app is built and signed in exactly one other place: the registered signing workbench, with its existing signing identity. build-app.sh --signed checks the Mac's fleet label against the registry's workbench role before it will start, and signing material never travels to the lab. The bundle is built once; every enrolled Mac receives that same signed bundle rather than building its own.

A Stable Identity Is What Keeps the Grant

The previous lesson showed an ad-hoc signature pinning the code hash, so every rebuild loses its Accessibility grant. The signed app is the opposite on purpose. It always has the bundle ID com.cwk.tinker, always installs at /Applications/Tinker.app, and is always signed by the same certificate — so its designated requirement names the identifier and the certificate leaf, not the code. A new version satisfies the old requirement, and TCC treats it as the app Dad already granted. The install script enforces this: if the new bundle's requirement differs from the installed one, it refuses with "Signing identity changed; preserving the installed app." An update that would silently cost Dad his grant on every Mac does not get installed.

Installing on One Mac

install-app.sh first checks that this Mac is one the registry enrolls for Tinker. It refuses to replace a running copy — "Restore its changes and quit normally before replacing the app." It verifies the signature, stages the bundle beside the destination, moves the old app aside as a rollback, moves the new one in, verifies again, and touches the bundle so its date says when it was installed. It renders the one tracked login-agent template for this Mac and loads it. The template has RunAtLoad and is limited to the Aqua (logged-in GUI) session, and it deliberately has no KeepAlive: a Tinker that quit to restore what it owns must stay quit until the next login or install. One rollback bundle is kept; older ones are removed only after the new app is verified in place.

Across the Family

On the other enrolled Macs, the family native deploy does the same job from the signing workbench: it fans out only to the Macs the registry enrolls, asks a running Tinker to quit — never signals it — boots out its login agent only after it has left, installs, and skips any Mac where Tinker would not quit, leaving the old bundle there. Each Mac needs its cwk-tinker environment first, created once by setup-runtime.sh, because the app door's worker runs in it.

Four Facts, Kept Separate

Signed, installed, granted, and working are four different facts. The install script ends with "no Accessibility prompt or preset was invoked" — it claims installation and nothing more. Dad grants Accessibility on each Mac himself, and that Mac's first live hide waits for him. Only then is "Tinker works on this Mac" a true sentence, and only about that Mac.

Code

The identity checks before an install touches /Applications (from scripts/install-app.sh, trimmed)·bash
if pgrep -x Tinker >/dev/null; then
  echo 'Tinker is running. Restore its changes and quit normally before replacing the app.' >&2
  exit 1
fi
codesign --verify --deep --strict "$APP"
codesign -dr - "$APP" 2>&1 | grep -F 'certificate leaf = H'      # certificate-anchored
[[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$APP/Contents/Info.plist")" == com.cwk.tinker ]]
if [[ -d "$DEST" ]]; then
  OLD_REQ="$(codesign -dr - "$DEST" 2>&1 | sed -n 's/^designated => //p')"
  NEW_REQ="$(codesign -dr - "$APP" 2>&1 | sed -n 's/^designated => //p')"
  [[ -n "$OLD_REQ" && "$OLD_REQ" == "$NEW_REQ" ]] ||
    { echo 'Signing identity changed; preserving the installed app.' >&2; exit 1; }
fi
The login agent template's decisive keys (deploy/com.cwk.tinker.plist)·text
Label                    com.cwk.tinker
ProgramArguments         /Applications/Tinker.app/Contents/MacOS/Tinker
RunAtLoad                true
LimitLoadToSessionType   Aqua
KeepAlive                (absent on purpose: a Tinker that quit to restore
                          what it owns must stay quit until the next login
                          or install)
The order of operations on each enrolled Mac·bash
# once per Mac: the environment the app door's worker runs in
bash scripts/setup-runtime.sh

# from the signing workbench, for the enrolled Macs only:
#   ask a running Tinker to quit -> wait for it to leave -> boot out its agent
#   -> install the signed bundle -> render and load the agent
#   (a Tinker that will not quit is skipped and keeps its bundle)

# then, on each Mac, by Dad: grant Accessibility, be present for the first live hide

External links

Exercise

A teammate proposes signing Tinker on each enrolled Mac with a local ad-hoc signature, to avoid moving bundles around. Using what this lesson and the last one showed, list every consequence for Dad, and then for the install script's checks.
Hint
Every update would change the code hash, so every Mac would lose its Accessibility grant on every update and Dad would re-grant by hand each time. The install script's 'certificate leaf' check and its old-vs-new requirement comparison would both fail, so it would refuse to install at all. Building once on the signing workbench and copying the same signed bundle is what keeps both the grant and the checks intact.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign in — Please sign in to comment.

No comments yet — be the first.