mirror of
https://github.com/morluto/rea
synced 2026-10-26 22:28:27 -04:00
277 lines
9.9 KiB
JavaScript
277 lines
9.9 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { execFile } from "node:child_process";
|
|
import { createHash } from "node:crypto";
|
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { promisify } from "node:util";
|
|
|
|
import { toolContract } from "../../../dist/contracts/toolContracts.js";
|
|
import {
|
|
artifactCliEvidence,
|
|
artifactMcpCall,
|
|
withArtifactMcp,
|
|
withBundleResourcesMcp,
|
|
} from "../../lib/artifact-e2e.mjs";
|
|
|
|
const exec = promisify(execFile);
|
|
|
|
// dyld_info abbreviates a terminal .dylib suffix; padding is part of the name.
|
|
const INSTALL_NAME_CASES = [
|
|
{ installName: "leading.dylib", importSource: "leading" },
|
|
{ installName: " leading.dylib ", importSource: " leading.dylib " },
|
|
];
|
|
|
|
/** Inspect the compiled bundle with real native utilities through both adapters. */
|
|
export async function verifyNativeProvenance(app, executable) {
|
|
const original = await readFile(executable);
|
|
const sha256 = createHash("sha256").update(original).digest("hex");
|
|
const symbols = ["_", "$s4main3FooV", "_", "plain_symbol", "__"];
|
|
const operations = [
|
|
["inspect_macho", []],
|
|
["inspect_signature", []],
|
|
["list_architectures", []],
|
|
["demangle_swift", symbols],
|
|
];
|
|
const observations = [];
|
|
const resourcePlistCli = toolContract("inspect_plist").outputSchema.parse(
|
|
await artifactCliEvidence("inspect-plist", app),
|
|
);
|
|
assert.equal(resourcePlistCli.subject, null);
|
|
assert.equal(resourcePlistCli.raw_result, null);
|
|
await withBundleResourcesMcp(app, async (client) => {
|
|
const response = await artifactMcpCall(client, {
|
|
name: "inspect_plist",
|
|
arguments: {},
|
|
});
|
|
assert.notEqual(response.isError, true, JSON.stringify(response));
|
|
const mcp = toolContract("inspect_plist").outputSchema.parse(
|
|
response.structuredContent,
|
|
);
|
|
assert.equal(mcp.subject, null);
|
|
assert.equal(mcp.raw_result, null);
|
|
assert.deepEqual(mcp.normalized_result, resourcePlistCli.normalized_result);
|
|
assert.deepEqual(
|
|
JSON.parse(response.content.find((item) => item.type === "text").text),
|
|
response.structuredContent,
|
|
);
|
|
await client.ping();
|
|
observations.push({
|
|
operation: "inspect_plist_resource_root",
|
|
commands: resourcePlistCli.normalized_result.provenance.length,
|
|
cli_bytes: Buffer.byteLength(JSON.stringify(resourcePlistCli)),
|
|
mcp_bytes: Buffer.byteLength(JSON.stringify(response)),
|
|
});
|
|
});
|
|
|
|
const binaryPlistCli = toolContract("inspect_plist").outputSchema.parse(
|
|
await artifactCliEvidence("inspect-plist", executable),
|
|
);
|
|
assert.equal(binaryPlistCli.subject?.digest.sha256, sha256);
|
|
assert.equal(binaryPlistCli.raw_result, null);
|
|
assert.equal(binaryPlistCli.normalized_result.resource_root, undefined);
|
|
await withArtifactMcp(app, async (client) => {
|
|
const plistResponse = await artifactMcpCall(client, {
|
|
name: "inspect_plist",
|
|
arguments: {},
|
|
});
|
|
assert.notEqual(plistResponse.isError, true, JSON.stringify(plistResponse));
|
|
const binaryPlistMcp = toolContract("inspect_plist").outputSchema.parse(
|
|
plistResponse.structuredContent,
|
|
);
|
|
assert.equal(binaryPlistMcp.subject?.digest.sha256, sha256);
|
|
assert.equal(binaryPlistMcp.raw_result, null);
|
|
assert.equal(binaryPlistMcp.normalized_result.resource_root, undefined);
|
|
assert.deepEqual(
|
|
binaryPlistMcp.normalized_result,
|
|
binaryPlistCli.normalized_result,
|
|
);
|
|
assert.deepEqual(
|
|
JSON.parse(
|
|
plistResponse.content.find((item) => item.type === "text").text,
|
|
),
|
|
plistResponse.structuredContent,
|
|
);
|
|
await client.ping();
|
|
observations.push({
|
|
operation: "inspect_plist_binary_bound",
|
|
commands: binaryPlistCli.normalized_result.provenance.length,
|
|
cli_bytes: Buffer.byteLength(JSON.stringify(binaryPlistCli)),
|
|
mcp_bytes: Buffer.byteLength(JSON.stringify(plistResponse)),
|
|
});
|
|
|
|
for (const [operation, arguments_] of operations) {
|
|
const cli = toolContract(operation).outputSchema.parse(
|
|
await artifactCliEvidence(
|
|
operation.replaceAll("_", "-"),
|
|
app,
|
|
arguments_,
|
|
),
|
|
);
|
|
const response = await artifactMcpCall(client, {
|
|
name: operation,
|
|
arguments: operation === "demangle_swift" ? { symbols } : {},
|
|
});
|
|
assert.notEqual(response.isError, true, JSON.stringify(response));
|
|
const mcp = toolContract(operation).outputSchema.parse(
|
|
response.structuredContent,
|
|
);
|
|
assert.equal(cli.raw_result, null);
|
|
assert.equal(mcp.raw_result, null);
|
|
assert.ok(cli.normalized_result.provenance.length > 0);
|
|
assert.deepEqual(mcp.normalized_result, cli.normalized_result);
|
|
if (operation === "demangle_swift")
|
|
assert.deepEqual(cli.normalized_result.symbols, [
|
|
{ input: "_", output: "", status: "invalid" },
|
|
{ input: "$s4main3FooV", output: "main.Foo", status: "demangled" },
|
|
{ input: "_", output: "", status: "invalid" },
|
|
{
|
|
input: "plain_symbol",
|
|
output: "plain_symbol",
|
|
status: "unchanged",
|
|
},
|
|
{ input: "__", output: "_", status: "unchanged" },
|
|
]);
|
|
|
|
if (operation === "inspect_macho") {
|
|
const delayed = cli.normalized_result.load_commands.items.find(
|
|
({ fields }) => fields.name === "@rpath/libdelay.dylib (offset 28)",
|
|
);
|
|
assert.equal(delayed?.kind, "LC_LOAD_DYLIB");
|
|
assert.equal(delayed.fields.options, "delay-init");
|
|
assert.equal(delayed.fields["time stamp"], undefined);
|
|
assert.ok(
|
|
cli.normalized_result.dependencies.items.some(
|
|
({ path }) => path === "@rpath/libdelay.dylib",
|
|
),
|
|
);
|
|
}
|
|
assert.deepEqual(
|
|
JSON.parse(response.content.find((item) => item.type === "text").text),
|
|
response.structuredContent,
|
|
);
|
|
await client.ping();
|
|
observations.push({
|
|
operation,
|
|
commands: cli.normalized_result.provenance.length,
|
|
cli_bytes: Buffer.byteLength(JSON.stringify(cli)),
|
|
mcp_bytes: Buffer.byteLength(JSON.stringify(response)),
|
|
});
|
|
}
|
|
});
|
|
assert.deepEqual(await readFile(executable), original);
|
|
return {
|
|
real_native_utilities: true,
|
|
target_sha256: sha256,
|
|
bytes_unchanged: true,
|
|
observations,
|
|
install_names: await verifyInstallNames(),
|
|
};
|
|
}
|
|
|
|
/** Compile independent inputs; their unusual loader paths are never executed. */
|
|
async function verifyInstallNames() {
|
|
const root = await mkdtemp(join(tmpdir(), "rea-macho-install-names-"));
|
|
const observations = [];
|
|
try {
|
|
const librarySource = join(root, "library.c");
|
|
const consumerSource = join(root, "consumer.c");
|
|
await writeFile(librarySource, "int exported_value(void) { return 42; }\n");
|
|
await writeFile(
|
|
consumerSource,
|
|
"extern int exported_value(void); int main(void) { return exported_value(); }\n",
|
|
);
|
|
for (const [
|
|
index,
|
|
{ installName, importSource },
|
|
] of INSTALL_NAME_CASES.entries()) {
|
|
const library = join(root, `library-${index}.dylib`);
|
|
const consumer = join(root, `consumer-${index}`);
|
|
const rpath = " @loader_path/Frameworks ";
|
|
await exec("/usr/bin/xcrun", [
|
|
"clang",
|
|
"-dynamiclib",
|
|
librarySource,
|
|
`-Wl,-install_name,${installName}`,
|
|
"-o",
|
|
library,
|
|
]);
|
|
await exec("/usr/bin/xcrun", [
|
|
"clang",
|
|
consumerSource,
|
|
library,
|
|
`-Wl,-rpath,${rpath}`,
|
|
"-o",
|
|
consumer,
|
|
]);
|
|
const original = await readFile(consumer);
|
|
const originalLibrary = await readFile(library);
|
|
const { stdout } = await exec("/usr/bin/xcrun", [
|
|
"otool",
|
|
"-l",
|
|
consumer,
|
|
]);
|
|
const lines = stdout.split("\n").map((line) => line.trimStart());
|
|
const nameRow = lines.find((line) =>
|
|
line.startsWith(`name ${installName} (offset `),
|
|
);
|
|
const pathRow = lines.find((line) =>
|
|
line.startsWith(`path ${rpath} (offset `),
|
|
);
|
|
assert.ok(nameRow, "linker did not retain the selected install name");
|
|
assert.ok(pathRow, "linker did not retain the selected rpath");
|
|
const cli = toolContract("inspect_macho").outputSchema.parse(
|
|
await artifactCliEvidence("inspect-macho", consumer),
|
|
);
|
|
const result = cli.normalized_result;
|
|
assert.equal(cli.raw_result, null);
|
|
assert.ok(
|
|
result.dependencies.items.some(({ path }) => path === installName),
|
|
);
|
|
assert.ok(
|
|
result.load_commands.items.some(
|
|
({ kind, fields }) =>
|
|
kind === "LC_LOAD_DYLIB" &&
|
|
fields.name === nameRow.slice("name ".length),
|
|
),
|
|
);
|
|
assert.ok(
|
|
result.load_commands.items.some(
|
|
({ kind, fields }) =>
|
|
kind === "LC_RPATH" &&
|
|
fields.path === pathRow.slice("path ".length),
|
|
),
|
|
);
|
|
assert.equal(
|
|
result.imports.items.find(({ name }) => name === "_exported_value")
|
|
?.source,
|
|
importSource,
|
|
);
|
|
assert.ok(result.provenance.some(({ tool }) => tool === "otool"));
|
|
await withArtifactMcp(consumer, async (client) => {
|
|
const response = await artifactMcpCall(client, {
|
|
name: "inspect_macho",
|
|
arguments: {},
|
|
});
|
|
assert.notEqual(response.isError, true, JSON.stringify(response));
|
|
const mcp = toolContract("inspect_macho").outputSchema.parse(
|
|
response.structuredContent,
|
|
);
|
|
assert.deepEqual(mcp.normalized_result, result);
|
|
});
|
|
assert.deepEqual(await readFile(consumer), original);
|
|
assert.deepEqual(await readFile(library), originalLibrary);
|
|
observations.push({
|
|
install_name: installName,
|
|
rpath,
|
|
target_sha256: createHash("sha256").update(original).digest("hex"),
|
|
bytes_unchanged: true,
|
|
cli_mcp_parity: true,
|
|
});
|
|
}
|
|
return observations;
|
|
} finally {
|
|
await rm(root, { recursive: true, force: true });
|
|
}
|
|
}
|