mirror of
https://github.com/morluto/rea.git
synced 2026-10-12 02:19:24 +00:00
Deliver complete Evidence directly through MCP with required nullable analysis profiles and immutable per-server delivery settings. Bind selected environments at construction and require typed cleanup outcomes with retained retry ownership. Remove test-only routing, duplicate session and snapshot metadata, producer-field repairs, and ambiguous provider arguments. Separate artifact byte identity from occurrence classification and retain typed source-map and partial native facts across CLI, MCP, and verifier consumers. BREAKING CHANGE: obsolete Evidence envelopes, session aliases, incomplete snapshots, and missing normalized producer facts are no longer accepted.
99 lines
3.4 KiB
TypeScript
99 lines
3.4 KiB
TypeScript
import { writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import { createCli } from "../../src/cli.js";
|
|
import { parseEvidence } from "../../src/domain/evidence.js";
|
|
import { createTestTempDirectory } from "../fixtures/temporaryDirectory.js";
|
|
|
|
const initialExitCode = process.exitCode;
|
|
afterEach(() => {
|
|
vi.unstubAllEnvs();
|
|
process.exitCode = initialExitCode;
|
|
});
|
|
|
|
const serve = async (
|
|
cli: ReturnType<typeof createCli>,
|
|
arguments_: string[],
|
|
) => {
|
|
let stdout = "";
|
|
await cli.serve([...arguments_, "--json"], {
|
|
env: {},
|
|
stdout: (text) => {
|
|
stdout += text;
|
|
},
|
|
exit: () => undefined,
|
|
});
|
|
const result: unknown = JSON.parse(stdout);
|
|
return result;
|
|
};
|
|
|
|
describe("CLI selected environment", () => {
|
|
it("retains the selected binary provider and launcher after caller and ambient environment changes", async () => {
|
|
vi.stubEnv("REA_ANALYSIS_PROVIDER", "ambient-provider");
|
|
vi.stubEnv("HOPPER_LAUNCHER_PATH", "/ambient/hopper");
|
|
const environment = {
|
|
REA_ANALYSIS_PROVIDER: "selected-provider",
|
|
HOPPER_LAUNCHER_PATH: process.execPath,
|
|
};
|
|
const cli = createCli(environment);
|
|
environment.REA_ANALYSIS_PROVIDER = "changed-provider";
|
|
environment.HOPPER_LAUNCHER_PATH = "/changed/hopper";
|
|
const root = await createTestTempDirectory("rea-cli-selected-env-");
|
|
const target = join(root, "fixture.hop");
|
|
await writeFile(target, "fixture");
|
|
|
|
for (const command of [
|
|
["decompile", target, "main"],
|
|
["read-bytes", target, "0x1000"],
|
|
]) {
|
|
const result = await serve(cli, command);
|
|
expect(result).toMatchObject({
|
|
code: "capability_unavailable",
|
|
details: { requested_provider_id: "selected-provider" },
|
|
});
|
|
}
|
|
for (const command of ["providers", "capabilities"]) {
|
|
const result = await serve(cli, [command]);
|
|
expect(result).toMatchObject({
|
|
analysis_provider_candidates: expect.arrayContaining([
|
|
expect.objectContaining({
|
|
provider: expect.objectContaining({ id: "hopper" }),
|
|
availability: expect.objectContaining({
|
|
diagnostics: expect.objectContaining({
|
|
launcher_path: process.execPath,
|
|
}),
|
|
}),
|
|
}),
|
|
]),
|
|
});
|
|
}
|
|
});
|
|
|
|
it("does not borrow invalid ambient settings or capture inherited environment in artifact Evidence", async () => {
|
|
vi.stubEnv("REA_GHIDRA_STARTUP_TIMEOUT_MS", "ambient-invalid-setting");
|
|
vi.stubEnv(
|
|
"REA_AMBIENT_CAPTURE_SENTINEL",
|
|
"ambient-value-must-not-be-captured",
|
|
);
|
|
const root = await createTestTempDirectory("rea-cli-isolated-artifact-");
|
|
const target = join(root, "empty.zip");
|
|
await writeFile(
|
|
target,
|
|
Buffer.from("504b0506000000000000000000000000000000000000", "hex"),
|
|
);
|
|
const cli = createCli({
|
|
REA_SELECTED_CAPTURE_SENTINEL: "selected-value-must-not-be-captured",
|
|
});
|
|
const result = await serve(cli, ["inspect-artifact", target]);
|
|
const evidence = parseEvidence(result);
|
|
expect(evidence.operation).toBe("inspect_artifact");
|
|
expect(evidence.subject?.local_path).toBe(target);
|
|
expect(evidence.environment).toBeNull();
|
|
const serialized = JSON.stringify(evidence);
|
|
expect(serialized).not.toContain("CAPTURE_SENTINEL");
|
|
expect(serialized).not.toContain("value-must-not-be-captured");
|
|
});
|
|
});
|