Files
rea/tests/boundary/filesystem/composedWorkflowEvidenceLinks.test.ts
T

393 lines
14 KiB
TypeScript

import { executeComposedWorkflow } from "../../../src/application/WorkflowEvidence.js";
import { parseAnalysisSnapshot } from "../../../src/domain/analysisSnapshot.js";
import { ok } from "../../../src/domain/result.js";
import { createDeferred } from "../../fixtures/binarySession.js";
import { expect, it } from "vitest";
import { runDirectAnalysis } from "../../../src/application/DirectAnalysis.js";
import { createEvidence, parseEvidence } from "../../../src/domain/evidence.js";
import { composedWorkflowFixture } from "../../fixtures/composedWorkflowEvidence.js";
import { readFile, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { createEvidenceBundle } from "../../../src/domain/evidenceBundle.js";
it.each([0, 1, 12])(
"does not replay an arbitrary historical workflow provenance when the snapshot binding is ambiguous (%i procedures)",
async (procedureCount) => {
const original = await composedWorkflowFixture();
original.summary.procedure_count = procedureCount;
const target = await original.open();
const snapshotPath = join(dirname(original.path), "analysis.json");
const current = parseEvidence(
await runDirectAnalysis(
original.dependencies,
original.path,
"binary_overview",
{},
{ snapshotPath },
),
);
expect(current.evidence_links).toHaveLength(1);
const snapshot = parseAnalysisSnapshot(
JSON.parse(await readFile(snapshotPath, "utf8")),
);
const uniqueReplay = await composedWorkflowFixture();
expect(uniqueReplay.session.importAnalysisSnapshot(snapshot).ok).toBe(true);
expect(uniqueReplay.session.importAnalysisSnapshot(snapshot)).toEqual(
ok(0),
);
const unique = parseEvidence(
await runDirectAnalysis(
uniqueReplay.dependencies,
original.path,
"binary_overview",
{},
{ snapshotPath },
),
);
expect(unique.evidence_id).toBe(current.evidence_id);
expect(unique.evidence_links).toEqual(current.evidence_links);
expect(uniqueReplay.calls).toEqual([]);
// Earlier composed observations did not carry links. Both are authentic,
// but the serialized replay binding does not identify which provenance won.
const historical = createEvidence(target, current.provider, {
operation: current.operation,
parameters: current.parameters,
result: current.normalized_result,
rawResult: current.raw_result,
analysisProfile: current.analysis_profile!,
confidence: "derived",
limitations: current.limitations,
});
expect(historical.evidence_links).toEqual([]);
expect(historical.evidence_id).not.toBe(current.evidence_id);
const ambiguous = parseAnalysisSnapshot({
...snapshot,
evidence_bundle: createEvidenceBundle([
...snapshot.evidence_bundle.records,
historical,
]),
});
expect(ambiguous.workflow_entries).toEqual(snapshot.workflow_entries);
await writeFile(snapshotPath, JSON.stringify(ambiguous));
const replay = await composedWorkflowFixture();
const delivered = parseEvidence(
await runDirectAnalysis(
replay.dependencies,
original.path,
"binary_overview",
{},
{ snapshotPath },
),
);
expect(delivered.normalized_result).toEqual(current.normalized_result);
expect([current.evidence_id, historical.evidence_id]).not.toContain(
delivered.evidence_id,
);
expect(delivered.evidence_links).toEqual(current.evidence_links);
expect(
delivered.limitations.some((limitation) =>
limitation.includes("this call did not re-run the provider"),
),
).toBe(true);
expect(replay.calls).toEqual([]);
const refreshedReplay = await composedWorkflowFixture();
const refreshed = parseEvidence(
await runDirectAnalysis(
refreshedReplay.dependencies,
original.path,
"binary_overview",
{},
{ snapshotPath },
),
);
expect(refreshed.evidence_id).toBe(delivered.evidence_id);
expect(refreshed.evidence_links).toEqual(delivered.evidence_links);
expect(refreshedReplay.calls).toEqual([]);
},
);
it.each([false, true])(
"links a profiled binary overview only to the atomic record it consumed (cached=%s)",
async (warmCache) => {
const fixture = await composedWorkflowFixture();
const { path, summary, calls, session } = fixture;
const createSession = async () => {
const opened = await session.open(path);
if (!opened.ok) throw opened.error;
const unrelated = await session.execute("address_name", {
document: "fixture",
address: "0x2000",
});
if (!unrelated.ok) throw unrelated.error;
if (warmCache) {
const warmed = await session.execute(
"read_binary_inventory_summary",
{},
);
if (!warmed.ok) throw warmed.error;
}
return session;
};
const dependencies = {
...fixture.dependencies,
createBinarySession: createSession,
};
try {
const evidence = parseEvidence(
await runDirectAnalysis(dependencies, path, "binary_overview", {}),
);
expect(evidence.normalized_result).toEqual(summary);
expect(evidence.confidence).toBe("derived");
const records = fixture.closedRecords();
const atomic = records.filter(
(record) => record.operation === "read_binary_inventory_summary",
);
const unrelated = records.filter(
(record) => record.operation === "address_name",
);
expect(atomic).toHaveLength(1);
expect(unrelated).toHaveLength(1);
expect(atomic[0]?.normalized_result).toEqual(summary);
expect(
calls.filter(
(operation) => operation === "read_binary_inventory_summary",
),
).toHaveLength(1);
// These are real, already committed ledger IDs, not hashes fabricated by
// the workflow and not a before/after scan used to infer consumption.
expect(evidence.evidence_links).toEqual(
atomic.map((record) => record.evidence_id),
);
expect(evidence.evidence_links).not.toContain(unrelated[0]?.evidence_id);
} finally {
expect((await session.close()).ok).toBe(true);
}
},
);
it("deduplicates repeated and nested consumed records without linking unrelated concurrent work", async () => {
const entered = createDeferred<void>();
const release = createDeferred<void>();
const fixture = await composedWorkflowFixture({
beforeSummary: async () => {
entered.resolve();
await release.promise;
},
});
await fixture.open();
const overview = executeComposedWorkflow(
fixture.session,
async (observed) => {
const first = await observed.execute("read_binary_inventory_summary", {});
if (!first.ok) return first;
const nested = await executeComposedWorkflow(observed, async (inner) => {
const repeated = await inner.execute(
"read_binary_inventory_summary",
{},
);
return repeated.ok ? ok(repeated.value.result) : repeated;
});
return nested.ok ? ok(nested.value.result) : nested;
},
);
await entered.promise;
try {
const other = await executeComposedWorkflow(
fixture.session,
async (observed) => {
const execution = await observed.execute("address_name", {
address: "0x2000",
document: "fixture",
});
return execution.ok ? ok(execution.value.result) : execution;
},
);
if (!other.ok) throw other.error;
release.resolve();
const result = await overview;
if (!result.ok) throw result.error;
const atomic = fixture.session
.exportEvidenceBundle()
.records.find(
(record) => record.operation === "read_binary_inventory_summary",
);
const unrelated = fixture.session
.exportEvidenceBundle()
.records.find((record) => record.operation === "address_name");
expect(atomic).toBeDefined();
expect(unrelated).toBeDefined();
expect(result.value.evidenceLinks).toEqual([atomic?.evidence_id]);
expect(other.value.evidenceLinks).toEqual([unrelated?.evidence_id]);
expect(
fixture.calls.filter(
(operation) => operation === "read_binary_inventory_summary",
),
).toHaveLength(1);
} finally {
release.resolve();
await overview;
}
});
it("rehydrates the original atomic identity from an authenticated snapshot without rerunning the provider", async () => {
const original = await composedWorkflowFixture();
await original.open();
const executed = await original.session.execute(
"read_binary_inventory_summary",
{},
);
if (!executed.ok) throw executed.error;
const exported = original.session.exportAnalysisSnapshot();
if (!exported.ok) throw exported.error;
const snapshot = parseAnalysisSnapshot(
JSON.parse(JSON.stringify(exported.value)),
);
const atomic = snapshot.evidence_bundle.records.find(
(record) => record.operation === "read_binary_inventory_summary",
);
expect(executed.value.evidenceId).toBe(atomic?.evidence_id);
const replay = await composedWorkflowFixture();
expect(replay.session.importAnalysisSnapshot(snapshot).ok).toBe(true);
await replay.open();
const composed = await executeComposedWorkflow(
replay.session,
async (observed) => {
const execution = await observed.execute(
"read_binary_inventory_summary",
{},
);
if (!execution.ok) return execution;
expect(execution.value.limitations).toContain(
"Loaded from a local REA analysis snapshot; this call did not re-run the provider.",
);
return ok(execution.value.result);
},
);
if (!composed.ok) throw composed.error;
expect(composed.value.evidenceLinks).toEqual([atomic?.evidence_id]);
expect(replay.calls).not.toContain("read_binary_inventory_summary");
expect(
replay.session.evidenceById(atomic!.evidence_id)?.normalized_result,
).toEqual(original.summary);
});
it.each(["profileless", "uncacheable"] as const)(
"does not trust provider-supplied Evidence IDs on %s executions",
async (mode) => {
const spoofedEvidenceId = `ev_${"f".repeat(64)}`;
const fixture = await composedWorkflowFixture({
profiled: mode !== "profileless",
live: mode === "uncacheable",
spoofedEvidenceId,
});
await fixture.open();
const composed = await executeComposedWorkflow(
fixture.session,
async (observed) => {
const execution = await observed.execute(
"read_binary_inventory_summary",
{},
);
if (!execution.ok) return execution;
expect(execution.value.evidenceId).toBeUndefined();
return ok(execution.value.result);
},
);
if (!composed.ok) throw composed.error;
expect(composed.value.evidenceLinks).toBeUndefined();
expect(fixture.session.exportEvidenceBundle().records).toEqual([]);
},
);
it("does not manufacture links for empty or failed composed calls", async () => {
const fixture = await composedWorkflowFixture();
await fixture.open();
const empty = await executeComposedWorkflow(fixture.session, async () =>
ok(null),
);
expect(empty).toEqual(ok({ result: null, limitations: [] }));
const failed = await executeComposedWorkflow(
fixture.session,
async (observed) => {
const result = await observed.execute("list_strings", {});
return result.ok ? ok(result.value.result) : result;
},
);
expect(failed.ok).toBe(false);
expect(fixture.session.exportEvidenceBundle().records).toEqual([]);
});
it("drops an old cached ID rather than guessing after an ambiguous snapshot replacement", async () => {
const fixture = await composedWorkflowFixture();
const target = await fixture.open();
const initial = await fixture.session.execute(
"read_binary_inventory_summary",
{},
);
if (!initial.ok) throw initial.error;
const snapshot = fixture.session.exportAnalysisSnapshot();
if (!snapshot.ok) throw snapshot.error;
const unrelated = await fixture.session.execute("address_name", {
address: "0x2000",
document: "fixture",
});
if (!unrelated.ok || unrelated.value.evidenceId === undefined)
throw new Error("Expected recorded dependency");
const alternative = createEvidence(target, fixture.profile.provider, {
operation: "read_binary_inventory_summary",
parameters: {},
result: fixture.summary,
analysisProfile: fixture.profile,
evidenceLinks: [unrelated.value.evidenceId],
});
expect(fixture.session.recordEvidence(alternative).ok).toBe(true);
const ambiguous = fixture.session.exportAnalysisSnapshot();
if (!ambiguous.ok) throw ambiguous.error;
const replay = await composedWorkflowFixture();
expect(replay.session.importAnalysisSnapshot(snapshot.value).ok).toBe(true);
await replay.open();
const before = await replay.session.execute(
"read_binary_inventory_summary",
{},
);
if (!before.ok) throw before.error;
expect(before.value.evidenceId).toBe(initial.value.evidenceId);
expect(replay.session.importAnalysisSnapshot(ambiguous.value).ok).toBe(true);
const after = await replay.session.execute(
"read_binary_inventory_summary",
{},
);
if (!after.ok) throw after.error;
expect(after.value.result).toEqual(fixture.summary);
expect(after.value.evidenceId).toBeUndefined();
expect(replay.calls).not.toContain("read_binary_inventory_summary");
});
it("replaces provider-supplied identity with the record actually committed by the session", async () => {
const spoofedEvidenceId = `ev_${"f".repeat(64)}`;
const fixture = await composedWorkflowFixture({ spoofedEvidenceId });
await fixture.open();
const executed = await fixture.session.execute(
"read_binary_inventory_summary",
{},
);
if (!executed.ok) throw executed.error;
const records = fixture.session.exportEvidenceBundle().records;
expect(records).toHaveLength(1);
expect(executed.value.evidenceId).toBe(records[0]?.evidence_id);
expect(executed.value.evidenceId).not.toBe(spoofedEvidenceId);
expect((await fixture.session.close()).ok).toBe(true);
await fixture.open();
const refreshed = await fixture.session.execute(
"read_binary_inventory_summary",
{},
);
if (!refreshed.ok) throw refreshed.error;
expect(
fixture.calls.filter(
(operation) => operation === "read_binary_inventory_summary",
),
).toHaveLength(2);
expect(fixture.session.hasEvidence(refreshed.value.evidenceId!)).toBe(true);
});