Files
rea/tests/boundary/cli/nativeSignatureCallerSelection.test.ts
T
morluto 535926ca2b fix(analysis): retain one-shot target selection provenance
Retain the exact selected CLI path in one-shot provider Evidence while preserving canonical subject identity and provider inputs. The shared request-provenance boundary replaces the artifact-only special case across native, managed, and bundle-resource routes. Remove the redundant parameter fallback and make the private managed helper receive explicit Evidence parameters.

Validation: real macOS codesign fixtures through the compiled CLI retained app aliases for signature, plist, and absent asset inspections, with direct-target controls. Archive selection, managed direct analysis, and snapshot replay regressions passed; Windows-specific replay cases were skipped on macOS. Build, static, format, and docs checks passed. Snapshot-backed direct request provenance still follows its existing authenticated query contract.

Refs: #5479
2026-10-25 01:45:23 +08:00

116 lines
4.5 KiB
TypeScript

import { execFile } from "node:child_process";
import { copyFile, mkdir, symlink, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { promisify } from "node:util";
import { describe, expect } from "vitest";
import { parseEvidence } from "../../../src/domain/evidence.js";
import { inspectPlistSchema } from "../../../src/domain/native/nativeInspection.js";
import { appleAssetCatalogResultSchema } from "../../../src/domain/apple/appleAssetCatalog.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { cliTest } from "../../support/cli/cliFixture.js";
const run = promisify(execFile);
const environment = {
REA_LOG_LEVEL: "silent",
REA_ANALYSIS_PROVIDER: "auto",
} as const;
const signedApp = async () => {
const root = await createTestTempDirectory("rea-selected-app-");
const app = join(root, "Probe.app");
const executable = join(app, "Contents/MacOS/Probe");
await mkdir(join(app, "Contents/MacOS"), { recursive: true });
await copyFile("/usr/bin/true", executable);
await writeFile(
join(app, "Contents/Info.plist"),
'<?xml version="1.0" encoding="UTF-8"?><plist version="1.0"><dict><key>CFBundleExecutable</key><string>Probe</string><key>CFBundleIdentifier</key><string>org.example.rea.probe</string><key>CFBundlePackageType</key><string>APPL</string></dict></plist>',
);
await run("/usr/bin/codesign", ["-s", "-", "-f", app]);
await symlink("Probe.app", join(root, "Selected.app"));
return { root, app, executable };
};
describe.skipIf(process.platform !== "darwin")(
"native app CLI caller selection",
() => {
cliTest(
"retains the selected app alias across signature, plist, and absent asset inspections",
async ({ cli }) => {
const { root, app, executable } = await signedApp();
for (const command of [
"inspect-signature",
"inspect-plist",
"inspect-asset-catalog",
]) {
const selectedRun = await cli.run({
arguments: [command, "Selected.app", "--json"],
cwd: root,
environment,
});
const directRun = await cli.run({
arguments: [command, "Probe.app", "--json"],
cwd: root,
environment,
});
expect(selectedRun.exitCode, selectedRun.stderr).toBe(0);
expect(directRun.exitCode, directRun.stderr).toBe(0);
const selected = parseEvidence(selectedRun.json);
const direct = parseEvidence(directRun.json);
expect(selected.parameters).toMatchObject({
input_path: "Selected.app",
});
expect(direct.parameters).toMatchObject({ input_path: "Probe.app" });
expect(selected.subject).toEqual(direct.subject);
if (command === "inspect-signature") {
expect(selected.subject?.local_path).toBe(executable);
expect(selected.normalized_result).toEqual(
direct.normalized_result,
);
} else if (command === "inspect-plist") {
const aliasResult = inspectPlistSchema.parse(
selected.normalized_result,
);
const directResult = inspectPlistSchema.parse(
direct.normalized_result,
);
expect(aliasResult.resource_root).toMatchObject({
caller_path: join(root, "Selected.app"),
canonical_path: app,
});
expect(directResult.resource_root).toMatchObject({
caller_path: app,
canonical_path: app,
});
expect({
...aliasResult,
resource_root: directResult.resource_root,
}).toEqual(directResult);
} else {
const aliasResult = appleAssetCatalogResultSchema.parse(
selected.normalized_result,
);
const directResult = appleAssetCatalogResultSchema.parse(
direct.normalized_result,
);
expect(aliasResult.catalogs).toEqual([]);
expect(aliasResult.resource_root).toMatchObject({
caller_path: join(root, "Selected.app"),
canonical_path: app,
});
expect(directResult.resource_root).toMatchObject({
caller_path: app,
canonical_path: app,
});
expect({
...aliasResult,
resource_root: directResult.resource_root,
}).toEqual(directResult);
}
}
},
);
},
);