From 4bb4c6fe6d34525c7665a9d38b584b026dd5cdd9 Mon Sep 17 00:00:00 2001 From: Ysopwnable <161784452+N0zoM1z0@users.noreply.github.com> Date: Fri, 9 Oct 2026 23:24:53 +0800 Subject: [PATCH] test(apple): verify compiled Mach-O root occurrence facts (#1300) test(artifacts): verify compiled Mach-O roles and permissions Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing) --- scripts/verify/apple/macho-occurrences.mjs | 86 ++++++++++++++++++++++ scripts/verify/apple/macos-bundle.mjs | 5 +- 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 scripts/verify/apple/macho-occurrences.mjs diff --git a/scripts/verify/apple/macho-occurrences.mjs b/scripts/verify/apple/macho-occurrences.mjs new file mode 100644 index 0000000000..9a7da4f4e0 --- /dev/null +++ b/scripts/verify/apple/macho-occurrences.mjs @@ -0,0 +1,86 @@ +import assert from "node:assert/strict"; +import { chmod, readFile, stat } from "node:fs/promises"; +import { relative, sep } from "node:path"; + +import { parseArtifactInventoryEvidence } from "../../../dist/domain/artifactInventoryEvidence.js"; +import { + artifactCliEvidence, + withArtifactMcp, +} from "../../lib/artifact-e2e.mjs"; + +/** Verify native file roles and permissions on the real compiled bundle fixture. */ +export async function verifyMachOOccurrences(app, executable) { + const originalMode = (await stat(executable)).mode & 0o7777; + const originalBytes = await readFile(executable); + const logicalPath = relative(app, executable).split(sep).join("/"); + const observations = []; + try { + for (const mode of [0o755, 0o644]) { + await chmod(executable, mode); + const directEvidence = await artifactCliEvidence( + "inspect-artifact", + executable, + ); + const direct = parseArtifactInventoryEvidence(directEvidence).inventory; + const containedEvidence = await artifactCliEvidence( + "inspect-artifact", + app, + ); + const contained = + parseArtifactInventoryEvidence(containedEvidence).inventory; + assert.equal(direct.complete, true); + assert.equal(contained.complete, true); + const root = direct.occurrences.find( + ({ logical_path }) => logical_path === ".", + ); + const nested = contained.occurrences.find( + ({ logical_path }) => logical_path === logicalPath, + ); + assert.ok(root); + assert.ok(nested); + assert.ok(["mach-o", "mach-o-universal"].includes(root.artifact_format)); + for (const occurrence of [root, nested]) { + assert.equal(occurrence.artifact_kind, "executable"); + assert.equal(occurrence.artifact_format, direct.manifest.root_format); + assert.equal(occurrence.executable, mode === 0o755); + } + assert.equal(root.artifact_id, nested.artifact_id); + assert.equal(root.artifact_id, direct.manifest.root_artifact_id); + const node = contained.nodes.find( + ({ artifact_id }) => artifact_id === nested.artifact_id, + ); + assert.ok(node); + assert.equal(node.sha256, direct.manifest.root_sha256); + assert.equal(node.format, root.artifact_format); + await withArtifactMcp(app, async (client) => { + const reply = await client.callTool({ + name: "inspect_artifact", + arguments: {}, + }); + assert.notEqual(reply.isError, true, JSON.stringify(reply)); + assert.deepEqual( + parseArtifactInventoryEvidence(reply.structuredContent).inventory, + contained, + ); + }); + observations.push({ + mode: mode.toString(8), + artifact_id: root.artifact_id, + artifact_kind: root.artifact_kind, + artifact_format: root.artifact_format, + executable: root.executable, + contained_cli_mcp_parity: true, + }); + } + assert.equal(observations[0].artifact_id, observations[1].artifact_id); + assert.deepEqual(await readFile(executable), originalBytes); + return { + direct_cli: true, + contained_cli_mcp: true, + bytes_unchanged: true, + observations, + }; + } finally { + await chmod(executable, originalMode); + } +} diff --git a/scripts/verify/apple/macos-bundle.mjs b/scripts/verify/apple/macos-bundle.mjs index 815c50a846..c10abcb2e0 100644 --- a/scripts/verify/apple/macos-bundle.mjs +++ b/scripts/verify/apple/macos-bundle.mjs @@ -16,6 +16,7 @@ import { } from "../../fixtures/apple/macos-bundle.mjs"; import { verifyDyldEnvironment } from "./dyld-environment.mjs"; import { verifyDylibResolution } from "./macos-dylib-e2e.mjs"; +import { verifyMachOOccurrences } from "./macho-occurrences.mjs"; const exec = promisify(execFile); @@ -67,7 +68,8 @@ const EXPECTED_BUNDLES = [ let report; try { - const { app } = await buildMacosBundleFixture(root); + const { app, executable } = await buildMacosBundleFixture(root); + const machoOccurrences = await verifyMachOOccurrences(app, executable); const zip = join(root, "MacFixture.zip"); await exec("/usr/bin/ditto", ["-c", "-k", "--keepParent", app, zip]); const staging = join(root, "dmg-source"); @@ -164,6 +166,7 @@ try { containers: containers.map(({ format }) => format), bundles: EXPECTED_BUNDLES.length, dmg_detached: true, + macho_occurrences: machoOccurrences, dylib_resolution: dylibs, dyld_environment: dyldEnvironment, };