diff --git a/scripts/messaging-runtime-provenance.test.ts b/scripts/messaging-runtime-provenance.test.ts index 73c6f390..c8156774 100644 --- a/scripts/messaging-runtime-provenance.test.ts +++ b/scripts/messaging-runtime-provenance.test.ts @@ -6,7 +6,7 @@ import { tmpdir } from "node:os"; import { gunzipSync } from "node:zlib"; import { MESSAGING_NATIVE_ARTIFACTS } from "../src/providers/messaging-native-artifacts"; -import { assertPatchStackIdentity, verify } from "./messaging-runtime-provenance"; +import { assertPatchStackIdentity, commandSucceeded, verify } from "./messaging-runtime-provenance"; describe("messaging runtime provenance", () => { test("pinned source trees tolerate reconstructed commit metadata but reject source drift", () => { @@ -19,6 +19,20 @@ describe("messaging runtime provenance", () => { expect(() => assertPatchStackIdentity("imsg", legacy, "3".repeat(40), "4".repeat(40))).toThrow("patch stack landed"); }); + test("a rebuild command succeeds only when it exits 0", () => { + expect(commandSucceeded({ kind: "exited", exitCode: 0, stdout: "", stderr: "" })).toBe(true); + expect(commandSucceeded({ kind: "exited", exitCode: 1, stdout: "", stderr: "" })).toBe(false); + expect(commandSucceeded({ kind: "timed-out", detail: "late", stdout: "", stderr: "" })).toBe(false); + expect(commandSucceeded({ kind: "signaled", detail: "SIGKILL", stdout: "", stderr: "" })).toBe(false); + }); + + test("every committed patch stack pins its reconstructed source tree", () => { + for (const vendor of ["imessage-direct", "whatsapp-linked-device"]) { + const record = JSON.parse(readFileSync(join(import.meta.dir, "..", "src", "plugins", vendor, "vendor", "provenance.json"), "utf8")) as { reviewedPatchStack: { sourceTree?: string } }; + expect(record.reviewedPatchStack.sourceTree).toMatch(/^[0-9a-f]{40}$/u); + } + }); + test("the committed compressed and executable pins verify from the checked-in bytes", async () => { await verify(); }); diff --git a/scripts/messaging-runtime-provenance.ts b/scripts/messaging-runtime-provenance.ts index f7feab0c..5bbafcf8 100644 --- a/scripts/messaging-runtime-provenance.ts +++ b/scripts/messaging-runtime-provenance.ts @@ -112,6 +112,15 @@ export function describeFailure(label: string, outcome: Awaited>): boolean { + return outcome.kind === "exited" && outcome.exitCode === 0; +} + async function must( command: readonly string[], cwd: string, @@ -123,7 +132,7 @@ async function must( environment: { ...process.env as Record, ...extraEnvironment }, timeoutMs: 15 * 60_000, }); - if (outcome.kind !== "succeeded") fail(describeFailure(label, outcome)); + if (!commandSucceeded(outcome)) fail(describeFailure(label, outcome)); return outcome.stdout.trim(); } diff --git a/src/plugins/imessage-direct/vendor/provenance.json b/src/plugins/imessage-direct/vendor/provenance.json index 5e89e456..45fda6e4 100644 --- a/src/plugins/imessage-direct/vendor/provenance.json +++ b/src/plugins/imessage-direct/vendor/provenance.json @@ -7,6 +7,7 @@ }, "reviewedPatchStack": { "tipCommit": "533789195c48480aef2cdc3a2377038301d5b861", + "sourceTree": "ac999492b328f3e95b0d8e306648a21e9aebb42d", "patches": [ { "file": "0001-fix-keep-AppleScript-send-payloads-out-of-child-argv.patch",