You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The release pipeline (.github/workflows/release.yml) builds macOS DMG + zip artifacts without a real signing identity:
app/electron-builder.yml sets identity: null and relies on the afterPack ad-hoc signing hook (app/tools/adhocSign.cjs) as a stopgap.
Ad-hoc signed downloads fail soft: Gatekeeper shows the "unverified developer" dialog on every fresh install.
macOS auto-update via electron-updater is blocked entirely — Squirrel.Mac rejects builds that are not signed + notarized.
This was a deliberate deferral ("Until GA signing lands…" in electron-builder.yml); this issue tracks landing it.
Goal
The release workflow produces properly signed, notarized, and stapled DMG (and zip) artifacts using the high5 Developer ID Application certificate, so downloads open without Gatekeeper warnings and the future auto-update path is unblocked.
The approach is already fully specified in docs/implementation-plan.md §7 ("Distribution + signing pipeline") and references/apple_dev.md (credential identifiers and gotchas — kept out of this issue intentionally).
Tasks
Add GitHub Actions secrets per the apple_dev.md CI naming convention (use the _HIGH5 suffix so a future _BYTE5 set drops in cleanly): APPLE_CERTIFICATE_P12_BASE64, APPLE_CERTIFICATE_PASSWORD, the ASC API key trio (preferred for CI) or APPLE_ID + APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID, KEYCHAIN_PASSWORD (random per run)
Extend the macOS leg of the build job in release.yml: create a temporary keychain from the base64 cert, import it, build + sign in one electron-builder pass, tear the keychain down afterwards
electron-builder.yml: replace identity: null with the real identity, enable hardenedRuntime, add an entitlements plist — the plist must contain no XML comments (Apple's AMFIUnserializeXML rejects them while plutil accepts them silently; documented gotcha in apple_dev.md)
Notarize via xcrun notarytool submit … --wait using the ASC API key, then xcrun stapler staple the .app and .dmg
Confirm adhocSign.cjs no-ops once a real identity is used (it should — verify, then keep or remove it)
Verify the uploaded artifacts (see acceptance criteria)
Acceptance criteria
codesign --verify --deep --strict passes on the .app with the Developer ID identity (not ad-hoc)
spctl -a -vv -t install accepts the DMG
xcrun stapler validate passes on the stapled .app/.dmg
A freshly downloaded DMG from the GitHub release opens on a clean macOS machine without any Gatekeeper dialog
Both arches (arm64 + x64) are signed and notarized
No credential material appears in workflow logs (keychain torn down, secrets masked)
Out of scope
byte5-branded signing — post-GA, user-elected identity swap only (implementation-plan.md §7)
electron-updater feed wiring — separate concern; this issue only removes its signing blocker
References
docs/implementation-plan.md §7 — Distribution + signing pipeline
references/apple_dev.md — credentials, identifiers, CI secret naming, gotchas
app/electron-builder.yml — current identity: null stopgap
app/tools/adhocSign.cjs — ad-hoc signing hook to be superseded
.github/workflows/release.yml — build job to extend
Problem
The release pipeline (
.github/workflows/release.yml) builds macOS DMG + zip artifacts without a real signing identity:app/electron-builder.ymlsetsidentity: nulland relies on theafterPackad-hoc signing hook (app/tools/adhocSign.cjs) as a stopgap.electron-updateris blocked entirely — Squirrel.Mac rejects builds that are not signed + notarized.This was a deliberate deferral ("Until GA signing lands…" in
electron-builder.yml); this issue tracks landing it.Goal
The release workflow produces properly signed, notarized, and stapled DMG (and zip) artifacts using the high5
Developer ID Applicationcertificate, so downloads open without Gatekeeper warnings and the future auto-update path is unblocked.The approach is already fully specified in
docs/implementation-plan.md§7 ("Distribution + signing pipeline") andreferences/apple_dev.md(credential identifiers and gotchas — kept out of this issue intentionally).Tasks
apple_dev.mdCI naming convention (use the_HIGH5suffix so a future_BYTE5set drops in cleanly):APPLE_CERTIFICATE_P12_BASE64,APPLE_CERTIFICATE_PASSWORD, the ASC API key trio (preferred for CI) orAPPLE_ID+APPLE_APP_SPECIFIC_PASSWORD,APPLE_TEAM_ID,KEYCHAIN_PASSWORD(random per run)buildjob inrelease.yml: create a temporary keychain from the base64 cert, import it, build + sign in one electron-builder pass, tear the keychain down afterwardselectron-builder.yml: replaceidentity: nullwith the real identity, enablehardenedRuntime, add an entitlements plist — the plist must contain no XML comments (Apple'sAMFIUnserializeXMLrejects them whileplutilaccepts them silently; documented gotcha inapple_dev.md)xcrun notarytool submit … --waitusing the ASC API key, thenxcrun stapler staplethe.appand.dmgadhocSign.cjsno-ops once a real identity is used (it should — verify, then keep or remove it)Acceptance criteria
codesign --verify --deep --strictpasses on the.appwith the Developer ID identity (not ad-hoc)spctl -a -vv -t installaccepts the DMGxcrun stapler validatepasses on the stapled.app/.dmgOut of scope
implementation-plan.md§7)electron-updaterfeed wiring — separate concern; this issue only removes its signing blockerReferences
docs/implementation-plan.md§7 — Distribution + signing pipelinereferences/apple_dev.md— credentials, identifiers, CI secret naming, gotchasapp/electron-builder.yml— currentidentity: nullstopgapapp/tools/adhocSign.cjs— ad-hoc signing hook to be superseded.github/workflows/release.yml— build job to extend