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
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { commentProjection, combineCoverage, functionMatch, identityProjection, isAutoName, normalizeCfg, project, referenceKindProjection, referenceProjection, sorted, stringAndNameProjection, } from "./functionComparisonNormalization.js";
|
|
1
|
+
import { parseFunctionEvidence } from "./functionDossierEvidence.js";
|
|
2
|
+
import { functionMatch } from "./functionComparisonNormalization.js";
|
|
4
3
|
import { functionComparisonResultSchema, } from "./functionComparisonSchemas.js";
|
|
5
|
-
import {
|
|
4
|
+
import { overallStatus, summarize, canonicalJson, } from "./functionComparisonResults.js";
|
|
5
|
+
import { compareDimensions } from "./functionComparisonDimensions.js";
|
|
6
6
|
export { functionComparisonInputSchema, functionComparisonResultSchema, } from "./functionComparisonSchemas.js";
|
|
7
|
-
const unresolvedDimension = (...[dimension, status, links, leftCount, rightCount, limitations]) => buildUnresolvedDimension({
|
|
8
|
-
dimension,
|
|
9
|
-
status,
|
|
10
|
-
links,
|
|
11
|
-
leftCount,
|
|
12
|
-
rightCount,
|
|
13
|
-
limitations,
|
|
14
|
-
});
|
|
15
7
|
/** Compare two explicit function Evidence page sets without fuzzy matching. */
|
|
16
8
|
export const compareFunctions = (leftInput, rightInput, offset, limit) => {
|
|
17
9
|
const left = parseFunctionEvidence(leftInput);
|
|
@@ -52,156 +44,3 @@ export const compareFunctions = (leftInput, rightInput, offset, limit) => {
|
|
|
52
44
|
].sort((a, b) => a.localeCompare(b)),
|
|
53
45
|
});
|
|
54
46
|
};
|
|
55
|
-
const compareDimensions = (left, right, links, providersDiffer) => [
|
|
56
|
-
compareIdentity(left, right, links, providersDiffer),
|
|
57
|
-
compareText("pseudocode", left.pseudocode.text, right.pseudocode.text, left.pseudocode.complete, right.pseudocode.complete, links, providersDiffer),
|
|
58
|
-
compareText("assembly", left.collections.assembly.items.join("\n"), right.collections.assembly.items.join("\n"), left.collections.assembly.complete, right.collections.assembly.complete, links, providersDiffer, left.collections.assembly.truncated || right.collections.assembly.truncated, "Assembly is opaque provider text; relocation normalization is unavailable."),
|
|
59
|
-
compareComments(left, right, links, providersDiffer),
|
|
60
|
-
compareCalls(left, right, links, providersDiffer),
|
|
61
|
-
compareReferences(left, right, links, providersDiffer),
|
|
62
|
-
compareStringsAndNames(left, right, links, providersDiffer),
|
|
63
|
-
compareCfg(left, right, links, providersDiffer),
|
|
64
|
-
];
|
|
65
|
-
const compareText = (...[dimension, left, right, leftComplete, rightComplete, links, providersDiffer, explicitTruncation, limitation,]) => {
|
|
66
|
-
const truncated = explicitTruncation ?? (!leftComplete || !rightComplete);
|
|
67
|
-
if (!leftComplete || !rightComplete || providersDiffer)
|
|
68
|
-
return unresolvedDimension(dimension, truncated ? "truncated" : "unknown", links, left.length, right.length, [
|
|
69
|
-
...(limitation === undefined ? [] : [limitation]),
|
|
70
|
-
...(providersDiffer
|
|
71
|
-
? ["Exact text comparison requires one provider identity."]
|
|
72
|
-
: []),
|
|
73
|
-
]);
|
|
74
|
-
const changes = diffLines(left, right, {
|
|
75
|
-
timeout: 100,
|
|
76
|
-
maxEditLength: 10_000,
|
|
77
|
-
});
|
|
78
|
-
if (changes === undefined)
|
|
79
|
-
return unresolvedDimension(dimension, "unknown", links, left.length, right.length, ["Bounded line diff exceeded its time or edit-distance limit."]);
|
|
80
|
-
const delta = changes.reduce((summary, change) => ({
|
|
81
|
-
added_lines: summary.added_lines + (change.added ? (change.count ?? 0) : 0),
|
|
82
|
-
removed_lines: summary.removed_lines + (change.removed ? (change.count ?? 0) : 0),
|
|
83
|
-
hunks: summary.hunks + (change.added || change.removed ? 1 : 0),
|
|
84
|
-
}), { added_lines: 0, removed_lines: 0, hunks: 0 });
|
|
85
|
-
return dimensionResult({
|
|
86
|
-
dimension,
|
|
87
|
-
status: delta.hunks === 0 ? "unchanged" : "changed",
|
|
88
|
-
left,
|
|
89
|
-
right,
|
|
90
|
-
links,
|
|
91
|
-
providersDiffer,
|
|
92
|
-
leftCount: [...left].length,
|
|
93
|
-
rightCount: [...right].length,
|
|
94
|
-
textDelta: delta,
|
|
95
|
-
limitations: limitation === undefined ? [] : [limitation],
|
|
96
|
-
});
|
|
97
|
-
};
|
|
98
|
-
const compareCollections = (...[dimension, left, right, leftCoverage, rightCoverage, links, providersDiffer,]) => {
|
|
99
|
-
if (!leftCoverage.complete || !rightCoverage.complete)
|
|
100
|
-
return unresolvedDimension(dimension, leftCoverage.truncated || rightCoverage.truncated
|
|
101
|
-
? "truncated"
|
|
102
|
-
: "unknown", links, left.length, right.length, []);
|
|
103
|
-
return compareValues(dimension, sorted(left), sorted(right), links, true, true, providersDiffer);
|
|
104
|
-
};
|
|
105
|
-
const compareComments = (left, right, links, providersDiffer) => {
|
|
106
|
-
const leftValues = commentProjection(left);
|
|
107
|
-
const rightValues = commentProjection(right);
|
|
108
|
-
if (leftValues === null || rightValues === null)
|
|
109
|
-
return unresolvedDimension("comments", "unknown", links, left.collections.comments.items.length, right.collections.comments.items.length, ["Comment locations could not be normalized relative to the function."]);
|
|
110
|
-
return compareCollections("comments", leftValues, rightValues, left.collections.comments, right.collections.comments, links, providersDiffer);
|
|
111
|
-
};
|
|
112
|
-
const compareStringsAndNames = (left, right, links, providersDiffer) => {
|
|
113
|
-
const leftValues = stringAndNameProjection(left);
|
|
114
|
-
const rightValues = stringAndNameProjection(right);
|
|
115
|
-
if (leftValues === null || rightValues === null)
|
|
116
|
-
return unresolvedDimension("strings_names", "unknown", links, null, null, [
|
|
117
|
-
"Reference source locations could not be normalized to function offsets.",
|
|
118
|
-
]);
|
|
119
|
-
return compareCollections("strings_names", leftValues, rightValues, combineCoverage(left.collections.referenced_strings, left.collections.referenced_names), combineCoverage(right.collections.referenced_strings, right.collections.referenced_names), links, providersDiffer);
|
|
120
|
-
};
|
|
121
|
-
const compareReferences = (left, right, links, providersDiffer) => {
|
|
122
|
-
const leftCoverage = combineCoverage(left.collections.incoming_references, left.collections.outgoing_references);
|
|
123
|
-
const rightCoverage = combineCoverage(right.collections.incoming_references, right.collections.outgoing_references);
|
|
124
|
-
if (!leftCoverage.complete || !rightCoverage.complete)
|
|
125
|
-
return unresolvedDimension("references", leftCoverage.truncated || rightCoverage.truncated
|
|
126
|
-
? "truncated"
|
|
127
|
-
: "unknown", links, leftCoverage.items.length, rightCoverage.items.length, []);
|
|
128
|
-
const leftProjection = referenceProjection(left);
|
|
129
|
-
const rightProjection = referenceProjection(right);
|
|
130
|
-
if (leftProjection.length === 0 && rightProjection.length === 0)
|
|
131
|
-
return compareValues("references", leftProjection, rightProjection, links, true, true, providersDiffer);
|
|
132
|
-
if (canonicalJson(leftProjection) !== canonicalJson(rightProjection))
|
|
133
|
-
return dimensionResult({
|
|
134
|
-
dimension: "references",
|
|
135
|
-
status: "changed",
|
|
136
|
-
left: leftProjection,
|
|
137
|
-
right: rightProjection,
|
|
138
|
-
links,
|
|
139
|
-
providersDiffer,
|
|
140
|
-
leftCount: leftProjection.length,
|
|
141
|
-
rightCount: rightProjection.length,
|
|
142
|
-
textDelta: null,
|
|
143
|
-
limitations: [
|
|
144
|
-
"Reference endpoints differ independently of provider reference-kind metadata.",
|
|
145
|
-
],
|
|
146
|
-
});
|
|
147
|
-
const leftKinds = referenceKindProjection(left);
|
|
148
|
-
const rightKinds = referenceKindProjection(right);
|
|
149
|
-
if (leftKinds !== null && rightKinds !== null)
|
|
150
|
-
return compareValues("references", leftKinds, rightKinds, links, true, true, providersDiffer);
|
|
151
|
-
return unresolvedDimension("references", "unknown", links, leftProjection.length, rightProjection.length, [
|
|
152
|
-
"At least one provider did not expose reference kinds, so equal endpoints do not prove equal edge semantics.",
|
|
153
|
-
]);
|
|
154
|
-
};
|
|
155
|
-
const compareIdentity = (left, right, links, providersDiffer) => {
|
|
156
|
-
if (isAutoName(left.procedure.name) || isAutoName(right.procedure.name))
|
|
157
|
-
return unresolvedDimension("identity", "unknown", links, null, null, [
|
|
158
|
-
"Address-derived function names are not stable cross-version identity.",
|
|
159
|
-
]);
|
|
160
|
-
return compareValues("identity", identityProjection(left), identityProjection(right), links, true, true, providersDiffer);
|
|
161
|
-
};
|
|
162
|
-
const compareCalls = (left, right, links, providersDiffer) => {
|
|
163
|
-
const leftValues = callProjection(left);
|
|
164
|
-
const rightValues = callProjection(right);
|
|
165
|
-
if ([...leftValues, ...rightValues].some(({ name }) => isAutoName(name)))
|
|
166
|
-
return unresolvedDimension("calls", "unknown", links, leftValues.length, rightValues.length, ["Address-derived callee or caller names cannot be matched safely."]);
|
|
167
|
-
return compareCollections("calls", leftValues, rightValues, combineCoverage(left.collections.callers, left.collections.callees), combineCoverage(right.collections.callers, right.collections.callees), links, providersDiffer);
|
|
168
|
-
};
|
|
169
|
-
const callProjection = (snapshot) => [
|
|
170
|
-
...project(snapshot.collections.callers, ({ name }) => ({
|
|
171
|
-
direction: "in",
|
|
172
|
-
name,
|
|
173
|
-
})),
|
|
174
|
-
...project(snapshot.collections.callees, ({ name }) => ({
|
|
175
|
-
direction: "out",
|
|
176
|
-
name,
|
|
177
|
-
})),
|
|
178
|
-
];
|
|
179
|
-
const compareCfg = (left, right, links, providersDiffer) => {
|
|
180
|
-
const leftBlocks = left.collections.basic_blocks;
|
|
181
|
-
const rightBlocks = right.collections.basic_blocks;
|
|
182
|
-
if (!leftBlocks.complete || !rightBlocks.complete)
|
|
183
|
-
return unresolvedDimension("cfg", leftBlocks.truncated || rightBlocks.truncated ? "truncated" : "unknown", links, leftBlocks.items.length, rightBlocks.items.length, []);
|
|
184
|
-
const leftGraph = normalizeCfg(leftBlocks.items);
|
|
185
|
-
const rightGraph = normalizeCfg(rightBlocks.items);
|
|
186
|
-
if (leftGraph === null || rightGraph === null)
|
|
187
|
-
return unresolvedDimension("cfg", "unknown", links, leftBlocks.items.length, rightBlocks.items.length, ["CFG addresses could not be normalized to local block indices."]);
|
|
188
|
-
return compareValues("cfg", leftGraph, rightGraph, links, true, true, providersDiffer);
|
|
189
|
-
};
|
|
190
|
-
const compareValues = (...[dimension, left, right, links, leftComplete, rightComplete, providersDiffer,]) => {
|
|
191
|
-
if (!leftComplete || !rightComplete)
|
|
192
|
-
return unresolvedDimension(dimension, "unknown", links, null, null, []);
|
|
193
|
-
const leftJson = canonicalJson(left);
|
|
194
|
-
const rightJson = canonicalJson(right);
|
|
195
|
-
return dimensionResult({
|
|
196
|
-
dimension,
|
|
197
|
-
status: leftJson === rightJson ? "unchanged" : "changed",
|
|
198
|
-
left,
|
|
199
|
-
right,
|
|
200
|
-
links,
|
|
201
|
-
providersDiffer,
|
|
202
|
-
leftCount: Array.isArray(left) ? left.length : null,
|
|
203
|
-
rightCount: Array.isArray(right) ? right.length : null,
|
|
204
|
-
textDelta: null,
|
|
205
|
-
limitations: [],
|
|
206
|
-
});
|
|
207
|
-
};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { diffLines } from "diff";
|
|
2
|
+
import { commentProjection, combineCoverage, identityProjection, isAutoName, normalizeCfg, project, referenceKindProjection, referenceProjection, sorted, stringAndNameProjection, } from "./functionComparisonNormalization.js";
|
|
3
|
+
import { canonicalJson, dimensionResult, unresolvedDimension as buildUnresolvedDimension, } from "./functionComparisonResults.js";
|
|
4
|
+
const unresolvedDimension = (...[dimension, status, links, leftCount, rightCount, limitations]) => buildUnresolvedDimension({
|
|
5
|
+
dimension,
|
|
6
|
+
status,
|
|
7
|
+
links,
|
|
8
|
+
leftCount,
|
|
9
|
+
rightCount,
|
|
10
|
+
limitations,
|
|
11
|
+
});
|
|
12
|
+
export const compareDimensions = (left, right, links, providersDiffer) => [
|
|
13
|
+
compareIdentity(left, right, links, providersDiffer),
|
|
14
|
+
compareText("pseudocode", left.pseudocode.text, right.pseudocode.text, left.pseudocode.complete, right.pseudocode.complete, links, providersDiffer),
|
|
15
|
+
compareText("assembly", left.collections.assembly.items.join("\n"), right.collections.assembly.items.join("\n"), left.collections.assembly.complete, right.collections.assembly.complete, links, providersDiffer, left.collections.assembly.truncated || right.collections.assembly.truncated, "Assembly is opaque provider text; relocation normalization is unavailable."),
|
|
16
|
+
compareComments(left, right, links, providersDiffer),
|
|
17
|
+
compareCalls(left, right, links, providersDiffer),
|
|
18
|
+
compareReferences(left, right, links, providersDiffer),
|
|
19
|
+
compareStringsAndNames(left, right, links, providersDiffer),
|
|
20
|
+
compareCfg(left, right, links, providersDiffer),
|
|
21
|
+
];
|
|
22
|
+
const compareText = (...[dimension, left, right, leftComplete, rightComplete, links, providersDiffer, explicitTruncation, limitation,]) => {
|
|
23
|
+
const truncated = explicitTruncation ?? (!leftComplete || !rightComplete);
|
|
24
|
+
if (!leftComplete || !rightComplete || providersDiffer)
|
|
25
|
+
return unresolvedDimension(dimension, truncated ? "truncated" : "unknown", links, left.length, right.length, [
|
|
26
|
+
...(limitation === undefined ? [] : [limitation]),
|
|
27
|
+
...(providersDiffer
|
|
28
|
+
? ["Exact text comparison requires one provider identity."]
|
|
29
|
+
: []),
|
|
30
|
+
]);
|
|
31
|
+
const changes = diffLines(left, right, {
|
|
32
|
+
timeout: 100,
|
|
33
|
+
maxEditLength: 10_000,
|
|
34
|
+
});
|
|
35
|
+
if (changes === undefined)
|
|
36
|
+
return unresolvedDimension(dimension, "unknown", links, left.length, right.length, ["Bounded line diff exceeded its time or edit-distance limit."]);
|
|
37
|
+
const delta = changes.reduce((summary, change) => ({
|
|
38
|
+
added_lines: summary.added_lines + (change.added ? (change.count ?? 0) : 0),
|
|
39
|
+
removed_lines: summary.removed_lines + (change.removed ? (change.count ?? 0) : 0),
|
|
40
|
+
hunks: summary.hunks + (change.added || change.removed ? 1 : 0),
|
|
41
|
+
}), { added_lines: 0, removed_lines: 0, hunks: 0 });
|
|
42
|
+
return dimensionResult({
|
|
43
|
+
dimension,
|
|
44
|
+
status: delta.hunks === 0 ? "unchanged" : "changed",
|
|
45
|
+
left,
|
|
46
|
+
right,
|
|
47
|
+
links,
|
|
48
|
+
providersDiffer,
|
|
49
|
+
leftCount: [...left].length,
|
|
50
|
+
rightCount: [...right].length,
|
|
51
|
+
textDelta: delta,
|
|
52
|
+
limitations: limitation === undefined ? [] : [limitation],
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
const compareCollections = (...[dimension, left, right, leftCoverage, rightCoverage, links, providersDiffer,]) => {
|
|
56
|
+
if (!leftCoverage.complete || !rightCoverage.complete)
|
|
57
|
+
return unresolvedDimension(dimension, leftCoverage.truncated || rightCoverage.truncated
|
|
58
|
+
? "truncated"
|
|
59
|
+
: "unknown", links, left.length, right.length, []);
|
|
60
|
+
return compareValues(dimension, sorted(left), sorted(right), links, true, true, providersDiffer);
|
|
61
|
+
};
|
|
62
|
+
const compareComments = (left, right, links, providersDiffer) => {
|
|
63
|
+
const leftValues = commentProjection(left);
|
|
64
|
+
const rightValues = commentProjection(right);
|
|
65
|
+
if (leftValues === null || rightValues === null)
|
|
66
|
+
return unresolvedDimension("comments", "unknown", links, left.collections.comments.items.length, right.collections.comments.items.length, ["Comment locations could not be normalized relative to the function."]);
|
|
67
|
+
return compareCollections("comments", leftValues, rightValues, left.collections.comments, right.collections.comments, links, providersDiffer);
|
|
68
|
+
};
|
|
69
|
+
const compareStringsAndNames = (left, right, links, providersDiffer) => {
|
|
70
|
+
const leftValues = stringAndNameProjection(left);
|
|
71
|
+
const rightValues = stringAndNameProjection(right);
|
|
72
|
+
if (leftValues === null || rightValues === null)
|
|
73
|
+
return unresolvedDimension("strings_names", "unknown", links, null, null, [
|
|
74
|
+
"Reference source locations could not be normalized to function offsets.",
|
|
75
|
+
]);
|
|
76
|
+
return compareCollections("strings_names", leftValues, rightValues, combineCoverage(left.collections.referenced_strings, left.collections.referenced_names), combineCoverage(right.collections.referenced_strings, right.collections.referenced_names), links, providersDiffer);
|
|
77
|
+
};
|
|
78
|
+
const compareReferences = (left, right, links, providersDiffer) => {
|
|
79
|
+
const leftCoverage = combineCoverage(left.collections.incoming_references, left.collections.outgoing_references);
|
|
80
|
+
const rightCoverage = combineCoverage(right.collections.incoming_references, right.collections.outgoing_references);
|
|
81
|
+
if (!leftCoverage.complete || !rightCoverage.complete)
|
|
82
|
+
return unresolvedDimension("references", leftCoverage.truncated || rightCoverage.truncated
|
|
83
|
+
? "truncated"
|
|
84
|
+
: "unknown", links, leftCoverage.items.length, rightCoverage.items.length, []);
|
|
85
|
+
const leftProjection = referenceProjection(left);
|
|
86
|
+
const rightProjection = referenceProjection(right);
|
|
87
|
+
if (leftProjection.length === 0 && rightProjection.length === 0)
|
|
88
|
+
return compareValues("references", leftProjection, rightProjection, links, true, true, providersDiffer);
|
|
89
|
+
if (canonicalJson(leftProjection) !== canonicalJson(rightProjection))
|
|
90
|
+
return dimensionResult({
|
|
91
|
+
dimension: "references",
|
|
92
|
+
status: "changed",
|
|
93
|
+
left: leftProjection,
|
|
94
|
+
right: rightProjection,
|
|
95
|
+
links,
|
|
96
|
+
providersDiffer,
|
|
97
|
+
leftCount: leftProjection.length,
|
|
98
|
+
rightCount: rightProjection.length,
|
|
99
|
+
textDelta: null,
|
|
100
|
+
limitations: [
|
|
101
|
+
"Reference endpoints differ independently of provider reference-kind metadata.",
|
|
102
|
+
],
|
|
103
|
+
});
|
|
104
|
+
const leftKinds = referenceKindProjection(left);
|
|
105
|
+
const rightKinds = referenceKindProjection(right);
|
|
106
|
+
if (leftKinds !== null && rightKinds !== null)
|
|
107
|
+
return compareValues("references", leftKinds, rightKinds, links, true, true, providersDiffer);
|
|
108
|
+
return unresolvedDimension("references", "unknown", links, leftProjection.length, rightProjection.length, [
|
|
109
|
+
"At least one provider did not expose reference kinds, so equal endpoints do not prove equal edge semantics.",
|
|
110
|
+
]);
|
|
111
|
+
};
|
|
112
|
+
const compareIdentity = (left, right, links, providersDiffer) => {
|
|
113
|
+
if (isAutoName(left.procedure.name) || isAutoName(right.procedure.name))
|
|
114
|
+
return unresolvedDimension("identity", "unknown", links, null, null, [
|
|
115
|
+
"Address-derived function names are not stable cross-version identity.",
|
|
116
|
+
]);
|
|
117
|
+
return compareValues("identity", identityProjection(left), identityProjection(right), links, true, true, providersDiffer);
|
|
118
|
+
};
|
|
119
|
+
const compareCalls = (left, right, links, providersDiffer) => {
|
|
120
|
+
const leftValues = callProjection(left);
|
|
121
|
+
const rightValues = callProjection(right);
|
|
122
|
+
if ([...leftValues, ...rightValues].some(({ name }) => isAutoName(name)))
|
|
123
|
+
return unresolvedDimension("calls", "unknown", links, leftValues.length, rightValues.length, ["Address-derived callee or caller names cannot be matched safely."]);
|
|
124
|
+
return compareCollections("calls", leftValues, rightValues, combineCoverage(left.collections.callers, left.collections.callees), combineCoverage(right.collections.callers, right.collections.callees), links, providersDiffer);
|
|
125
|
+
};
|
|
126
|
+
const callProjection = (snapshot) => [
|
|
127
|
+
...project(snapshot.collections.callers, ({ name }) => ({
|
|
128
|
+
direction: "in",
|
|
129
|
+
name,
|
|
130
|
+
})),
|
|
131
|
+
...project(snapshot.collections.callees, ({ name }) => ({
|
|
132
|
+
direction: "out",
|
|
133
|
+
name,
|
|
134
|
+
})),
|
|
135
|
+
];
|
|
136
|
+
const compareCfg = (left, right, links, providersDiffer) => {
|
|
137
|
+
const leftBlocks = left.collections.basic_blocks;
|
|
138
|
+
const rightBlocks = right.collections.basic_blocks;
|
|
139
|
+
if (!leftBlocks.complete || !rightBlocks.complete)
|
|
140
|
+
return unresolvedDimension("cfg", leftBlocks.truncated || rightBlocks.truncated ? "truncated" : "unknown", links, leftBlocks.items.length, rightBlocks.items.length, []);
|
|
141
|
+
const leftGraph = normalizeCfg(leftBlocks.items);
|
|
142
|
+
const rightGraph = normalizeCfg(rightBlocks.items);
|
|
143
|
+
if (leftGraph === null || rightGraph === null)
|
|
144
|
+
return unresolvedDimension("cfg", "unknown", links, leftBlocks.items.length, rightBlocks.items.length, ["CFG addresses could not be normalized to local block indices."]);
|
|
145
|
+
return compareValues("cfg", leftGraph, rightGraph, links, true, true, providersDiffer);
|
|
146
|
+
};
|
|
147
|
+
const compareValues = (...[dimension, left, right, links, leftComplete, rightComplete, providersDiffer,]) => {
|
|
148
|
+
if (!leftComplete || !rightComplete)
|
|
149
|
+
return unresolvedDimension(dimension, "unknown", links, null, null, []);
|
|
150
|
+
const leftJson = canonicalJson(left);
|
|
151
|
+
const rightJson = canonicalJson(right);
|
|
152
|
+
return dimensionResult({
|
|
153
|
+
dimension,
|
|
154
|
+
status: leftJson === rightJson ? "unchanged" : "changed",
|
|
155
|
+
left,
|
|
156
|
+
right,
|
|
157
|
+
links,
|
|
158
|
+
providersDiffer,
|
|
159
|
+
leftCount: Array.isArray(left) ? left.length : null,
|
|
160
|
+
rightCount: Array.isArray(right) ? right.length : null,
|
|
161
|
+
textDelta: null,
|
|
162
|
+
limitations: [],
|
|
163
|
+
});
|
|
164
|
+
};
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { evidenceSchema } from "./evidence.js";
|
|
3
|
-
const evidenceInput = z.union([
|
|
4
|
-
evidenceSchema,
|
|
5
|
-
z.array(evidenceSchema).min(1).max(100),
|
|
6
|
-
]);
|
|
7
2
|
const comparisonStatusSchema = z.enum([
|
|
8
3
|
"unchanged",
|
|
9
4
|
"added",
|
|
@@ -25,9 +20,9 @@ const dimensionNameSchema = z.enum([
|
|
|
25
20
|
const evidenceIdSchema = z.string().regex(/^ev_[a-f0-9]{64}$/u);
|
|
26
21
|
const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
|
|
27
22
|
/** Strict bounded input for explicit function-to-function comparison. */
|
|
28
|
-
export const functionComparisonInputSchema = z.
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
export const functionComparisonInputSchema = z.strictObject({
|
|
24
|
+
left_evidence_ids: z.array(evidenceIdSchema).min(1).max(100),
|
|
25
|
+
right_evidence_ids: z.array(evidenceIdSchema).min(1).max(100),
|
|
31
26
|
offset: z.number().int().min(0).default(0),
|
|
32
27
|
limit: z.number().int().min(1).max(100).default(100),
|
|
33
28
|
unknown_registry_approved: z.literal(true).optional(),
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Project Zod failures to secret-safe caller correction metadata. */
|
|
2
|
+
export const projectInputIssues = (issues, input) => issues.flatMap((issue) => projectIssue(issue, input));
|
|
3
|
+
const projectIssue = (issue, input) => {
|
|
4
|
+
const path = issue.path.flatMap((part) => typeof part === "string" || typeof part === "number" ? [part] : []);
|
|
5
|
+
if (issue.code === "unrecognized_keys")
|
|
6
|
+
return issue.keys.map((key) => ({
|
|
7
|
+
path: [...path, key],
|
|
8
|
+
reason: "unknown_argument",
|
|
9
|
+
}));
|
|
10
|
+
if (issue.code === "invalid_type")
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
path,
|
|
14
|
+
reason: valueAtPath(input, path) === undefined
|
|
15
|
+
? "missing_argument"
|
|
16
|
+
: "invalid_type",
|
|
17
|
+
expected: safeExpected(issue.expected),
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
if (issue.code === "too_small")
|
|
21
|
+
return [boundedIssue(path, "minimum", numericBound(issue.minimum))];
|
|
22
|
+
if (issue.code === "too_big")
|
|
23
|
+
return [boundedIssue(path, "maximum", numericBound(issue.maximum))];
|
|
24
|
+
if (issue.code === "invalid_format")
|
|
25
|
+
return [{ path, reason: "invalid_format", expected: issue.format }];
|
|
26
|
+
if (issue.code === "invalid_value")
|
|
27
|
+
return [
|
|
28
|
+
{
|
|
29
|
+
path,
|
|
30
|
+
reason: "invalid_value",
|
|
31
|
+
expected: issue.values.filter(isSafeExpected),
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
return [{ path, reason: "invalid_value" }];
|
|
35
|
+
};
|
|
36
|
+
const valueAtPath = (input, path) => {
|
|
37
|
+
let current = input;
|
|
38
|
+
for (const part of path) {
|
|
39
|
+
if (typeof current !== "object" || current === null)
|
|
40
|
+
return undefined;
|
|
41
|
+
current = current[part];
|
|
42
|
+
}
|
|
43
|
+
return current;
|
|
44
|
+
};
|
|
45
|
+
const numericBound = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
46
|
+
const isSafeExpected = (value) => value === null || ["string", "number", "boolean"].includes(typeof value);
|
|
47
|
+
const safeExpected = (value) => isSafeExpected(value) ? value : "schema-defined value";
|
|
48
|
+
const boundedIssue = (path, key, value) => ({
|
|
49
|
+
path,
|
|
50
|
+
reason: "out_of_range",
|
|
51
|
+
...(value === undefined ? {} : { [key]: value }),
|
|
52
|
+
});
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { isAbsolute } from "node:path";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { javascriptApplicationGraphSchema } from "./javascriptApplicationGraph.js";
|
|
4
|
+
const MAX_GRAPH_NODES = 100_000;
|
|
5
|
+
const MAX_GRAPH_EDGES = 200_000;
|
|
6
|
+
const countSchema = z.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
|
|
7
|
+
const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
|
|
8
|
+
/** Default hard bounds for one local JavaScript application analysis. */
|
|
9
|
+
export const JAVASCRIPT_APPLICATION_ANALYSIS_DEFAULT_LIMITS = {
|
|
10
|
+
max_entries: 8_000,
|
|
11
|
+
max_total_artifact_bytes: 512 * 1_024 * 1_024,
|
|
12
|
+
max_artifact_entry_bytes: 128 * 1_024 * 1_024,
|
|
13
|
+
max_compression_ratio: 1_000,
|
|
14
|
+
max_depth: 64,
|
|
15
|
+
max_path_bytes: 4_096,
|
|
16
|
+
max_text_files: 5_000,
|
|
17
|
+
max_total_text_bytes: 128 * 1_024 * 1_024,
|
|
18
|
+
max_text_file_bytes: 8 * 1_024 * 1_024,
|
|
19
|
+
max_ast_nodes: 2_000_000,
|
|
20
|
+
max_findings: 8_000,
|
|
21
|
+
max_modules: 20_000,
|
|
22
|
+
max_source_map_sources: 5_000,
|
|
23
|
+
max_parse_milliseconds: 30_000,
|
|
24
|
+
};
|
|
25
|
+
/** Combined artifact, text, AST, and graph projection bounds. */
|
|
26
|
+
export const javascriptApplicationAnalysisLimitsSchema = z
|
|
27
|
+
.strictObject({
|
|
28
|
+
max_entries: z.number().int().min(1).max(1_000_000).default(8_000),
|
|
29
|
+
max_total_artifact_bytes: z
|
|
30
|
+
.number()
|
|
31
|
+
.int()
|
|
32
|
+
.min(1)
|
|
33
|
+
.max(Number.MAX_SAFE_INTEGER)
|
|
34
|
+
.default(512 * 1_024 * 1_024),
|
|
35
|
+
max_artifact_entry_bytes: z
|
|
36
|
+
.number()
|
|
37
|
+
.int()
|
|
38
|
+
.min(1)
|
|
39
|
+
.max(Number.MAX_SAFE_INTEGER)
|
|
40
|
+
.default(128 * 1_024 * 1_024),
|
|
41
|
+
max_compression_ratio: z.number().min(1).max(100_000).default(1_000),
|
|
42
|
+
max_depth: z.number().int().min(1).max(100).default(64),
|
|
43
|
+
max_path_bytes: z.number().int().min(1).max(65_535).default(4_096),
|
|
44
|
+
max_text_files: z.number().int().min(1).max(100_000).default(5_000),
|
|
45
|
+
max_total_text_bytes: z
|
|
46
|
+
.number()
|
|
47
|
+
.int()
|
|
48
|
+
.min(1)
|
|
49
|
+
.max(512 * 1_024 * 1_024)
|
|
50
|
+
.default(128 * 1_024 * 1_024),
|
|
51
|
+
max_text_file_bytes: z
|
|
52
|
+
.number()
|
|
53
|
+
.int()
|
|
54
|
+
.min(1)
|
|
55
|
+
.max(64 * 1_024 * 1_024)
|
|
56
|
+
.default(8 * 1_024 * 1_024),
|
|
57
|
+
max_ast_nodes: z.number().int().min(1).max(20_000_000).default(2_000_000),
|
|
58
|
+
max_findings: z.number().int().min(1).max(200_000).default(8_000),
|
|
59
|
+
max_modules: z.number().int().min(1).max(100_000).default(20_000),
|
|
60
|
+
max_source_map_sources: z.number().int().min(1).max(100_000).default(5_000),
|
|
61
|
+
max_parse_milliseconds: z
|
|
62
|
+
.number()
|
|
63
|
+
.int()
|
|
64
|
+
.min(1)
|
|
65
|
+
.max(300_000)
|
|
66
|
+
.default(30_000),
|
|
67
|
+
})
|
|
68
|
+
.superRefine((limits, context) => {
|
|
69
|
+
const projectedNodes = 7 * limits.max_entries +
|
|
70
|
+
2 * limits.max_findings +
|
|
71
|
+
limits.max_modules +
|
|
72
|
+
limits.max_source_map_sources +
|
|
73
|
+
1;
|
|
74
|
+
if (projectedNodes > MAX_GRAPH_NODES)
|
|
75
|
+
context.addIssue({
|
|
76
|
+
code: "custom",
|
|
77
|
+
path: ["max_entries"],
|
|
78
|
+
message: "Combined application-analysis limits can exceed the 100000-node graph contract",
|
|
79
|
+
});
|
|
80
|
+
const projectedEdges = 9 * limits.max_entries +
|
|
81
|
+
6 * limits.max_findings +
|
|
82
|
+
limits.max_modules +
|
|
83
|
+
limits.max_source_map_sources;
|
|
84
|
+
if (projectedEdges > MAX_GRAPH_EDGES)
|
|
85
|
+
context.addIssue({
|
|
86
|
+
code: "custom",
|
|
87
|
+
path: ["max_entries"],
|
|
88
|
+
message: "Combined application-analysis limits can exceed the 200000-edge graph contract",
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
/** Public target-free request for bounded static JavaScript application analysis. */
|
|
92
|
+
export const analyzeJavaScriptApplicationInputSchema = z.strictObject({
|
|
93
|
+
input_path: z
|
|
94
|
+
.string()
|
|
95
|
+
.min(1)
|
|
96
|
+
.max(16_384)
|
|
97
|
+
.refine(isAbsolute, "JavaScript application input path must be absolute"),
|
|
98
|
+
format: z.enum(["auto", "asar", "directory"]).default("auto"),
|
|
99
|
+
approved: z.literal(true),
|
|
100
|
+
source_map_read_approved: z.boolean().default(false),
|
|
101
|
+
limits: javascriptApplicationAnalysisLimitsSchema.default(JAVASCRIPT_APPLICATION_ANALYSIS_DEFAULT_LIMITS),
|
|
102
|
+
});
|
|
103
|
+
/** Compact counts for the high-level Electron architecture/security surface. */
|
|
104
|
+
const electronBoundarySummarySchema = z.strictObject({
|
|
105
|
+
browser_windows: countSchema,
|
|
106
|
+
explicit_web_preferences: countSchema,
|
|
107
|
+
preload_entrypoints: countSchema,
|
|
108
|
+
context_bridge_apis: countSchema,
|
|
109
|
+
exposed_api_members: countSchema,
|
|
110
|
+
ipc: z.strictObject({
|
|
111
|
+
operations: countSchema,
|
|
112
|
+
literal_channels: countSchema,
|
|
113
|
+
dynamic_channel_operations: countSchema,
|
|
114
|
+
renderer_transmissions: countSchema,
|
|
115
|
+
renderer_listeners: countSchema,
|
|
116
|
+
main_handlers: countSchema,
|
|
117
|
+
paired_renderer_transmissions: countSchema,
|
|
118
|
+
ambiguous_renderer_transmissions: countSchema,
|
|
119
|
+
unpaired_literal_renderer_transmissions: countSchema,
|
|
120
|
+
}),
|
|
121
|
+
sender_validation_observations: countSchema,
|
|
122
|
+
utility_processes: countSchema,
|
|
123
|
+
resolved_utility_entrypoints: countSchema,
|
|
124
|
+
native_addon_bindings: countSchema,
|
|
125
|
+
resolved_native_addon_bindings: countSchema,
|
|
126
|
+
});
|
|
127
|
+
const reconstructionStatisticsSchema = z.strictObject({
|
|
128
|
+
relevant_files: countSchema,
|
|
129
|
+
nested_asar_containers: countSchema,
|
|
130
|
+
text_files_selected: countSchema,
|
|
131
|
+
text_bytes_read: countSchema,
|
|
132
|
+
omitted_text_files: countSchema,
|
|
133
|
+
limit_omitted_text_files: countSchema,
|
|
134
|
+
policy_filtered_text_files: countSchema,
|
|
135
|
+
invalid_utf8_files: countSchema,
|
|
136
|
+
parsed_javascript_files: countSchema,
|
|
137
|
+
visited_ast_nodes: countSchema,
|
|
138
|
+
findings: countSchema,
|
|
139
|
+
modules: countSchema,
|
|
140
|
+
parse_failures: countSchema,
|
|
141
|
+
truncated_scopes: countSchema,
|
|
142
|
+
});
|
|
143
|
+
/** Strict high-level result returned inside Evidence v2. */
|
|
144
|
+
export const javascriptApplicationAnalysisResultSchema = z.strictObject({
|
|
145
|
+
schema_version: z.literal(1),
|
|
146
|
+
input_path: z.string().min(1).max(16_384),
|
|
147
|
+
format: z.enum(["asar", "directory"]),
|
|
148
|
+
root_artifact_sha256: digestSchema,
|
|
149
|
+
inventory_manifest_id: z.string().regex(/^agm_[a-f0-9]{64}$/u),
|
|
150
|
+
inventory_graph_sha256: digestSchema,
|
|
151
|
+
graph: javascriptApplicationGraphSchema,
|
|
152
|
+
summary: electronBoundarySummarySchema,
|
|
153
|
+
statistics: reconstructionStatisticsSchema,
|
|
154
|
+
limitations: z.array(z.string().min(1).max(4_096)).max(1_000),
|
|
155
|
+
});
|