docs/update-mac-certificates.md
Related macOS docs:
This rotation updates the certificate bundle and provisioning profiles used by the macOS GitHub Actions runners. Perform it on a Mac with access to the Apple Developer team.
Keep the currently working identities valid until the replacement bundle has passed local and CI signing checks. Revoking first creates an avoidable release outage and can destroy the only usable private-key pairing.
Record which Apple Distribution, Mac Installer Distribution, and Developer ID identities the current workflows use:
security find-identity -v -p codesigning
Export the working identities and private keys from Keychain Access → My Certificates to an encrypted PKCS#12 backup. Store it in the team's secure credential storage.
Record the active certificate expiration dates and the profile names used by
mas_provision_profile and dl_provision_profile.
If Apple's certificate quota prevents creating a replacement alongside the working certificate, confirm the backup can be imported and schedule a maintenance window before revoking anything.
Do not remove or revoke the old identities yet.
Create profiles only after the new certificates exist:
Create a Mac App Store profile for com.super-productivity.app using the new
Apple Distribution certificate. Save it as
tools/mac-profiles/mas.provisionprofile.
If the direct-download workflow still uses a Developer ID profile, create it
with the new Developer ID Application certificate and save it as
tools/mac-profiles/dl.provisionprofile.
Inspect each profile and confirm its embedded certificate is one of the new identities:
security cms -D -i tools/mac-profiles/mas.provisionprofile
security cms -D -i tools/mac-profiles/dl.provisionprofile
The profile certificate and the identity selected for signing must match. The dynamic verification procedure is in Mac App Store signing.
In Keychain Access, export the replacement identities and their private keys
as one password-protected all-certs.p12. Use a newly generated password.
Verify that the bundle imports into a temporary keychain before uploading it.
Base64-encode the bundle and profiles:
base64 -i all-certs.p12 -o all-certs.b64
base64 -i tools/mac-profiles/mas.provisionprofile -o mas-profile.b64
base64 -i tools/mac-profiles/dl.provisionprofile -o dmg-profile.b64
Update the GitHub Actions secrets referenced by the workflows:
mac_certs and mac_certs_passwordmas_provision_profiledl_provision_profileThe workflow files are authoritative for secret names and whether a profile is still required. Never commit PKCS#12 files, encoded secret files, or passwords.
Build and verify the Mac App Store package:
cp tools/mac-profiles/mas.provisionprofile embedded.provisionprofile
npm run build
npm run dist:mac:mas:buildOnly
codesign -dv --verbose=4 \
".tmp/app-builds/mas-universal/Super Productivity.app"
pkgutil --check-signature \
.tmp/app-builds/mas-universal/super*.pkg
For a local direct-download notarization test, enter credentials through silent prompts so the app-specific password is not written to shell history. Run the following in Bash; the subshell limits the exported values to the build:
(
set -e
read -r -p "Apple ID: " APPLE_ID
read -r -s -p "App-specific password: " APPLE_APP_SPECIFIC_PASSWORD
printf "\n"
read -r -p "Apple team ID: " APPLE_TEAM_ID
export APPLE_ID APPLE_APP_SPECIFIC_PASSWORD APPLE_TEAM_ID
npm run build
npm run dist:mac:dl
)
Verify the DMG signature and notarization:
codesign --verify --deep --strict --verbose=2 "<path-to-built-app>"
spctl --assess --type open --context context:primary-signature -vv \
"<path-to-dmg>"
xcrun stapler validate "<path-to-dmg>"
Run the macOS signing workflow that exercises the updated secrets and confirm its certificate/profile diagnostics match.
Only after both replacement build paths pass: