Sign builds and releases with a stable code identity
swiftc linker-signs only the inner binary, leaving the bundle unsigned and its codesign identifier as "launcher" rather than the bundle id. More importantly it leaves the app ad-hoc signed, and macOS pins an ad-hoc app's Accessibility grant to its exact cdhash instead of to a designated requirement. Every build mints a new cdhash, so each rebuild-and-replace silently revoked the permission while the app stayed listed and ticked under Privacy & Security — and every release did the same to everyone who updated. That was the root cause of the window tags never appearing. - build.sh signs the bundle with its real identifier, honours SHANNONCOAT_SIGN_IDENTITY, and fails outright rather than falling back to ad-hoc when an identity was asked for explicitly. - The identity is read from a gitignored .env, so it doesn't have to be retyped every build. Parsed rather than sourced, so a stray command in the file can't execute as a side effect of building, and so an existing environment variable still wins. .env.example carries the full one-time setup. - release.yml imports the certificate into a throwaway keychain, builds, verifies, and deletes the keychain on if: always(). It stays inert until the three secrets exist, and fails the release rather than shipping ad-hoc. - Guards the empty-password case explicitly: macOS cannot import an OpenSSL-produced PKCS#12 with an empty password, and reports it as "MAC verification failed (wrong password?)", which sends you hunting for a wrong password rather than a missing one. Nothing local catches this, since the login keychain imports the PEM pair and needs no password. - Ignores *.p12 and *.pem as a backstop; the certificate belongs outside the working tree entirely. Verified end-to-end: two from-scratch builds produce byte-identical designated requirements where ad-hoc differs every time, and six rebuild-reinstall cycles under a real certificate kept the Accessibility grant with no System Settings interaction. This buys permission persistence, not Gatekeeper approval — a self-signed certificate isn't notarized, so downloads still need System Settings -> Privacy & Security -> Open Anyway.
This commit is contained in:
+12
@@ -7,6 +7,18 @@ icon/AppIcon.iconset/
|
||||
# Session handoff notes — local only, never committed
|
||||
CHECKPOINT.md
|
||||
|
||||
# Local build configuration, read by build.sh — holds the code-signing
|
||||
# identity and, optionally, the certificate password. See .env.example for
|
||||
# the shape of it. Never committed.
|
||||
.env
|
||||
|
||||
# Belt and braces: private key material must never land in the repo, even
|
||||
# gitignored. Keep the certificate itself outside the working tree (the
|
||||
# setup notes in .env.example use ~/.shannoncoat-signing/) — this pattern
|
||||
# only exists to catch a stray copy before it becomes a commit.
|
||||
*.p12
|
||||
*.pem
|
||||
|
||||
# Local reference material (e.g. nested checkouts of other projects) — not
|
||||
# part of this project, never meant to be committed.
|
||||
.scratch/
|
||||
|
||||
Reference in New Issue
Block a user