rea-agents 1.6.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -66
- package/bridge/ghidra/ReaGhidraBridge.java +2075 -0
- package/bridge/hopper_bridge.py +13 -3
- package/dist/application/AbortablePromise.js +25 -0
- package/dist/application/AnalysisProvider.js +3 -0
- package/dist/application/AnalysisProviderEvaluation.js +60 -0
- package/dist/application/AnalysisProviderRegistry.js +228 -0
- package/dist/application/AnalysisSnapshotCache.js +41 -21
- package/dist/application/AnalysisSnapshotFiles.js +5 -6
- package/dist/application/BinarySession.js +218 -101
- package/dist/application/CapabilityInventory.js +18 -0
- package/dist/application/CompositeProvider.js +20 -8
- package/dist/application/CrossVersionInvestigation.js +10 -6
- package/dist/application/DirectAnalysis.js +49 -35
- package/dist/application/Doctor.js +110 -8
- package/dist/application/ElectronBoundaryAnalysis.js +96 -0
- package/dist/application/ElectronBoundaryGraph.js +9 -0
- package/dist/application/ElectronBoundaryGraphContext.js +62 -0
- package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
- package/dist/application/ElectronBoundaryGraphNative.js +86 -0
- package/dist/application/ElectronBoundaryGraphWindows.js +199 -0
- package/dist/application/EnhancedTools.js +39 -14
- package/dist/application/InvestigationProviders.js +41 -0
- package/dist/application/JavaScriptApplicationEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
- package/dist/application/JavaScriptApplicationService.js +74 -0
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
- package/dist/application/JavaScriptArtifactAnalysis.js +305 -0
- package/dist/application/JavaScriptArtifactAnalysisTypes.js +1 -0
- package/dist/application/JavaScriptArtifactFiles.js +231 -0
- package/dist/application/JavaScriptArtifactGraphAccumulator.js +54 -0
- package/dist/application/JavaScriptArtifactGraphBuilder.js +144 -0
- package/dist/application/JavaScriptArtifactGraphContext.js +205 -0
- package/dist/application/JavaScriptArtifactGraphDocuments.js +108 -0
- package/dist/application/JavaScriptArtifactGraphEvidence.js +99 -0
- package/dist/application/JavaScriptArtifactGraphFindings.js +271 -0
- package/dist/application/JavaScriptArtifactGraphStructure.js +409 -0
- package/dist/application/JavaScriptArtifactReconstruction.js +77 -0
- package/dist/application/JavaScriptArtifactReconstructionInput.js +18 -0
- package/dist/application/JavaScriptReplayPlanning.js +201 -0
- package/dist/application/JavaScriptReplayService.js +266 -0
- package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
- package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
- package/dist/application/MacHopper.js +20 -4
- package/dist/application/ManagedApplicationGraphService.js +55 -0
- package/dist/application/ManagedMemberComparisonService.js +122 -0
- package/dist/application/ManagedNativeVerificationService.js +39 -0
- package/dist/application/ManagedReconstructionService.js +58 -0
- package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
- package/dist/application/PermissionAuthority.js +1 -1
- package/dist/application/ProcessCaptureLifecycle.js +1 -1
- package/dist/application/ProcessHarness.js +1 -1
- package/dist/application/ProcessSampling.js +16 -12
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/SessionProviderRouter.js +219 -0
- package/dist/application/Setup.js +84 -60
- package/dist/application/SetupClients.js +1 -1
- package/dist/application/SetupPlan.js +9 -2
- package/dist/application/SupportedClients.js +40 -16
- package/dist/application/Upgrade.js +1 -1
- package/dist/application/runtime.js +11 -6
- package/dist/artifacts/AsarArtifactReader.js +23 -3
- package/dist/browser/CdpBrowserProvider.js +4 -2
- package/dist/browser/CdpCaptureEvents.js +49 -0
- package/dist/browser/CdpElectronInspection.js +106 -162
- package/dist/browser/CdpElectronProvider.js +9 -3
- package/dist/browser/CdpElectronScriptEvents.js +69 -0
- package/dist/browser/CdpElectronScripts.js +94 -0
- package/dist/browser/CdpElectronWorkers.js +56 -0
- package/dist/browser/CdpEndpoint.js +14 -1
- package/dist/browser/CdpPageCapture.js +8 -4
- package/dist/catalogIdentity.js +6 -42
- package/dist/cli.js +446 -34
- package/dist/cliApplicationCommands.js +62 -0
- package/dist/cliBrowserAdvancedCommands.js +5 -4
- package/dist/cliBrowserCommands.js +5 -4
- package/dist/cliCommandNames.js +56 -0
- package/dist/cliElectronCommands.js +106 -3
- package/dist/cliEvidenceCommands.js +4 -3
- package/dist/cliInvestigationCommands.js +2 -1
- package/dist/cliJsonInput.js +54 -0
- package/dist/cliPolicyCommands.js +2 -1
- package/dist/cliProcessCommands.js +3 -2
- package/dist/config.js +101 -2
- package/dist/contracts/applicationToolContracts.js +91 -0
- package/dist/contracts/artifactToolContracts.js +5 -9
- package/dist/contracts/browserToolContracts.js +14 -62
- package/dist/contracts/electronToolContracts.js +45 -19
- package/dist/contracts/enhancedInputs.js +2 -2
- package/dist/contracts/errorSchemas.js +1 -0
- package/dist/contracts/investigationExamples.js +0 -6
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
- package/dist/contracts/managedToolContracts.js +153 -0
- package/dist/contracts/managedWorkflowExamples.js +346 -0
- package/dist/contracts/managedWorkflowToolContracts.js +203 -0
- package/dist/contracts/nativeToolContracts.js +2 -6
- package/dist/contracts/promptContracts.js +18 -2
- package/dist/contracts/providerSelection.js +28 -0
- package/dist/contracts/sessionLifecycleInputs.js +2 -0
- package/dist/contracts/toolContractExamples.js +10 -25
- package/dist/contracts/toolContracts.js +69 -65
- package/dist/contracts/toolEffects.js +160 -0
- package/dist/contracts/toolOutputSchemas.js +152 -42
- package/dist/doctorRuntime.js +47 -0
- package/dist/domain/analysisProfile.js +78 -0
- package/dist/domain/analysisSnapshot.js +92 -46
- package/dist/domain/artifactComparison.js +3 -4
- package/dist/domain/artifactGraph.js +1 -0
- package/dist/domain/binaryTarget.js +4 -29
- package/dist/domain/browserObservation.js +3 -0
- package/dist/domain/bundleComparison.js +4 -4
- package/dist/domain/electronObservation.js +13 -0
- package/dist/domain/electronStaticAnalysis.js +9 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +194 -0
- package/dist/domain/electronStaticAnalysisIpc.js +171 -0
- package/dist/domain/electronStaticAnalysisNative.js +164 -0
- package/dist/domain/electronStaticAnalysisTypes.js +1 -0
- package/dist/domain/electronStaticAnalysisValues.js +103 -0
- package/dist/domain/errors.js +148 -7
- package/dist/domain/evidence.js +44 -5
- package/dist/domain/evidenceBundle.js +9 -7
- package/dist/domain/functionComparison.js +9 -3
- package/dist/domain/functionComparisonNormalization.js +37 -0
- package/dist/domain/functionComparisonSchemas.js +3 -8
- package/dist/domain/functionDossierEvidence.js +4 -1
- package/dist/domain/hopperValues.js +66 -9
- package/dist/domain/inputIssueProjection.js +52 -0
- package/dist/domain/investigationWorkspace.js +2 -1
- package/dist/domain/javascriptApplicationAnalysis.js +155 -0
- package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +379 -0
- package/dist/domain/javascriptApplicationGraph.js +282 -0
- package/dist/domain/javascriptApplicationGraphSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionItems.js +221 -0
- package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
- package/dist/domain/javascriptAstFingerprint.js +143 -0
- package/dist/domain/javascriptFeatureSeed.js +140 -0
- package/dist/domain/javascriptFeatureTrace.js +232 -0
- package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
- package/dist/domain/javascriptFeatureTraversal.js +88 -0
- package/dist/domain/javascriptNativeHandoff.js +85 -0
- package/dist/domain/javascriptReplay.js +361 -0
- package/dist/domain/javascriptRuntimeLoadState.js +106 -0
- package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
- package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
- package/dist/domain/javascriptRuntimeStaticCandidates.js +191 -0
- package/dist/domain/javascriptStaticAnalysis.js +346 -0
- package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +274 -0
- package/dist/domain/javascriptStaticAnalysisState.js +23 -0
- package/dist/domain/javascriptStaticAnalysisTypes.js +1 -0
- package/dist/domain/managedApplicationGraph.js +556 -0
- package/dist/domain/managedArtifact.js +444 -0
- package/dist/domain/managedMemberComparison.js +565 -0
- package/dist/domain/managedNativeVerification.js +408 -0
- package/dist/domain/managedReconstruction.js +183 -0
- package/dist/domain/managedRuntimeCorrelation.js +175 -0
- package/dist/domain/reconstructionVerificationSchemas.js +1 -3
- package/dist/dotnet/ManagedArtifactInspector.js +318 -0
- package/dist/dotnet/ManagedMemberInspector.js +887 -0
- package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
- package/dist/dotnet/ManagedMetadataInventory.js +368 -0
- package/dist/dotnet/ManagedMetadataLayout.js +322 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +391 -0
- package/dist/dotnet/ManagedPeReader.js +157 -0
- package/dist/dotnet/ManagedReaderFailure.js +10 -0
- package/dist/dotnet/ManagedStaticProvider.js +203 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +37 -0
- package/dist/ghidra/GhidraClient.js +400 -0
- package/dist/ghidra/GhidraClientTypes.js +1 -0
- package/dist/ghidra/GhidraDefaults.js +20 -0
- package/dist/ghidra/GhidraDiagnostics.js +43 -0
- package/dist/ghidra/GhidraDoctor.js +59 -0
- package/dist/ghidra/GhidraFunctionValues.js +264 -0
- package/dist/ghidra/GhidraInstallation.js +239 -0
- package/dist/ghidra/GhidraInventoryValues.js +217 -0
- package/dist/ghidra/GhidraLauncher.js +139 -0
- package/dist/ghidra/GhidraProvider.js +366 -0
- package/dist/ghidra/GhidraRequestQueue.js +98 -0
- package/dist/ghidra/GhidraResponseBuffer.js +31 -0
- package/dist/ghidra/GhidraResponseRouter.js +24 -0
- package/dist/ghidra/GhidraSessionError.js +39 -0
- package/dist/ghidra/GhidraSessionValues.js +62 -0
- package/dist/ghidra/GhidraSocketConnection.js +46 -0
- package/dist/ghidra/protocol.js +69 -0
- package/dist/hopper/BridgeLauncher.js +19 -54
- package/dist/hopper/HopperAnalysisProfile.js +106 -0
- package/dist/hopper/HopperClient.js +154 -162
- package/dist/hopper/HopperProvider.js +99 -7
- package/dist/hopper/HopperSessionValues.js +27 -0
- package/dist/hopper/HopperSocketConnection.js +31 -0
- package/dist/main.js +14 -0
- package/dist/native/NativeMacOSProvider.js +3 -1
- package/dist/process/PendingOperations.js +59 -0
- package/dist/process/PrivateRuntimeRoot.js +33 -0
- package/dist/process/ProviderDeadline.js +95 -0
- package/dist/process/ProviderProcess.js +275 -0
- package/dist/replay/JavaScriptReplayWorker.js +286 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +434 -0
- package/dist/replay/LinuxRuntimeClosure.js +46 -0
- package/dist/replay/LinuxSeccompPolicy.js +40 -0
- package/dist/replay/ReplayWorkerProtocol.js +55 -0
- package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
- package/dist/server/createServer.js +53 -0
- package/dist/server/promptCompletion.js +9 -3
- package/dist/server/registerApplicationTools.js +115 -0
- package/dist/server/registerArtifactComparisonTool.js +16 -9
- package/dist/server/registerBrowserTools.js +33 -8
- package/dist/server/registerBundleComparisonTool.js +17 -20
- package/dist/server/registerElectronTools.js +45 -3
- package/dist/server/registerEnhancedTools.js +67 -19
- package/dist/server/registerEvidenceTools.js +5 -1
- package/dist/server/registerFunctionComparisonTool.js +14 -7
- package/dist/server/registerInvestigationTools.js +21 -17
- package/dist/server/registerManagedTools.js +6 -0
- package/dist/server/registerManagedWorkflowTools.js +277 -0
- package/dist/server/registerOfficialTools.js +11 -8
- package/dist/server/registerProcessComparisonTool.js +25 -47
- package/dist/server/registerSessionStatusTool.js +7 -7
- package/dist/server/registerSessionTools.js +57 -87
- package/dist/server/sessionEvidence.js +14 -19
- package/dist/server/toolInputValidation.js +77 -0
- package/dist/server/toolRegistrationOptions.js +79 -2
- package/dist/server/toolResult.js +25 -17
- package/package.json +17 -7
- package/scripts/rea.mjs +36 -2
- package/skills/rea-analysis/SKILL.md +59 -3
- /package/dist/{application → process}/ProcessOwnership.js +0 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import canonicalize from "canonicalize";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { browserAllowedOriginsSchema, browserEndpointSchema, webPageInspectionSchema, } from "./browserObservation.js";
|
|
5
|
+
import { electronFileRootsSchema, electronPageInspectionSchema, } from "./electronObservation.js";
|
|
6
|
+
import { parseEvidence } from "./evidence.js";
|
|
7
|
+
import { javascriptApplicationAnalysisResultSchema, } from "./javascriptApplicationAnalysis.js";
|
|
8
|
+
import { compareCodePoints, } from "./javascriptApplicationGraph.js";
|
|
9
|
+
/** Parse and semantically bind every static analysis Evidence layer. */
|
|
10
|
+
export const parseStaticLayers = (layers) => layers
|
|
11
|
+
.map((layer) => parseStaticLayer(layer))
|
|
12
|
+
.sort((left, right) => compareCodePoints(left.layerId, right.layerId));
|
|
13
|
+
/** Parse only supported passive web/Electron inspection Evidence. */
|
|
14
|
+
export const parseRuntimeCaptures = (observations) => observations
|
|
15
|
+
.map((observation) => parseRuntimeCapture(observation))
|
|
16
|
+
.sort((left, right) => compareCodePoints(left.evidence.evidence_id, right.evidence.evidence_id));
|
|
17
|
+
export const digestCanonical = (value) => {
|
|
18
|
+
const encoded = canonicalize(value);
|
|
19
|
+
if (encoded === undefined)
|
|
20
|
+
throw new TypeError("Runtime reconciliation could not canonicalize input");
|
|
21
|
+
return createHash("sha256").update(encoded).digest("hex");
|
|
22
|
+
};
|
|
23
|
+
const parseStaticLayer = (layer) => {
|
|
24
|
+
const evidence = parseEvidence(layer.analysis);
|
|
25
|
+
assertEvidenceIdentity(evidence, {
|
|
26
|
+
operation: "analyze_javascript_application",
|
|
27
|
+
predicate: "rea.javascript-application-analysis/v1",
|
|
28
|
+
providerId: "rea-javascript-application",
|
|
29
|
+
providerName: "REA JavaScript application analyzer",
|
|
30
|
+
providerVersion: "1",
|
|
31
|
+
authority: "shipped-artifact",
|
|
32
|
+
confidence: "derived",
|
|
33
|
+
});
|
|
34
|
+
const result = javascriptApplicationAnalysisResultSchema.parse(evidence.normalized_result);
|
|
35
|
+
if (evidence.subject === null ||
|
|
36
|
+
evidence.subject.digest.sha256 !== result.root_artifact_sha256 ||
|
|
37
|
+
evidence.subject.format !== result.format ||
|
|
38
|
+
evidence.subject.local_path !== result.input_path)
|
|
39
|
+
throw new TypeError("JavaScript application Evidence subject disagrees with its result");
|
|
40
|
+
const parameters = z
|
|
41
|
+
.object({
|
|
42
|
+
approved: z.literal(true),
|
|
43
|
+
source_map_read_approved: z.boolean(),
|
|
44
|
+
})
|
|
45
|
+
.passthrough()
|
|
46
|
+
.parse(evidence.parameters);
|
|
47
|
+
return {
|
|
48
|
+
layerId: `jrl_${digestCanonical({
|
|
49
|
+
role: layer.role,
|
|
50
|
+
evidence_id: evidence.evidence_id,
|
|
51
|
+
runtime_mappings: layer.runtime_mappings,
|
|
52
|
+
})}`,
|
|
53
|
+
role: layer.role,
|
|
54
|
+
evidence,
|
|
55
|
+
result,
|
|
56
|
+
graph: result.graph,
|
|
57
|
+
runtimeMappings: layer.runtime_mappings,
|
|
58
|
+
sourceMapReadApproved: parameters.source_map_read_approved,
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
const parseRuntimeCapture = (input) => {
|
|
62
|
+
const evidence = parseEvidence(input);
|
|
63
|
+
if (evidence.operation === "inspect_web_page") {
|
|
64
|
+
assertEvidenceIdentity(evidence, {
|
|
65
|
+
operation: "inspect_web_page",
|
|
66
|
+
predicate: "rea.web-page-inspection/v2",
|
|
67
|
+
providerId: "rea-cdp-browser",
|
|
68
|
+
providerName: "REA Chrome DevTools Protocol observation provider",
|
|
69
|
+
providerVersion: "2",
|
|
70
|
+
authority: "external-service",
|
|
71
|
+
confidence: "observed",
|
|
72
|
+
});
|
|
73
|
+
const inspection = webPageInspectionSchema.parse(evidence.normalized_result);
|
|
74
|
+
assertRuntimeParameters(evidence, {
|
|
75
|
+
kind: "browser",
|
|
76
|
+
targetId: inspection.target.target_id,
|
|
77
|
+
targetOrigin: inspection.target.origin,
|
|
78
|
+
sourceIncluded: inspection.scripts.items.some(({ source }) => source.included),
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
kind: "browser",
|
|
82
|
+
evidence,
|
|
83
|
+
inspection,
|
|
84
|
+
captureSha256: digestCanonical(inspection),
|
|
85
|
+
scriptsCompleteWithinScope: scriptsComplete(inspection.completeness),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (evidence.operation === "inspect_electron_page") {
|
|
89
|
+
assertEvidenceIdentity(evidence, {
|
|
90
|
+
operation: "inspect_electron_page",
|
|
91
|
+
predicate: "rea.electron-page-inspection/v1",
|
|
92
|
+
providerId: "rea-cdp-electron",
|
|
93
|
+
providerName: "REA Electron file-page CDP observation provider",
|
|
94
|
+
providerVersion: "1",
|
|
95
|
+
authority: "external-service",
|
|
96
|
+
confidence: "observed",
|
|
97
|
+
});
|
|
98
|
+
const inspection = electronPageInspectionSchema.parse(evidence.normalized_result);
|
|
99
|
+
assertRuntimeParameters(evidence, {
|
|
100
|
+
kind: "electron",
|
|
101
|
+
targetId: inspection.target.target_id,
|
|
102
|
+
sourceIncluded: inspection.scripts.items.some(({ source }) => source.included),
|
|
103
|
+
});
|
|
104
|
+
return {
|
|
105
|
+
kind: "electron",
|
|
106
|
+
evidence,
|
|
107
|
+
inspection,
|
|
108
|
+
captureSha256: digestCanonical(inspection),
|
|
109
|
+
scriptsCompleteWithinScope: scriptsComplete(inspection.completeness),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
throw new TypeError("Runtime reconciliation requires inspect_web_page or inspect_electron_page Evidence");
|
|
113
|
+
};
|
|
114
|
+
const assertRuntimeParameters = (evidence, expected) => {
|
|
115
|
+
const common = {
|
|
116
|
+
target_id: z.string().trim().min(1).max(256),
|
|
117
|
+
cdp_endpoint: browserEndpointSchema,
|
|
118
|
+
include_script_sources: z.boolean(),
|
|
119
|
+
};
|
|
120
|
+
if (expected.kind === "browser") {
|
|
121
|
+
const parameters = z
|
|
122
|
+
.object({ ...common, allowed_origins: browserAllowedOriginsSchema })
|
|
123
|
+
.passthrough()
|
|
124
|
+
.parse(evidence.parameters);
|
|
125
|
+
if (parameters.target_id !== expected.targetId)
|
|
126
|
+
throw new TypeError("Runtime Evidence target disagrees with its captured result");
|
|
127
|
+
if (!parameters.allowed_origins.includes(expected.targetOrigin))
|
|
128
|
+
throw new TypeError("Browser Evidence target is outside its recorded origin scope");
|
|
129
|
+
if (expected.sourceIncluded && !parameters.include_script_sources)
|
|
130
|
+
throw new TypeError("Runtime Evidence contains source without source-capture approval");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const parameters = z
|
|
134
|
+
.object({
|
|
135
|
+
...common,
|
|
136
|
+
allowed_file_roots: electronFileRootsSchema,
|
|
137
|
+
source_capture_approved: z.boolean(),
|
|
138
|
+
})
|
|
139
|
+
.passthrough()
|
|
140
|
+
.parse(evidence.parameters);
|
|
141
|
+
if (parameters.target_id !== expected.targetId)
|
|
142
|
+
throw new TypeError("Runtime Evidence target disagrees with its captured result");
|
|
143
|
+
if (expected.sourceIncluded &&
|
|
144
|
+
(!parameters.include_script_sources ||
|
|
145
|
+
parameters.source_capture_approved !== true))
|
|
146
|
+
throw new TypeError("Runtime Evidence contains source without source-capture approval");
|
|
147
|
+
};
|
|
148
|
+
const scriptsComplete = (completeness) => !completeness.truncated_sections.includes("scripts") &&
|
|
149
|
+
!completeness.unavailable_sections.includes("scripts") &&
|
|
150
|
+
completeness.dropped_events.scripts === 0;
|
|
151
|
+
const assertEvidenceIdentity = (evidence, expected) => {
|
|
152
|
+
if (evidence.operation !== expected.operation ||
|
|
153
|
+
evidence.predicate_type !== expected.predicate ||
|
|
154
|
+
evidence.provider.id !== expected.providerId ||
|
|
155
|
+
evidence.provider.name !== expected.providerName ||
|
|
156
|
+
evidence.provider.version !== expected.providerVersion ||
|
|
157
|
+
evidence.authority !== expected.authority ||
|
|
158
|
+
evidence.confidence !== expected.confidence)
|
|
159
|
+
throw new TypeError(`Evidence does not match the supported ${expected.operation} contract`);
|
|
160
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { compareCodePoints, } from "./javascriptApplicationGraph.js";
|
|
2
|
+
import { digestCanonical, } from "./javascriptRuntimeReconciliationParsing.js";
|
|
3
|
+
import { javascriptRuntimeReconciliationResultSchema, } from "./javascriptRuntimeReconciliationSchemas.js";
|
|
4
|
+
/** Build and verify the deterministic caller-visible reconciliation result. */
|
|
5
|
+
export const createJavaScriptRuntimeReconciliationResult = (input) => {
|
|
6
|
+
const completion = completionFlags(input);
|
|
7
|
+
const semantic = {
|
|
8
|
+
schema_version: 1,
|
|
9
|
+
static_layers: staticLayerSummaries(input.layers),
|
|
10
|
+
runtime_captures: captureSummaries(input.captures, input.runtime),
|
|
11
|
+
graph: input.graph,
|
|
12
|
+
summary: reconciliationSummary(input),
|
|
13
|
+
reconciliations: input.matching.items,
|
|
14
|
+
static_load_states: input.loadStates.states,
|
|
15
|
+
source_map_authority: sourceMapAuthority(input),
|
|
16
|
+
coverage: reconciliationCoverage(input, completion),
|
|
17
|
+
evidence_links: uniqueSorted([
|
|
18
|
+
...input.layers.map(({ evidence }) => evidence.evidence_id),
|
|
19
|
+
...input.captures.map(({ evidence }) => evidence.evidence_id),
|
|
20
|
+
]),
|
|
21
|
+
limitations: reconciliationLimitations(completion),
|
|
22
|
+
};
|
|
23
|
+
return javascriptRuntimeReconciliationResultSchema.parse({
|
|
24
|
+
reconciliation_id: `jrr_${digestCanonical(semantic)}`,
|
|
25
|
+
...semantic,
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
const staticLayerSummaries = (layers) => layers.map((layer) => ({
|
|
29
|
+
layer_id: layer.layerId,
|
|
30
|
+
role: layer.role,
|
|
31
|
+
evidence_id: layer.evidence.evidence_id,
|
|
32
|
+
graph_id: layer.graph.graph_id,
|
|
33
|
+
root_artifact_sha256: layer.result.root_artifact_sha256,
|
|
34
|
+
input_path: layer.result.input_path,
|
|
35
|
+
format: layer.result.format,
|
|
36
|
+
runtime_mappings: [...layer.runtimeMappings],
|
|
37
|
+
}));
|
|
38
|
+
const captureSummaries = (captures, runtime) => captures.map((capture) => {
|
|
39
|
+
const targetNode = runtime.targetNodeByEvidenceId.get(capture.evidence.evidence_id);
|
|
40
|
+
if (targetNode === undefined)
|
|
41
|
+
throw new TypeError("Runtime projection omitted a required target node");
|
|
42
|
+
return {
|
|
43
|
+
evidence_id: capture.evidence.evidence_id,
|
|
44
|
+
capture_sha256: capture.captureSha256,
|
|
45
|
+
kind: capture.kind,
|
|
46
|
+
target_node_id: targetNode.node_id,
|
|
47
|
+
target_key: capture.inspection.target.target_id,
|
|
48
|
+
target_location: capture.kind === "browser"
|
|
49
|
+
? capture.inspection.target.url.slice(0, 4_096)
|
|
50
|
+
: capture.inspection.target.file_path.slice(0, 4_096),
|
|
51
|
+
frames: capture.inspection.frames.length,
|
|
52
|
+
scripts: capture.inspection.scripts.items.length,
|
|
53
|
+
workers: capture.inspection.workers.length,
|
|
54
|
+
scripts_complete_within_scope: capture.scriptsCompleteWithinScope,
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
const reconciliationSummary = (input) => ({
|
|
58
|
+
runtime_targets: countBy(input.runtime.entities, "kind", "target"),
|
|
59
|
+
runtime_frames: countBy(input.runtime.entities, "kind", "frame"),
|
|
60
|
+
runtime_scripts: countBy(input.runtime.entities, "kind", "script"),
|
|
61
|
+
runtime_workers: countBy(input.runtime.entities, "kind", "worker"),
|
|
62
|
+
matched: countBy(input.matching.items, "status", "matched"),
|
|
63
|
+
ambiguous: countBy(input.matching.items, "status", "ambiguous"),
|
|
64
|
+
unmatched: countBy(input.matching.items, "status", "unmatched"),
|
|
65
|
+
unknown: countBy(input.matching.items, "status", "unknown"),
|
|
66
|
+
static_loaded: countBy(input.loadStates.states, "status", "loaded"),
|
|
67
|
+
static_resident: countBy(input.loadStates.states, "status", "resident-in-loaded-asset"),
|
|
68
|
+
static_not_observed: countBy(input.loadStates.states, "status", "not-observed-in-capture"),
|
|
69
|
+
static_unknown: countBy(input.loadStates.states, "status", "unknown"),
|
|
70
|
+
});
|
|
71
|
+
const sourceMapAuthority = (input) => ({
|
|
72
|
+
used_for_primary_matching: false,
|
|
73
|
+
static_layers_with_read_approval: input.layers.filter(({ sourceMapReadApproved }) => sourceMapReadApproved).length,
|
|
74
|
+
runtime_script_declarations: input.captures.reduce((total, capture) => total +
|
|
75
|
+
(capture.kind === "browser"
|
|
76
|
+
? capture.inspection.scripts.items.filter(({ source_map_url: url }) => url !== null).length
|
|
77
|
+
: 0), 0),
|
|
78
|
+
limitation: "Source-map declarations and approved original-source reads retain separate static authority and are not used as primary runtime byte matches.",
|
|
79
|
+
});
|
|
80
|
+
const reconciliationCoverage = (input, completion) => ({
|
|
81
|
+
status: completion.outputTruncated || completion.inputTruncated
|
|
82
|
+
? "truncated"
|
|
83
|
+
: completion.inputPartial
|
|
84
|
+
? "partial"
|
|
85
|
+
: "complete-within-inputs",
|
|
86
|
+
truncated: completion.outputTruncated || completion.inputTruncated,
|
|
87
|
+
omitted_runtime_entities: input.runtime.omittedEntities,
|
|
88
|
+
omitted_reconciliation_items: input.matching.omittedItems,
|
|
89
|
+
omitted_static_load_states: input.loadStates.omittedStates,
|
|
90
|
+
omitted_graph_items: input.omittedGraphItems,
|
|
91
|
+
});
|
|
92
|
+
const completionFlags = (input) => ({
|
|
93
|
+
outputTruncated: input.runtime.omittedEntities > 0 ||
|
|
94
|
+
input.matching.omittedItems > 0 ||
|
|
95
|
+
input.loadStates.omittedStates > 0 ||
|
|
96
|
+
input.omittedGraphItems > 0,
|
|
97
|
+
inputTruncated: input.layers.some(({ graph }) => graph.coverage.truncated) ||
|
|
98
|
+
input.captures.some(({ inspection }) => inspection.completeness.conditions.includes("truncated")),
|
|
99
|
+
inputPartial: input.layers.some(({ graph }) => graph.coverage.status !== "complete") ||
|
|
100
|
+
input.captures.some(({ inspection }) => inspection.completeness.status !== "complete_within_window"),
|
|
101
|
+
});
|
|
102
|
+
const reconciliationLimitations = (completion) => uniqueSorted([
|
|
103
|
+
"Only caller-supplied, semantically verified Evidence records were reconciled.",
|
|
104
|
+
"Digest equality establishes byte identity but not code reachability, module initialization, or feature execution.",
|
|
105
|
+
"A static module resident in an observed bundle is not reported as executed.",
|
|
106
|
+
"Not-observed means absent from the bounded captures in scope, never globally unloaded.",
|
|
107
|
+
"Caller-declared file and URL mappings are inference inputs and do not expand CDP origin or filesystem-root authority.",
|
|
108
|
+
"Source-map authority remains separate from passive runtime authority.",
|
|
109
|
+
...(completion.inputPartial
|
|
110
|
+
? ["One or more static graphs or passive captures were incomplete."]
|
|
111
|
+
: []),
|
|
112
|
+
...(completion.outputTruncated
|
|
113
|
+
? [
|
|
114
|
+
"Caller limits omitted runtime entities or reconciliation classifications.",
|
|
115
|
+
]
|
|
116
|
+
: []),
|
|
117
|
+
]);
|
|
118
|
+
const countBy = (items, key, value) => items.filter((item) => item[key] === value).length;
|
|
119
|
+
const uniqueSorted = (values) => [...new Set(values)].sort(compareCodePoints);
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { createJavaScriptApplicationEdge, createJavaScriptApplicationNode, } from "./javascriptApplicationGraph.js";
|
|
2
|
+
/** Project authorized passive capture metadata into capture-scoped JAG nodes. */
|
|
3
|
+
export const projectRuntimeCaptures = (captures, maximumEntities) => {
|
|
4
|
+
if (maximumEntities < captures.length)
|
|
5
|
+
throw new TypeError("Runtime entity limit must admit one target for every capture");
|
|
6
|
+
const all = captures.flatMap(projectCapture);
|
|
7
|
+
const targets = all.filter(({ kind }) => kind === "target");
|
|
8
|
+
const nonTargets = all.filter(({ kind }) => kind !== "target");
|
|
9
|
+
const retained = [...targets, ...nonTargets].slice(0, maximumEntities);
|
|
10
|
+
const retainedIds = new Set(retained.map(({ node }) => node.node_id));
|
|
11
|
+
const nodes = retained.map(({ node }) => node);
|
|
12
|
+
const edges = captures
|
|
13
|
+
.flatMap((capture) => runtimeEdges(capture, all))
|
|
14
|
+
.filter(({ source_node_id: source, target_node_id: target }) => retainedIds.has(source) && retainedIds.has(target));
|
|
15
|
+
const targetNodeByEvidenceId = new Map(retained
|
|
16
|
+
.filter(({ kind }) => kind === "target")
|
|
17
|
+
.map(({ capture, node }) => [capture.evidence.evidence_id, node]));
|
|
18
|
+
return {
|
|
19
|
+
entities: retained,
|
|
20
|
+
nodes,
|
|
21
|
+
edges,
|
|
22
|
+
targetNodeByEvidenceId,
|
|
23
|
+
omittedEntities: all.length - retained.length,
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
const projectCapture = (capture) => {
|
|
27
|
+
const target = targetEntity(capture);
|
|
28
|
+
return [
|
|
29
|
+
target,
|
|
30
|
+
...frameEntities(capture),
|
|
31
|
+
...scriptEntities(capture),
|
|
32
|
+
...workerEntities(capture),
|
|
33
|
+
];
|
|
34
|
+
};
|
|
35
|
+
const targetEntity = (capture) => {
|
|
36
|
+
const target = capture.inspection.target;
|
|
37
|
+
const location = "url" in target
|
|
38
|
+
? { kind: "url", value: target.url }
|
|
39
|
+
: { kind: "file", value: target.file_path };
|
|
40
|
+
return runtimeEntity(capture, {
|
|
41
|
+
kind: "target",
|
|
42
|
+
nodeKind: "target",
|
|
43
|
+
runtimeKey: target.target_id,
|
|
44
|
+
targetKey: target.target_id,
|
|
45
|
+
frameKey: null,
|
|
46
|
+
scriptKey: null,
|
|
47
|
+
location,
|
|
48
|
+
staticKind: "renderer",
|
|
49
|
+
sourceSha256: null,
|
|
50
|
+
label: target.title,
|
|
51
|
+
properties: {
|
|
52
|
+
runtime_type: target.type,
|
|
53
|
+
location: location.value.slice(0, 4_096),
|
|
54
|
+
attached: target.attached,
|
|
55
|
+
},
|
|
56
|
+
section: "target",
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
const frameEntities = (capture) => capture.inspection.frames.map((frame) => {
|
|
60
|
+
const location = "url" in frame
|
|
61
|
+
? { kind: "url", value: frame.url }
|
|
62
|
+
: { kind: "file", value: frame.file_path };
|
|
63
|
+
return runtimeEntity(capture, {
|
|
64
|
+
kind: "frame",
|
|
65
|
+
nodeKind: "frame",
|
|
66
|
+
runtimeKey: frame.frame_id,
|
|
67
|
+
targetKey: capture.inspection.target.target_id,
|
|
68
|
+
frameKey: frame.frame_id,
|
|
69
|
+
scriptKey: null,
|
|
70
|
+
location,
|
|
71
|
+
staticKind: "renderer",
|
|
72
|
+
sourceSha256: null,
|
|
73
|
+
label: location.value,
|
|
74
|
+
properties: {
|
|
75
|
+
parent_frame_id: frame.parent_frame_id,
|
|
76
|
+
location: location.value.slice(0, 4_096),
|
|
77
|
+
},
|
|
78
|
+
section: "frames",
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
const scriptEntities = (capture) => capture.inspection.scripts.items.map((script) => {
|
|
82
|
+
const location = "url" in script
|
|
83
|
+
? { kind: "url", value: script.url }
|
|
84
|
+
: { kind: "file", value: script.file_path };
|
|
85
|
+
return runtimeEntity(capture, {
|
|
86
|
+
kind: "script",
|
|
87
|
+
nodeKind: "runtime-script-instance",
|
|
88
|
+
runtimeKey: script.script_key,
|
|
89
|
+
targetKey: capture.inspection.target.target_id,
|
|
90
|
+
frameKey: script.frame_id,
|
|
91
|
+
scriptKey: script.script_key,
|
|
92
|
+
location,
|
|
93
|
+
staticKind: "javascript",
|
|
94
|
+
sourceSha256: script.source.included
|
|
95
|
+
? script.source.artifact.sha256
|
|
96
|
+
: null,
|
|
97
|
+
label: location.value,
|
|
98
|
+
properties: {
|
|
99
|
+
location: location.value.slice(0, 4_096),
|
|
100
|
+
cdp_hash: script.cdp_hash,
|
|
101
|
+
length: script.length,
|
|
102
|
+
is_module: script.is_module,
|
|
103
|
+
language: script.language,
|
|
104
|
+
source_sha256: script.source.included
|
|
105
|
+
? script.source.artifact.sha256
|
|
106
|
+
: null,
|
|
107
|
+
...("source_map_url" in script
|
|
108
|
+
? { source_map_url: script.source_map_url }
|
|
109
|
+
: {}),
|
|
110
|
+
},
|
|
111
|
+
section: "scripts",
|
|
112
|
+
...(script.source.included
|
|
113
|
+
? { artifactSha256: script.source.artifact.sha256 }
|
|
114
|
+
: {}),
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
const workerEntities = (capture) => capture.inspection.workers.map((worker) => {
|
|
118
|
+
const location = "url" in worker
|
|
119
|
+
? { kind: "url", value: worker.url }
|
|
120
|
+
: { kind: "file", value: worker.file_path };
|
|
121
|
+
const serviceWorker = worker.type.includes("service");
|
|
122
|
+
return runtimeEntity(capture, {
|
|
123
|
+
kind: "worker",
|
|
124
|
+
nodeKind: serviceWorker ? "service-worker" : "worker",
|
|
125
|
+
runtimeKey: worker.target_id,
|
|
126
|
+
targetKey: worker.target_id,
|
|
127
|
+
frameKey: worker.parent_frame_id,
|
|
128
|
+
scriptKey: null,
|
|
129
|
+
location,
|
|
130
|
+
staticKind: serviceWorker ? "service-worker" : "worker",
|
|
131
|
+
sourceSha256: null,
|
|
132
|
+
label: location.value,
|
|
133
|
+
properties: {
|
|
134
|
+
runtime_type: worker.type,
|
|
135
|
+
location: location.value.slice(0, 4_096),
|
|
136
|
+
attached: worker.attached,
|
|
137
|
+
opener_target_id: worker.opener_target_id,
|
|
138
|
+
parent_frame_id: worker.parent_frame_id,
|
|
139
|
+
},
|
|
140
|
+
section: "workers",
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
const runtimeEntity = (capture, input) => ({
|
|
144
|
+
kind: input.kind,
|
|
145
|
+
section: input.section,
|
|
146
|
+
capture,
|
|
147
|
+
runtimeKey: input.runtimeKey,
|
|
148
|
+
location: input.location,
|
|
149
|
+
frameKey: input.frameKey,
|
|
150
|
+
sourceSha256: input.sourceSha256,
|
|
151
|
+
staticKind: input.staticKind,
|
|
152
|
+
node: createJavaScriptApplicationNode({
|
|
153
|
+
kind: input.nodeKind,
|
|
154
|
+
identity: {
|
|
155
|
+
strategy: "runtime-instance",
|
|
156
|
+
stability: "capture-only",
|
|
157
|
+
capture_sha256: capture.captureSha256,
|
|
158
|
+
runtime_key: input.runtimeKey,
|
|
159
|
+
},
|
|
160
|
+
observations: [
|
|
161
|
+
{
|
|
162
|
+
label: input.label.slice(0, 1_024) || null,
|
|
163
|
+
properties: input.properties,
|
|
164
|
+
evidence: runtimeEvidence(capture, input),
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
}),
|
|
168
|
+
});
|
|
169
|
+
const runtimeEvidence = (capture, input) => ({
|
|
170
|
+
authority: "passive-cdp-runtime",
|
|
171
|
+
state: "observed",
|
|
172
|
+
confidence: "exact",
|
|
173
|
+
artifact: input.artifactSha256 === undefined
|
|
174
|
+
? {
|
|
175
|
+
available: false,
|
|
176
|
+
reason: input.section === "scripts" ? "not-observed" : "not-applicable",
|
|
177
|
+
detail: input.section === "scripts"
|
|
178
|
+
? "Script source bytes were not included in this passive capture."
|
|
179
|
+
: "This runtime entity has no standalone artifact bytes.",
|
|
180
|
+
}
|
|
181
|
+
: {
|
|
182
|
+
available: true,
|
|
183
|
+
artifact_id: `art_${input.artifactSha256}`,
|
|
184
|
+
sha256: input.artifactSha256,
|
|
185
|
+
},
|
|
186
|
+
location: {
|
|
187
|
+
available: true,
|
|
188
|
+
value: {
|
|
189
|
+
kind: "runtime",
|
|
190
|
+
capture_sha256: capture.captureSha256,
|
|
191
|
+
target_key: input.targetKey,
|
|
192
|
+
frame_key: input.frameKey,
|
|
193
|
+
script_key: input.scriptKey,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
extractor: {
|
|
197
|
+
name: capture.evidence.provider.id,
|
|
198
|
+
version: capture.evidence.provider.version ??
|
|
199
|
+
(capture.kind === "browser" ? "2" : "1"),
|
|
200
|
+
operation: capture.kind === "browser" ? "inspect_web_page" : "inspect_electron_page",
|
|
201
|
+
executable_sha256: null,
|
|
202
|
+
},
|
|
203
|
+
coverage: runtimeSectionCoverage(capture, input.section),
|
|
204
|
+
limitations: [
|
|
205
|
+
"The entity was observed only within one bounded passive CDP capture.",
|
|
206
|
+
...(runtimeSectionComplete(capture, input.section)
|
|
207
|
+
? []
|
|
208
|
+
: [
|
|
209
|
+
`The runtime ${input.section} inventory was incomplete within this capture.`,
|
|
210
|
+
]),
|
|
211
|
+
],
|
|
212
|
+
evidence_ids: [capture.evidence.evidence_id],
|
|
213
|
+
});
|
|
214
|
+
const runtimeEdges = (capture, entities) => {
|
|
215
|
+
const local = entities.filter(({ capture: candidate }) => candidate.evidence.evidence_id === capture.evidence.evidence_id);
|
|
216
|
+
const target = local.find(({ kind }) => kind === "target");
|
|
217
|
+
if (target === undefined)
|
|
218
|
+
return [];
|
|
219
|
+
const frames = new Map(local
|
|
220
|
+
.filter(({ kind }) => kind === "frame")
|
|
221
|
+
.map((entity) => [entity.runtimeKey, entity]));
|
|
222
|
+
return local.flatMap((entity) => {
|
|
223
|
+
if (entity === target)
|
|
224
|
+
return [];
|
|
225
|
+
const parent = (entity.kind === "script" || entity.kind === "worker") &&
|
|
226
|
+
entity.frameKey !== null
|
|
227
|
+
? (frames.get(entity.frameKey) ?? target)
|
|
228
|
+
: target;
|
|
229
|
+
return [
|
|
230
|
+
createJavaScriptApplicationEdge({
|
|
231
|
+
source_node_id: parent.node.node_id,
|
|
232
|
+
target_node_id: entity.node.node_id,
|
|
233
|
+
relation: entity.kind === "script" ? "loads" : "contains",
|
|
234
|
+
properties: { basis: "passive-cdp-observation" },
|
|
235
|
+
evidence: runtimeRelationshipEvidence(capture, entity),
|
|
236
|
+
}),
|
|
237
|
+
];
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
const runtimeRelationshipEvidence = (capture, entity) => ({
|
|
241
|
+
authority: "passive-cdp-runtime",
|
|
242
|
+
state: "observed",
|
|
243
|
+
confidence: "exact",
|
|
244
|
+
artifact: {
|
|
245
|
+
available: false,
|
|
246
|
+
reason: "not-applicable",
|
|
247
|
+
detail: "The relationship is runtime metadata, not standalone bytes.",
|
|
248
|
+
},
|
|
249
|
+
location: {
|
|
250
|
+
available: true,
|
|
251
|
+
value: {
|
|
252
|
+
kind: "runtime",
|
|
253
|
+
capture_sha256: capture.captureSha256,
|
|
254
|
+
target_key: capture.inspection.target.target_id,
|
|
255
|
+
frame_key: entity.frameKey,
|
|
256
|
+
script_key: entity.kind === "script" ? entity.runtimeKey : null,
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
extractor: {
|
|
260
|
+
name: capture.evidence.provider.id,
|
|
261
|
+
version: capture.evidence.provider.version ??
|
|
262
|
+
(capture.kind === "browser" ? "2" : "1"),
|
|
263
|
+
operation: capture.kind === "browser" ? "inspect_web_page" : "inspect_electron_page",
|
|
264
|
+
executable_sha256: null,
|
|
265
|
+
},
|
|
266
|
+
coverage: runtimeSectionCoverage(capture, entity.section),
|
|
267
|
+
limitations: [
|
|
268
|
+
"The relationship was observed only within one bounded passive CDP capture.",
|
|
269
|
+
],
|
|
270
|
+
evidence_ids: [capture.evidence.evidence_id],
|
|
271
|
+
});
|
|
272
|
+
const runtimeSectionComplete = (capture, section) => {
|
|
273
|
+
if (section === "target")
|
|
274
|
+
return true;
|
|
275
|
+
if (section === "scripts")
|
|
276
|
+
return capture.scriptsCompleteWithinScope;
|
|
277
|
+
return (!capture.inspection.completeness.truncated_sections.includes(section) &&
|
|
278
|
+
!capture.inspection.completeness.unavailable_sections.includes(section));
|
|
279
|
+
};
|
|
280
|
+
const runtimeSectionCoverage = (capture, section) => {
|
|
281
|
+
if (runtimeSectionComplete(capture, section))
|
|
282
|
+
return {
|
|
283
|
+
status: "complete",
|
|
284
|
+
truncated: false,
|
|
285
|
+
omitted_count: 0,
|
|
286
|
+
limits: [],
|
|
287
|
+
};
|
|
288
|
+
const truncated = section !== "target" &&
|
|
289
|
+
capture.inspection.completeness.truncated_sections.includes(section);
|
|
290
|
+
return {
|
|
291
|
+
status: "partial",
|
|
292
|
+
truncated,
|
|
293
|
+
omitted_count: null,
|
|
294
|
+
limits: truncated
|
|
295
|
+
? [
|
|
296
|
+
{
|
|
297
|
+
name: `passive-cdp-${section}-limit`,
|
|
298
|
+
value: runtimeSectionCount(capture, section),
|
|
299
|
+
unit: "items",
|
|
300
|
+
},
|
|
301
|
+
]
|
|
302
|
+
: [],
|
|
303
|
+
};
|
|
304
|
+
};
|
|
305
|
+
const runtimeSectionCount = (capture, section) => {
|
|
306
|
+
switch (section) {
|
|
307
|
+
case "target":
|
|
308
|
+
return 1;
|
|
309
|
+
case "frames":
|
|
310
|
+
return capture.inspection.frames.length;
|
|
311
|
+
case "scripts":
|
|
312
|
+
return capture.inspection.scripts.items.length;
|
|
313
|
+
case "workers":
|
|
314
|
+
return capture.inspection.workers.length;
|
|
315
|
+
}
|
|
316
|
+
};
|