From c383c881e564f954416df6de249f68a52994bcb9 Mon Sep 17 00:00:00 2001 From: mrdulasolutions Date: Wed, 13 May 2026 17:19:14 -0400 Subject: [PATCH] fix(sidecar/prepare-node): ad-hoc sign bundled node so `tauri dev` works MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `npm run tauri:dev` was unusable on macOS 14.4+ (and stricter on 15+): the bundled aos-mail-node binary spawned and was immediately SIGKILL'd by `amfid` (Apple Mobile File Integrity), so the sidecar died on launch with `WARN sidecar terminated: signal: Some(9)`. Tauri's shell plugin then logged `sidecar stdin write failed: Broken pipe` and the app sat broken at the splash. Root cause: prepare-node-binary.mjs explicitly strips the Node Foundation signature (`codesign --remove-signature`) with a comment that "Tauri will re-sign with our Developer ID at bundle time." That's true for `tauri build` (via tauri-action's keychain dance), but in `tauri dev` nothing re-signs — the binary stays unsigned, and modern macOS refuses to execute unsigned arm64 Mach-O binaries. Fix: after the strip, add a `codesign --sign - --force` ad-hoc signing step. Ad-hoc signatures satisfy `amfid` for local execution and don't interfere with tauri-action's later `codesign --force` with the real Developer ID cert in production builds — `--force` replaces whatever signature is there. Verified locally: `aos-mail-node --version` now returns v24.14.0 (exit 0) instead of dying with exit 137. The running `tauri dev` session picked up the new binary on its next file-change rebuild and the sidecar booted cleanly: `sidecar: ready, listening on stdin`. Co-Authored-By: Claude Opus 4.7 --- sidecar/scripts/prepare-node-binary.mjs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sidecar/scripts/prepare-node-binary.mjs b/sidecar/scripts/prepare-node-binary.mjs index 9c45cbc..a59f935 100644 --- a/sidecar/scripts/prepare-node-binary.mjs +++ b/sidecar/scripts/prepare-node-binary.mjs @@ -109,13 +109,21 @@ function main() { copyFileSync(sysNode, dest); } - // Strip whatever signature came from Node Foundation; Tauri will re-sign - // with our Developer ID at bundle time. + // Strip Node Foundation's signature, then ad-hoc sign so the binary can + // actually execute. Background: on macOS 14.4+ (and 15+ more strictly), + // `amfid` SIGKILLs unsigned arm64 Mach-O binaries the moment they exec. + // The original Node Foundation signature would work for execution but + // doesn't match our final .app's signing chain, so production builds + // need it stripped. Replacing it with an ad-hoc signature (`--sign -`) + // is the only way to have the binary be both executable *now* (for + // `tauri dev`) and clean-slate for tauri-action's later `codesign + // --force` re-sign with the Developer ID cert. try { execSync(`codesign --remove-signature "${dest}"`, { stdio: "ignore" }); } catch { // already unsigned — fine } + execSync(`codesign --sign - --force --timestamp=none "${dest}"`, { stdio: "ignore" }); execSync(`chmod +x "${dest}"`); const size = (statSync(dest).size / 1024 / 1024).toFixed(1);