diff --git a/launcher/afterPackMac.js b/launcher/afterPackMac.js new file mode 100644 index 000000000..24998ee14 --- /dev/null +++ b/launcher/afterPackMac.js @@ -0,0 +1,20 @@ +const { execSync } = require("child_process"); +const path = require("path"); + +// electron-builder v26 no longer re-signs bundled frameworks when no certificate is +// provided. The Electron Framework ships pre-signed with the Electron project's Apple +// Team ID, causing macOS 26+ to reject the load because the main executable has no +// Team ID. Re-sign everything with ad-hoc ("-") so all binaries share a consistent +// (empty) Team ID and dyld's validation passes. +exports.default = async function afterPackMac(context) { + if (context.electronPlatformName !== "darwin") return; + + const appPath = path.join(context.appOutDir, `${context.packager.appInfo.productFilename}.app`); + + console.log(`[afterPackMac] Ad-hoc re-signing for macOS 26+ Team ID compatibility:`); + console.log(`[afterPackMac] ${appPath}`); + + execSync(`codesign --force --deep --sign - "${appPath}"`, { stdio: "inherit" }); + + console.log(`[afterPackMac] Done.`); +}; diff --git a/launcher/vue.config.js b/launcher/vue.config.js index ffaaeab85..4c6b236d2 100755 --- a/launcher/vue.config.js +++ b/launcher/vue.config.js @@ -1,4 +1,5 @@ const shouldNotarize = process.env.NOTARIZE === "true"; +const isSigned = process.env.CSC_IDENTITY_AUTO_DISCOVERY !== "false"; module.exports = { parallel: false, pluginOptions: { @@ -12,6 +13,7 @@ module.exports = { appId: "com.stereum.launcher", productName: "Stereum-Launcher", ...(shouldNotarize ? { afterSign: "@sapien99/vue-cli-plugin-electron-builder-notarize" } : {}), + ...(!isSigned ? { afterPack: "./afterPackMac.js" } : {}), buildDependenciesFromSource: false, nodeGypRebuild: false, npmRebuild: false, @@ -27,8 +29,16 @@ module.exports = { artifactName: "Stereum-Launcher-${version}.${ext}", }, mac: { - hardenedRuntime: true, - entitlements: "./node_modules/@sapien99/vue-cli-plugin-electron-builder-notarize/entitlements.mac.inherit.plist", + // hardenedRuntime requires consistent Team IDs across all binaries; only enable + // when actually signing, otherwise the Electron Framework's pre-signed Team ID + // differs from the unsigned main binary and dyld refuses to load it (macOS 14.4+) + hardenedRuntime: isSigned, + ...(isSigned + ? { + entitlements: "./node_modules/@sapien99/vue-cli-plugin-electron-builder-notarize/entitlements.mac.inherit.plist", + entitlementsInherit: "./node_modules/@sapien99/vue-cli-plugin-electron-builder-notarize/entitlements.mac.inherit.plist", + } + : {}), gatekeeperAssess: false, artifactName: "Stereum-Launcher-${version}.${ext}", x64ArchFiles: "**/*.node",