rea-agents 1.7.0 → 2.1.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 +112 -59
- package/bridge/ghidra/ReaGhidraBridge.java +96 -11
- package/dist/application/ArtifactExtraction.js +1 -1
- package/dist/application/ArtifactInventory/classify.js +42 -0
- package/dist/application/ArtifactInventory/hash.js +43 -0
- package/dist/application/ArtifactInventory/reader.js +41 -0
- package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
- package/dist/application/ArtifactInventory/scanReader.js +124 -0
- package/dist/application/ArtifactInventory/types.js +10 -0
- package/dist/application/ArtifactInventory.js +9 -351
- package/dist/application/AuthorizedArtifactInventory.js +2 -2
- package/dist/application/BinarySession.js +47 -270
- package/dist/application/BinarySessionExecution.js +28 -0
- package/dist/application/BinarySessionOpen.js +39 -0
- package/dist/application/BinarySessionRecords.js +149 -0
- package/dist/application/BinarySessionStatus.js +75 -0
- package/dist/application/CapabilityInventory.js +42 -2
- package/dist/application/ClientRegistrationStatus.js +1 -1
- package/dist/application/CrossVersionInventory.js +8 -2
- package/dist/application/CrossVersionInvestigation.js +11 -29
- package/dist/application/CrossVersionInvestigationCollections.js +23 -0
- package/dist/application/DirectAnalysis.js +47 -44
- package/dist/application/Doctor.js +165 -197
- package/dist/application/DoctorDiagnostics.js +180 -0
- package/dist/application/ElectronBoundaryAnalysis.js +112 -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 +223 -0
- package/dist/application/EnhancedToolPagination.js +22 -0
- package/dist/application/EnhancedToolTypes.js +4 -0
- package/dist/application/EnhancedTools.js +58 -50
- package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
- package/dist/application/InvestigationProviders.js +30 -0
- package/dist/application/InvestigationWorkspaceStore.js +24 -10
- 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 +52 -7
- package/dist/application/JavaScriptArtifactFiles.js +6 -2
- package/dist/application/JavaScriptArtifactGraphBuilder.js +82 -17
- package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
- package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
- package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
- package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
- package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
- package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
- package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
- package/dist/application/JavaScriptArtifactReconstruction.js +4 -1
- package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
- package/dist/application/JavaScriptJsonModules.js +39 -0
- package/dist/application/JavaScriptModuleRelationships.js +262 -0
- package/dist/application/JavaScriptReplayPermission.js +16 -0
- package/dist/application/JavaScriptReplayPlanning.js +201 -0
- package/dist/application/JavaScriptReplayService.js +292 -0
- package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
- package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
- package/dist/application/LinuxHopper.js +10 -0
- package/dist/application/MacHopper.js +22 -11
- 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/NodeRuntimeCharacterizationService.js +196 -0
- package/dist/application/PermissionAuthority.js +106 -63
- package/dist/application/ProcessCaptureCapability.js +1 -1
- package/dist/application/ProcessCapturePermission.js +13 -0
- package/dist/application/ProcessCli.js +2 -12
- package/dist/application/ProcessHarness.js +1 -1
- package/dist/application/ProcessSampling.js +15 -11
- package/dist/application/ProjectPermissionStore.js +49 -9
- package/dist/application/RealHopperAssertions.js +76 -0
- package/dist/application/ReconstructionCoverageService.js +69 -0
- package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
- package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
- package/dist/application/Setup.js +147 -259
- package/dist/application/SetupClientConfiguration.js +220 -0
- package/dist/application/SetupClients.js +24 -2
- package/dist/application/SetupPlan.js +123 -12
- package/dist/application/SetupSkill.js +26 -12
- package/dist/application/SupportedClients.js +1 -0
- package/dist/application/Uninstall.js +6 -3
- package/dist/application/WindowsCapabilities.js +86 -0
- package/dist/application/runtime.js +2 -0
- package/dist/artifacts/AsarArtifactReader.js +11 -0
- package/dist/browser/BrowserProcessStartup.js +88 -0
- package/dist/browser/CdpCaptureDocuments.js +12 -8
- package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
- package/dist/browser/CdpCaptureEventHandlers.js +336 -0
- package/dist/browser/CdpCaptureEventHelpers.js +71 -0
- package/dist/browser/CdpCaptureEventState.js +1 -0
- package/dist/browser/CdpCaptureEventTypes.js +1 -0
- package/dist/browser/CdpCaptureEvents.js +46 -464
- package/dist/browser/CdpElectronInspection.js +106 -162
- package/dist/browser/CdpElectronProvider.js +5 -1
- package/dist/browser/CdpElectronScriptEvents.js +69 -0
- package/dist/browser/CdpElectronScripts.js +94 -0
- package/dist/browser/CdpElectronWorkers.js +56 -0
- package/dist/browser/CdpObservationSession.js +51 -8
- package/dist/browser/CdpPageCapture.js +12 -129
- package/dist/browser/CdpPageCaptureScripts.js +97 -0
- package/dist/browser/CdpPageCaptureWorkers.js +46 -0
- package/dist/browser/CdpWebMcpDiscovery.js +38 -14
- package/dist/browser/PngVisualDiff.js +9 -2
- package/dist/catalogIdentity.js +8 -1
- package/dist/cli/artifactCommands.js +82 -0
- package/dist/cli/coreAnalysisCommands.js +232 -0
- package/dist/cli/managedCommands.js +397 -0
- package/dist/cli/managedProjectGraphCommand.js +24 -0
- package/dist/cli/options.js +9 -0
- package/dist/cli/setupCommands.js +108 -0
- package/dist/cli/types.js +1 -0
- package/dist/cli/utilityCommands.js +122 -0
- package/dist/cli.js +13 -383
- package/dist/cliApplicationCommands.js +176 -0
- package/dist/cliBrowserAdvancedCommands.js +73 -16
- package/dist/cliBrowserCommands.js +39 -115
- package/dist/cliCommandNames.js +17 -0
- package/dist/cliElectronCommands.js +100 -27
- package/dist/cliEvidenceCommands.js +13 -2
- package/dist/cliInvestigationCommands.js +53 -10
- package/dist/cliJsonInput.js +54 -0
- package/dist/cliObservationOptions.js +137 -0
- package/dist/cliPolicyCommands.js +80 -46
- package/dist/cliSetup.js +289 -0
- package/dist/config/environment.js +107 -0
- package/dist/config/parseConfig.js +228 -0
- package/dist/config/parsers.js +68 -0
- package/dist/config/permissions.js +30 -0
- package/dist/config/types.js +1 -0
- package/dist/config.js +1 -292
- package/dist/contracts/applicationToolContracts.js +225 -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/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 +2 -0
- package/dist/contracts/toolContractExamples.js +10 -25
- package/dist/contracts/toolContracts.js +49 -47
- package/dist/contracts/toolEffects.js +174 -0
- package/dist/contracts/toolOutputSchemaGroups.js +232 -0
- package/dist/contracts/toolOutputSchemaPrimitives.js +327 -0
- package/dist/contracts/toolOutputSchemas.js +2 -535
- package/dist/doctorRuntime.js +42 -1
- package/dist/domain/analysisErrorPresentation.js +234 -0
- package/dist/domain/analysisErrorProjection.js +284 -0
- package/dist/domain/artifactComparison.js +37 -19
- package/dist/domain/binaryTarget.js +87 -37
- package/dist/domain/browserObservation.js +1 -282
- package/dist/domain/browserObservationSchemas.js +286 -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 +206 -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 +32 -448
- package/dist/domain/functionComparison.js +4 -165
- package/dist/domain/functionComparisonDimensions.js +164 -0
- package/dist/domain/functionComparisonSchemas.js +3 -8
- package/dist/domain/inputIssueProjection.js +52 -0
- package/dist/domain/javascriptApplicationAnalysis.js +155 -0
- package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
- package/dist/domain/javascriptApplicationGraph.js +2 -1
- package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
- package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionItems.js +233 -0
- package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
- package/dist/domain/javascriptExportInstrumentation.js +97 -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 +100 -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 +193 -0
- package/dist/domain/javascriptSemanticAnalysis.js +386 -0
- package/dist/domain/javascriptSemanticIr.js +30 -0
- package/dist/domain/javascriptSemanticProjection.js +366 -0
- package/dist/domain/javascriptSemanticState.js +40 -0
- package/dist/domain/javascriptSemanticTraversal.js +22 -0
- package/dist/domain/javascriptSemanticValues.js +352 -0
- package/dist/domain/javascriptStaticAnalysis.js +26 -254
- package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
- package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +81 -2
- package/dist/domain/javascriptStaticAnalysisState.js +6 -0
- package/dist/domain/knownPageCoverage.js +21 -0
- package/dist/domain/managedApplicationGraph.js +206 -0
- package/dist/domain/managedApplicationGraphCoverage.js +170 -0
- package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
- package/dist/domain/managedApplicationGraphNodes.js +336 -0
- package/dist/domain/managedArtifact.js +452 -0
- package/dist/domain/managedMemberComparison.js +211 -0
- package/dist/domain/managedMemberComparisonCoverage.js +72 -0
- package/dist/domain/managedMemberComparisonMatch.js +356 -0
- package/dist/domain/managedNativeVerification.js +46 -0
- package/dist/domain/managedNativeVerificationMatch.js +272 -0
- package/dist/domain/managedNativeVerificationSchemas.js +141 -0
- package/dist/domain/managedReconstruction.js +196 -0
- package/dist/domain/managedRuntimeCorrelation.js +184 -0
- package/dist/domain/nodeRuntimeCharacterization.js +66 -0
- package/dist/domain/permissionPolicy.js +2 -0
- package/dist/domain/reconstructionCoverage.js +387 -0
- package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
- package/dist/domain/reconstructionVerificationSchemas.js +9 -3
- package/dist/domain/runtimeCharacterization.js +85 -0
- package/dist/domain/webBundleAnalyzer.js +3 -409
- package/dist/domain/webBundleAnalyzerAst.js +77 -0
- package/dist/domain/webBundleAnalyzerInspection.js +307 -0
- package/dist/domain/webBundleAnalyzerResult.js +120 -0
- package/dist/dotnet/ManagedArtifactInspector.js +339 -0
- package/dist/dotnet/ManagedMemberInspector.js +153 -0
- package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
- package/dist/dotnet/ManagedMemberRows.js +120 -0
- package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
- package/dist/dotnet/ManagedMetadataInventory.js +104 -0
- package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
- package/dist/dotnet/ManagedMetadataLayout.js +259 -0
- package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
- package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +143 -0
- package/dist/dotnet/ManagedPeReader.js +188 -0
- package/dist/dotnet/ManagedReaderFailure.js +10 -0
- package/dist/dotnet/ManagedStaticProvider.js +203 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraClient.js +76 -91
- package/dist/ghidra/GhidraClientStartup.js +29 -0
- package/dist/ghidra/GhidraClientWire.js +34 -0
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraDiagnostics.js +6 -1
- package/dist/ghidra/GhidraInstallation.js +20 -15
- package/dist/ghidra/GhidraLauncher.js +93 -29
- package/dist/ghidra/GhidraProvider.js +67 -161
- package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
- package/dist/ghidra/GhidraSessionValues.js +2 -0
- package/dist/ghidra/GhidraSocketConnection.js +44 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
- package/dist/ghidra/GhidraTransport.js +71 -0
- package/dist/identity.js +3 -2
- package/dist/main/messages.js +5 -0
- package/dist/main/reload.js +49 -0
- package/dist/main/shutdown.js +25 -0
- package/dist/main/startup.js +14 -0
- package/dist/main/state.js +26 -0
- package/dist/main/transport.js +61 -0
- package/dist/main/types.js +1 -0
- package/dist/main.js +35 -132
- package/dist/process/PrivateRuntimeRoot.js +3 -2
- package/dist/process/ProcessOwnership.js +35 -0
- package/dist/process/ProviderProcess.js +2 -0
- package/dist/replay/JavaScriptReplayWorker.js +300 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +217 -0
- package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
- package/dist/replay/LinuxRuntimeClosure.js +46 -0
- package/dist/replay/LinuxSeccompPolicy.js +40 -0
- package/dist/replay/ReplayOutcome.js +95 -0
- package/dist/replay/ReplayProcessLifecycle.js +71 -0
- package/dist/replay/ReplayWorkerProtocol.js +55 -0
- package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
- package/dist/server/ProcessCaptureElicitation.js +157 -0
- package/dist/server/createServer.js +158 -41
- package/dist/server/registerApplicationTools/characterization.js +57 -0
- package/dist/server/registerApplicationTools/compareVersions.js +34 -0
- package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
- package/dist/server/registerApplicationTools/coverage.js +84 -0
- package/dist/server/registerApplicationTools/helpers.js +42 -0
- package/dist/server/registerApplicationTools/traceFeature.js +26 -0
- package/dist/server/registerApplicationTools/types.js +1 -0
- package/dist/server/registerApplicationTools.js +13 -0
- package/dist/server/registerArtifactComparisonTool.js +16 -9
- package/dist/server/registerBrowserTools.js +61 -60
- package/dist/server/registerBundleComparisonTool.js +17 -20
- package/dist/server/registerElectronTools.js +39 -12
- package/dist/server/registerEnhancedTools.js +52 -15
- package/dist/server/registerEvidenceResources.js +54 -0
- package/dist/server/registerEvidenceTools.js +5 -1
- package/dist/server/registerFunctionComparisonTool.js +14 -7
- package/dist/server/registerInvestigationTools/helpers.js +74 -0
- package/dist/server/registerInvestigationTools/types.js +1 -0
- package/dist/server/registerInvestigationTools.js +103 -132
- package/dist/server/registerManagedTools.js +6 -0
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
- package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
- package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
- package/dist/server/registerManagedWorkflowTools/types.js +1 -0
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
- package/dist/server/registerManagedWorkflowTools.js +13 -0
- package/dist/server/registerOfficialTools.js +81 -67
- package/dist/server/registerProcessComparisonTool.js +25 -47
- package/dist/server/registerSessionRecordTools.js +137 -0
- package/dist/server/registerSessionStatusTool.js +9 -8
- package/dist/server/registerSessionTools.js +77 -216
- package/dist/server/sessionAvailabilityPolicy.js +10 -0
- package/dist/server/sessionEvidence.js +14 -19
- package/dist/server/toolInputValidation.js +77 -0
- package/dist/server/toolRegistrationOptions.js +177 -2
- package/dist/server/toolResult.js +30 -17
- package/package.json +21 -14
- package/scripts/rea.mjs +1 -1
- package/skills/{rea-analysis → reverse-engineer-anything}/SKILL.md +75 -6
- package/scripts/prepare-node-pty.mjs +0 -35
- package/scripts/rebuild-native.mjs +0 -22
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { artifactLocalIdentity, createElectronRoleNode, javascriptAnalysisCoverage, linkElectronRoleToAsset, } from "./JavaScriptArtifactGraphContext.js";
|
|
2
|
+
import { astObservationEvidence } from "./JavaScriptArtifactGraphEvidence.js";
|
|
3
|
+
import { addElectronAstEdge, addElectronInferenceEdge, electronFindingSourceNode, electronRangeKey, } from "./ElectronBoundaryGraphContext.js";
|
|
4
|
+
import { resolveArtifactPathByContext } from "./JavaScriptArtifactPathResolution.js";
|
|
5
|
+
/** Project BrowserWindow, contextBridge, preload, and utility-process facts. */
|
|
6
|
+
export const addElectronWindowBoundaries = (context) => {
|
|
7
|
+
for (const analyzed of context.analysis.files) {
|
|
8
|
+
const { file, javascript } = analyzed;
|
|
9
|
+
if (javascript === null)
|
|
10
|
+
continue;
|
|
11
|
+
const coverage = javascriptAnalysisCoverage(javascript, context.input);
|
|
12
|
+
for (const value of javascript.electron.browser_windows) {
|
|
13
|
+
const source = electronFindingSourceNode(context, file, value.module_key);
|
|
14
|
+
if (source !== undefined)
|
|
15
|
+
addBrowserWindow({ context, file, source, value, coverage });
|
|
16
|
+
}
|
|
17
|
+
for (const value of javascript.electron.context_bridge_apis) {
|
|
18
|
+
const source = electronFindingSourceNode(context, file, value.module_key);
|
|
19
|
+
if (source !== undefined)
|
|
20
|
+
addContextBridge({ context, file, source, value, coverage });
|
|
21
|
+
}
|
|
22
|
+
for (const value of javascript.electron.utility_processes) {
|
|
23
|
+
const source = electronFindingSourceNode(context, file, value.module_key);
|
|
24
|
+
if (source !== undefined)
|
|
25
|
+
addUtilityProcess({ context, file, source, value, coverage });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const addBrowserWindow = (input) => {
|
|
30
|
+
const { context, file, value, coverage } = input;
|
|
31
|
+
const window = context.accumulator.addNode({
|
|
32
|
+
kind: "browser-window",
|
|
33
|
+
identity: artifactLocalIdentity(file.sha256, "electron-browser-window", electronRangeKey(value.location)),
|
|
34
|
+
observations: [
|
|
35
|
+
{
|
|
36
|
+
label: `BrowserWindow@${electronRangeKey(value.location)}`,
|
|
37
|
+
properties: {
|
|
38
|
+
source_path: file.path,
|
|
39
|
+
options_status: value.options_status,
|
|
40
|
+
web_preferences_status: value.web_preferences_status,
|
|
41
|
+
web_preferences: value.web_preferences,
|
|
42
|
+
omitted_web_preferences: value.omitted_web_preferences,
|
|
43
|
+
preload_path: value.preload_path,
|
|
44
|
+
preload_resolution_context: value.preload_resolution_context,
|
|
45
|
+
absence_means_default: false,
|
|
46
|
+
},
|
|
47
|
+
evidence: astObservationEvidence({
|
|
48
|
+
sha256: file.sha256,
|
|
49
|
+
path: file.path,
|
|
50
|
+
range: value.location,
|
|
51
|
+
operation: "observe-browser-window-construction",
|
|
52
|
+
coverage,
|
|
53
|
+
limitations: [
|
|
54
|
+
"Only explicitly present webPreferences are reported; omitted properties are not interpreted as Electron defaults.",
|
|
55
|
+
],
|
|
56
|
+
}),
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
addElectronAstEdge(context, {
|
|
61
|
+
source: input.source,
|
|
62
|
+
target: window,
|
|
63
|
+
file,
|
|
64
|
+
range: value.location,
|
|
65
|
+
coverage,
|
|
66
|
+
relation: "contains",
|
|
67
|
+
operation: "locate-browser-window-construction",
|
|
68
|
+
properties: { source_path: file.path },
|
|
69
|
+
});
|
|
70
|
+
addWindowPreload(input, window);
|
|
71
|
+
};
|
|
72
|
+
const addWindowPreload = (input, window) => {
|
|
73
|
+
const declared = input.value.preload_path;
|
|
74
|
+
if (declared === null)
|
|
75
|
+
return;
|
|
76
|
+
const resolution = resolveArtifactPathByContext({
|
|
77
|
+
declaredPath: declared,
|
|
78
|
+
sourcePath: input.file.path,
|
|
79
|
+
context: input.value.preload_resolution_context ?? "module-specifier",
|
|
80
|
+
files: input.context.filesByPath,
|
|
81
|
+
});
|
|
82
|
+
const role = createElectronRoleNode(input.context, {
|
|
83
|
+
kind: "electron-preload",
|
|
84
|
+
anchor: input.file,
|
|
85
|
+
resolution,
|
|
86
|
+
mechanism: "BrowserWindow:webPreferences.preload",
|
|
87
|
+
range: input.value.location,
|
|
88
|
+
coverage: input.coverage,
|
|
89
|
+
});
|
|
90
|
+
addElectronInferenceEdge(input.context, {
|
|
91
|
+
source: window,
|
|
92
|
+
target: role,
|
|
93
|
+
file: input.file,
|
|
94
|
+
range: input.value.location,
|
|
95
|
+
coverage: input.coverage,
|
|
96
|
+
relation: "loads",
|
|
97
|
+
operation: "associate-browser-window-preload",
|
|
98
|
+
properties: {
|
|
99
|
+
declared_path: declared,
|
|
100
|
+
resolution_context: resolution.resolution_context,
|
|
101
|
+
resolved_path: resolution.resolved_path,
|
|
102
|
+
resolution_status: resolution.resolution_status,
|
|
103
|
+
limitations: resolution.limitations,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
linkElectronRoleToAsset(input.context, {
|
|
107
|
+
role,
|
|
108
|
+
anchor: input.file,
|
|
109
|
+
resolution,
|
|
110
|
+
range: input.value.location,
|
|
111
|
+
coverage: input.coverage,
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
const addContextBridge = (input) => {
|
|
115
|
+
const { context, file, value, coverage } = input;
|
|
116
|
+
const bridge = context.accumulator.addNode({
|
|
117
|
+
kind: "context-bridge-api",
|
|
118
|
+
identity: artifactLocalIdentity(file.sha256, "electron-context-bridge", `${value.world}:${value.api_key ?? value.api_key_expression ?? "[missing]"}:${electronRangeKey(value.location)}`),
|
|
119
|
+
observations: [
|
|
120
|
+
{
|
|
121
|
+
label: value.api_key,
|
|
122
|
+
properties: {
|
|
123
|
+
world: value.world,
|
|
124
|
+
world_id: value.world_id,
|
|
125
|
+
api_key: value.api_key,
|
|
126
|
+
api_key_expression: value.api_key_expression,
|
|
127
|
+
api_status: value.api_status,
|
|
128
|
+
members: value.members,
|
|
129
|
+
unknown_members: value.unknown_members,
|
|
130
|
+
omitted_members: value.omitted_members,
|
|
131
|
+
},
|
|
132
|
+
evidence: astObservationEvidence({
|
|
133
|
+
sha256: file.sha256,
|
|
134
|
+
path: file.path,
|
|
135
|
+
range: value.location,
|
|
136
|
+
operation: "observe-context-bridge-api",
|
|
137
|
+
coverage,
|
|
138
|
+
}),
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
});
|
|
142
|
+
addElectronInferenceEdge(context, {
|
|
143
|
+
source: input.source,
|
|
144
|
+
target: bridge,
|
|
145
|
+
file,
|
|
146
|
+
range: value.location,
|
|
147
|
+
coverage,
|
|
148
|
+
relation: "exposes",
|
|
149
|
+
operation: "map-context-bridge-exposure",
|
|
150
|
+
properties: {
|
|
151
|
+
world: value.world,
|
|
152
|
+
api_key: value.api_key,
|
|
153
|
+
resolution: value.api_key === null ? "dynamic" : "literal",
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
const addUtilityProcess = (input) => {
|
|
158
|
+
const { context, file, value, coverage } = input;
|
|
159
|
+
const utility = context.accumulator.addNode({
|
|
160
|
+
kind: "electron-utility",
|
|
161
|
+
identity: artifactLocalIdentity(file.sha256, "electron-utility-process", `${value.module_path ?? value.module_expression ?? "[missing]"}:${electronRangeKey(value.location)}`),
|
|
162
|
+
observations: [
|
|
163
|
+
{
|
|
164
|
+
label: value.service_name ?? value.module_path,
|
|
165
|
+
properties: {
|
|
166
|
+
module_path: value.module_path,
|
|
167
|
+
module_resolution_context: value.module_resolution_context,
|
|
168
|
+
module_expression: value.module_expression,
|
|
169
|
+
service_name: value.service_name,
|
|
170
|
+
},
|
|
171
|
+
evidence: astObservationEvidence({
|
|
172
|
+
sha256: file.sha256,
|
|
173
|
+
path: file.path,
|
|
174
|
+
range: value.location,
|
|
175
|
+
operation: "observe-utility-process-fork",
|
|
176
|
+
coverage,
|
|
177
|
+
}),
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
});
|
|
181
|
+
addElectronInferenceEdge(context, {
|
|
182
|
+
source: input.source,
|
|
183
|
+
target: utility,
|
|
184
|
+
file,
|
|
185
|
+
range: value.location,
|
|
186
|
+
coverage,
|
|
187
|
+
relation: "loads",
|
|
188
|
+
operation: "map-utility-process-launch",
|
|
189
|
+
properties: {
|
|
190
|
+
declared_path: value.module_path,
|
|
191
|
+
expression: value.module_expression,
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
if (value.module_path === null)
|
|
195
|
+
return;
|
|
196
|
+
const resolution = resolveArtifactPathByContext({
|
|
197
|
+
declaredPath: value.module_path,
|
|
198
|
+
sourcePath: file.path,
|
|
199
|
+
context: value.module_resolution_context ?? "module-specifier",
|
|
200
|
+
files: context.filesByPath,
|
|
201
|
+
});
|
|
202
|
+
const resolved = resolution.resolved_path;
|
|
203
|
+
const target = resolved === null
|
|
204
|
+
? undefined
|
|
205
|
+
: (context.assetNodes.get(resolved) ?? context.fileNodes.get(resolved));
|
|
206
|
+
if (target === undefined)
|
|
207
|
+
return;
|
|
208
|
+
addElectronInferenceEdge(context, {
|
|
209
|
+
source: utility,
|
|
210
|
+
target,
|
|
211
|
+
file,
|
|
212
|
+
range: value.location,
|
|
213
|
+
coverage,
|
|
214
|
+
relation: "maps_to",
|
|
215
|
+
operation: "resolve-utility-process-entrypoint",
|
|
216
|
+
properties: {
|
|
217
|
+
declared_path: value.module_path,
|
|
218
|
+
resolution_context: resolution.resolution_context,
|
|
219
|
+
resolved_path: resolved,
|
|
220
|
+
resolution_status: resolution.resolution_status,
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { AnalysisOutputError } from "../domain/errors.js";
|
|
2
|
+
import { parseAddressedPage } from "../domain/hopperValues.js";
|
|
3
|
+
import { err, ok } from "../domain/result.js";
|
|
4
|
+
/** Read all addressed entries while enforcing advancing provider pagination. */
|
|
5
|
+
export const readAllAddressed = async (input) => {
|
|
6
|
+
const entries = [];
|
|
7
|
+
let offset = 0;
|
|
8
|
+
while (true) {
|
|
9
|
+
const result = await input.call(input.tool, { offset, limit: 500 }, input.signal);
|
|
10
|
+
if (!result.ok)
|
|
11
|
+
return result;
|
|
12
|
+
const page = parseAddressedPage(result.value);
|
|
13
|
+
if (!page.ok)
|
|
14
|
+
return page;
|
|
15
|
+
entries.push(...page.value.items);
|
|
16
|
+
if (!page.value.hasMore || page.value.nextOffset === null)
|
|
17
|
+
return ok(entries);
|
|
18
|
+
if (page.value.nextOffset <= offset)
|
|
19
|
+
return err(new AnalysisOutputError(input.tool, "provider returned a non-advancing pagination offset"));
|
|
20
|
+
offset = page.value.nextOffset;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { AnalysisInputError } from "../domain/errors.js";
|
|
2
|
+
import { err } from "../domain/result.js";
|
|
3
|
+
import { enhancedInputSchemas, } from "../contracts/enhancedInputs.js";
|
|
4
|
+
export const invalidEnhancedInput = (name, cause) => Promise.resolve(err(new AnalysisInputError(name, { cause })));
|
|
@@ -1,81 +1,108 @@
|
|
|
1
1
|
import { enhancedInputSchemas } from "../contracts/enhancedInputs.js";
|
|
2
|
-
import {
|
|
3
|
-
import { addressDistance, parseDocuments, parseFunctionDossier,
|
|
2
|
+
import { AnalysisCancelledError, AnalysisOutputError, projectAnalysisError, } from "../domain/errors.js";
|
|
3
|
+
import { addressDistance, parseAddressedPage, parseDocuments, parseFunctionDossier, parseListCount, parseRelatedAddresses, parseSegments, } from "../domain/hopperValues.js";
|
|
4
4
|
import { err, ok } from "../domain/result.js";
|
|
5
5
|
import { categorizeSwiftTypes, discoverObjcClasses, discoverObjcProtocols, discoverSwiftClasses, } from "../domain/symbolAnalysis.js";
|
|
6
|
+
import { invalidEnhancedInput, } from "./EnhancedToolTypes.js";
|
|
7
|
+
import { readAllAddressed } from "./EnhancedToolPagination.js";
|
|
6
8
|
/**
|
|
7
9
|
* Composes direct provider operations into bounded reverse-engineering tools.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
+
* Direct callers use `execute`; adapters that own validation use
|
|
11
|
+
* `executeValidated` so an MCP input is parsed exactly once.
|
|
10
12
|
*/
|
|
11
13
|
export class EnhancedTools {
|
|
12
14
|
analysis;
|
|
13
15
|
constructor(analysis) {
|
|
14
16
|
this.analysis = analysis;
|
|
15
17
|
}
|
|
16
|
-
/** Parse
|
|
18
|
+
/** Parse an untrusted direct-call input once, then dispatch exhaustively. */
|
|
17
19
|
execute(name, input, signal) {
|
|
18
20
|
switch (name) {
|
|
19
21
|
case "swift_classes": {
|
|
20
22
|
const parsed = enhancedInputSchemas.swift_classes.safeParse(input);
|
|
21
23
|
return parsed.success
|
|
22
|
-
? this
|
|
23
|
-
:
|
|
24
|
+
? this.executeValidated({ name, input: parsed.data }, signal)
|
|
25
|
+
: invalidEnhancedInput(name, parsed.error);
|
|
24
26
|
}
|
|
25
27
|
case "get_objc_classes": {
|
|
26
28
|
const parsed = enhancedInputSchemas.get_objc_classes.safeParse(input);
|
|
27
29
|
return parsed.success
|
|
28
|
-
? this
|
|
29
|
-
:
|
|
30
|
+
? this.executeValidated({ name, input: parsed.data }, signal)
|
|
31
|
+
: invalidEnhancedInput(name, parsed.error);
|
|
30
32
|
}
|
|
31
33
|
case "get_objc_protocols":
|
|
32
|
-
return this
|
|
34
|
+
return this.executeValidated({ name, input: {} }, signal);
|
|
33
35
|
case "batch_decompile": {
|
|
34
36
|
const parsed = enhancedInputSchemas.batch_decompile.safeParse(input);
|
|
35
37
|
return parsed.success
|
|
36
|
-
? this
|
|
37
|
-
:
|
|
38
|
+
? this.executeValidated({ name, input: parsed.data }, signal)
|
|
39
|
+
: invalidEnhancedInput(name, parsed.error);
|
|
38
40
|
}
|
|
39
41
|
case "get_call_graph": {
|
|
40
42
|
const parsed = enhancedInputSchemas.get_call_graph.safeParse(input);
|
|
41
43
|
return parsed.success
|
|
42
|
-
? this
|
|
43
|
-
:
|
|
44
|
+
? this.executeValidated({ name, input: parsed.data }, signal)
|
|
45
|
+
: invalidEnhancedInput(name, parsed.error);
|
|
44
46
|
}
|
|
45
47
|
case "analyze_swift_types":
|
|
46
|
-
return this
|
|
48
|
+
return this.executeValidated({ name, input: {} }, signal);
|
|
47
49
|
case "find_xrefs_to_name": {
|
|
48
50
|
const parsed = enhancedInputSchemas.find_xrefs_to_name.safeParse(input);
|
|
49
51
|
return parsed.success
|
|
50
|
-
? this
|
|
51
|
-
:
|
|
52
|
+
? this.executeValidated({ name, input: parsed.data }, signal)
|
|
53
|
+
: invalidEnhancedInput(name, parsed.error);
|
|
52
54
|
}
|
|
53
55
|
case "binary_overview": {
|
|
54
56
|
const parsed = enhancedInputSchemas.binary_overview.safeParse(input);
|
|
55
57
|
return parsed.success
|
|
56
|
-
? this
|
|
57
|
-
:
|
|
58
|
+
? this.executeValidated({ name, input: parsed.data }, signal)
|
|
59
|
+
: invalidEnhancedInput(name, parsed.error);
|
|
58
60
|
}
|
|
59
61
|
case "analyze_function": {
|
|
60
62
|
const parsed = enhancedInputSchemas.analyze_function.safeParse(input);
|
|
61
63
|
return parsed.success
|
|
62
|
-
? this
|
|
63
|
-
:
|
|
64
|
+
? this.executeValidated({ name, input: parsed.data }, signal)
|
|
65
|
+
: invalidEnhancedInput(name, parsed.error);
|
|
64
66
|
}
|
|
65
67
|
case "trace_feature": {
|
|
66
68
|
const parsed = enhancedInputSchemas.trace_feature.safeParse(input);
|
|
67
69
|
return parsed.success
|
|
68
|
-
? this
|
|
69
|
-
:
|
|
70
|
+
? this.executeValidated({ name, input: parsed.data }, signal)
|
|
71
|
+
: invalidEnhancedInput(name, parsed.error);
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
}
|
|
75
|
+
/** Dispatch input already parsed by a trusted adapter boundary. */
|
|
76
|
+
executeValidated(call, signal) {
|
|
77
|
+
switch (call.name) {
|
|
78
|
+
case "swift_classes":
|
|
79
|
+
return this.#swiftClasses(call.input.pattern, signal);
|
|
80
|
+
case "get_objc_classes":
|
|
81
|
+
return this.#objcClasses(call.input.pattern, signal);
|
|
82
|
+
case "get_objc_protocols":
|
|
83
|
+
return this.#objcProtocols(signal);
|
|
84
|
+
case "batch_decompile":
|
|
85
|
+
return this.#batchDecompile(call.input.addresses, signal);
|
|
86
|
+
case "get_call_graph":
|
|
87
|
+
return this.#callGraph(call.input, signal);
|
|
88
|
+
case "analyze_swift_types":
|
|
89
|
+
return this.#analyzeSwiftTypes(signal);
|
|
90
|
+
case "find_xrefs_to_name":
|
|
91
|
+
return this.#findXrefs(call.input.name, signal);
|
|
92
|
+
case "binary_overview":
|
|
93
|
+
return this.#binaryOverview(call.input, signal);
|
|
94
|
+
case "analyze_function":
|
|
95
|
+
return this.#analyzeFunction(call.input, signal);
|
|
96
|
+
case "trace_feature":
|
|
97
|
+
return this.#traceFeature(call.input, signal);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
73
100
|
async #analyzeFunction(input, signal) {
|
|
74
101
|
const result = await this.#call("analyze_function", input, signal);
|
|
75
102
|
return result.ok ? parseFunctionDossier(result.value) : result;
|
|
76
103
|
}
|
|
77
104
|
async #swiftClasses(pattern, signal) {
|
|
78
|
-
const procedures = await this.#
|
|
105
|
+
const procedures = await this.#allAddressed("list_procedures", signal);
|
|
79
106
|
return procedures.ok
|
|
80
107
|
? ok(discoverSwiftClasses(procedures.value, pattern))
|
|
81
108
|
: procedures;
|
|
@@ -164,7 +191,7 @@ export class EnhancedTools {
|
|
|
164
191
|
return ok(graph);
|
|
165
192
|
}
|
|
166
193
|
async #analyzeSwiftTypes(signal) {
|
|
167
|
-
const procedures = await this.#
|
|
194
|
+
const procedures = await this.#allAddressed("list_procedures", signal);
|
|
168
195
|
return procedures.ok
|
|
169
196
|
? ok(categorizeSwiftTypes(procedures.value))
|
|
170
197
|
: procedures;
|
|
@@ -193,7 +220,7 @@ export class EnhancedTools {
|
|
|
193
220
|
const [segmentsResult, documentsResult, procedures, stringsResult] = await Promise.all([
|
|
194
221
|
this.#call("list_segments", {}, signal),
|
|
195
222
|
this.#call("list_documents", {}, signal),
|
|
196
|
-
this.#
|
|
223
|
+
this.#allAddressed("list_procedures", signal),
|
|
197
224
|
this.#call("list_strings", {}, signal),
|
|
198
225
|
]);
|
|
199
226
|
if (!segmentsResult.ok)
|
|
@@ -333,28 +360,12 @@ export class EnhancedTools {
|
|
|
333
360
|
residual: [...residual],
|
|
334
361
|
});
|
|
335
362
|
}
|
|
336
|
-
async #allProcedures(signal) {
|
|
337
|
-
return this.#allAddressed("list_procedures", signal);
|
|
338
|
-
}
|
|
339
363
|
async #allAddressed(tool, signal) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
return result;
|
|
346
|
-
const page = parseAddressedPage(result.value);
|
|
347
|
-
if (!page.ok)
|
|
348
|
-
return page;
|
|
349
|
-
entries.push(...page.value.items);
|
|
350
|
-
if (!page.value.hasMore || page.value.nextOffset === null) {
|
|
351
|
-
return ok(entries);
|
|
352
|
-
}
|
|
353
|
-
if (page.value.nextOffset <= offset) {
|
|
354
|
-
return err(new AnalysisOutputError(tool, "provider returned a non-advancing pagination offset"));
|
|
355
|
-
}
|
|
356
|
-
offset = page.value.nextOffset;
|
|
357
|
-
}
|
|
364
|
+
return readAllAddressed({
|
|
365
|
+
call: (name, arguments_, operationSignal) => this.#call(name, arguments_, operationSignal),
|
|
366
|
+
tool,
|
|
367
|
+
...(signal === undefined ? {} : { signal }),
|
|
368
|
+
});
|
|
358
369
|
}
|
|
359
370
|
async #call(name, arguments_, signal) {
|
|
360
371
|
if (signal?.aborted === true)
|
|
@@ -363,6 +374,3 @@ export class EnhancedTools {
|
|
|
363
374
|
return execution.ok ? ok(execution.value.result) : execution;
|
|
364
375
|
}
|
|
365
376
|
}
|
|
366
|
-
const invalidInput = (name, cause) => Promise.resolve(err(new AnalysisInputError(name, {
|
|
367
|
-
cause,
|
|
368
|
-
})));
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { instrumentJavaScriptExport, } from "../domain/javascriptExportInstrumentation.js";
|
|
2
|
+
/** Decorate one exact replay source with deterministic in-memory instrumentation. */
|
|
3
|
+
export class InstrumentedJavaScriptReplayHost {
|
|
4
|
+
delegate;
|
|
5
|
+
input;
|
|
6
|
+
instrumentation = null;
|
|
7
|
+
constructor(delegate, input) {
|
|
8
|
+
this.delegate = delegate;
|
|
9
|
+
this.input = input;
|
|
10
|
+
}
|
|
11
|
+
async readSource(path, maximumBytes) {
|
|
12
|
+
const source = await this.delegate.readSource(path, maximumBytes);
|
|
13
|
+
if (path !== this.input.artifact_path)
|
|
14
|
+
return source;
|
|
15
|
+
const instrumented = instrumentJavaScriptExport(source.bytes, this.input);
|
|
16
|
+
if (instrumented.bytes.byteLength > maximumBytes)
|
|
17
|
+
throw new RangeError("Instrumented JavaScript exceeds the replay module byte limit");
|
|
18
|
+
this.instrumentation = instrumented;
|
|
19
|
+
return { canonicalPath: source.canonicalPath, bytes: instrumented.bytes };
|
|
20
|
+
}
|
|
21
|
+
identifyExecutable(path, versionArguments) {
|
|
22
|
+
return this.delegate.identifyExecutable(path, versionArguments);
|
|
23
|
+
}
|
|
24
|
+
identifyWorker() {
|
|
25
|
+
return this.delegate.identifyWorker();
|
|
26
|
+
}
|
|
27
|
+
identifyRuntimeClosure(nodePath) {
|
|
28
|
+
return this.delegate.identifyRuntimeClosure(nodePath);
|
|
29
|
+
}
|
|
30
|
+
seccompDigest() {
|
|
31
|
+
return this.delegate.seccompDigest();
|
|
32
|
+
}
|
|
33
|
+
probe(policy) {
|
|
34
|
+
return this.delegate.probe(policy);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -15,6 +15,36 @@ export const ARTIFACT_GRAPH_PROVIDER = {
|
|
|
15
15
|
name: "REA safe artifact graph provider",
|
|
16
16
|
version: "1",
|
|
17
17
|
};
|
|
18
|
+
/** Provider identity for execution-free managed PE/CLI analysis. */
|
|
19
|
+
export const MANAGED_STATIC_PROVIDER = {
|
|
20
|
+
id: "rea-dotnet-static",
|
|
21
|
+
name: "REA managed static analysis provider",
|
|
22
|
+
version: "1",
|
|
23
|
+
};
|
|
24
|
+
/** Provider identity for deterministic managed-code comparison workflows. */
|
|
25
|
+
export const MANAGED_WORKFLOW_PROVIDER = {
|
|
26
|
+
id: "rea-dotnet-workflows",
|
|
27
|
+
name: "REA managed-code workflows",
|
|
28
|
+
version: "1",
|
|
29
|
+
};
|
|
30
|
+
/** Provider identity for deterministic static JavaScript application analysis. */
|
|
31
|
+
export const JAVASCRIPT_APPLICATION_PROVIDER = {
|
|
32
|
+
id: "rea-javascript-application",
|
|
33
|
+
name: "REA JavaScript application analyzer",
|
|
34
|
+
version: "1",
|
|
35
|
+
};
|
|
36
|
+
/** Provider identity for static/passive-runtime JavaScript reconciliation. */
|
|
37
|
+
export const JAVASCRIPT_RUNTIME_RECONCILIATION_PROVIDER = {
|
|
38
|
+
id: "rea-javascript-runtime-reconciliation",
|
|
39
|
+
name: "REA JavaScript runtime reconciliation",
|
|
40
|
+
version: "1",
|
|
41
|
+
};
|
|
42
|
+
/** Provider identity for graph-native feature tracing and version comparison. */
|
|
43
|
+
export const JAVASCRIPT_APPLICATION_WORKFLOW_PROVIDER = {
|
|
44
|
+
id: "rea-javascript-application-workflows",
|
|
45
|
+
name: "REA JavaScript application workflows",
|
|
46
|
+
version: "1",
|
|
47
|
+
};
|
|
18
48
|
/** Provider identity for deterministic cross-artifact comparisons. */
|
|
19
49
|
export const ARTIFACT_COMPARISON_PROVIDER = {
|
|
20
50
|
id: "rea-artifact-comparison",
|
|
@@ -5,27 +5,41 @@ import { isJsonWithinLimits } from "../domain/jsonLimits.js";
|
|
|
5
5
|
import { InvestigationWorkspaceError } from "../domain/errors.js";
|
|
6
6
|
import { parseInvestigationWorkspace, serializeInvestigationWorkspace, } from "../domain/investigationWorkspace.js";
|
|
7
7
|
import { err, ok } from "../domain/result.js";
|
|
8
|
+
const investigationWorkspaceCodec = {
|
|
9
|
+
parse: parseInvestigationWorkspace,
|
|
10
|
+
serialize: serializeInvestigationWorkspace,
|
|
11
|
+
validateNext: validateNextRevision,
|
|
12
|
+
};
|
|
8
13
|
/** Read a validated workspace, returning null only when it does not exist. */
|
|
9
|
-
export const readInvestigationWorkspace = async (path, policy) =>
|
|
14
|
+
export const readInvestigationWorkspace = async (path, policy) => readRevisionedWorkspace(path, policy, investigationWorkspaceCodec);
|
|
15
|
+
/** Read one root-confined, owner-only revisioned workspace document. */
|
|
16
|
+
export const readRevisionedWorkspace = async (path, policy, codec) => {
|
|
10
17
|
if (policy.roots.length === 0)
|
|
11
18
|
return err(new InvestigationWorkspaceError("read", "disabled"));
|
|
12
19
|
try {
|
|
13
20
|
const destination = await resolveDestination(path, policy.roots);
|
|
14
21
|
if (destination === null)
|
|
15
22
|
return err(new InvestigationWorkspaceError("read", "outside-root"));
|
|
16
|
-
return await readWorkspaceFile(destination, policy);
|
|
23
|
+
return await readWorkspaceFile(destination, policy, codec);
|
|
17
24
|
}
|
|
18
25
|
catch (cause) {
|
|
19
26
|
return err(new InvestigationWorkspaceError("read", "io", { cause }));
|
|
20
27
|
}
|
|
21
28
|
};
|
|
22
29
|
/** Atomically append one CAS-linked workspace revision under an exclusive lock. */
|
|
23
|
-
export const writeInvestigationWorkspace = async (workspace, path, expectedRevision, policy) => {
|
|
30
|
+
export const writeInvestigationWorkspace = async (workspace, path, expectedRevision, policy) => writeRevisionedWorkspace(path, policy, {
|
|
31
|
+
document: workspace,
|
|
32
|
+
expectedRevision,
|
|
33
|
+
codec: investigationWorkspaceCodec,
|
|
34
|
+
});
|
|
35
|
+
/** Atomically append one validated CAS-linked revision under an exclusive lock. */
|
|
36
|
+
export const writeRevisionedWorkspace = async (path, policy, input) => {
|
|
37
|
+
const { document, expectedRevision, codec } = input;
|
|
24
38
|
if (policy.roots.length === 0)
|
|
25
39
|
return err(new InvestigationWorkspaceError("update", "disabled"));
|
|
26
40
|
let encoded;
|
|
27
41
|
try {
|
|
28
|
-
encoded =
|
|
42
|
+
encoded = codec.serialize(document);
|
|
29
43
|
}
|
|
30
44
|
catch (cause) {
|
|
31
45
|
return err(new InvestigationWorkspaceError("update", "integrity", { cause }));
|
|
@@ -42,10 +56,10 @@ export const writeInvestigationWorkspace = async (workspace, path, expectedRevis
|
|
|
42
56
|
if (!acquired.ok)
|
|
43
57
|
return acquired;
|
|
44
58
|
lock = acquired.value;
|
|
45
|
-
const current = await readWorkspaceFile(destination, policy);
|
|
59
|
+
const current = await readWorkspaceFile(destination, policy, codec);
|
|
46
60
|
if (!current.ok)
|
|
47
61
|
return current;
|
|
48
|
-
const checked =
|
|
62
|
+
const checked = codec.validateNext(current.value, document, expectedRevision);
|
|
49
63
|
if (!checked.ok)
|
|
50
64
|
return checked;
|
|
51
65
|
await writeFileAtomic(destination, encoded, {
|
|
@@ -76,7 +90,7 @@ const resolveDestination = async (path, roots) => {
|
|
|
76
90
|
}
|
|
77
91
|
return null;
|
|
78
92
|
};
|
|
79
|
-
const readWorkspaceFile = async (destination, policy) => {
|
|
93
|
+
const readWorkspaceFile = async (destination, policy, codec) => {
|
|
80
94
|
const stats = await lstat(destination).catch((cause) => {
|
|
81
95
|
if (isFileNotFound(cause))
|
|
82
96
|
return undefined;
|
|
@@ -101,7 +115,7 @@ const readWorkspaceFile = async (destination, policy) => {
|
|
|
101
115
|
if (!isJsonWithinLimits(decoded, policy))
|
|
102
116
|
return err(new InvestigationWorkspaceError("read", "too-large"));
|
|
103
117
|
try {
|
|
104
|
-
return ok(
|
|
118
|
+
return ok(codec.parse(decoded));
|
|
105
119
|
}
|
|
106
120
|
catch (cause) {
|
|
107
121
|
return err(new InvestigationWorkspaceError("read", "integrity", { cause }));
|
|
@@ -168,7 +182,7 @@ const releaseLock = async (lock) => {
|
|
|
168
182
|
await lock.handle.close().catch(() => undefined);
|
|
169
183
|
await unlink(lock.path).catch(() => undefined);
|
|
170
184
|
};
|
|
171
|
-
|
|
185
|
+
function validateNextRevision(current, next, expectedRevision) {
|
|
172
186
|
if ((current?.revision ?? null) !== expectedRevision)
|
|
173
187
|
return err(new InvestigationWorkspaceError("update", "revision-conflict"));
|
|
174
188
|
if (current === null) {
|
|
@@ -182,7 +196,7 @@ const validateNextRevision = (current, next, expectedRevision) => {
|
|
|
182
196
|
next.previous_revision_digest === current.revision_digest
|
|
183
197
|
? ok(null)
|
|
184
198
|
: err(new InvestigationWorkspaceError("update", "revision-conflict"));
|
|
185
|
-
}
|
|
199
|
+
}
|
|
186
200
|
const isFileNotFound = (cause) => errorCode(cause) === "ENOENT";
|
|
187
201
|
const isAlreadyExists = (cause) => errorCode(cause) === "EEXIST";
|
|
188
202
|
const errorCode = (cause) => typeof cause === "object" && cause !== null && "code" in cause
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createEvidence, } from "../domain/evidence.js";
|
|
2
|
+
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
3
|
+
import { JAVASCRIPT_APPLICATION_PROVIDER } from "./InvestigationProviders.js";
|
|
4
|
+
/** Create Evidence v2 for one deterministic local JavaScript application graph. */
|
|
5
|
+
export const createJavaScriptApplicationEvidence = (input, result) => createEvidence({
|
|
6
|
+
path: result.input_path,
|
|
7
|
+
sha256: result.root_artifact_sha256,
|
|
8
|
+
format: result.format,
|
|
9
|
+
}, JAVASCRIPT_APPLICATION_PROVIDER, {
|
|
10
|
+
predicateType: "rea.javascript-application-analysis/v1",
|
|
11
|
+
operation: "analyze_javascript_application",
|
|
12
|
+
parameters: parameters(input),
|
|
13
|
+
result: jsonValueSchema.parse(result),
|
|
14
|
+
rawResult: null,
|
|
15
|
+
confidence: "derived",
|
|
16
|
+
authority: "shipped-artifact",
|
|
17
|
+
environment: null,
|
|
18
|
+
limitations: result.limitations,
|
|
19
|
+
locations: [{ kind: "artifact-path", path: "artifact-root" }],
|
|
20
|
+
});
|
|
21
|
+
const parameters = (input) => ({
|
|
22
|
+
format: input.format,
|
|
23
|
+
approved: input.approved,
|
|
24
|
+
source_map_read_approved: input.source_map_read_approved,
|
|
25
|
+
limits: input.limits,
|
|
26
|
+
});
|