A signature is read by other programs
On macOS a code signature is more than a seal on a bundle. Other programs read it and decide things from it. macOS remembers Dad's microphone and camera grants against it, the Keychain decides by it who may open an item, and 1Password's desktop app reads it before it will talk to a browser at all. So the choice of identity that signs Voyager has consequences far outside the build.
The first brick was signed with the family's own self-signed identity, cwk-codesign, the one family Mac apps use so that their grants survive rebuilds. Then the engine gate's first case, W1, met 1Password. Track 2 told the result and track 8 told the debugging. The short version: 1Password's helper accepts a browser only when its signature carries a team identifier under Apple's chain and enforces the hardened runtime, and cwk-codesign has neither. This lesson is the signing that came out of that measurement.
One file knows
Every signing decision lives in scripts/signing.zsh. It is never run on its own. build-app.sh and doctor.sh both source it, so the build and the report cannot disagree about which identity is meant. Its header (first block) gives the reason in one paragraph.
The default is found, not configured. The script lists the Mac's valid code-signing identities, keeps those named Apple Development: …, and takes the first whose certificate names the paid team as its organizational unit. A Mac without one falls back to cwk-codesign, and then the hardened runtime defaults to off, because the family identity is only for builds that never meet 1Password. Two environment variables override the identity and the runtime, so every departure from the default is spelled out on the command line.
| Identity | Hardened runtime | Designated requirement | 1Password |
|---|---|---|---|
| The paid team's Apple Development | on by default | bundle id, Apple's chain, the team | accepted, measured |
cwk-codesign | off by default | bundle id, the certificate's hash | refused, measured |
What the designated requirement pins
A designated requirement is the rule a signature must satisfy for macOS to treat a new build as the same app. Privacy grants and Keychain access are stored against it. A rebuild that fails the old requirement is a stranger to macOS: the microphone prompt comes back, and 1Password's consent is gone.
For an Apple-issued identity, codesign's own default requirement pins the certificate's common name. That looks stable until the certificate is renewed, and renewal always comes. So Voyager hands codesign a requirement of its own (second block): the bundle identifier, anchor apple generic for Apple's chain, the team in the leaf certificate's organizational unit, and the extension that marks an Apple development certificate. A renewed certificate from the same team satisfies every clause, so the grants and the consent carry over.
Then the build reads the requirement back out of the signed bundle and checks that the clauses which make it stable are there: the bundle identifier, anchor apple generic and the team. It checks the staged bundle, the copy staged for install, and the installed app, each time. Know what that check is, though. It looks for those clauses inside the string and never compares the whole string, so a requirement that lost the development-certificate marker, or gained a common-name pin beside the team, would still pass. What it refuses is a requirement missing one of the three.
The hardened runtime has a price
The hardened runtime is what 1Password demands, and it is also a set of refusals. One of them: an app under it gets no microphone and no camera unless its entitlements claim them. A browser has to claim both, because any page may ask for either. The third block is the whole entitlements file, and its comment draws the boundary. The claim only lets a page's request reach Voyager. Whether that page gets the device is still decided by the trust zone and by macOS.
The build does not assume the runtime flag took effect. After signing, it reads the signature's details back and stops with HARD_FAIL if the runtime was asked for and is missing, or if the signing authority is not the identity it meant to use.
Rules that fell out of it
- Never sign Voyager with the family identity to match the family. The house sign says it in those words. Looking like the sibling apps is no reason when the measurement says the program that matters refuses it.
- Sign where the keychain is open. One Mac in the fleet, reached over ssh, could not sign: its login keychain was locked outside the graphical session, and
codesignfailed witherrSecInternalComponent. That is a fact about that keychain in that session, not a law of ssh, and the house sign records it for that one Mac. The answer was not to fight the keychain. Voyager is built and signed on the workbench and copied to other Macs by the family's deploy script. The copy keeps its signature, so it keeps its grants. - The next step waits for a reason. A Developer ID certificate with notarization comes only if a Mac in the fleet or a renewal breaks this arrangement, and that request belongs to Codex Chief Pippa.