refactor(javascript): parse runtime evidence into one verified owner

This commit is contained in:
morluto committed 2026-10-10 03:52:35 +08:00
1 parent 415145d04f
commit 006b295f1d
15 files changed
+839 -512

No files matched your search

@@ -1,14 +1,15 @@
import { resolve } from "node:path";
import { z } from "zod";
import {
AnalysisInputError,
AnalysisProtocolError,
} from "../../domain/analysisErrorCore.js";
import { AnalysisProtocolError } from "../../domain/analysisErrorCore.js";
import { type AnalysisError } from "../../domain/analysisErrorBase.js";
import type { Evidence } from "../../domain/evidence.js";
import { analysisInputErrorFromIssues } from "../../domain/inputIssueProjection.js";
import { reconcileJavaScriptRuntime } from "../../domain/javascript/javascriptRuntimeReconciliation.js";
import {
parseRuntimeReconciliationInput,
reconcileJavaScriptRuntime,
type ParsedRuntimeReconciliationInput,
} from "../../domain/javascript/javascriptRuntimeReconciliation.js";
import { reconcileJavaScriptRuntimeInputSchema } from "../../domain/javascript/javascriptRuntimeReconciliationSchemas.js";
import { err, ok, type Result } from "../../domain/result.js";
import { createJavaScriptRuntimeReconciliationEvidence } from "./JavaScriptRuntimeReconciliationEvidence.js";
@@ -31,26 +32,30 @@ export const reconcileJavaScriptRuntimeEvidence = (
export const reconcileJavaScriptRuntimeEvidenceValidated = (
parsedInput: z.output<typeof reconcileJavaScriptRuntimeInputSchema>,
): Result<Evidence, AnalysisError> => {
let parsed: ParsedRuntimeReconciliationInput;
try {
const input = reconcileJavaScriptRuntimeInputSchema.parse(
parsed = parseRuntimeReconciliationInput(
normalizeRuntimeMappingRoots(parsedInput),
);
const result = reconcileJavaScriptRuntime(input);
return ok(createJavaScriptRuntimeReconciliationEvidence(input, result));
} catch (cause: unknown) {
if (cause instanceof z.ZodError)
return err(
analysisInputErrorFromIssues(OPERATION, cause.issues, parsedInput),
);
if (
cause instanceof TypeError &&
SAFE_RECONCILIATION_INPUT_CONSTRAINTS.has(cause.message)
)
return err(
new AnalysisInputError(OPERATION, undefined, [
{ path: [], reason: "invalid_value", message: cause.message },
]),
);
return err(
new AnalysisProtocolError(
"JavaScript runtime reconciliation input parsing failed",
{ cause },
),
);
}
try {
const result = reconcileJavaScriptRuntime(parsed);
return ok(
createJavaScriptRuntimeReconciliationEvidence(parsed.input, result),
);
} catch (cause: unknown) {
return err(
new AnalysisProtocolError(
"JavaScript runtime reconciliation produced an invalid result",
@@ -83,23 +88,3 @@ const isPortableAbsolutePath = (path: string): boolean =>
path.startsWith("/") ||
/^[a-z]:[\\/]/iu.test(path) ||
/^(?:\\\\|\/\/)[^\\/]+[\\/][^\\/]+(?:[\\/]|$)/u.test(path);
const SAFE_RECONCILIATION_INPUT_CONSTRAINTS = new Set([
"JavaScript application Evidence subject disagrees with its result",
"Runtime reconciliation requires inspect_web_page, inspect_electron_page, observe_javascript_runtime, or capture_electron_scenario Evidence",
"Runtime Evidence target or declared role disagrees with its result",
"Runtime Evidence contains an invalid builtin location",
"Runtime Evidence target disagrees with its captured result",
"Browser Evidence target is outside its recorded origin scope",
"Runtime Evidence contains source without source-capture selection",
"Active Electron Evidence application path disagrees with its configured root",
...[
"inspect_web_page",
"inspect_electron_page",
"observe_javascript_runtime",
"capture_electron_scenario",
].map(
(operation) =>
`Evidence does not match the supported ${operation} contract`,
),
]);
@@ -1,13 +1,21 @@
import { createEvidence } from "../../domain/evidence.js";
import { reconcileJavaScriptRuntime } from "../../domain/javascript/javascriptRuntimeReconciliation.js";
import {
parseRuntimeReconciliationInput,
reconcileJavaScriptRuntime,
} from "../../domain/javascript/javascriptRuntimeReconciliation.js";
import {
JAVASCRIPT_APPLICATION_EVIDENCE_EXAMPLE,
JAVASCRIPT_RUNTIME_RECONCILIATION_EXAMPLE,
} from "./javascriptRuntimeReconciliationExample.js";
import { createHistoricalSourceGraph } from "../../domain/referenceSourceGraph.js";
import { reconcileJavaScriptRuntimeInputSchema } from "../../domain/javascript/javascriptRuntimeReconciliationSchemas.js";
const reconciliation = reconcileJavaScriptRuntime(
JAVASCRIPT_RUNTIME_RECONCILIATION_EXAMPLE,
parseRuntimeReconciliationInput(
reconcileJavaScriptRuntimeInputSchema.parse(
JAVASCRIPT_RUNTIME_RECONCILIATION_EXAMPLE,
),
),
);
const reconciliationEvidence = createEvidence(
undefined,
@@ -2,22 +2,42 @@ import { classifyStaticLoadStates } from "./javascriptRuntimeLoadState.js";
import { buildReconciledApplicationGraph } from "./javascriptRuntimeReconciliationGraph.js";
import { reconcileRuntimeEntities } from "./javascriptRuntimeReconciliationMatching.js";
import {
parseRuntimeCaptures,
parseStaticLayers,
type ParsedStaticLayer,
} from "./javascriptRuntimeReconciliationParsing.js";
import {
parseRuntimeCaptures,
type ParsedRuntimeCapture,
} from "./javascriptRuntimeReconciliationCaptureParsing.js";
import { createJavaScriptRuntimeReconciliationResult } from "./javascriptRuntimeReconciliationResult.js";
import type { JavaScriptRuntimeReconciliationResult } from "./javascriptRuntimeReconciliationSchemas.js";
import { reconcileJavaScriptRuntimeInputSchema } from "./javascriptRuntimeReconciliationSchemas.js";
import type { ReconcileJavaScriptRuntimeInput } from "./javascriptRuntimeReconciliationSchemas.js";
import { projectRuntimeCaptures } from "./javascriptRuntimeReconciliationRuntime.js";
import { collectStaticRuntimeCandidates } from "./javascriptRuntimeStaticCandidates.js";
/** Verified caller input and the static and runtime facts parsed from it. */
export interface ParsedRuntimeReconciliationInput {
readonly input: ReconcileJavaScriptRuntimeInput;
readonly layers: readonly ParsedStaticLayer[];
readonly captures: readonly ParsedRuntimeCapture[];
}
/** Parse caller Evidence once into the owner consumed by reconciliation. */
export const parseRuntimeReconciliationInput = (
input: ReconcileJavaScriptRuntimeInput,
): ParsedRuntimeReconciliationInput => ({
input,
layers: parseStaticLayers(input.static_layers, ["static_layers"]),
captures: parseRuntimeCaptures(input.runtime_observations, [
"runtime_observations",
]),
});
/** Reconcile static JAG layers with authorized passive CDP Evidence. */
export const reconcileJavaScriptRuntime = (
input: unknown,
parsed: ParsedRuntimeReconciliationInput,
): JavaScriptRuntimeReconciliationResult => {
const parsed = reconcileJavaScriptRuntimeInputSchema.parse(input);
const layers = parseStaticLayers(parsed.static_layers);
const captures = parseRuntimeCaptures(parsed.runtime_observations);
const { layers, captures } = parsed;
const runtime = projectRuntimeCaptures(captures);
const candidates = collectStaticRuntimeCandidates(layers);
const matching = reconcileRuntimeEntities({
@@ -3,6 +3,10 @@ import { isAbsolute } from "node:path";
import { digestCanonicalValue } from "../canonicalDigest.js";
import { isPathWithinRoot } from "../localPath.js";
import { z } from "zod";
import {
invalidInput,
parseAtPath,
} from "./javascriptRuntimeReconciliationInputValidation.js";
import {
classifyBrowserCompleteness,
@@ -13,23 +17,30 @@ import {
type ElectronActiveObservationResult,
} from "./electronActiveObservation.js";
import type { Evidence } from "../evidence.js";
import type { ParsedRuntimeCapture } from "./javascriptRuntimeReconciliationParsing.js";
import type { ParsedRuntimeCapture } from "./javascriptRuntimeReconciliationCaptureParsing.js";
/** Parse active Electron Evidence as a bounded, target-only runtime capture. */
export const parseActiveElectronCapture = (
evidence: Evidence,
): ParsedRuntimeCapture => {
assertIdentity(evidence);
const result = electronActiveObservationResultSchema.parse(
const result = parseAtPath(
(value) => electronActiveObservationResultSchema.parse(value),
evidence.normalized_result,
["normalized_result"],
);
const parameters = parseAtPath(
(value) =>
z
.object({
application_path: absolutePathSchema,
application_root: absolutePathSchema,
})
.passthrough()
.parse(value),
evidence.parameters,
["parameters"],
);
const parameters = z
.object({
application_path: absolutePathSchema,
application_root: absolutePathSchema,
})
.passthrough()
.parse(evidence.parameters);
if (
result.application.application_path !== parameters.application_path ||
!isPathWithinRoot(
@@ -37,7 +48,8 @@ export const parseActiveElectronCapture = (
result.application.application_path,
)
)
throw new TypeError(
throw invalidInput(
["normalized_result", "application", "application_path"],
"Active Electron Evidence application path disagrees with its configured root",
);
return {
@@ -62,11 +74,11 @@ const assertIdentity = (evidence: Evidence): void => {
evidence.authority !== "controlled-replay" ||
evidence.confidence !== "observed"
)
throw new TypeError(
throw invalidInput(
[],
"Evidence does not match the supported capture_electron_scenario contract",
);
};
const normalizeInspection = (
result: ElectronActiveObservationResult,
): {
@@ -0,0 +1,481 @@
import { z } from "zod";
import {
browserAllowedOriginsSchema,
browserEndpointSchema,
} from "../browserObservation.js";
import {
webPageInspectionSchema,
type WebPageInspection,
} from "../browserObservationSchemas.js";
import {
classifyBrowserCompleteness,
type BrowserCompleteness,
} from "../browserCompleteness.js";
import {
electronPageInspectionSchema,
type ElectronPageInspection,
} from "./electronObservation.js";
import {
javascriptRuntimeObservationSchema,
javascriptRuntimeKindSchema,
type JavaScriptRuntimeObservation,
type JavaScriptRuntimeTargetLocation,
} from "./javascriptRuntimeObservation.js";
import { digestCanonicalValue } from "../canonicalDigest.js";
import { compareUnicodeCodePoints } from "../unicodeCodePointOrder.js";
import { parseEvidence, type Evidence } from "../evidence.js";
import { parseActiveElectronCapture } from "./javascriptRuntimeReconciliationActive.js";
import {
assertEvidenceIdentity,
invalidInput,
parseAtPath,
} from "./javascriptRuntimeReconciliationInputValidation.js";
interface RuntimeCaptureBase {
readonly evidence: Evidence;
readonly captureSha256: string;
readonly scriptsCompleteWithinScope: boolean;
}
interface NormalizedV8Inspection {
readonly target:
| {
readonly target_id: string;
readonly type: string;
readonly title: string;
readonly attached: boolean;
readonly file_path: string;
}
| {
readonly target_id: string;
readonly type: string;
readonly title: string;
readonly attached: boolean;
readonly url: string;
}
| {
readonly target_id: string;
readonly type: string;
readonly title: string;
readonly attached: boolean;
readonly unresolved_location: Extract<
JavaScriptRuntimeObservation["target"]["location"],
{ kind: "unresolved" }
>;
};
readonly frames: readonly [];
readonly scripts: {
readonly items: readonly (Readonly<{
script_key: string;
frame_id: string | null;
cdp_hash: string | null;
length: number | null;
is_module: boolean | null;
language: null;
source: { readonly included: false; readonly reason: string };
}> &
(
| { readonly file_path: string }
| { readonly url: string }
| {
readonly unresolved_location: Extract<
JavaScriptRuntimeObservation["scripts"]["items"][number]["location"],
{ kind: "unresolved" }
>;
}
))[];
};
readonly workers: readonly [];
readonly completeness: BrowserCompleteness;
}
export type ParsedRuntimeCapture =
| (RuntimeCaptureBase & {
readonly kind: "browser";
readonly inspection: WebPageInspection;
})
| (RuntimeCaptureBase & {
readonly kind: "electron";
readonly inspection: ElectronPageInspection;
})
| (RuntimeCaptureBase & {
readonly kind: "v8-inspector";
readonly inspection: NormalizedV8Inspection;
})
| (RuntimeCaptureBase & {
readonly kind: "electron-active";
readonly inspection: {
readonly target: {
readonly target_id: string;
readonly type: string;
readonly title: string;
readonly attached: boolean;
readonly file_path: string;
};
readonly frames: readonly [];
readonly scripts: { readonly items: readonly [] };
readonly workers: readonly [];
readonly completeness: BrowserCompleteness;
};
});
/** Parse only supported passive web/Electron inspection Evidence. */
export const parseRuntimeCaptures = (
observations: readonly Evidence[],
path: readonly (string | number)[] = ["runtime_observations"],
): ParsedRuntimeCapture[] =>
observations
.map((observation, index) =>
parseRuntimeCapture(observation, [...path, index]),
)
.sort((left, right) =>
compareUnicodeCodePoints(
left.evidence.evidence_id,
right.evidence.evidence_id,
),
);
const parseRuntimeCapture = (
input: Evidence,
evidencePath: readonly (string | number)[],
): ParsedRuntimeCapture => {
const evidence = parseAtPath(parseEvidence, input, evidencePath);
if (evidence.operation === "inspect_web_page")
return parseBrowserCapture(evidence, evidencePath);
if (evidence.operation === "inspect_electron_page")
return parseElectronCapture(evidence, evidencePath);
if (evidence.operation === "observe_javascript_runtime")
return parseV8Capture(evidence, evidencePath);
if (evidence.operation === "capture_electron_scenario") {
return parseAtPath(
() => parseActiveElectronCapture(evidence),
evidence,
evidencePath,
);
}
throw invalidInput(
evidencePath,
"Runtime reconciliation requires inspect_web_page, inspect_electron_page, observe_javascript_runtime, or capture_electron_scenario Evidence",
);
};
const parseBrowserCapture = (
evidence: Evidence,
path: readonly (string | number)[],
): ParsedRuntimeCapture => {
assertEvidenceIdentity(
evidence,
{
operation: "inspect_web_page",
predicate: "rea.web-page-inspection",
providerId: "rea-cdp-browser",
providerName: "REA Chrome DevTools Protocol observation provider",
providerVersion: "2",
authority: "external-service",
confidence: "observed",
},
path,
);
const inspection = parseAtPath(
(value) => webPageInspectionSchema.parse(value),
evidence.normalized_result,
[...path, "normalized_result"],
);
assertRuntimeParameters(
evidence,
{
kind: "browser",
targetId: inspection.target.target_id,
targetOrigin: inspection.target.origin,
sourceIncluded: inspection.scripts.items.some(
({ source }) => source.included,
),
},
path,
);
return {
kind: "browser",
evidence,
inspection,
captureSha256: digestCanonicalValue(inspection, "Runtime reconciliation"),
scriptsCompleteWithinScope: scriptsComplete(inspection.completeness),
};
};
const parseElectronCapture = (
evidence: Evidence,
path: readonly (string | number)[],
): ParsedRuntimeCapture => {
assertEvidenceIdentity(
evidence,
{
operation: "inspect_electron_page",
predicate: "rea.electron-page-inspection",
providerId: "rea-cdp-electron",
providerName: "REA Electron file-page CDP observation provider",
providerVersion: "1",
authority: "external-service",
confidence: "observed",
},
path,
);
const inspection = parseAtPath(
(value) => electronPageInspectionSchema.parse(value),
evidence.normalized_result,
[...path, "normalized_result"],
);
assertRuntimeParameters(
evidence,
{
kind: "electron",
targetId: inspection.target.target_id,
sourceIncluded: inspection.scripts.items.some(
({ source }) => source.included,
),
},
path,
);
return {
kind: "electron",
evidence,
inspection,
captureSha256: digestCanonicalValue(inspection, "Runtime reconciliation"),
scriptsCompleteWithinScope: scriptsComplete(inspection.completeness),
};
};
const parseV8Capture = (
evidence: Evidence,
path: readonly (string | number)[],
): ParsedRuntimeCapture => {
assertEvidenceIdentity(
evidence,
{
operation: "observe_javascript_runtime",
predicate: "rea.javascript-runtime-observation",
providerId: "rea-v8-inspector",
providerName: "REA passive Node/Electron V8 Inspector provider",
providerVersion: "1",
authority: "external-service",
confidence: "observed",
},
path,
);
const result = parseAtPath(
(value) => javascriptRuntimeObservationSchema.parse(value),
evidence.normalized_result,
[...path, "normalized_result"],
);
assertV8RuntimeParameters(evidence, result, path);
return {
kind: "v8-inspector",
evidence,
inspection: normalizeV8Inspection(result),
captureSha256: digestCanonicalValue(result, "Runtime reconciliation"),
scriptsCompleteWithinScope: false,
};
};
const assertV8RuntimeParameters = (
evidence: Evidence,
result: JavaScriptRuntimeObservation,
path: readonly (string | number)[],
): void => {
const parameters = parseAtPath(
(value) =>
z
.object({
inspector_endpoint: browserEndpointSchema,
target_id: z.string().trim().min(1),
runtime_kind: javascriptRuntimeKindSchema.optional(),
})
.passthrough()
.parse(value),
evidence.parameters,
[...path, "parameters"],
);
if (
parameters.target_id !== result.target.target_id ||
(parameters.runtime_kind !== undefined &&
parameters.runtime_kind !== result.target.runtime_kind)
)
throw invalidInput(
[...path, "parameters", "target_id"],
"Runtime Evidence target or declared role disagrees with its result",
);
if (
result.target.location.kind === "builtin" &&
!result.target.location.specifier.startsWith("node:")
)
throw invalidInput(
[...path, "normalized_result", "target", "location"],
"Runtime Evidence contains an invalid builtin location",
);
for (const [index, { location }] of result.scripts.items.entries())
if (location.kind === "builtin" && !location.specifier.startsWith("node:"))
throw invalidInput(
[...path, "normalized_result", "scripts", "items", index, "location"],
"Runtime Evidence contains an invalid builtin location",
);
};
const normalizeV8Inspection = (
result: JavaScriptRuntimeObservation,
): NormalizedV8Inspection => ({
target: {
target_id: result.target.target_id,
type: result.target.protocol_type,
title: result.target.runtime_kind,
attached: result.target.attached,
...(result.target.location.kind === "unresolved"
? { unresolved_location: result.target.location }
: runtimeLocation(result.target.location)),
},
frames: [],
scripts: {
items: result.scripts.items.map((script) => ({
script_key: script.script_key,
frame_id: script.execution_context_key,
...runtimeLocation(script.location),
cdp_hash: script.cdp_hash,
length: script.length,
is_module: script.is_module,
language: null,
source: {
included: false,
reason: "V8 Inspector source capture is outside passive authority.",
},
})),
},
workers: [],
completeness: classifyBrowserCompleteness({
policyFilteredSections: new Set(
excludedV8Scripts(result) > 0 ? ["scripts"] : [],
),
attachLimitedSections: new Set([
"frames",
"scripts",
"script_sources",
"workers",
]),
truncatedSections: new Set(result.capture.truncated ? ["scripts"] : []),
unavailableSections: new Set(["frames", "script_sources", "workers"]),
excluded:
excludedV8Scripts(result) === 0
? []
: [
{
section: "scripts",
reason: "out_of_target_scope",
count: excludedV8Scripts(result),
},
],
droppedEvents: {
scripts: result.capture.events_dropped,
network_requests: 0,
console_events: 0,
websocket_connections: 0,
websocket_frames: 0,
webmcp_tools: 0,
timeline_events: 0,
},
}),
});
const runtimeLocation = (
location: JavaScriptRuntimeTargetLocation,
):
| { readonly file_path: string }
| { readonly url: string }
| {
readonly unresolved_location: Extract<
JavaScriptRuntimeTargetLocation,
{ kind: "unresolved" }
>;
} => {
if (location.kind === "unresolved") return { unresolved_location: location };
if (location.kind === "file") return { file_path: location.file_path };
if (location.kind === "url") return { url: location.sanitized_url };
return { url: location.specifier };
};
const excludedV8Scripts = (result: JavaScriptRuntimeObservation): number =>
Object.values(result.scripts.excluded).reduce(
(total, count) => total + count,
0,
);
const assertRuntimeParameters = (
evidence: Evidence,
expected:
| {
readonly kind: "browser";
readonly targetId: string;
readonly targetOrigin: string;
readonly sourceIncluded: boolean;
}
| {
readonly kind: "electron";
readonly targetId: string;
readonly sourceIncluded: boolean;
},
path: readonly (string | number)[],
): void => {
const common = {
target_id: z.string().trim().min(1),
cdp_endpoint: browserEndpointSchema,
include_script_sources: z.boolean(),
};
if (expected.kind === "browser") {
const parameters = parseAtPath(
(value) =>
z
.object({ ...common, allowed_origins: browserAllowedOriginsSchema })
.passthrough()
.parse(value),
evidence.parameters,
[...path, "parameters"],
);
if (parameters.target_id !== expected.targetId)
throw invalidInput(
[...path, "parameters", "target_id"],
"Runtime Evidence target disagrees with its captured result",
);
if (!parameters.allowed_origins.includes(expected.targetOrigin))
throw invalidInput(
[...path, "parameters", "allowed_origins"],
"Browser Evidence target is outside its recorded origin scope",
);
if (expected.sourceIncluded && !parameters.include_script_sources)
throw invalidInput(
[...path, "parameters", "include_script_sources"],
"Runtime Evidence contains source without source-capture selection",
);
return;
}
const parameters = parseAtPath(
(value) => z.object(common).passthrough().parse(value),
evidence.parameters,
[...path, "parameters"],
);
if (parameters.target_id !== expected.targetId)
throw invalidInput(
[...path, "parameters", "target_id"],
"Runtime Evidence target disagrees with its captured result",
);
if (expected.sourceIncluded && !parameters.include_script_sources)
throw invalidInput(
[...path, "parameters", "include_script_sources"],
"Runtime Evidence contains source without source-capture selection",
);
};
const scriptsComplete = (completeness: {
readonly truncated_sections: readonly string[];
readonly unavailable_sections: readonly string[];
readonly dropped_events: { readonly scripts: number };
}): boolean =>
!completeness.truncated_sections.includes("scripts") &&
!completeness.unavailable_sections.includes("scripts") &&
completeness.dropped_events.scripts === 0;
@@ -7,10 +7,8 @@ import type {
ApplicationEdge,
ApplicationNode,
} from "./javascriptApplicationGraphSchemas.js";
import type {
ParsedRuntimeCapture,
ParsedStaticLayer,
} from "./javascriptRuntimeReconciliationParsing.js";
import type { ParsedStaticLayer } from "./javascriptRuntimeReconciliationParsing.js";
import type { ParsedRuntimeCapture } from "./javascriptRuntimeReconciliationCaptureParsing.js";
import { uniqueSorted } from "../canonicalOrdering.js";
import { compareUnicodeCodePoints } from "../unicodeCodePointOrder.js";
import type { RuntimeProjection } from "./javascriptRuntimeReconciliationRuntime.js";
@@ -0,0 +1,57 @@
import { z } from "zod";
import type { Evidence } from "../evidence.js";
/** Prefix caller paths on a nested Zod validation boundary. */
export const parseAtPath = <Value>(
parse: (input: unknown) => Value,
input: unknown,
path: readonly (string | number)[],
): Value => {
try {
return parse(input);
} catch (cause: unknown) {
if (cause instanceof z.ZodError)
throw new z.ZodError(
cause.issues.map((issue) => ({
...issue,
path: [...path, ...issue.path],
})),
);
throw cause;
}
};
/** Represent one semantic caller constraint as a standard validation issue. */
export const invalidInput = (
path: readonly (string | number)[],
message: string,
): z.ZodError => new z.ZodError([{ code: "custom", path: [...path], message }]);
/** Verify an authenticated Evidence record against one runtime workflow. */
export const assertEvidenceIdentity = (
evidence: Evidence,
expected: {
readonly operation: string;
readonly predicate: string;
readonly providerId: string;
readonly providerName: string;
readonly providerVersion: string;
readonly authority: Evidence["authority"];
readonly confidence: Evidence["confidence"];
},
path: readonly (string | number)[],
): void => {
if (
evidence.operation !== expected.operation ||
evidence.predicate_type !== expected.predicate ||
evidence.provider.id !== expected.providerId ||
evidence.provider.name !== expected.providerName ||
evidence.provider.version !== expected.providerVersion ||
evidence.authority !== expected.authority ||
evidence.confidence !== expected.confidence
)
throw invalidInput(
path,
`Evidence does not match the supported ${expected.operation} contract`,
);
};
@@ -1,27 +1,3 @@
import { z } from "zod";
import {
browserAllowedOriginsSchema,
browserEndpointSchema,
} from "../browserObservation.js";
import {
webPageInspectionSchema,
type WebPageInspection,
} from "../browserObservationSchemas.js";
import {
classifyBrowserCompleteness,
type BrowserCompleteness,
} from "../browserCompleteness.js";
import {
electronPageInspectionSchema,
type ElectronPageInspection,
} from "./electronObservation.js";
import {
javascriptRuntimeObservationSchema,
javascriptRuntimeKindSchema,
type JavaScriptRuntimeObservation,
type JavaScriptRuntimeTargetLocation,
} from "./javascriptRuntimeObservation.js";
import { digestCanonicalValue } from "../canonicalDigest.js";
import { compareUnicodeCodePoints } from "../unicodeCodePointOrder.js";
import { parseEvidence, type Evidence } from "../evidence.js";
@@ -29,9 +5,13 @@ import {
javascriptApplicationAnalysisResultSchema,
type JavaScriptApplicationAnalysisResult,
} from "./javascriptApplicationAnalysis.js";
import { type JavaScriptApplicationGraph } from "./javascriptApplicationGraph.js";
import { parseActiveElectronCapture } from "./javascriptRuntimeReconciliationActive.js";
import type { JavaScriptApplicationGraph } from "./javascriptApplicationGraph.js";
import type { ReconcileJavaScriptRuntimeInput } from "./javascriptRuntimeReconciliationSchemas.js";
import {
assertEvidenceIdentity,
invalidInput,
parseAtPath,
} from "./javascriptRuntimeReconciliationInputValidation.js";
type StaticLayerInput =
ReconcileJavaScriptRuntimeInput["static_layers"][number];
@@ -46,138 +26,50 @@ export interface ParsedStaticLayer {
readonly runtimeMappings: readonly RuntimeMapping[];
}
interface RuntimeCaptureBase {
readonly evidence: Evidence;
readonly captureSha256: string;
readonly scriptsCompleteWithinScope: boolean;
}
interface NormalizedV8Inspection {
readonly target:
| {
readonly target_id: string;
readonly type: string;
readonly title: string;
readonly attached: boolean;
readonly file_path: string;
}
| {
readonly target_id: string;
readonly type: string;
readonly title: string;
readonly attached: boolean;
readonly url: string;
}
| {
readonly target_id: string;
readonly type: string;
readonly title: string;
readonly attached: boolean;
readonly unresolved_location: Extract<
JavaScriptRuntimeObservation["target"]["location"],
{ kind: "unresolved" }
>;
};
readonly frames: readonly [];
readonly scripts: {
readonly items: readonly (Readonly<{
script_key: string;
frame_id: string | null;
cdp_hash: string | null;
length: number | null;
is_module: boolean | null;
language: null;
source: { readonly included: false; readonly reason: string };
}> &
(
| { readonly file_path: string }
| { readonly url: string }
| {
readonly unresolved_location: Extract<
JavaScriptRuntimeObservation["scripts"]["items"][number]["location"],
{ kind: "unresolved" }
>;
}
))[];
};
readonly workers: readonly [];
readonly completeness: BrowserCompleteness;
}
export type ParsedRuntimeCapture =
| (RuntimeCaptureBase & {
readonly kind: "browser";
readonly inspection: WebPageInspection;
})
| (RuntimeCaptureBase & {
readonly kind: "electron";
readonly inspection: ElectronPageInspection;
})
| (RuntimeCaptureBase & {
readonly kind: "v8-inspector";
readonly inspection: NormalizedV8Inspection;
})
| (RuntimeCaptureBase & {
readonly kind: "electron-active";
readonly inspection: {
readonly target: {
readonly target_id: string;
readonly type: string;
readonly title: string;
readonly attached: boolean;
readonly file_path: string;
};
readonly frames: readonly [];
readonly scripts: { readonly items: readonly [] };
readonly workers: readonly [];
readonly completeness: BrowserCompleteness;
};
});
/** Parse and semantically bind every static analysis Evidence layer. */
export const parseStaticLayers = (
layers: readonly StaticLayerInput[],
path: readonly (string | number)[] = ["static_layers"],
): ParsedStaticLayer[] =>
layers
.map((layer) => parseStaticLayer(layer))
.map((layer, index) =>
parseStaticLayer(layer, [...path, index, "analysis"]),
)
.sort((left, right) =>
compareUnicodeCodePoints(left.layerId, right.layerId),
);
/** Parse only supported passive web/Electron inspection Evidence. */
export const parseRuntimeCaptures = (
observations: readonly Evidence[],
): ParsedRuntimeCapture[] =>
observations
.map((observation) => parseRuntimeCapture(observation))
.sort((left, right) =>
compareUnicodeCodePoints(
left.evidence.evidence_id,
right.evidence.evidence_id,
),
);
const parseStaticLayer = (layer: StaticLayerInput): ParsedStaticLayer => {
const evidence = parseEvidence(layer.analysis);
const result = javascriptApplicationAnalysisResultSchema.parse(
const parseStaticLayer = (
layer: StaticLayerInput,
evidencePath: readonly (string | number)[],
): ParsedStaticLayer => {
const evidence = parseAtPath(parseEvidence, layer.analysis, evidencePath);
const result = parseAtPath(
(value) => javascriptApplicationAnalysisResultSchema.parse(value),
evidence.normalized_result,
[...evidencePath, "normalized_result"],
);
assertEvidenceIdentity(
evidence,
{
operation: "analyze_javascript_application",
predicate: "rea.javascript-application-analysis",
providerId: "rea-javascript-application",
providerName: "REA JavaScript application analyzer",
providerVersion: "1",
authority: "shipped-artifact",
confidence: "derived",
},
evidencePath,
);
assertEvidenceIdentity(evidence, {
operation: "analyze_javascript_application",
predicate: "rea.javascript-application-analysis",
providerId: "rea-javascript-application",
providerName: "REA JavaScript application analyzer",
providerVersion: "1",
authority: "shipped-artifact",
confidence: "derived",
});
if (
evidence.subject === null ||
evidence.subject.digest.sha256 !== result.root_artifact_sha256 ||
evidence.subject.format !== result.format ||
evidence.subject.local_path !== result.input_path
)
throw new TypeError(
throw invalidInput(
[...evidencePath, "subject"],
"JavaScript application Evidence subject disagrees with its result",
);
return {
@@ -196,294 +88,3 @@ const parseStaticLayer = (layer: StaticLayerInput): ParsedStaticLayer => {
runtimeMappings: layer.runtime_mappings,
};
};
const parseRuntimeCapture = (input: Evidence): ParsedRuntimeCapture => {
const evidence = parseEvidence(input);
if (evidence.operation === "inspect_web_page") {
assertEvidenceIdentity(evidence, {
operation: "inspect_web_page",
predicate: "rea.web-page-inspection",
providerId: "rea-cdp-browser",
providerName: "REA Chrome DevTools Protocol observation provider",
providerVersion: "2",
authority: "external-service",
confidence: "observed",
});
const inspection = webPageInspectionSchema.parse(
evidence.normalized_result,
);
assertRuntimeParameters(evidence, {
kind: "browser",
targetId: inspection.target.target_id,
targetOrigin: inspection.target.origin,
sourceIncluded: inspection.scripts.items.some(
({ source }) => source.included,
),
});
return {
kind: "browser",
evidence,
inspection,
captureSha256: digestCanonicalValue(inspection, "Runtime reconciliation"),
scriptsCompleteWithinScope: scriptsComplete(inspection.completeness),
};
}
if (evidence.operation === "inspect_electron_page") {
assertEvidenceIdentity(evidence, {
operation: "inspect_electron_page",
predicate: "rea.electron-page-inspection",
providerId: "rea-cdp-electron",
providerName: "REA Electron file-page CDP observation provider",
providerVersion: "1",
authority: "external-service",
confidence: "observed",
});
const inspection = electronPageInspectionSchema.parse(
evidence.normalized_result,
);
assertRuntimeParameters(evidence, {
kind: "electron",
targetId: inspection.target.target_id,
sourceIncluded: inspection.scripts.items.some(
({ source }) => source.included,
),
});
return {
kind: "electron",
evidence,
inspection,
captureSha256: digestCanonicalValue(inspection, "Runtime reconciliation"),
scriptsCompleteWithinScope: scriptsComplete(inspection.completeness),
};
}
if (evidence.operation === "observe_javascript_runtime") {
assertEvidenceIdentity(evidence, {
operation: "observe_javascript_runtime",
predicate: "rea.javascript-runtime-observation",
providerId: "rea-v8-inspector",
providerName: "REA passive Node/Electron V8 Inspector provider",
providerVersion: "1",
authority: "external-service",
confidence: "observed",
});
const result = javascriptRuntimeObservationSchema.parse(
evidence.normalized_result,
);
assertV8RuntimeParameters(evidence, result);
const inspection = normalizeV8Inspection(result);
return {
kind: "v8-inspector",
evidence,
inspection,
captureSha256: digestCanonicalValue(result, "Runtime reconciliation"),
scriptsCompleteWithinScope: false,
};
}
if (evidence.operation === "capture_electron_scenario") {
return parseActiveElectronCapture(evidence);
}
throw new TypeError(
"Runtime reconciliation requires inspect_web_page, inspect_electron_page, observe_javascript_runtime, or capture_electron_scenario Evidence",
);
};
const assertV8RuntimeParameters = (
evidence: Evidence,
result: JavaScriptRuntimeObservation,
): void => {
const parameters = z
.object({
inspector_endpoint: browserEndpointSchema,
target_id: z.string().trim().min(1),
runtime_kind: javascriptRuntimeKindSchema.optional(),
})
.passthrough()
.parse(evidence.parameters);
if (
parameters.target_id !== result.target.target_id ||
(parameters.runtime_kind !== undefined &&
parameters.runtime_kind !== result.target.runtime_kind)
)
throw new TypeError(
"Runtime Evidence target or declared role disagrees with its result",
);
for (const location of [
result.target.location,
...result.scripts.items.map(({ location }) => location),
])
if (location.kind === "builtin" && !location.specifier.startsWith("node:"))
throw new TypeError(
"Runtime Evidence contains an invalid builtin location",
);
};
const normalizeV8Inspection = (
result: JavaScriptRuntimeObservation,
): NormalizedV8Inspection => ({
target: {
target_id: result.target.target_id,
type: result.target.protocol_type,
title: result.target.runtime_kind,
attached: result.target.attached,
...(result.target.location.kind === "unresolved"
? { unresolved_location: result.target.location }
: runtimeLocation(result.target.location)),
},
frames: [],
scripts: {
items: result.scripts.items.map((script) => ({
script_key: script.script_key,
frame_id: script.execution_context_key,
...runtimeLocation(script.location),
cdp_hash: script.cdp_hash,
length: script.length,
is_module: script.is_module,
language: null,
source: {
included: false,
reason: "V8 Inspector source capture is outside passive authority.",
},
})),
},
workers: [],
completeness: classifyBrowserCompleteness({
policyFilteredSections: new Set(
excludedV8Scripts(result) > 0 ? ["scripts"] : [],
),
attachLimitedSections: new Set([
"frames",
"scripts",
"script_sources",
"workers",
]),
truncatedSections: new Set(result.capture.truncated ? ["scripts"] : []),
unavailableSections: new Set(["frames", "script_sources", "workers"]),
excluded:
excludedV8Scripts(result) === 0
? []
: [
{
section: "scripts",
reason: "out_of_target_scope",
count: excludedV8Scripts(result),
},
],
droppedEvents: {
scripts: result.capture.events_dropped,
network_requests: 0,
console_events: 0,
websocket_connections: 0,
websocket_frames: 0,
webmcp_tools: 0,
timeline_events: 0,
},
}),
});
const runtimeLocation = (
location: JavaScriptRuntimeTargetLocation,
):
| { readonly file_path: string }
| { readonly url: string }
| {
readonly unresolved_location: Extract<
JavaScriptRuntimeTargetLocation,
{ kind: "unresolved" }
>;
} => {
if (location.kind === "unresolved") return { unresolved_location: location };
if (location.kind === "file") return { file_path: location.file_path };
if (location.kind === "url") return { url: location.sanitized_url };
return { url: location.specifier };
};
const excludedV8Scripts = (result: JavaScriptRuntimeObservation): number =>
Object.values(result.scripts.excluded).reduce(
(total, count) => total + count,
0,
);
const assertRuntimeParameters = (
evidence: Evidence,
expected:
| {
readonly kind: "browser";
readonly targetId: string;
readonly targetOrigin: string;
readonly sourceIncluded: boolean;
}
| {
readonly kind: "electron";
readonly targetId: string;
readonly sourceIncluded: boolean;
},
): void => {
const common = {
target_id: z.string().trim().min(1),
cdp_endpoint: browserEndpointSchema,
include_script_sources: z.boolean(),
};
if (expected.kind === "browser") {
const parameters = z
.object({ ...common, allowed_origins: browserAllowedOriginsSchema })
.passthrough()
.parse(evidence.parameters);
if (parameters.target_id !== expected.targetId)
throw new TypeError(
"Runtime Evidence target disagrees with its captured result",
);
if (!parameters.allowed_origins.includes(expected.targetOrigin))
throw new TypeError(
"Browser Evidence target is outside its recorded origin scope",
);
if (expected.sourceIncluded && !parameters.include_script_sources)
throw new TypeError(
"Runtime Evidence contains source without source-capture selection",
);
return;
}
const parameters = z.object(common).passthrough().parse(evidence.parameters);
if (parameters.target_id !== expected.targetId)
throw new TypeError(
"Runtime Evidence target disagrees with its captured result",
);
if (expected.sourceIncluded && !parameters.include_script_sources)
throw new TypeError(
"Runtime Evidence contains source without source-capture selection",
);
};
const scriptsComplete = (completeness: {
readonly truncated_sections: readonly string[];
readonly unavailable_sections: readonly string[];
readonly dropped_events: { readonly scripts: number };
}): boolean =>
!completeness.truncated_sections.includes("scripts") &&
!completeness.unavailable_sections.includes("scripts") &&
completeness.dropped_events.scripts === 0;
const assertEvidenceIdentity = (
evidence: Evidence,
expected: {
readonly operation: string;
readonly predicate: string;
readonly providerId: string;
readonly providerName: string;
readonly providerVersion: string;
readonly authority: Evidence["authority"];
readonly confidence: Evidence["confidence"];
},
): void => {
if (
evidence.operation !== expected.operation ||
evidence.predicate_type !== expected.predicate ||
evidence.provider.id !== expected.providerId ||
evidence.provider.name !== expected.providerName ||
evidence.provider.version !== expected.providerVersion ||
evidence.authority !== expected.authority ||
evidence.confidence !== expected.confidence
)
throw new TypeError(
`Evidence does not match the supported ${expected.operation} contract`,
);
};
@@ -3,10 +3,8 @@ import { digestCanonicalValue } from "../canonicalDigest.js";
import { uniqueSorted } from "../canonicalOrdering.js";
import type { StaticLoadStateProjection } from "./javascriptRuntimeLoadState.js";
import type { RuntimeMatchingProjection } from "./javascriptRuntimeReconciliationMatching.js";
import type {
ParsedRuntimeCapture,
ParsedStaticLayer,
} from "./javascriptRuntimeReconciliationParsing.js";
import type { ParsedStaticLayer } from "./javascriptRuntimeReconciliationParsing.js";
import type { ParsedRuntimeCapture } from "./javascriptRuntimeReconciliationCaptureParsing.js";
import {
javascriptRuntimeReconciliationResultSchema,
type JavaScriptRuntimeReconciliationResult,
@@ -8,7 +8,7 @@ import type {
ApplicationNode,
} from "./javascriptApplicationGraphSchemas.js";
import type { ApplicationGraphEvidence } from "./javascriptApplicationEvidenceSchemas.js";
import type { ParsedRuntimeCapture } from "./javascriptRuntimeReconciliationParsing.js";
import type { ParsedRuntimeCapture } from "./javascriptRuntimeReconciliationCaptureParsing.js";
export interface RuntimeReconciliationEntity {
readonly kind: "target" | "frame" | "script" | "worker";
@@ -12,7 +12,7 @@ import { publishWebScripts } from "../../../src/browser/assets/PublishWebScripts
import { selectScriptCapture } from "../../../src/browser/assets/ScriptCaptureAdapters.js";
import { inspectWebPageInputSchema } from "../../../src/domain/browserObservation.js";
import { inspectElectronPageInputSchema } from "../../../src/domain/javascript/electronObservation.js";
import { parseRuntimeCaptures } from "../../../src/domain/javascript/javascriptRuntimeReconciliationParsing.js";
import { parseRuntimeCaptures } from "../../../src/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.js";
import { projectRuntimeCaptures } from "../../../src/domain/javascript/javascriptRuntimeReconciliationRuntime.js";
import { V8InspectorProvider } from "../../../src/inspector/V8InspectorProvider.js";
import { startFakeCdpBrowser } from "../../fixtures/fakeCdpBrowser.js";
@@ -5,11 +5,13 @@ import { pathToFileURL } from "node:url";
import { describe, expect, test } from "vitest";
import { createJavaScriptRuntimeObservationEvidence } from "../../../src/application/javascript/JavaScriptRuntimeObservationEvidence.js";
import { createBrowserEvidence } from "../../../src/application/BrowserEvidence.js";
import {
listJavaScriptRuntimeTargets,
observeJavaScriptRuntime,
} from "../../../src/application/javascript/JavaScriptRuntimeObservationService.js";
import { reconcileJavaScriptRuntimeEvidence } from "../../../src/application/javascript/JavaScriptRuntimeReconciliationService.js";
import { CdpBrowserProvider } from "../../../src/browser/CdpBrowserProvider.js";
import { V8_INSPECTOR_PROVIDER_IDENTITY } from "../../../src/inspector/providerIdentity.js";
import { V8InspectorProvider } from "../../../src/inspector/V8InspectorProvider.js";
import { JAVASCRIPT_RUNTIME_RECONCILIATION_EXAMPLE } from "../../../src/contracts/javascript/javascriptRuntimeReconciliationExample.js";
@@ -18,10 +20,102 @@ import type {
ObserveJavaScriptRuntimeInput,
} from "../../../src/domain/javascript/javascriptRuntimeObservation.js";
import { observeJavaScriptRuntimeInputSchema } from "../../../src/domain/javascript/javascriptRuntimeObservation.js";
import { inspectWebPageInputSchema } from "../../../src/domain/browserObservation.js";
import { createEvidence } from "../../../src/domain/evidence.js";
import { javascriptRuntimeReconciliationResultSchema } from "../../../src/domain/javascript/javascriptRuntimeReconciliationSchemas.js";
import { startFakeV8Inspector } from "../../fixtures/inspector/fakeV8Inspector.js";
import { startFakeCdpBrowser } from "../../fixtures/fakeCdpBrowser.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
test("reports static-layer Evidence digest failure at its caller path", () => {
const layer = JAVASCRIPT_RUNTIME_RECONCILIATION_EXAMPLE.static_layers[0];
if (layer === undefined) throw new Error("Expected a static layer example");
const runtime = createJavaScriptRuntimeObservationEvidence(
"observe_javascript_runtime",
{
inspector_endpoint: "http://127.0.0.1:9229",
target_id: "example-v8-target",
runtime_kind: "electron-main",
observation_ms: 100,
},
runtimeObservation("/tmp/index.html", "/tmp/main.js"),
V8_INSPECTOR_PROVIDER_IDENTITY,
);
const result = reconcileJavaScriptRuntimeEvidence({
static_layers: [
{
...layer,
analysis: { ...layer.analysis, evidence_id: `ev_${"0".repeat(64)}` },
},
],
runtime_observations: [runtime],
});
expect(result).toMatchObject({
ok: false,
error: {
_tag: "AnalysisInputError",
issues: [
{
path: ["static_layers", 0, "analysis", "evidence_id"],
reason: "invalid_value",
message: "Evidence semantic identifier does not match its record",
},
],
},
});
});
test("reports browser origin scope mismatch at the caller parameter path", async () => {
const browser = await startFakeCdpBrowser();
try {
const provider = new CdpBrowserProvider();
const input = inspectWebPageInputSchema.parse({
cdp_endpoint: browser.endpoint,
allowed_origins: [browser.allowedOrigin],
target_id: "allowed-page",
observation_ms: 0,
});
const observed = await provider.inspectPage(input);
if (!observed.ok) throw observed.error;
const evidence = createBrowserEvidence(
"inspect_web_page",
input,
observed.value,
provider.identity(),
);
const invalidEvidence = createEvidence(undefined, evidence.provider, {
predicateType: evidence.predicate_type,
operation: evidence.operation,
parameters: { ...evidence.parameters, allowed_origins: [] },
result: evidence.normalized_result,
confidence: evidence.confidence,
authority: evidence.authority,
environment: evidence.environment,
limitations: evidence.limitations,
});
const result = reconcileJavaScriptRuntimeEvidence({
static_layers: JAVASCRIPT_RUNTIME_RECONCILIATION_EXAMPLE.static_layers,
runtime_observations: [invalidEvidence],
});
expect(result).toMatchObject({
ok: false,
error: {
_tag: "AnalysisInputError",
issues: [
{
path: ["runtime_observations", 0, "parameters", "allowed_origins"],
reason: "invalid_value",
message:
"Browser Evidence target is outside its recorded origin scope",
},
],
},
});
} finally {
await browser.close();
}
});
describe("Inspector execution-context lifecycle metadata", () => {
test.each([
[
@@ -7,10 +7,21 @@ import { expect, test } from "vitest";
import { analyzeJavaScriptApplication } from "../../../src/application/javascript/JavaScriptApplicationService.js";
import { createJavaScriptRuntimeObservationEvidence } from "../../../src/application/javascript/JavaScriptRuntimeObservationEvidence.js";
import { V8InspectorProvider } from "../../../src/inspector/V8InspectorProvider.js";
import { reconcileJavaScriptRuntime } from "../../../src/domain/javascript/javascriptRuntimeReconciliation.js";
import {
parseRuntimeReconciliationInput,
reconcileJavaScriptRuntime,
} from "../../../src/domain/javascript/javascriptRuntimeReconciliation.js";
import { reconcileJavaScriptRuntimeInputSchema } from "../../../src/domain/javascript/javascriptRuntimeReconciliationSchemas.js";
import { startFakeV8Inspector } from "../../fixtures/inspector/fakeV8Inspector.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
const reconcileInput = (input: unknown) =>
reconcileJavaScriptRuntime(
parseRuntimeReconciliationInput(
reconcileJavaScriptRuntimeInputSchema.parse(input),
),
);
test("keeps unresolved target identity unknown while matching verified loaded scripts", async () => {
const root = await createTestTempDirectory("rea-unresolved-runtime-");
const entry = join(root, "entry.js");
@@ -37,7 +48,7 @@ test("keeps unresolved target identity unknown while matching verified loaded sc
observed.value,
provider.identity(),
);
const result = reconcileJavaScriptRuntime({
const result = reconcileInput({
static_layers: [{ role: "application", analysis: analysis.value }],
runtime_observations: [evidence],
});
@@ -9,10 +9,21 @@ import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { createElectronEvidence } from "../../../src/application/javascript/ElectronEvidence.js";
import { analyzeJavaScriptApplication } from "../../../src/application/javascript/JavaScriptApplicationService.js";
import { reconcileJavaScriptRuntime } from "../../../src/domain/javascript/javascriptRuntimeReconciliation.js";
import {
parseRuntimeReconciliationInput,
reconcileJavaScriptRuntime,
} from "../../../src/domain/javascript/javascriptRuntimeReconciliation.js";
import { reconcileJavaScriptRuntimeInputSchema } from "../../../src/domain/javascript/javascriptRuntimeReconciliationSchemas.js";
import { inspectElectronPageInputSchema } from "../../../src/domain/javascript/electronObservation.js";
import { createWebTextArtifact } from "../../../src/domain/webContentArtifact.js";
const reconcileInput = (input: unknown) =>
reconcileJavaScriptRuntime(
parseRuntimeReconciliationInput(
reconcileJavaScriptRuntimeInputSchema.parse(input),
),
);
const SOURCE = `const worker = new Worker("./worker.js");\nexport const observed = worker;\n`;
const execute = promisify(execFile);
@@ -36,7 +47,7 @@ it("keeps byte-identical cross-layer candidates explicitly ambiguous", async ()
writeFile(join(runtime, "app.js"), SOURCE),
writeFile(join(runtime, "index.html"), "<script></script>"),
]);
const result = reconcileJavaScriptRuntime({
const result = reconcileInput({
static_layers: [
{
role: "application",
@@ -82,7 +93,7 @@ it("retains all runtime entities and static load states without projection caps"
}),
];
const result = reconcileJavaScriptRuntime({
const result = reconcileInput({
static_layers: [{ role: "application", analysis: staticEvidence }],
runtime_observations: runtimeObservations,
});
@@ -121,7 +132,7 @@ it("rejects runtime source bytes whose Evidence omits source-capture approval",
});
expect(() =>
reconcileJavaScriptRuntime({
reconcileInput({
static_layers: [{ role: "application", analysis: staticEvidence }],
runtime_observations: [contradictoryRuntime],
}),
@@ -131,7 +142,7 @@ it("rejects runtime source bytes whose Evidence omits source-capture approval",
it("keeps graph omission counts unknown when a runtime section is unavailable", async () => {
const fixture = await applicationFixture();
temporary.push(fixture);
const result = reconcileJavaScriptRuntime({
const result = reconcileInput({
static_layers: [
{ role: "application", analysis: await analyzeFixture(fixture) },
],
@@ -8,20 +8,71 @@ import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { createElectronEvidence } from "../../../src/application/javascript/ElectronEvidence.js";
import { createElectronActiveEvidence } from "../../../src/application/javascript/ElectronActiveEvidence.js";
import { analyzeJavaScriptApplication } from "../../../src/application/javascript/JavaScriptApplicationService.js";
import { reconcileJavaScriptRuntime } from "../../../src/domain/javascript/javascriptRuntimeReconciliation.js";
import { reconcileJavaScriptRuntimeEvidence } from "../../../src/application/javascript/JavaScriptRuntimeReconciliationService.js";
import { createEvidence } from "../../../src/domain/evidence.js";
import {
parseRuntimeReconciliationInput,
reconcileJavaScriptRuntime,
} from "../../../src/domain/javascript/javascriptRuntimeReconciliation.js";
import { reconcileJavaScriptRuntimeInputSchema } from "../../../src/domain/javascript/javascriptRuntimeReconciliationSchemas.js";
import { javascriptRuntimeReconciliationResultSchema } from "../../../src/domain/javascript/javascriptRuntimeReconciliationSchemas.js";
import { electronActiveObservationInputSchema } from "../../../src/domain/javascript/electronActiveObservation.js";
import { inspectElectronPageInputSchema } from "../../../src/domain/javascript/electronObservation.js";
import { createWebTextArtifact } from "../../../src/domain/webContentArtifact.js";
import { createElectronActiveObservationFixtureResult } from "../../../src/domain/javascript/electronActiveObservation.fixture.js";
const reconcileInput = (input: unknown) =>
reconcileJavaScriptRuntime(
parseRuntimeReconciliationInput(
reconcileJavaScriptRuntimeInputSchema.parse(input),
),
);
const SOURCE = `const worker = new Worker("./worker.js");\nexport const observed = worker;\n`;
it("preserves source-capture input paths for runtime Evidence", async () => {
const root = await applicationFixture();
const application = await analyzeFixture(root);
const runtime = electronRuntimeEvidence(root, SOURCE);
const invalidRuntime = createEvidence(undefined, runtime.provider, {
predicateType: runtime.predicate_type,
operation: runtime.operation,
parameters: { ...runtime.parameters, include_script_sources: false },
result: runtime.normalized_result,
confidence: runtime.confidence,
authority: runtime.authority,
});
const result = reconcileJavaScriptRuntimeEvidence({
static_layers: [{ role: "application", analysis: application }],
runtime_observations: [invalidRuntime],
});
expect(result).toMatchObject({
ok: false,
error: {
_tag: "AnalysisInputError",
issues: [
{
path: [
"runtime_observations",
0,
"parameters",
"include_script_sources",
],
reason: "invalid_value",
message:
"Runtime Evidence contains source without source-capture selection",
},
],
},
});
});
it("reconciles runtime scripts inside dot-prefixed child directories", async () => {
const root = await applicationFixture();
await mkdir(join(root, "..cache"));
await writeFile(join(root, "..cache", "app.js"), SOURCE);
const result = reconcileJavaScriptRuntime({
const result = reconcileInput({
static_layers: [
{ role: "application", analysis: await analyzeFixture(root) },
],
@@ -48,7 +99,7 @@ it("matches renderer, frame, script bytes, and worker without claiming execution
const staticEvidence = await analyzeFixture(fixture);
const runtimeEvidence = electronRuntimeEvidence(fixture, SOURCE);
const result = reconcileJavaScriptRuntime({
const result = reconcileInput({
static_layers: [{ role: "application", analysis: staticEvidence }],
runtime_observations: [runtimeEvidence],
});
@@ -143,7 +194,7 @@ it("reports a captured digest disagreement instead of accepting a path match", a
"export const observed = 'different';\n",
);
const result = reconcileJavaScriptRuntime({
const result = reconcileInput({
static_layers: [{ role: "application", analysis: staticEvidence }],
runtime_observations: [runtimeEvidence],
});
@@ -181,7 +232,7 @@ it("reconciles active Electron as a partial target-only runtime capture", async
},
);
const result = reconcileJavaScriptRuntime({
const result = reconcileInput({
static_layers: [{ role: "application", analysis: staticEvidence }],
runtime_observations: [runtimeEvidence],
});
@@ -280,7 +331,7 @@ it("imports an operator-provided cache layer through an explicit file mapping",
includeWorker: false,
});
const result = reconcileJavaScriptRuntime({
const result = reconcileInput({
static_layers: [
{ role: "application", analysis: applicationEvidence },
{