From a31d5cbdc32c0c54de49e2031e5dc3a57d855020 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chalifour?= Date: Wed, 16 Sep 2026 12:18:39 +0200 Subject: [PATCH 1/2] fix(release): restore macOS 27 binary compatibility Bun 1.4.0 emitted invalid ad-hoc Mach-O signatures that macOS 27 rejects at launch. Build release artifacts with Bun 1.4.2, keep the matching type metadata in sync, and verify Darwin signatures during release smoke tests so malformed binaries cannot be published again. --- .bun-version | 2 +- cli/bun.lock | 6 +++--- cli/package.json | 4 ++-- cli/scripts/release.test.ts | 15 +++++++++++++++ cli/scripts/release.ts | 10 ++++++++++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/.bun-version b/.bun-version index 88c5fb8..9df886c 100644 --- a/.bun-version +++ b/.bun-version @@ -1 +1 @@ -1.4.0 +1.4.2 diff --git a/cli/bun.lock b/cli/bun.lock index 1b3c2c4..f8bd11d 100644 --- a/cli/bun.lock +++ b/cli/bun.lock @@ -10,7 +10,7 @@ "yaml": "2.9.0", }, "devDependencies": { - "@types/bun": "1.4.0", + "@types/bun": "1.4.2", "eslint-plugin-no-relative-import-paths": "1.6.1", "knip": "6.32.2", "openapi-typescript": "7.13.0", @@ -212,7 +212,7 @@ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], - "@types/bun": ["@types/bun@1.4.0", "", { "dependencies": { "bun-types": "1.4.0" } }, "sha512-K+lZULY23vRgK/CfTjFIV+tyifaNdSMlPh9j+6mQ/cLfpOznLyAuzgV/JQysyECpkBQLVMSyvjlr2fBUSA9wFQ=="], + "@types/bun": ["@types/bun@1.4.2", "", { "dependencies": { "bun-types": "1.4.2" } }, "sha512-GimotNn7+ZV0uVArItBbriZsR1oNf0+WTzPkdcFrzShI7k2norL0uzEaJT8T33dWr7O/c9ZDuAFQrctKCi72oQ=="], "@types/node": ["@types/node@26.0.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw=="], @@ -226,7 +226,7 @@ "brace-expansion": ["brace-expansion@2.1.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA=="], - "bun-types": ["bun-types@1.4.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-iIKw23BspnQQYd3prITOBxeUsxBHnwzX6YJfGMuNOZzeNcMmVqzIIVGRm1l69ogaPQmb4wB6BN8mA5bE9YuC5Q=="], + "bun-types": ["bun-types@1.4.2", "", { "dependencies": { "@types/node": "*" } }, "sha512-bxV1FgK7yBIzjRe5zBozIM4Bem11ZJcCXSrjWRG3YWLt8yFDePu4cLjpebO8OvPeIE9trbyPF4fuj3Cia4Fj3w=="], "change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], diff --git a/cli/package.json b/cli/package.json index a16d271..2982214 100644 --- a/cli/package.json +++ b/cli/package.json @@ -51,7 +51,7 @@ "yaml": "2.9.0" }, "devDependencies": { - "@types/bun": "1.4.0", + "@types/bun": "1.4.2", "eslint-plugin-no-relative-import-paths": "1.6.1", "knip": "6.32.2", "openapi-typescript": "7.13.0", @@ -63,5 +63,5 @@ "engines": { "bun": ">=1.1.0" }, - "packageManager": "bun@1.4.0" + "packageManager": "bun@1.4.2" } diff --git a/cli/scripts/release.test.ts b/cli/scripts/release.test.ts index c3d6775..7588932 100644 --- a/cli/scripts/release.test.ts +++ b/cli/scripts/release.test.ts @@ -13,6 +13,7 @@ import { nativeReleaseTarget, readToolchainContract, RELEASE_MANIFEST_SCHEMA_VERSION, + signatureVerificationCommand, stageCommandReferenceAssets, SUPPORTED_BUN_RUNTIME_RANGE, writeReleaseMetadata, @@ -153,6 +154,20 @@ describe("release target manifest", () => { "Unsupported native release platform: win32-x64.", ); }); + + test("verifies macOS release signatures before executing binaries", () => { + const darwinTarget = RELEASE_TARGETS.find(({ platform }) => platform === "darwin-arm64")!; + const linuxTarget = RELEASE_TARGETS.find(({ platform }) => platform === "linux-arm64")!; + const executable = "/tmp/altertable-test-binary"; + + expect(signatureVerificationCommand(darwinTarget, executable)).toEqual([ + "codesign", + "--verify", + "--strict", + executable, + ]); + expect(signatureVerificationCommand(linuxTarget, executable)).toBeUndefined(); + }); }); describe("release toolchain contract", () => { diff --git a/cli/scripts/release.ts b/cli/scripts/release.ts index 41e88a9..de40602 100644 --- a/cli/scripts/release.ts +++ b/cli/scripts/release.ts @@ -144,6 +144,14 @@ export function compileCommand(target: ReleaseTarget, outputPath: string): strin ]; } +export function signatureVerificationCommand( + target: ReleaseTarget, + executable: string, +): string[] | undefined { + if (target.os !== "darwin") return undefined; + return ["codesign", "--verify", "--strict", executable]; +} + export function nativeReleaseTarget( platform: NodeJS.Platform = process.platform, architecture: string = process.arch, @@ -387,6 +395,8 @@ export async function smokeReleaseTarget( ): Promise { const executable = join(outputDirectory, target.asset); await assertNonemptyFile(executable); + const verifySignature = signatureVerificationCommand(target, executable); + if (verifySignature) await run(verifySignature); const version = (await runCapture([executable, "--version"])).trim(); if (version !== VERSION) { throw new Error(`${target.asset} reported version ${version}; expected ${VERSION}.`); From 05d8a953b17dc1016f83869af03a8e02ef971ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chalifour?= Date: Wed, 16 Sep 2026 13:42:09 +0200 Subject: [PATCH 2/2] fix(release): re-sign Darwin artifacts after compilation Bun 1.4.2 still emits an invalid ad-hoc signature for the x64 target. Replace Bun's signature for both Darwin artifacts with the system codesign tool before strict verification so the ARM64 and Intel release paths share the same valid signing boundary. --- cli/scripts/release.test.ts | 12 +++++++++++- cli/scripts/release.ts | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cli/scripts/release.test.ts b/cli/scripts/release.test.ts index 7588932..005508d 100644 --- a/cli/scripts/release.test.ts +++ b/cli/scripts/release.test.ts @@ -13,6 +13,7 @@ import { nativeReleaseTarget, readToolchainContract, RELEASE_MANIFEST_SCHEMA_VERSION, + darwinSignatureCommand, signatureVerificationCommand, stageCommandReferenceAssets, SUPPORTED_BUN_RUNTIME_RANGE, @@ -155,17 +156,26 @@ describe("release target manifest", () => { ); }); - test("verifies macOS release signatures before executing binaries", () => { + test("signs and verifies macOS release binaries", () => { const darwinTarget = RELEASE_TARGETS.find(({ platform }) => platform === "darwin-arm64")!; const linuxTarget = RELEASE_TARGETS.find(({ platform }) => platform === "linux-arm64")!; const executable = "/tmp/altertable-test-binary"; + expect(darwinSignatureCommand(darwinTarget, executable)).toEqual([ + "codesign", + "--force", + "--sign", + "-", + "--timestamp=none", + executable, + ]); expect(signatureVerificationCommand(darwinTarget, executable)).toEqual([ "codesign", "--verify", "--strict", executable, ]); + expect(darwinSignatureCommand(linuxTarget, executable)).toBeUndefined(); expect(signatureVerificationCommand(linuxTarget, executable)).toBeUndefined(); }); }); diff --git a/cli/scripts/release.ts b/cli/scripts/release.ts index de40602..ef3ab7e 100644 --- a/cli/scripts/release.ts +++ b/cli/scripts/release.ts @@ -144,6 +144,14 @@ export function compileCommand(target: ReleaseTarget, outputPath: string): strin ]; } +export function darwinSignatureCommand( + target: ReleaseTarget, + executable: string, +): string[] | undefined { + if (target.os !== "darwin") return undefined; + return ["codesign", "--force", "--sign", "-", "--timestamp=none", executable]; +} + export function signatureVerificationCommand( target: ReleaseTarget, executable: string, @@ -172,6 +180,8 @@ export async function compileReleaseTarget( const outputPath = join(outputDirectory, target.asset); await run(compileCommand(target, outputPath)); await assertNonemptyFile(outputPath); + const signingCommand = darwinSignatureCommand(target, outputPath); + if (signingCommand) await run(signingCommand); return outputPath; }