Fixes #5148. Add opt-in durable managed member summaries and authenticated paging while preserving complete default output, original Evidence, cleanup ownership and queued cancellation. Verified with bounded real Newtonsoft/Redux/Rust tasks, independent oracles, 556 focused tests and the expanded domain gate; paired token estimates and latency tradeoffs are recorded in experiments/analysis-efficiency/managed-cli.md.
491 lines
17 KiB
TypeScript
491 lines
17 KiB
TypeScript
import { getHeapStatistics } from "node:v8";
|
|
import { Client, InMemoryTransport } from "@modelcontextprotocol/client";
|
|
import { createServer } from "../../src/server/createServer.js";
|
|
import { parseMcpToolError } from "../fixtures/mcpToolError.js";
|
|
import { loadNativeMatchingBundleSources } from "../../src/application/native/NativeMatchingBundleSources.js";
|
|
import { NativeMatchingAdmission } from "../../src/application/native/NativeMatchingAdmission.js";
|
|
import { matchNativeFunctionsInputSchema } from "../../src/contracts/native/functionMatchingContracts.js";
|
|
import { createEvidence } from "../../src/domain/evidence.js";
|
|
import { runProviderAnalysis } from "../../src/application/DirectAnalysis.js";
|
|
import type { DirectAnalysisDependencies } from "../../src/application/DirectAnalysisDependencies.js";
|
|
import { parseConfig } from "../../src/config/parseConfig.js";
|
|
import {
|
|
isImmutableEvidence,
|
|
parseEvidence,
|
|
type Evidence,
|
|
} from "../../src/domain/evidence.js";
|
|
import { ok } from "../../src/domain/result.js";
|
|
import { observed } from "../fixtures/analysisExecution.js";
|
|
import {
|
|
createBinarySessionTargets,
|
|
createTestBinarySession,
|
|
} from "../fixtures/binarySession.js";
|
|
import { readdir, writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { afterEach, expect, it, vi } from "vitest";
|
|
import {
|
|
createImmutableEvidenceBundle,
|
|
parseImmutableEvidenceBundle,
|
|
} from "../../src/domain/evidenceBundle.js";
|
|
import { ArtifactResourceScope } from "../../src/artifacts/ArtifactResourceScope.js";
|
|
import {
|
|
deliverAnalysisEvidence,
|
|
inspectAnalysisViewFromBundle,
|
|
} from "../../src/application/EvidenceBundleCommands.js";
|
|
import { readImmutableEvidenceBundle } from "../../src/application/EvidenceBundleFiles.js";
|
|
import { requireAuthenticationHeadroom } from "../../src/application/JsonAuthenticationHeadroom.js";
|
|
import { SOURCE_TO_BUNDLE_COMPARISON_EXAMPLE } from "../../src/contracts/javascript/javascriptApplicationWorkflowExamples.js";
|
|
import { createTestTempDirectory } from "../fixtures/temporaryDirectory.js";
|
|
import { holdFirstFileRead } from "../support/holdFirstFileRead.js";
|
|
|
|
vi.mock("../../src/application/JsonAuthenticationHeadroom.js", { spy: true });
|
|
vi.mock("node:v8", { spy: true });
|
|
vi.mock("../../src/domain/evidenceBundle.js", { spy: true });
|
|
afterEach(() => vi.restoreAllMocks());
|
|
|
|
it.each(["compare_bundles", "match_native_functions"])(
|
|
"attributes bundle authentication refusal to the actual %s boundary",
|
|
async (operation) => {
|
|
const { path, parent } = await savedParent();
|
|
const actual = await vi.importActual<
|
|
typeof import("../../src/application/JsonAuthenticationHeadroom.js")
|
|
>("../../src/application/JsonAuthenticationHeadroom.js");
|
|
vi.mocked(requireAuthenticationHeadroom).mockImplementation(
|
|
(value, options) =>
|
|
actual.requireAuthenticationHeadroom(value, {
|
|
...options,
|
|
availableBytes: 0,
|
|
}),
|
|
);
|
|
const resources = new ArtifactResourceScope();
|
|
try {
|
|
if (operation === "match_native_functions") {
|
|
const source = {
|
|
kind: "retained-evidence",
|
|
evidence_id: parent.evidence_id,
|
|
};
|
|
await expect(
|
|
loadNativeMatchingBundleSources({
|
|
input: matchNativeFunctionsInputSchema.parse({
|
|
left: source,
|
|
right: source,
|
|
}),
|
|
paths: [path],
|
|
resources,
|
|
admission: new NativeMatchingAdmission(operation),
|
|
}),
|
|
).rejects.toMatchObject({
|
|
_tag: "AnalysisResourceConstraintError",
|
|
operation,
|
|
});
|
|
} else {
|
|
const session = createTestBinarySession(() => {
|
|
throw new Error("Comparison must not open a target");
|
|
});
|
|
const server = createServer({ kind: "session", session });
|
|
const client = new Client({
|
|
name: "bundle-operation-refusal",
|
|
version: "1",
|
|
});
|
|
const [clientTransport, serverTransport] =
|
|
InMemoryTransport.createLinkedPair();
|
|
try {
|
|
await server.connect(serverTransport);
|
|
await client.connect(clientTransport);
|
|
const result = await client.callTool({
|
|
name: operation,
|
|
arguments: { left_bundle_path: path, right_bundle_path: path },
|
|
});
|
|
expect(result.isError).toBe(true);
|
|
expect(parseMcpToolError(result)).toMatchObject({
|
|
error: { code: "resource_constraint", details: { operation } },
|
|
});
|
|
expect(session.exportEvidenceBundle().records).toEqual([]);
|
|
} finally {
|
|
await client.close();
|
|
await server.close();
|
|
await session.close();
|
|
}
|
|
}
|
|
} finally {
|
|
vi.mocked(requireAuthenticationHeadroom).mockImplementation(
|
|
actual.requireAuthenticationHeadroom,
|
|
);
|
|
await resources.close();
|
|
}
|
|
expect(resources.hasPending).toBe(false);
|
|
},
|
|
);
|
|
|
|
const savedParent = async () => {
|
|
const root = await createTestTempDirectory("rea-managed-bundle-guard-");
|
|
const path = join(root, "parent.json");
|
|
const parent = SOURCE_TO_BUNDLE_COMPARISON_EXAMPLE.application;
|
|
await writeFile(
|
|
path,
|
|
JSON.stringify(createImmutableEvidenceBundle([parent])),
|
|
);
|
|
return { path, parent };
|
|
};
|
|
|
|
it("keeps the owning operation when native matching reloads a needed earlier bundle", async () => {
|
|
const root = await createTestTempDirectory("rea-native-bundle-reload-");
|
|
const path = join(root, "parent.json"),
|
|
empty = join(root, "empty.json");
|
|
const parent = createEvidence(
|
|
undefined,
|
|
{ id: "fixture", name: "Fixture", version: "1" },
|
|
{ operation: "list_procedures", parameters: {}, result: {} },
|
|
);
|
|
await writeFile(
|
|
path,
|
|
JSON.stringify(createImmutableEvidenceBundle([parent])),
|
|
);
|
|
await writeFile(empty, JSON.stringify(createImmutableEvidenceBundle([])));
|
|
const actual = await vi.importActual<
|
|
typeof import("../../src/application/JsonAuthenticationHeadroom.js")
|
|
>("../../src/application/JsonAuthenticationHeadroom.js");
|
|
let reads = 0;
|
|
vi.mocked(requireAuthenticationHeadroom).mockImplementation(
|
|
(value, options) =>
|
|
actual.requireAuthenticationHeadroom(
|
|
value,
|
|
++reads === 3 ? { ...options, availableBytes: 0 } : options,
|
|
),
|
|
);
|
|
const resources = new ArtifactResourceScope();
|
|
const source = { kind: "retained-evidence", evidence_id: parent.evidence_id };
|
|
try {
|
|
await expect(
|
|
loadNativeMatchingBundleSources({
|
|
input: matchNativeFunctionsInputSchema.parse({
|
|
left: source,
|
|
right: source,
|
|
}),
|
|
paths: [path, empty],
|
|
resources,
|
|
admission: new NativeMatchingAdmission("match_native_functions"),
|
|
}),
|
|
).rejects.toMatchObject({
|
|
_tag: "AnalysisResourceConstraintError",
|
|
operation: "match_native_functions",
|
|
});
|
|
expect(reads).toBe(3);
|
|
} finally {
|
|
vi.mocked(requireAuthenticationHeadroom).mockImplementation(
|
|
actual.requireAuthenticationHeadroom,
|
|
);
|
|
await resources.close();
|
|
}
|
|
expect(resources.hasPending).toBe(false);
|
|
});
|
|
|
|
it("admits bundle authentication before cloning and hashing retained records", async () => {
|
|
const { path } = await savedParent();
|
|
const actual = await vi.importActual<
|
|
typeof import("../../src/application/JsonAuthenticationHeadroom.js")
|
|
>("../../src/application/JsonAuthenticationHeadroom.js");
|
|
vi.mocked(requireAuthenticationHeadroom).mockImplementationOnce(
|
|
(value, options) =>
|
|
actual.requireAuthenticationHeadroom(value, {
|
|
...options,
|
|
availableBytes: 0,
|
|
}),
|
|
);
|
|
vi.mocked(parseImmutableEvidenceBundle).mockClear();
|
|
const resources = new ArtifactResourceScope();
|
|
try {
|
|
expect(
|
|
await readImmutableEvidenceBundle(path, undefined, resources),
|
|
).toMatchObject({
|
|
ok: false,
|
|
error: { _tag: "AnalysisResourceConstraintError", resource: "memory" },
|
|
});
|
|
expect(parseImmutableEvidenceBundle).not.toHaveBeenCalled();
|
|
} finally {
|
|
await resources.close();
|
|
}
|
|
expect(resources.hasPending).toBe(false);
|
|
});
|
|
|
|
it("preserves the view operation and caller reason when bundle I/O is cancelled", async () => {
|
|
const { path, parent } = await savedParent();
|
|
const held = await holdFirstFileRead(path);
|
|
const controller = new AbortController();
|
|
const reason = new Error("cancel managed bundle page");
|
|
const resources = new ArtifactResourceScope();
|
|
try {
|
|
const pending = inspectAnalysisViewFromBundle(
|
|
{
|
|
source: { kind: "retained-evidence", evidence_id: parent.evidence_id },
|
|
view: { kind: "summary" },
|
|
},
|
|
path,
|
|
resources,
|
|
controller.signal,
|
|
);
|
|
await held.firstRead;
|
|
controller.abort(reason);
|
|
held.release();
|
|
const result = await pending;
|
|
expect(result).toMatchObject({
|
|
ok: false,
|
|
error: {
|
|
_tag: "AnalysisCancelledError",
|
|
operation: "inspect_analysis_view",
|
|
},
|
|
});
|
|
if (result.ok) throw new Error("Expected cancelled bundle read");
|
|
expect(result.error.cause).toBe(reason);
|
|
} finally {
|
|
held.release();
|
|
await resources.close();
|
|
}
|
|
expect(resources.hasPending).toBe(false);
|
|
});
|
|
|
|
it("retains completed parent facts when bundle publication cannot admit authentication", async () => {
|
|
const root = await createTestTempDirectory("rea-managed-delivery-guard-");
|
|
const evidence = SOURCE_TO_BUNDLE_COMPARISON_EXAMPLE.application;
|
|
const actual = await vi.importActual<
|
|
typeof import("../../src/application/JsonAuthenticationHeadroom.js")
|
|
>("../../src/application/JsonAuthenticationHeadroom.js");
|
|
vi.mocked(requireAuthenticationHeadroom).mockImplementationOnce(
|
|
(value, options) =>
|
|
actual.requireAuthenticationHeadroom(value, {
|
|
...options,
|
|
availableBytes: 0,
|
|
}),
|
|
);
|
|
vi.mocked(createImmutableEvidenceBundle).mockClear();
|
|
const result = await deliverAnalysisEvidence(
|
|
evidence,
|
|
join(root, "parent.json"),
|
|
"summary",
|
|
);
|
|
expect(result).toMatchObject({
|
|
ok: false,
|
|
error: { _tag: "AnalysisResourceConstraintError", resource: "memory" },
|
|
});
|
|
if (result.ok) throw new Error("Expected refused bundle authentication");
|
|
expect(result.error.partialObservation).toBe(evidence);
|
|
expect(createImmutableEvidenceBundle).not.toHaveBeenCalled();
|
|
expect(await readdir(root)).toEqual([]);
|
|
});
|
|
|
|
it("projects a rejected managed parent by reference without cloning under low headroom", async () => {
|
|
const root = await createTestTempDirectory(
|
|
"rea-managed-low-heap-projection-",
|
|
);
|
|
const [target] = await createBinarySessionTargets();
|
|
const source = {
|
|
rows: Array.from({ length: 512 }, (_, token) => ({
|
|
token,
|
|
name: "member",
|
|
})),
|
|
};
|
|
let closes = 0;
|
|
const session = () =>
|
|
createTestBinarySession(() => ({
|
|
execute: async () => observed(source),
|
|
close: async () => {
|
|
closes += 1;
|
|
return ok(null);
|
|
},
|
|
}));
|
|
const dependencies: DirectAnalysisDependencies = {
|
|
readConfiguration: () => parseConfig({}),
|
|
createBinarySession: session,
|
|
createNativeDispatchBinarySession: session,
|
|
createArtifactBinarySession: session,
|
|
createNativeBinarySession: session,
|
|
createManagedBinarySession: session,
|
|
};
|
|
const actual = await vi.importActual<
|
|
typeof import("../../src/application/JsonAuthenticationHeadroom.js")
|
|
>("../../src/application/JsonAuthenticationHeadroom.js");
|
|
let parent: Evidence | undefined;
|
|
vi.mocked(requireAuthenticationHeadroom).mockImplementationOnce(
|
|
(value, options) => {
|
|
parent = parseEvidence(value);
|
|
expect(isImmutableEvidence(parent)).toBe(true);
|
|
expect(parent).toBe(value);
|
|
return actual.requireAuthenticationHeadroom(value, {
|
|
...options,
|
|
availableBytes: 0,
|
|
});
|
|
},
|
|
);
|
|
const result = await runProviderAnalysis(
|
|
dependencies,
|
|
target,
|
|
"inspect_managed_members",
|
|
{},
|
|
undefined,
|
|
undefined,
|
|
{
|
|
detail: "summary",
|
|
evidenceBundlePath: join(root, "parent.json"),
|
|
},
|
|
);
|
|
expect(result).toMatchObject({
|
|
code: "resource_constraint",
|
|
details: { operation: "inspect_managed_members" },
|
|
});
|
|
if (typeof result !== "object" || result === null || Array.isArray(result))
|
|
throw new Error("Expected CLI error");
|
|
const details = result.details;
|
|
if (typeof details !== "object" || details === null || Array.isArray(details))
|
|
throw new Error("Expected CLI error details");
|
|
expect(details.partial_observation).toBe(parent);
|
|
expect(parent?.normalized_result).toEqual(source);
|
|
expect(Object.isFrozen(source.rows[0])).toBe(false);
|
|
expect(closes).toBe(1);
|
|
expect(await readdir(root)).toEqual([]);
|
|
});
|
|
|
|
it.each(["JSON assembly", "bundle authentication"])(
|
|
"attributes low-headroom %s to the invoking view",
|
|
async (stage) => {
|
|
const { path, parent } = await savedParent();
|
|
const actualV8 = await vi.importActual<typeof import("node:v8")>("node:v8");
|
|
if (stage === "JSON assembly") {
|
|
vi.mocked(getHeapStatistics).mockReturnValue({
|
|
...getHeapStatistics(),
|
|
total_available_size: 0,
|
|
});
|
|
} else {
|
|
const actual = await vi.importActual<
|
|
typeof import("../../src/application/JsonAuthenticationHeadroom.js")
|
|
>("../../src/application/JsonAuthenticationHeadroom.js");
|
|
vi.mocked(requireAuthenticationHeadroom).mockImplementationOnce(
|
|
(value, options) =>
|
|
actual.requireAuthenticationHeadroom(value, {
|
|
...options,
|
|
availableBytes: 0,
|
|
}),
|
|
);
|
|
}
|
|
const resources = new ArtifactResourceScope();
|
|
try {
|
|
expect(
|
|
await inspectAnalysisViewFromBundle(
|
|
{
|
|
source: {
|
|
kind: "retained-evidence",
|
|
evidence_id: parent.evidence_id,
|
|
},
|
|
view: { kind: "summary" },
|
|
},
|
|
path,
|
|
resources,
|
|
),
|
|
).toMatchObject({
|
|
ok: false,
|
|
error: {
|
|
_tag: "AnalysisResourceConstraintError",
|
|
operation: "inspect_analysis_view",
|
|
},
|
|
});
|
|
} finally {
|
|
vi.mocked(getHeapStatistics).mockImplementation(
|
|
actualV8.getHeapStatistics,
|
|
);
|
|
await resources.close();
|
|
}
|
|
expect(resources.hasPending).toBe(false);
|
|
},
|
|
);
|
|
|
|
it("authenticates escaped payloads without serializing either complete bundle", async () => {
|
|
const root = await createTestTempDirectory("rea-escaped-bundle-");
|
|
const path = join(root, "parent.json");
|
|
const escaped = '\u0000\u0001\\"😀\ud800'.repeat(20000);
|
|
const example = SOURCE_TO_BUNDLE_COMPARISON_EXAMPLE.application;
|
|
const parent = createEvidence(undefined, example.provider, {
|
|
predicateType: example.predicate_type,
|
|
operation: example.operation,
|
|
parameters: example.parameters,
|
|
result: example.normalized_result,
|
|
rawResult: { escaped },
|
|
});
|
|
await writeFile(
|
|
path,
|
|
JSON.stringify(createImmutableEvidenceBundle([parent])),
|
|
);
|
|
const stringify = JSON.stringify;
|
|
const fullDocuments: unknown[] = [];
|
|
vi.spyOn(JSON, "stringify").mockImplementation((value: unknown) => {
|
|
if (
|
|
typeof value === "object" &&
|
|
value !== null &&
|
|
Object.hasOwn(value, "records")
|
|
) {
|
|
fullDocuments.push(value);
|
|
throw new Error(
|
|
"Document-sized JSON allocation forbidden during authentication",
|
|
);
|
|
}
|
|
return stringify(value);
|
|
});
|
|
const resources = new ArtifactResourceScope();
|
|
try {
|
|
const loaded = await readImmutableEvidenceBundle(
|
|
path,
|
|
undefined,
|
|
resources,
|
|
);
|
|
if (!loaded.ok) throw loaded.error;
|
|
expect(loaded.value.records[0]?.evidence_id).toBe(parent.evidence_id);
|
|
expect(loaded.value.records[0]?.raw_result).toEqual({ escaped });
|
|
expect(fullDocuments).toEqual([]);
|
|
} finally {
|
|
await resources.close();
|
|
}
|
|
expect(resources.hasPending).toBe(false);
|
|
});
|
|
|
|
it("seals a fresh object-heavy Evidence tree without retaining a set of completed rows", () => {
|
|
const provider = { id: "fixture", name: "Fixture", version: "1" };
|
|
const row = { seal_probe: true, fields: [1, 2] };
|
|
const result = { rows: Array.from({ length: 512 }, () => row) };
|
|
const observation = {
|
|
operation: "inspect_managed_members",
|
|
parameters: {},
|
|
result,
|
|
};
|
|
const complete = createEvidence(undefined, provider, observation);
|
|
const add = Set.prototype.add;
|
|
const guarded = vi.spyOn(Set.prototype, "add").mockImplementation(function (
|
|
this: Set<unknown>,
|
|
value: unknown,
|
|
) {
|
|
if (
|
|
typeof value === "object" &&
|
|
value !== null &&
|
|
Object.hasOwn(value, "seal_probe") &&
|
|
this.size > 32
|
|
)
|
|
throw new Error(
|
|
"Sealing retained completed rows beyond its ancestry budget",
|
|
);
|
|
return add.call(this, value);
|
|
});
|
|
let sealed;
|
|
try {
|
|
sealed = createEvidence(undefined, provider, observation, {
|
|
immutable: true,
|
|
});
|
|
} finally {
|
|
guarded.mockRestore();
|
|
}
|
|
expect(sealed).toEqual(complete);
|
|
expect(isImmutableEvidence(sealed)).toBe(true);
|
|
const data = sealed.normalized_result as typeof result;
|
|
expect(data.rows[0]).not.toBe(row);
|
|
expect(data.rows[0]).not.toBe(data.rows[1]);
|
|
expect(Object.isFrozen(data.rows[0]!.fields)).toBe(true);
|
|
expect(Object.isFrozen(row)).toBe(false);
|
|
expect(parseEvidence(sealed)).toBe(sealed);
|
|
});
|