#!/usr/bin/env node import assert from "node:assert/strict"; import { createHash, randomUUID } from "node:crypto"; import { createReadStream } from "node:fs"; import { readFile, writeFile } from "node:fs/promises"; import { isAbsolute, join } from "node:path"; import { performance } from "node:perf_hooks"; import { fileURLToPath } from "node:url"; import { parseArgs } from "node:util"; import { Client } from "@modelcontextprotocol/client"; import { StdioClientTransport } from "@modelcontextprotocol/client/stdio"; import { createEvidence } from "../../../dist/domain/evidence.js"; import { PrivateRuntimeRoot } from "../../../dist/process/PrivateRuntimeRoot.js"; import { OwnedCommandFailure, runOwnedCommand, } from "../../../dist/process/OwnedCommand.js"; import { closeVerifierResources } from "../../lib/verifier-cleanup.mjs"; import { matchesStructuredScopeExpectation, structuredScopeExpectationsSchema, } from "../../lib/javascript-file-scope-oracle.mjs"; const { values } = parseArgs({ options: { artifact: { type: "string" }, "addon-path": { type: "string" }, "native-sha256": { type: "string" }, "source-path": { type: "string", multiple: true }, "structured-path": { type: "string", multiple: true }, "structured-expectations": { type: "string" }, "validate-structured-from-export": { type: "boolean", default: false }, "analysis-timeout-ms": { type: "string" }, "expect-timeout": { type: "boolean", default: false }, rounds: { type: "string", default: "3" }, "cli-parity": { type: "boolean", default: false }, "tokenizer-python": { type: "string" }, "require-safe": { type: "boolean", default: false }, }, strict: true, }); assert.ok( values.artifact && isAbsolute(values.artifact), "--artifact must be absolute", ); assert.ok( values["addon-path"] && !isAbsolute(values["addon-path"]) && values["addon-path"] .split("/") .every((part) => part !== "" && part !== "." && part !== ".."), "--addon-path must be a normalized archive-relative path", ); assert.match( values["native-sha256"] ?? "", /^[a-f0-9]{64}$/, "--native-sha256 pins prior native bytes; it does not prove availability", ); const rounds = Number(values.rounds); assert.ok(Number.isSafeInteger(rounds) && rounds > 0); const analysisTimeoutMs = values["analysis-timeout-ms"] === undefined ? undefined : Number(values["analysis-timeout-ms"]); assert.ok( analysisTimeoutMs === undefined || (Number.isSafeInteger(analysisTimeoutMs) && analysisTimeoutMs > 0), ); assert.ok(!values["expect-timeout"] || analysisTimeoutMs !== undefined); assert.ok(!values["validate-structured-from-export"] || values["cli-parity"]); const structuredExpectations = structuredScopeExpectationsSchema.parse( JSON.parse(values["structured-expectations"] ?? "{}"), ); for (const path of Object.keys(structuredExpectations)) assert.ok( values["structured-path"]?.includes(path), `Expected structured path was not selected for verification: ${path}`, ); if (values["expect-timeout"]) for (const path of values["structured-path"] ?? []) assert.ok( Object.hasOwn(structuredExpectations, path), `--structured-expectations must name the expected operation/status for ${path}`, ); const environment = { PATH: process.env.PATH ?? "/usr/bin:/bin", REA_LOG_LEVEL: "silent", REA_ANALYSIS_PROVIDER: "auto", HOPPER_LAUNCHER_PATH: "/rea-unconfigured-deep-provider/hopper", }; const transport = new StdioClientTransport({ command: process.execPath, args: [fileURLToPath(new URL("../../rea.mjs", import.meta.url)), "mcp"], env: environment, stderr: "pipe", }); const client = new Client({ name: "javascript-native-handoff-verifier", version: "1", }); const serialize = (value) => JSON.stringify(value); const digest = (value) => createHash("sha256").update(serialize(value)).digest("hex"); const fileDigest = async (path) => { const hash = createHash("sha256"); for await (const chunk of createReadStream(path)) hash.update(chunk); return hash.digest("hex"); }; const simulatedNativeEvidence = (path, sha256) => createEvidence( { path, sha256, format: "raw-binary" }, { id: "ghidra", name: "Ghidra", version: "simulated" }, { operation: "binary_overview", parameters: {}, result: { summary: "Simulated subject-linkage input; no native provider executed.", }, limitations: ["No native provider behavior is established."], }, ); let temporary; let primaryError; let retainTemporary = false; let report; const ownedCommand = async (command, arguments_, timeoutMs = 60_000) => { try { return await runOwnedCommand( { command, arguments: arguments_, cwd: temporary.path, env: environment, runId: `rea-native-handoff-${randomUUID()}`, expectedCommand: command === process.execPath ? process.execPath : null, sweepTokenOwnedProcesses: true, }, { timeoutMs, diagnosticBytes: 16 * 1024 * 1024 }, ); } catch (cause) { retainTemporary ||= cause instanceof OwnedCommandFailure && cause.cleanupOwner !== undefined; throw cause; } }; try { const archiveSha256 = await fileDigest(values.artifact); const companion = join(`${values.artifact}.unpacked`, values["addon-path"]); let companionSha256 = null; try { companionSha256 = await fileDigest(companion); } catch (cause) { if (cause?.code !== "ENOENT") throw cause; } if (companionSha256 !== null) assert.equal(companionSha256, values["native-sha256"]); const native = simulatedNativeEvidence(companion, values["native-sha256"]); const container = simulatedNativeEvidence(values.artifact, archiveSha256); await client.connect(transport); transport.stderr?.on("data", () => undefined); const tools = (await client.listTools()).tools; const catalog = tools.map(({ name, description, inputSchema }) => ({ name, description, inputSchema, })); const selected = catalog.filter(({ name }) => ["analyze_javascript_application", "trace_application_feature"].includes( name, ), ); assert.equal(selected.length, 2); const call = async (name, arguments_, allowTimeout = false) => { const response = await client.callTool( { name, arguments: arguments_ }, { timeout: 360_000 }, ); let projection = response.structuredContent; if (response.isError === true) { assert.ok( allowTimeout, serialize({ name, arguments: arguments_, response }), ); const text = response.content.find(({ type }) => type === "text"); assert.ok(text?.type === "text"); projection = JSON.parse(text.text); assert.equal(projection.error.code, "provider_timeout"); assert.equal( projection.error.details.partial_observation.kind, "retained-evidence", ); } else assert.ok(projection?.evidence_id); return { request: { name, arguments: arguments_ }, response: projection, wire_response: response, }; }; const prepStart = performance.now(); const preparation = await call( "analyze_javascript_application", { input_path: values.artifact, detail: "summary", ...(analysisTimeoutMs === undefined ? {} : { analysis_timeout_ms: analysisTimeoutMs }), ...(values["source-path"] === undefined ? {} : { source_paths: values["source-path"] }), }, values["expect-timeout"], ); const preparationMs = performance.now() - prepStart; const timedOut = preparation.wire_response.isError === true; assert.equal(timedOut, values["expect-timeout"]); if (!timedOut) assert.equal(preparation.response.subject.digest.sha256, archiveSha256); const sourceId = timedOut ? preparation.response.error.details.partial_observation.evidence_id : preparation.response.normalized_result.parent_evidence_id; assert.match(sourceId, /^ev_[a-f0-9]{64}$/); const query = { application: { kind: "retained-evidence", evidence_id: sourceId }, native_observations: [container, native], seed: { kind: "string", value: values["addon-path"], match: "exact", case_sensitive: true, }, direction: "outgoing", }; const samples = []; let first; for (let round = 0; round < rounds; round++) { const start = performance.now(); const result = await call("trace_application_feature", query); const elapsedMs = performance.now() - start; if (first === undefined) first = result; else assert.equal(result.response.evidence_id, first.response.evidence_id); samples.push({ round, elapsed_ms: elapsedMs, structured_reply_bytes: Buffer.byteLength(serialize(result.response)), full_tool_reply_bytes: Buffer.byteLength(serialize(result.wire_response)), }); } const trace = first.response.normalized_result; const addons = trace.graph.nodes.filter( ({ kind }) => kind === "native-addon", ); assert.equal( addons.length, 1, "The selected native add-on must remain visible", ); const addon = addons[0]; const unavailable = addon.observations.some( ({ properties }) => properties.availability === "unavailable", ); const expectedLinks = [ sourceId, ...(companionSha256 === null ? [] : [native.evidence_id]), ].sort(); const safeIdentity = serialize(trace.evidence_links) === serialize(expectedLinks) && (companionSha256 === null ? unavailable && addon.identity.strategy !== "content-digest" && trace.coverage.status === "partial" && trace.native_handoffs.length === 0 : addon.identity.strategy === "content-digest" && addon.identity.sha256 === companionSha256 && trace.native_handoffs.length === 1 && trace.native_handoffs[0].artifact_sha256 === companionSha256 && trace.native_handoffs[0].status === "evidence-linked" && serialize(trace.native_handoffs[0].evidence_ids) === serialize([native.evidence_id])); const analysisScopes = (result, path) => result.graph.nodes.flatMap((node) => node.kind !== "unknown" ? [] : node.observations.flatMap((observation) => observation.properties.path === path && observation.properties.analysis_failure !== undefined ? [{ node_id: node.node_id, ...observation }] : [], ), ); const nativeScopes = analysisScopes(trace, values["addon-path"]); const structuredQueries = []; const structuredScopes = []; for (const path of values["validate-structured-from-export"] ? [] : (values["structured-path"] ?? [])) { const result = await call("trace_application_feature", { ...query, native_observations: [], seed: { ...query.seed, value: path }, }); structuredQueries.push(result); structuredScopes.push({ source: "retained-feature-trace", path, scopes: analysisScopes(result.response.normalized_result, path), evidence_id: result.response.evidence_id, source_coverage: result.response.normalized_result.coverage, graph_coverage: result.response.normalized_result.graph.coverage, }); } let cliParity = null; if (values["cli-parity"]) { temporary = await PrivateRuntimeRoot.create({ prefix: "rea-native-handoff-verifier-", }); const bundlePath = join(temporary.path, "bundle.json"); const exported = await client.callTool({ name: "export_evidence_bundle", arguments: { path: bundlePath }, }); assert.notEqual(exported.isError, true, serialize(exported)); const bundle = JSON.parse(await readFile(bundlePath, "utf8")); const parent = bundle.records.find( ({ evidence_id }) => evidence_id === sourceId, ); assert.ok(parent, "Export omitted the retained parent"); assert.equal(parent.normalized_result.root_artifact_sha256, archiveSha256); if (values["validate-structured-from-export"]) for (const path of values["structured-path"] ?? []) { const retained = parent.normalized_result; const matchingNodes = retained.graph.nodes.filter((node) => node.observations.some(({ properties }) => properties.path === path), ); assert.ok(matchingNodes.length > 0, `Missing retained path: ${path}`); // Diagnostic validation of the complete backend record is distinct // from the inline native analyst task used by this control's tokens. structuredScopes.push({ source: "exported-parent-validation", path, scopes: analysisScopes(retained, path), source_evidence_id: parent.evidence_id, retained_matching_nodes: matchingNodes.length, graph_coverage: retained.graph.coverage, }); } const request = join(temporary.path, "trace.json"); // The CLI's portable file contract takes complete Evidence; MCP resolves a // same-session reference into the same shared application workflow. await writeFile(request, serialize({ ...query, application: parent })); const result = await ownedCommand( process.execPath, [ fileURLToPath(new URL("../../rea.mjs", import.meta.url)), "trace-application-feature", request, "--json", ], 120_000, ); const evidence = JSON.parse(result.stdout.text); assert.deepEqual(evidence.normalized_result, trace); assert.equal(evidence.evidence_id, first.response.evidence_id); cliParity = { exact_cli_mcp_trace_parity: true, evidence_id: evidence.evidence_id, }; } const safeApplicability = nativeScopes.length === 0 && structuredScopes.every(({ path, scopes }) => timedOut ? matchesStructuredScopeExpectation( scopes, structuredExpectations[path], ) : scopes.length === 0, ); let tokenCosts = null; if (values["tokenizer-python"]) { temporary ??= await PrivateRuntimeRoot.create({ prefix: "rea-native-handoff-verifier-", }); const input = join(temporary.path, "token-input.json"); await writeFile( input, serialize({ catalog, selected, preparation, queries: [first, ...structuredQueries], }), ); const result = await ownedCommand(values["tokenizer-python"], [ "-c", `import json,sys,tiktoken with open(sys.argv[1],encoding='utf-8') as f:d=json.load(f) enc=tiktoken.get_encoding('cl100k_base') def n(v):return len(enc.encode(json.dumps(v,ensure_ascii=False,separators=(',',':')),disallowed_special=())) requests=n(d['preparation']['request'])+sum(n(q['request']) for q in d['queries']) structured=n(d['preparation']['response'])+sum(n(q['response']) for q in d['queries']) full_reply=n(d['preparation']['wire_response'])+sum(n(q['wire_response']) for q in d['queries']) s=n(d['selected']);a=n(d['catalog']) print(json.dumps(dict(tokenizer='cl100k_base',tiktoken_version=tiktoken.__version__,selected_catalog=s,full_catalog=a,requests=requests,structured_replies=structured,full_tool_replies=full_reply,selected_catalog_structured_task=s+requests+structured,full_catalog_structured_task=a+requests+structured,selected_catalog_full_reply_task=s+requests+full_reply,full_catalog_full_reply_task=a+requests+full_reply)))`, input, ]); tokenCosts = JSON.parse(result.stdout.text); } report = { scope: "Real shipped-ASAR native identity through public CLI/stdio MCP; simulated native Evidence only, no provider/application executed", artifact: { path: values.artifact, sha256: archiveSha256 }, addon_path: values["addon-path"], companion_sha256_observed: companionSha256, prior_native_sha256_supplied: values["native-sha256"], source_paths: values["source-path"] ?? null, preparation_outcome: timedOut ? "provider_timeout" : "completed", analysis_timeout_ms: analysisTimeoutMs ?? null, parent_evidence_id: sourceId, trace_evidence_id: first.response.evidence_id, trace_subject: first.response.subject, preparation_ms: preparationMs, samples, safe_identity: safeIdentity, safe_applicability: safeApplicability, native_analysis_scopes: nativeScopes, structured_scopes: structuredScopes, structured_expectations: structuredExpectations, modeled_structured_trace_count: structuredQueries.length, node: { node_id: addon.node_id, identity: addon.identity, unavailable_observed: unavailable, basis: addon.observations.map(({ evidence }) => ({ authority: evidence.authority, state: evidence.state, confidence: evidence.confidence, artifact: evidence.artifact, location: evidence.location, })), }, native_handoffs: trace.native_handoffs, evidence_links: trace.evidence_links, source_coverage: trace.coverage, graph_coverage: trace.graph.coverage, facts_sha256: digest({ node: addon, native_handoffs: trace.native_handoffs, evidence_links: trace.evidence_links, coverage: trace.coverage, }), cli_parity: cliParity, token_costs: tokenCosts, conditions: "Fresh MCP session, selected analysis followed by retained traces. Task token counts include one analysis summary or parsed timeout error, one native trace and each requested structured-path trace, with name/description/inputSchema catalog projections. Structured Evidence/parsed error and complete-tool-reply projections are alternatives, not billing. Repeated native rounds, export, CLI parity and tokenizer are validation overhead outside task tokens but inside total resource receipts. Filesystem/build caches uncontrolled. Incorrect identity/applicability is not a successful equivalent task or efficiency credit.", }; if (values["require-safe"]) { assert.ok(safeIdentity, "Native identity/linkage oracle failed"); assert.ok(safeApplicability, "File analysis applicability oracle failed"); } } catch (cause) { primaryError = cause; throw cause; } finally { await closeVerifierResources( [ () => client.close(), () => transport.close(), async () => { if (retainTemporary) throw new Error( `Command cleanup incomplete; retaining owned inputs at ${temporary?.path}.`, ); await temporary?.close(); }, ], primaryError, ); } console.log(serialize(report));