mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
Own operation results and exact rejections in withVerifierCleanup, including undefined, null and independent cleanup failures. Remove the optional-primary cleanup contract and migrate every caller, preserving returns, annotations, signal restoration and dependent cleanup order. Make Frida/JEB reporters fail on reasonless rejections and retain JEB fixture files while provider cleanup is incomplete. Own the nested packaged WASM verifier and expose its composite process/root cleanup capability for retry. Update runnable docs and isolated fixture dependencies. Validation: 547 focused cases in 20 files, eight isolated boundary unit checks, static/build/docs/discovery gates and duplication check (3.58%). Node process, SDK and descriptor cleanup are exercised; provider and packaging results in orchestration tests are simulated. Pack/install subprocess ownership remains with the existing shared package runner outside the nested-command change.
179 lines
6.0 KiB
TypeScript
179 lines
6.0 KiB
TypeScript
import {
|
|
copyFile,
|
|
mkdir,
|
|
readFile,
|
|
readdir,
|
|
writeFile,
|
|
} from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
|
|
import { expect } from "vitest";
|
|
|
|
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
|
import { processTest } from "../../support/process/processFixture.js";
|
|
|
|
type Provider = "frida" | "jeb";
|
|
type Primary = "undefined" | "null" | "success";
|
|
|
|
const cases = (["frida", "jeb"] as const).flatMap((provider) =>
|
|
[
|
|
{ primary: "undefined", closeFails: false },
|
|
{ primary: "null", closeFails: false },
|
|
{ primary: "undefined", closeFails: true },
|
|
{ primary: "success", closeFails: true },
|
|
].map(({ primary, closeFails }) => ({
|
|
provider,
|
|
primary: primary as Primary,
|
|
closeFails,
|
|
})),
|
|
);
|
|
|
|
/** Copy the actual script; substitute only the engine-facing module boundary. */
|
|
const verifierFixture = async (provider: Provider) => {
|
|
const root = await createTestTempDirectory("rea-provider-verifier-cleanup-");
|
|
const temporary = join(root, "temporary");
|
|
await mkdir(temporary);
|
|
await mkdir(join(root, "scripts", "lib"), { recursive: true });
|
|
await mkdir(join(root, "dist", "application", provider), { recursive: true });
|
|
await writeFile(join(root, "package.json"), '{"type":"module"}\n');
|
|
const script = join(root, "scripts", `verify-${provider}.mjs`);
|
|
await copyFile(
|
|
new URL(`../../../scripts/verify-${provider}.mjs`, import.meta.url),
|
|
script,
|
|
);
|
|
await copyFile(
|
|
new URL("../../../scripts/lib/verifier-cleanup.mjs", import.meta.url),
|
|
join(root, "scripts", "lib", "verifier-cleanup.mjs"),
|
|
);
|
|
const closeBody = `
|
|
await appendFile(process.env.REA_TEST_VERIFIER_CLOSE_LOG, "${provider}\\n");
|
|
if (process.env.REA_TEST_VERIFIER_CLOSE_FAIL === "1")
|
|
throw new Error("controlled ${provider} cleanup denial");
|
|
`;
|
|
const primaryBody = `
|
|
if (process.env.REA_TEST_VERIFIER_PRIMARY === "undefined") throw undefined;
|
|
if (process.env.REA_TEST_VERIFIER_PRIMARY === "null") throw null;
|
|
`;
|
|
|
|
if (provider === "frida") {
|
|
await mkdir(join(root, "dist", "frida"));
|
|
await mkdir(join(root, "dist", "contracts"));
|
|
await writeFile(
|
|
join(root, "dist", "frida", "FridaInstrumentationManager.js"),
|
|
`import { appendFile } from "node:fs/promises";
|
|
export class FridaInstrumentationManager {
|
|
async closeAll() { ${closeBody} }
|
|
}
|
|
`,
|
|
);
|
|
await writeFile(
|
|
join(
|
|
root,
|
|
"dist",
|
|
"application",
|
|
"frida",
|
|
"FridaInstrumentationService.js",
|
|
),
|
|
`export class FridaInstrumentationService {
|
|
async instrument() {
|
|
${primaryBody}
|
|
return { ok: true, value: {
|
|
cleanupError: null,
|
|
evidence: { normalized_result: {
|
|
pid: 77,
|
|
messages: [{ type: "send", payload: { rea_frida_verification: "ok", pid: 77 } }],
|
|
} },
|
|
} };
|
|
}
|
|
}
|
|
`,
|
|
);
|
|
await writeFile(
|
|
join(root, "dist", "contracts", "fridaRemoteAddress.js"),
|
|
"export const isValidFridaRemoteAddress = () => false;\n",
|
|
);
|
|
} else {
|
|
await mkdir(join(root, "dist", "composition"));
|
|
await writeFile(
|
|
join(root, "dist", "composition", "jeb.js"),
|
|
`import { appendFile } from "node:fs/promises";
|
|
export const createJebAnalysisProvider = () => ({
|
|
async close() { ${closeBody} },
|
|
});
|
|
`,
|
|
);
|
|
await writeFile(
|
|
join(root, "dist", "application", "jeb", "JebAnalysisService.js"),
|
|
`export class JebAnalysisService {
|
|
async execute(operation) {
|
|
${primaryBody}
|
|
const result = {
|
|
inspect_jeb_client: { engine: { version: "simulated", gui_client: false, endpoint: "simulated" } },
|
|
open_jeb_project: { input_files: [{ contents_sha256_hash: "${"a".repeat(64)}" }] },
|
|
list_jeb_units: { units: [{ id: "simulated-unit" }] },
|
|
decompile_jeb_item: { text: "simulated marker" },
|
|
}[operation];
|
|
if (result === undefined) throw new Error("Unexpected simulated operation: " + operation);
|
|
return { ok: true, value: { normalized_result: result } };
|
|
}
|
|
}
|
|
`,
|
|
);
|
|
}
|
|
|
|
return { root, script, temporary, closeLog: join(root, "close.log") };
|
|
};
|
|
|
|
// These are simulated provider outcomes exercising real verifier orchestration;
|
|
// they establish no Frida instrumentation or JEB engine behavior.
|
|
processTest.for(cases)(
|
|
"$provider verifier preserves primary=$primary with closeFails=$closeFails",
|
|
async ({ provider, primary, closeFails }, { processes }) => {
|
|
const fixture = await verifierFixture(provider);
|
|
const result = await processes.run(
|
|
process.execPath,
|
|
[
|
|
fixture.script,
|
|
...(provider === "jeb"
|
|
? ["--item-address", "simulated-item", "--marker", "simulated marker"]
|
|
: []),
|
|
],
|
|
{
|
|
cwd: fixture.root,
|
|
env: {
|
|
...process.env,
|
|
TMPDIR: fixture.temporary,
|
|
TEMP: fixture.temporary,
|
|
TMP: fixture.temporary,
|
|
REA_TEST_VERIFIER_PRIMARY: primary,
|
|
REA_TEST_VERIFIER_CLOSE_FAIL: closeFails ? "1" : "0",
|
|
REA_TEST_VERIFIER_CLOSE_LOG: fixture.closeLog,
|
|
},
|
|
timeoutMs: 10_000,
|
|
},
|
|
);
|
|
|
|
expect(result.signal, result.stderr).toBeNull();
|
|
expect(result.exitCode, result.stderr).toBe(1);
|
|
const reasons = [
|
|
...(primary === "success" ? [] : [primary]),
|
|
...(closeFails ? [`controlled ${provider} cleanup denial`] : []),
|
|
];
|
|
const label = provider === "frida" ? "Frida" : "JEB";
|
|
const retained = await readdir(fixture.temporary);
|
|
let retainedMessage = "";
|
|
if (provider === "jeb" && closeFails) {
|
|
expect(retained).toHaveLength(1);
|
|
const name = retained[0];
|
|
if (name === undefined) throw new Error("Missing retained JEB fixture");
|
|
expect(name).toMatch(/^rea-jeb-/u);
|
|
retainedMessage = `JEB fixture retained at ${join(fixture.temporary, name)}\n`;
|
|
} else expect(retained).toEqual([]);
|
|
expect(result.stderr).toBe(
|
|
`${retainedMessage}${label} real-provider verification failed: ${reasons.join("; ")}\n`,
|
|
);
|
|
expect(result.stdout).toBe("");
|
|
expect(await readFile(fixture.closeLog, "utf8")).toBe(`${provider}\n`);
|
|
},
|
|
);
|