Files
rea/src/application/JavaScriptReplayService.ts
T
morlutoandGitHub b8a9da0c0f refactor(mcp): make analysis states unrepresentable (#468)
* refactor(config): parse capability settings into exact states

* refactor(runtime): encode replay and process outcomes exactly

* refactor: make analysis states unrepresentable

* refactor(mcp): register canonical schemas with SDK

* fix: preserve capability and catalog invariants

* fix(build): remove stale compiled modules

* fix(replay): update real verifier policy dependency

* fix(package): verify the complete MCP catalog

* fix(test): supply complete replay reload policy

* refactor(contracts): centralize output schema lookup

* refactor(mcp): delegate protocol boundaries to SDK

* fix(browser): approve real source capture

* fix(mcp): preserve catalog guidance
2026-08-10 02:28:11 +08:00

524 lines
16 KiB
TypeScript

import { z } from "zod";
import writeFileAtomic from "write-file-atomic";
import {
controlledReplayInputSchema,
replayExecutionResultSchema,
controlledReplayOutputSchema,
replayEvidenceSchema,
type ControlledReplayExecutionInput,
type ControlledReplayInput,
} from "../domain/javascriptReplay.js";
import {
AnalysisCapabilityUnavailableError,
AnalysisCancelledError,
AnalysisInputError,
AnalysisProtocolError,
PermissionRequiredError,
ReplayPlanStaleError,
type AnalysisError,
} from "../domain/errors.js";
import { createEvidence } from "../domain/evidence.js";
import { projectInputIssues } from "../domain/inputIssueProjection.js";
import { jsonValueSchema, type JsonValue } from "../domain/jsonValue.js";
import { err, ok, type Result } from "../domain/result.js";
import type { ExecutionOptions } from "./AnalysisProvider.js";
import type { PermissionAuthority } from "./PermissionAuthority.js";
import { replayPermissionRequest } from "./JavaScriptReplayPermission.js";
import {
digestBytes,
prepareReplayPlan,
type EnabledJavaScriptReplayPolicy,
type JavaScriptReplayHost,
type JavaScriptReplayPolicy,
type JavaScriptReplayRunner,
} from "./JavaScriptReplayPlanning.js";
const OPERATION = "run_controlled_replay" as const;
const isAborted = (signal: AbortSignal | undefined): boolean =>
signal?.aborted === true;
export interface JavaScriptReplayDependencies {
readonly policy: () => JavaScriptReplayPolicy;
readonly host: JavaScriptReplayHost;
readonly runner: JavaScriptReplayRunner;
readonly authority: PermissionAuthority | undefined;
}
/** Plan or execute one content-bound extracted-module replay experiment. */
export const runControlledReplay = async (
dependencies: JavaScriptReplayDependencies,
rawInput: unknown,
options: ExecutionOptions = {},
): Promise<Result<JsonValue, AnalysisError>> => {
const parsed = controlledReplayInputSchema.safeParse(rawInput);
if (!parsed.success)
return err(
new AnalysisInputError(
OPERATION,
{ cause: parsed.error },
projectInputIssues(parsed.error.issues, rawInput),
),
);
return runControlledReplayValidated(dependencies, parsed.data, options);
};
/** Plan or execute replay input already parsed by a trusted adapter. */
export const runControlledReplayValidated = async (
dependencies: JavaScriptReplayDependencies,
input: ControlledReplayInput,
options: ExecutionOptions = {},
): Promise<Result<JsonValue, AnalysisError>> => {
const authorized = await authorizeReplay(
dependencies,
dependencies.policy(),
input,
options.signal,
);
if (!authorized.ok) return authorized;
const prepared = await prepareValidatedReplay(
dependencies,
authorized.value,
input,
options.signal,
);
if (!prepared.ok) return prepared;
if (isAborted(options.signal))
return err(new AnalysisCancelledError(OPERATION));
if (input.mode === "plan")
return ok(
asJson({
phase: "plan",
plan: prepared.value.publicPlan,
source_evidence: [],
evidence: null,
}),
);
if (input.plan_digest !== prepared.value.publicPlan.plan_digest)
return err(
new ReplayPlanStaleError(
input.plan_digest,
prepared.value.publicPlan.plan_digest,
),
);
const exportContext = await authorizeReproducerExport(
dependencies.authority,
input,
prepared.value,
);
if (!exportContext.ok) return exportContext;
const executed = await executeValidatedReplay({
runner: dependencies.runner,
policy: authorized.value,
prepared: prepared.value,
exportContext: exportContext.value,
options,
});
if (!executed.ok) return executed;
try {
return ok(
buildReplayOutput(
prepared.value,
executed.value.executed,
executed.value.sourceEvidence,
),
);
} catch (cause: unknown) {
return err(
new AnalysisProtocolError(
cause instanceof z.ZodError
? "Controlled replay produced an invalid bounded result"
: "Controlled replay could not establish or clean up its sandbox",
{ cause },
),
);
}
};
const authorizeReplay = async (
dependencies: JavaScriptReplayDependencies,
policy: JavaScriptReplayPolicy,
input: ControlledReplayInput,
signal: AbortSignal | undefined,
): Promise<Result<EnabledJavaScriptReplayPolicy, AnalysisError>> => {
if (policy.status === "disabled")
return err(
new AnalysisCapabilityUnavailableError(
"rea-javascript-replay",
OPERATION,
"controlled replay is disabled; configure exact roots and executables before enabling it",
),
);
if (dependencies.authority === undefined)
return err(
new AnalysisCapabilityUnavailableError(
"rea-javascript-replay",
OPERATION,
"JavaScript replay permission policy is not configured",
),
);
if (isAborted(signal)) return err(new AnalysisCancelledError(OPERATION));
const request = replayPermissionRequest(input, policy);
const authorized =
input.mode === "plan"
? await dependencies.authority.explain(request, "read")
: await dependencies.authority.authorize(request, "read");
if (!authorized.ok)
return err(
authorized.error instanceof PermissionRequiredError
? authorized.error
: new AnalysisProtocolError(authorized.error.message, {
cause: authorized.error,
}),
);
return ok(policy);
};
const prepareValidatedReplay = async (
dependencies: JavaScriptReplayDependencies,
policy: EnabledJavaScriptReplayPolicy,
input: ControlledReplayInput,
signal: AbortSignal | undefined,
): Promise<
Result<Awaited<ReturnType<typeof prepareReplayPlan>>, AnalysisError>
> => {
if (isAborted(signal)) return err(new AnalysisCancelledError(OPERATION));
try {
return ok(await prepareReplayPlan(input, policy, dependencies.host));
} catch (cause: unknown) {
return err(
new AnalysisCapabilityUnavailableError(
"rea-javascript-replay",
OPERATION,
cause instanceof Error ? cause.message : "replay planning failed",
),
);
}
};
interface ReproducerExportContext {
readonly path: string;
readonly includeSources: boolean;
}
const authorizeReproducerExport = async (
authority: PermissionAuthority | undefined,
input: ControlledReplayExecutionInput,
prepared: Awaited<ReturnType<typeof prepareReplayPlan>>,
): Promise<Result<ReproducerExportContext | undefined, AnalysisError>> => {
if (input.reproducer_export === undefined) return ok(undefined);
if (authority === undefined)
return err(
new AnalysisCapabilityUnavailableError(
"rea-javascript-replay",
OPERATION,
"JavaScript replay permission policy is not configured",
),
);
const exportAuthorized = await authority.authorize(
{
capability: "evidence_write",
roots: [input.reproducer_export.path],
executables: [],
environment_names: [],
network: "none",
mount: false,
operation_identity: `${OPERATION}:reproducer:${prepared.publicPlan.plan_digest}`,
},
"write",
);
if (!exportAuthorized.ok)
return err(
exportAuthorized.error instanceof PermissionRequiredError
? exportAuthorized.error
: new AnalysisProtocolError(exportAuthorized.error.message, {
cause: exportAuthorized.error,
}),
);
const canonicalExportPath = exportAuthorized.value.request.roots[0];
if (canonicalExportPath !== input.reproducer_export.path)
return err(
new AnalysisInputError(`${OPERATION}:reproducer_export:path`, {
cause: new TypeError(
`Use the canonical reproducer path: ${canonicalExportPath ?? "unavailable"}`,
),
}),
);
return ok({
path: canonicalExportPath,
includeSources: input.reproducer_export.include_sources === true,
});
};
interface ReplayExecutionContext {
readonly runner: JavaScriptReplayRunner;
readonly policy: EnabledJavaScriptReplayPolicy;
readonly prepared: Awaited<ReturnType<typeof prepareReplayPlan>>;
readonly exportContext: ReproducerExportContext | undefined;
readonly options: ExecutionOptions;
}
const executeValidatedReplay = async (
context: ReplayExecutionContext,
): Promise<
Result<
{
readonly executed: z.infer<typeof replayExecutionResultSchema>;
readonly sourceEvidence: ReturnType<typeof createReplayEvidence>[];
},
AnalysisError
>
> => {
const { runner, policy, prepared, exportContext, options } = context;
await options.progress?.report({
phase: OPERATION,
completed: 0,
total: 1,
message: "Admitting approved modules into the isolated replay worker",
});
if (isAborted(options.signal))
return err(new AnalysisCancelledError(OPERATION));
try {
let executed = replayExecutionResultSchema.parse(
await runner.execute(prepared, policy, options.signal),
);
await options.progress?.report({
phase: OPERATION,
completed: 1,
total: 1,
message: "Controlled replay stopped and sandbox cleanup was observed",
terminal: true,
});
if (executed.termination === "cancelled")
return err(new AnalysisCancelledError(OPERATION));
executed = await applyReproducerExport(executed, exportContext, prepared);
const sourceEvidence = buildSourceEvidence(prepared, executed);
return ok({ executed, sourceEvidence });
} catch (cause: unknown) {
return err(
new AnalysisProtocolError(
cause instanceof z.ZodError
? "Controlled replay produced an invalid bounded result"
: "Controlled replay could not establish or clean up its sandbox",
{ cause },
),
);
}
};
const applyReproducerExport = async (
executed: z.infer<typeof replayExecutionResultSchema>,
exportContext: ReproducerExportContext | undefined,
prepared: Awaited<ReturnType<typeof prepareReplayPlan>>,
): Promise<z.infer<typeof replayExecutionResultSchema>> => {
if (exportContext === undefined || executed.cleanup.state !== "complete")
return executed;
const manifest = {
schema_version: 1,
plan: prepared.publicPlan,
result: executed,
sources: exportContext.includeSources
? {
left: prepared.leftSources,
...(prepared.rightSources === undefined
? {}
: { right: prepared.rightSources }),
}
: null,
};
const encoded = Buffer.from(`${JSON.stringify(manifest, null, 2)}\n`);
try {
await writeFileAtomic(exportContext.path, encoded, {
mode: 0o600,
});
return replayExecutionResultSchema.parse({
...executed,
reproducer: {
state: "written",
path: exportContext.path,
sha256: digestBytes(encoded),
},
});
} catch (cause: unknown) {
return replayExecutionResultSchema.parse({
...executed,
limitations: [
...executed.limitations,
"Replay completed, but the separately approved reproducer export failed.",
],
reproducer: {
state: "failed",
path: exportContext.path,
error:
cause instanceof Error
? cause.message
: "unknown reproducer export failure",
},
});
}
};
const buildSourceEvidence = (
prepared: Awaited<ReturnType<typeof prepareReplayPlan>>,
executed: z.infer<typeof replayExecutionResultSchema>,
): ReturnType<typeof createReplayEvidence>[] => {
const leftCount = prepared.publicPlan.cases.length;
return [
createReplayEvidence(
prepared,
executed,
"left",
executed.outcomes.slice(0, leftCount),
),
...(prepared.publicPlan.right === undefined
? []
: [
createReplayEvidence(
prepared,
executed,
"right",
executed.outcomes.slice(leftCount),
),
]),
];
};
const buildReplayOutput = (
prepared: Awaited<ReturnType<typeof prepareReplayPlan>>,
executed: z.infer<typeof replayExecutionResultSchema>,
sourceEvidence: ReturnType<typeof createReplayEvidence>[],
): JsonValue => {
const subject = prepared.publicPlan.left.modules[0];
const evidence = createEvidence(
subject === undefined
? undefined
: {
path: subject.canonical_path,
sha256: subject.sha256,
format: "javascript",
},
{
id: "rea-javascript-replay",
name: "REA isolated JavaScript replay",
version: "1",
},
{
predicateType: "javascript-controlled-replay",
operation: OPERATION,
parameters: {
replay_plan: jsonValueSchema.parse(
JSON.parse(JSON.stringify(prepared.publicPlan)),
),
},
result: jsonValueSchema.parse(JSON.parse(JSON.stringify(executed))),
rawResult: jsonValueSchema.parse(
JSON.parse(
JSON.stringify({
cases: prepared.publicPlan.cases,
outcomes: executed.outcomes,
stderr: executed.stderr,
}),
),
),
confidence: executed.comparison === undefined ? "observed" : "derived",
authority: "controlled-replay",
environment: {
id: prepared.publicPlan.plan_digest,
platform: process.platform,
architecture: process.arch,
isolation: "container",
},
limitations: executed.limitations,
locations: prepared.publicPlan.left.modules.map((module) => ({
kind: "artifact-path" as const,
path: module.canonical_path,
})),
evidenceLinks: sourceEvidence.map(({ evidence_id: id }) => id),
},
);
return asJson({
phase: "execute",
plan: null,
source_evidence: sourceEvidence.map((item) =>
replayEvidenceSchema.parse(item),
),
evidence: replayEvidenceSchema.parse(evidence),
});
};
const createReplayEvidence = (
prepared: Awaited<ReturnType<typeof prepareReplayPlan>>,
executed: z.infer<typeof replayExecutionResultSchema>,
side: "left" | "right",
outcomes: z.infer<typeof replayExecutionResultSchema>["outcomes"],
) => {
const manifest =
side === "left" ? prepared.publicPlan.left : prepared.publicPlan.right;
const subject = manifest?.modules[0];
const result = replayExecutionResultSchema.parse({
...executed,
outcomes,
comparison: undefined,
reproducer: null,
});
return createEvidence(
subject === undefined
? undefined
: {
path: subject.canonical_path,
sha256: subject.sha256,
format: "javascript",
},
{
id: "rea-javascript-replay",
name: "REA isolated JavaScript replay",
version: "1",
},
{
predicateType: "javascript-controlled-replay-observation",
operation: OPERATION,
parameters: {
replay_plan: jsonValueSchema.parse(
JSON.parse(JSON.stringify(prepared.publicPlan)),
),
side,
},
result: jsonValueSchema.parse(JSON.parse(JSON.stringify(result))),
rawResult: jsonValueSchema.parse(
JSON.parse(
JSON.stringify({ cases: prepared.publicPlan.cases, outcomes }),
),
),
confidence: "observed",
authority: "controlled-replay",
environment: {
id: prepared.publicPlan.plan_digest,
platform: process.platform,
architecture: process.arch,
isolation: "container",
},
limitations: executed.limitations,
locations: (manifest?.modules ?? []).map((module) => ({
kind: "artifact-path" as const,
path: module.canonical_path,
})),
},
);
};
const asJson = (value: unknown): JsonValue => {
const serialized: unknown = JSON.parse(
JSON.stringify(controlledReplayOutputSchema.parse(value)),
);
return jsonValueSchema.parse(serialized);
};