Skip to content

Refuse a half-configured signing setup, and write the runbook - #7

Merged
las7 merged 1 commit into
mainfrom
fix/notarize-guards
Aug 15, 2026
Merged

Refuse a half-configured signing setup, and write the runbook#7
las7 merged 1 commit into
mainfrom
fix/notarize-guards

Conversation

@las7

@las7 las7 commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #6. Two gaps in the sign and notarize step, which has never executed, plus the runbook that makes it executable.

Half-configured signing was the worst available outcome

The step keyed on MACOS_CERTIFICATE alone. With a certificate but no notary credentials it would sign, then fail at notarytool — and a Developer ID binary that is not notarized is refused by Gatekeeper with the same dialog as an unsigned one. The release would look signed, the secrets would look configured, and the user-visible symptom would be identical. Now it is all six or none, and a partial set fails naming exactly which are missing.

Verified against all three paths by extracting the step's script and running it:

none set  -> ::warning ... ships an ad-hoc signed binary        (exit 0)
half set  -> ::error Missing: MACOS_SIGN_IDENTITY MACOS_NOTARY_KEY_ID ...  (exit 1)
all set   -> proceeds into the macOS-only `security` commands

codesign --verify does not verify what we need

It passes just as happily against an ad-hoc signature or an "Apple Development" certificate, both of which Gatekeeper refuses exactly like no signature at all. The signing authority is now asserted to contain Developer ID Application after signing, rather than assumed from the fact that --sign exited 0.

.github/MACOS-SIGNING.md

The runbook. Three things in it that are not obvious:

  • No Mac is required. The certificate can be produced entirely on Linux with openssl — generate the key and CSR, upload the CSR, convert the .cer, export a .p12. This avoids the Keychain Access route completely.
  • Individual vs organization is a real fork. Organization enrollment needs a legal entity and a D-U-N-S number, and no Reachpad legal entity exists yet — that is company formation, not an afternoon. Individual takes hours and shows a person's name in the certificate. Recommended: start individual; re-signing under an org later costs nothing, because these are bare binaries with no bundle identity or team-ID-keyed update rules.
  • A bare Mach-O cannot be stapled. xcrun stapler needs a bundle, disk image or package, so a notarized reachpad still requires an online notarization check on first run. Closing that means a signed, notarized, stapled .pkg — a second artifact and a second signing identity, worth doing only if someone actually reports the offline case.

It also states plainly what this does not fix: nothing any advertised install path suffers from. brew, npm and curl … | sh all avoid com.apple.quarantine entirely. This buys exactly one thing — a browser download from the releases page — for $99/year.

Two gaps in a step that has never executed.

It keyed on MACOS_CERTIFICATE alone, so a certificate without notary
credentials would sign and then fail at notarytool — and a Developer ID
binary that is not notarized is refused by Gatekeeper with the SAME
dialog as an unsigned one. The release would look signed, the secrets
would look configured, and the symptom would be unchanged. All six or
none now, with the missing ones named.

And codesign --verify passes against an ad-hoc or an Apple Development
signature just as happily as a Developer ID one, while Gatekeeper
refuses both like no signature at all. The authority is asserted after
signing rather than assumed.

.github/MACOS-SIGNING.md is the runbook: the openssl path that produces
all six secrets on Linux with no Mac, the individual-vs-organization
call (no Reachpad legal entity exists, so organization is company
formation, not an afternoon), and the limit worth knowing before
paying — a bare Mach-O cannot be stapled, so notarization is still
checked online on first run.

Greentree-Change-Id: b313a40fdf40d088b620ec9e8ce17130
@las7
las7 merged commit 6aef553 into main Aug 15, 2026
2 checks passed
@las7
las7 deleted the fix/notarize-guards branch August 15, 2026 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant