rea-agents 3.1.0 → 3.2.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 +72 -95
- package/bridge/ghidra/ReaGhidraBridge.java +609 -841
- package/bridge/hopper_bridge.py +99 -344
- package/dist/application/AbortablePromise.js +6 -3
- package/dist/application/AnalysisSnapshotCache.js +0 -1
- package/dist/application/AnalysisSnapshotFiles.js +7 -7
- package/dist/application/AndroidApplicationService.js +1 -1
- package/dist/application/AppleApplicationService.js +1 -1
- package/dist/application/ArtifactExtraction.js +35 -54
- package/dist/application/ArtifactExtractionDestination.js +17 -0
- package/dist/application/ArtifactGraphConstruction.js +2 -17
- package/dist/application/ArtifactInventory/classify.js +2 -6
- package/dist/application/ArtifactInventory/hash.js +2 -20
- package/dist/application/ArtifactInventory/scanCanonical.js +8 -12
- package/dist/application/ArtifactInventory/scanReader.js +69 -51
- package/dist/application/ArtifactInventory.js +6 -14
- package/dist/application/AuthorizedArtifactInventory.js +3 -13
- package/dist/application/BinarySession.js +41 -13
- package/dist/application/BinarySessionComposition.js +0 -11
- package/dist/application/BinarySessionOpen.js +2 -1
- package/dist/application/BinarySessionRecords.js +5 -93
- package/dist/application/BinarySessionStatus.js +5 -16
- package/dist/application/BinaryTargetResolver.js +216 -0
- package/dist/application/BrowserEvidence.js +42 -58
- package/dist/application/BrowserObservationService.js +3 -6
- package/dist/application/BrowserScenarioCaptureService.js +3 -6
- package/dist/application/BrowserScenarioEvidence.js +3 -3
- package/dist/application/CallPathTracing.js +2 -36
- package/dist/application/CapabilityInventory.js +10 -15
- package/dist/application/ClientConfigurationDocument.js +27 -0
- package/dist/application/ClientRegistrationStatus.js +16 -13
- package/dist/application/CommandShimReplay.js +14 -1
- package/dist/application/DirectAnalysis.js +22 -46
- package/dist/application/DirectAnalysisStatus.js +5 -61
- package/dist/application/Doctor.js +11 -32
- package/dist/application/DoctorDiagnostics.js +1 -2
- package/dist/application/DoctorScope.js +1 -1
- package/dist/application/ElectronActiveEvidence.js +3 -8
- package/dist/application/ElectronActiveObservationService.js +3 -6
- package/dist/application/ElectronBoundaryAnalysis.js +7 -8
- package/dist/application/ElectronBoundaryGraphContext.js +1 -1
- package/dist/application/ElectronBoundaryGraphIpc.js +3 -3
- package/dist/application/ElectronBoundaryGraphNative.js +1 -2
- package/dist/application/ElectronBoundaryGraphWindows.js +6 -8
- package/dist/application/ElectronEvidence.js +4 -7
- package/dist/application/ElectronObservationService.js +5 -9
- package/dist/application/EnhancedLiteralTracing.js +42 -65
- package/dist/application/EnhancedTools.js +76 -44
- package/dist/application/EvidenceBundleCommands.js +11 -11
- package/dist/application/EvidenceBundleFiles.js +9 -15
- package/dist/application/EvidenceLedger.js +6 -41
- package/dist/application/FilesystemSnapshot.js +2 -3
- package/dist/application/InterfaceBuilderAnalysis.js +266 -0
- package/dist/application/InventoryProjectionEvidence.js +4 -2
- package/dist/application/InvestigationProviders.js +1 -1
- package/dist/application/JavaScriptApplicationEvidence.js +2 -5
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +6 -10
- package/dist/application/JavaScriptApplicationService.js +6 -29
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +5 -5
- package/dist/application/JavaScriptApplicationWorkflowService.js +0 -8
- package/dist/application/JavaScriptArtifactAnalysis.js +38 -127
- package/dist/application/JavaScriptArtifactFiles.js +67 -107
- package/dist/application/JavaScriptArtifactGraphAccumulator.js +0 -7
- package/dist/application/JavaScriptArtifactGraphBuilder.js +7 -58
- package/dist/application/JavaScriptArtifactGraphBundlers.js +1 -6
- package/dist/application/JavaScriptArtifactGraphContext.js +12 -39
- package/dist/application/JavaScriptArtifactGraphDocuments.js +4 -11
- package/dist/application/JavaScriptArtifactGraphEvidence.js +0 -14
- package/dist/application/JavaScriptArtifactGraphFindings.js +3 -3
- package/dist/application/JavaScriptArtifactGraphStructure.js +16 -17
- package/dist/application/JavaScriptArtifactPathResolution.js +61 -49
- package/dist/application/JavaScriptArtifactReconstruction.js +5 -10
- package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -14
- package/dist/application/JavaScriptJsonModules.js +2 -2
- package/dist/application/JavaScriptModuleRelationships.js +22 -27
- package/dist/application/JavaScriptReplayPlanning.js +9 -3
- package/dist/application/JavaScriptReplayService.js +6 -32
- package/dist/application/JavaScriptReturnShapeProjection.js +12 -42
- package/dist/application/JavaScriptRuntimeObservationEvidence.js +7 -8
- package/dist/application/JavaScriptRuntimeObservationService.js +4 -8
- package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +2 -3
- package/dist/application/JavaScriptSemanticGraphBuilder.js +11 -41
- package/dist/application/JavaScriptSemanticGraphConstruction.js +5 -29
- package/dist/application/JavaScriptSemanticGraphEvidence.js +1 -1
- package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +1 -1
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +0 -13
- package/dist/application/JavaScriptSemanticGraphProjection.js +1 -3
- package/dist/application/JavaScriptSemanticTraceService.js +1 -10
- package/dist/application/JsonFiles.js +79 -0
- package/dist/application/LinuxHopper.js +11 -9
- package/dist/application/LoopbackReplay.js +26 -23
- package/dist/application/LoopbackReplayRecorder.js +29 -1
- package/dist/application/ManagedApplicationGraphService.js +1 -2
- package/dist/application/ManagedMemberComparisonService.js +11 -41
- package/dist/application/ManagedNativeVerificationService.js +1 -2
- package/dist/application/ManagedReconstructionService.js +1 -1
- package/dist/application/ManagedRuntimeCorrelationService.js +5 -8
- package/dist/application/NativeApiInspection.js +2 -7
- package/dist/application/NativeUiActionTrace.js +394 -0
- package/dist/application/NodeRuntimeCharacterizationService.js +3 -7
- package/dist/application/PermissionAuthority.js +15 -7
- package/dist/application/PermissionFailure.js +5 -0
- package/dist/application/ProcessCaptureAuthority.js +5 -7
- package/dist/application/ProcessCaptureJournal.js +3 -2
- package/dist/application/ProcessCaptureLifecycle.js +5 -12
- package/dist/application/ProcessCheckpoints.js +29 -11
- package/dist/application/ProcessCli.js +6 -16
- package/dist/application/ProcessEvidence.js +5 -7
- package/dist/application/ProcessHarness.js +52 -17
- package/dist/application/ProcessReactiveCoordinator.js +2 -4
- package/dist/application/ProcessReactiveEffects.js +9 -3
- package/dist/application/ProcessReactiveHarness.js +13 -7
- package/dist/application/ProcessSampling.js +2 -4
- package/dist/application/ProcessTimer.js +39 -0
- package/dist/application/ProjectPermissionStore.js +39 -96
- package/dist/application/RealHopperAssertions.js +20 -66
- package/dist/application/ReconstructionCoverageService.js +12 -58
- package/dist/application/ReconstructionObligationAuthority.js +2 -2
- package/dist/application/ReconstructionObligationCandidates.js +4 -4
- package/dist/application/ReconstructionObligationLedgerEvaluation.js +8 -15
- package/dist/application/ReconstructionObligationLedgerProjection.js +3 -7
- package/dist/application/ReconstructionObligationLedgerService.js +19 -38
- package/dist/application/ReferenceSourceImport.js +19 -45
- package/dist/application/ReferenceSourceImportEntries.js +2 -4
- package/dist/application/ReferenceSourceImportPolicy.js +5 -32
- package/dist/application/ReferenceSourceImportTypes.js +0 -16
- package/dist/application/RuntimeExecutableDiagnostics.js +55 -29
- package/dist/application/SessionProviderRouter.js +2 -2
- package/dist/application/Setup.js +1 -3
- package/dist/application/SetupClientConfiguration.js +22 -93
- package/dist/application/SetupRegistrationEnvironment.js +0 -7
- package/dist/application/StoreFileLock.js +119 -0
- package/dist/application/TerminalRenderer.js +2 -3
- package/dist/application/Uninstall.js +9 -14
- package/dist/application/UnknownEvidence.js +1 -1
- package/dist/artifacts/ArtifactPaths.js +2 -5
- package/dist/artifacts/ArtifactProvider.js +36 -58
- package/dist/artifacts/DirectoryArtifactReader.js +13 -8
- package/dist/artifacts/MachOSliceArtifactReader.js +1 -5
- package/dist/artifacts/NativeDmgArtifactReader.js +11 -11
- package/dist/artifacts/NibArchive.js +269 -0
- package/dist/artifacts/SafeOutputTree.js +15 -24
- package/dist/browser/BrowserProcessStartup.js +1 -2
- package/dist/browser/CdpAuthorizedMainFrame.js +16 -0
- package/dist/browser/CdpBrowserProvider.js +3 -13
- package/dist/browser/CdpCanonicalJsonDigest.js +9 -0
- package/dist/browser/CdpCaptureDocuments.js +28 -76
- package/dist/browser/CdpCaptureEventBodyShapes.js +13 -33
- package/dist/browser/CdpCaptureEventHandlers.js +22 -87
- package/dist/browser/CdpCaptureEvents.js +2 -8
- package/dist/browser/CdpCaptureStorage.js +9 -20
- package/dist/browser/CdpCaptureStorageFingerprints.js +85 -98
- package/dist/browser/CdpCaptureValues.js +21 -21
- package/dist/browser/CdpConnection.js +10 -25
- package/dist/browser/CdpElectronInspection.js +26 -50
- package/dist/browser/CdpElectronProvider.js +10 -35
- package/dist/browser/CdpElectronScriptEvents.js +8 -16
- package/dist/browser/CdpElectronScripts.js +6 -35
- package/dist/browser/CdpElectronWorkers.js +6 -10
- package/dist/browser/CdpEndpoint.js +25 -41
- package/dist/browser/CdpObservationSession.js +14 -26
- package/dist/browser/CdpPageCapture.js +34 -48
- package/dist/browser/CdpPageCaptureScripts.js +1 -19
- package/dist/browser/CdpPageCaptureWorkers.js +6 -10
- package/dist/browser/CdpSafeMetadata.js +19 -22
- package/dist/browser/CdpScreenshot.js +3 -5
- package/dist/browser/CdpTargetSession.js +1 -2
- package/dist/browser/CdpWebMcpDiscovery.js +13 -22
- package/dist/browser/ElectronFileScope.js +8 -19
- package/dist/browser/JavaScriptRuntimeScope.js +9 -14
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +31 -64
- package/dist/browser/PlaywrightElectronActiveActions.js +54 -69
- package/dist/browser/PlaywrightElectronActiveProvider.js +14 -34
- package/dist/browser/PlaywrightExecutionBoundary.js +16 -5
- package/dist/browser/PlaywrightScenarioActions.js +3 -7
- package/dist/browser/PlaywrightScenarioArtifacts.js +23 -92
- package/dist/browser/PlaywrightScenarioBrowser.js +3 -5
- package/dist/browser/PlaywrightScenarioEvents.js +45 -94
- package/dist/browser/PlaywrightScenarioSession.js +14 -30
- package/dist/browser/PngVisualDiff.js +22 -14
- package/dist/browser/SensitiveTextCapture.js +0 -17
- package/dist/browser/V8InspectorCaptureProjection.js +7 -8
- package/dist/browser/V8InspectorEndpoint.js +12 -14
- package/dist/browser/V8InspectorProvider.js +20 -61
- package/dist/browser/WebSourceMapFetcher.js +56 -176
- package/dist/catalogIdentity.js +0 -54
- package/dist/cli/artifactCommands.js +49 -77
- package/dist/cli/coreAnalysisCommands.js +83 -133
- package/dist/cli/javascriptApplicationAnalysis.js +1 -9
- package/dist/cli/managedCommands.js +5 -270
- package/dist/cli/setupCommands.js +3 -12
- package/dist/cli/utilityCommands.js +7 -41
- package/dist/cli.js +0 -2
- package/dist/cliApplicationCommands.js +42 -112
- package/dist/cliBrowserAdvancedCommands.js +10 -106
- package/dist/cliBrowserCommands.js +15 -127
- package/dist/cliBrowserContext.js +30 -0
- package/dist/cliCommandNames.js +4 -5
- package/dist/cliElectronCommands.js +8 -72
- package/dist/cliEvidenceCommands.js +8 -77
- package/dist/cliJavaScriptRuntimeCommands.js +9 -91
- package/dist/cliJsonInput.js +4 -14
- package/dist/cliObservationOptions.js +11 -96
- package/dist/cliPolicyCommands.js +2 -17
- package/dist/cliProcessCommands.js +3 -3
- package/dist/cliSetup.js +0 -13
- package/dist/config/browserScenario.js +2 -2
- package/dist/config/environment.js +0 -9
- package/dist/config/parseConfig.js +1 -33
- package/dist/config/parsers.js +6 -27
- package/dist/config/passiveObservation.js +7 -77
- package/dist/config/permissions.js +0 -7
- package/dist/contracts/analysisSearchContract.js +2 -5
- package/dist/contracts/applicationToolContracts.js +56 -109
- package/dist/contracts/applicationWorkflowInputContracts.js +27 -102
- package/dist/contracts/artifactComparisonExample.js +58 -60
- package/dist/contracts/artifactToolContracts.js +20 -67
- package/dist/contracts/browserScenarioToolContracts.js +6 -51
- package/dist/contracts/browserToolContracts.js +8 -73
- package/dist/contracts/electronToolContracts.js +8 -108
- package/dist/contracts/enhancedInputs.js +23 -54
- package/dist/contracts/errorSchemas.js +0 -1
- package/dist/contracts/functionComparisonExample.js +10 -24
- package/dist/contracts/functionInstructionContract.js +1 -3
- package/dist/contracts/functionWorkflowToolContracts.js +2 -2
- package/dist/contracts/hopperMemoryContracts.js +3 -3
- package/dist/contracts/investigationExamples.js +14 -11
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +12 -19
- package/dist/contracts/javascriptRuntimeObservationToolContracts.js +2 -20
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +45 -12
- package/dist/contracts/managedToolContracts.js +6 -95
- package/dist/contracts/managedWorkflowExamples.js +77 -128
- package/dist/contracts/managedWorkflowToolContracts.js +51 -77
- package/dist/contracts/nativeToolContracts.js +7 -11
- package/dist/contracts/processCaptureExample.js +2 -69
- package/dist/contracts/promptContracts.js +49 -67
- package/dist/contracts/providerSelection.js +0 -1
- package/dist/contracts/reconstructionReadinessExample.js +1 -6
- package/dist/contracts/sessionStatusContract.js +1 -17
- package/dist/contracts/sessionToolSchemas.js +6 -15
- package/dist/contracts/toolContractExamples.js +11 -11
- package/dist/contracts/toolContractHelpers.js +0 -4
- package/dist/contracts/toolContracts.js +60 -71
- package/dist/contracts/toolEffects.js +5 -13
- package/dist/contracts/toolOutputSchemaGroups.js +37 -91
- package/dist/contracts/toolOutputSchemaPrimitives.js +16 -56
- package/dist/contracts/toolSchemaMetadata.js +8 -19
- package/dist/contracts/unknownContractExamples.js +0 -2
- package/dist/domain/analysisErrorPresentation.js +46 -54
- package/dist/domain/analysisErrorProjection.js +28 -37
- package/dist/domain/analysisProfile.js +3 -31
- package/dist/domain/analysisSnapshot.js +3 -12
- package/dist/domain/androidApplication.js +15 -54
- package/dist/domain/appleApplication.js +24 -67
- package/dist/domain/artifactComparison.js +11 -29
- package/dist/domain/artifactGraph.js +14 -44
- package/dist/domain/artifactInspection.js +38 -69
- package/dist/domain/artifactInventoryEvidence.js +27 -21
- package/dist/domain/binaryTarget.js +2 -221
- package/dist/domain/browserCaptureComparison.js +47 -24
- package/dist/domain/browserObservation.js +28 -193
- package/dist/domain/browserObservationSchemas.js +5 -23
- package/dist/domain/browserScenario.js +11 -14
- package/dist/domain/browserScenarioCapture.js +11 -12
- package/dist/domain/browserScenarioCaptureValues.js +146 -84
- package/dist/domain/browserScenarioDiff.js +2 -59
- package/dist/domain/browserScenarioDiffEvidence.js +51 -0
- package/dist/domain/browserScenarioDiffValues.js +21 -38
- package/dist/domain/browserScenarioValues.js +80 -109
- package/dist/domain/browserSession.js +4 -7
- package/dist/domain/bundleComparison.js +6 -32
- package/dist/domain/bytecodeProvider.js +20 -19
- package/dist/domain/callPath.js +47 -167
- package/dist/domain/callPathSchemas.js +79 -0
- package/dist/domain/changedBehavior.js +34 -60
- package/dist/domain/completionLedgerGeneration.js +8 -14
- package/dist/domain/conformancePackage.js +126 -97
- package/dist/domain/conformanceReplay.js +36 -8
- package/dist/domain/conformanceTrustGate.js +23 -14
- package/dist/domain/customProtocolCapture.js +1 -1
- package/dist/domain/electronActiveObservation.js +70 -103
- package/dist/domain/electronObservation.js +14 -80
- package/dist/domain/electronStaticAnalysisBrowser.js +36 -46
- package/dist/domain/electronStaticAnalysisIpc.js +38 -14
- package/dist/domain/electronStaticAnalysisNative.js +1 -8
- package/dist/domain/electronStaticAnalysisValues.js +10 -17
- package/dist/domain/errors.js +33 -54
- package/dist/domain/eventProcessTree.js +20 -12
- package/dist/domain/evidence.js +2 -10
- package/dist/domain/evidenceBundle.js +3 -5
- package/dist/domain/evidenceCompletionLedger.js +6 -8
- package/dist/domain/functionComparison.js +4 -14
- package/dist/domain/functionComparisonNormalization.js +4 -11
- package/dist/domain/functionComparisonResults.js +25 -15
- package/dist/domain/functionComparisonSchemas.js +49 -33
- package/dist/domain/functionDossierEvidence.js +31 -156
- package/dist/domain/hopperStartupFailure.js +1 -1
- package/dist/domain/hopperValues.js +15 -136
- package/dist/domain/interfaceBuilderGraph.js +654 -0
- package/dist/domain/javascriptApplicationAnalysis.js +8 -112
- package/dist/domain/javascriptApplicationChangeGraph.js +22 -82
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +59 -47
- package/dist/domain/javascriptApplicationGraph.js +3 -13
- package/dist/domain/javascriptApplicationGraphSchemas.js +12 -34
- package/dist/domain/javascriptApplicationVersionComparison.js +26 -30
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +123 -68
- package/dist/domain/javascriptApplicationVersionItems.js +120 -53
- package/dist/domain/javascriptApplicationVersionKeys.js +24 -11
- package/dist/domain/javascriptAstFingerprint.js +25 -58
- package/dist/domain/javascriptAstValues.js +9 -0
- package/dist/domain/javascriptExportInstrumentation.js +2 -4
- package/dist/domain/javascriptExportShapeComparison.js +6 -7
- package/dist/domain/javascriptExportShapeComparisonSchemas.js +68 -75
- package/dist/domain/javascriptExportShapeSelection.js +17 -19
- package/dist/domain/javascriptFeatureSeed.js +20 -12
- package/dist/domain/javascriptFeatureTrace.js +13 -67
- package/dist/domain/javascriptFeatureTraceSchemas.js +24 -52
- package/dist/domain/javascriptFeatureTraversal.js +1 -44
- package/dist/domain/javascriptNativeHandoff.js +1 -1
- package/dist/domain/javascriptReplay.js +24 -41
- package/dist/domain/javascriptRuntimeLoadState.js +3 -8
- package/dist/domain/javascriptRuntimeObservation.js +42 -103
- package/dist/domain/javascriptRuntimeReconciliation.js +1 -3
- package/dist/domain/javascriptRuntimeReconciliationActive.js +8 -17
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +10 -23
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +18 -12
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +16 -45
- package/dist/domain/javascriptRuntimeReconciliationResult.js +4 -5
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +8 -12
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +33 -48
- package/dist/domain/javascriptRuntimeStaticCandidates.js +3 -3
- package/dist/domain/javascriptSemanticAnalysis.js +12 -45
- package/dist/domain/javascriptSemanticAsyncEffects.js +1 -9
- package/dist/domain/javascriptSemanticCallResolution.js +6 -16
- package/dist/domain/javascriptSemanticCalls.js +5 -32
- package/dist/domain/javascriptSemanticChildProcesses.js +1 -11
- package/dist/domain/javascriptSemanticCoverage.js +11 -0
- package/dist/domain/javascriptSemanticDataEffectHelpers.js +1 -8
- package/dist/domain/javascriptSemanticDataEffects.js +1 -11
- package/dist/domain/javascriptSemanticFingerprints.js +3 -5
- package/dist/domain/javascriptSemanticGraphSchemas.js +25 -51
- package/dist/domain/javascriptSemanticGraphSerialization.js +2 -13
- package/dist/domain/javascriptSemanticIr.js +1 -29
- package/dist/domain/javascriptSemanticObjects.js +1 -5
- package/dist/domain/javascriptSemanticPrimitives.js +2 -9
- package/dist/domain/javascriptSemanticProjection.js +0 -18
- package/dist/domain/javascriptSemanticPromises.js +9 -16
- package/dist/domain/javascriptSemanticProvenance.js +16 -19
- package/dist/domain/javascriptSemanticQuery.js +17 -139
- package/dist/domain/javascriptSemanticQueryAssessment.js +9 -37
- package/dist/domain/javascriptSemanticQueryIdentity.js +2 -23
- package/dist/domain/javascriptSemanticQuerySchemas.js +14 -107
- package/dist/domain/javascriptSemanticResources.js +1 -6
- package/dist/domain/javascriptSemanticReturns.js +10 -27
- package/dist/domain/javascriptSemanticValueTypes.js +1 -0
- package/dist/domain/javascriptSemanticValues.js +44 -62
- package/dist/domain/javascriptStaticAnalysis.js +21 -43
- package/dist/domain/javascriptStaticAnalysisBundler.js +34 -93
- package/dist/domain/javascriptStaticAnalysisCalls.js +17 -16
- package/dist/domain/javascriptStaticAnalysisFindings.js +3 -19
- package/dist/domain/javascriptStaticAnalysisHelpers.js +47 -88
- package/dist/domain/javascriptStaticAnalysisState.js +1 -5
- package/dist/domain/javascriptStaticAnalysisTypes.js +1 -0
- package/dist/domain/jsonShape.js +7 -33
- package/dist/domain/localPath.js +7 -0
- package/dist/domain/managedApplicationGraph.js +9 -41
- package/dist/domain/managedApplicationGraphCoverage.js +24 -156
- package/dist/domain/managedApplicationGraphNodes.js +10 -13
- package/dist/domain/managedArtifact.js +14 -27
- package/dist/domain/managedMemberComparison.js +90 -92
- package/dist/domain/managedMemberComparisonCoverage.js +11 -33
- package/dist/domain/managedMemberComparisonItems.js +221 -0
- package/dist/domain/managedMemberComparisonMatch.js +8 -208
- package/dist/domain/managedNativeVerification.js +3 -6
- package/dist/domain/managedNativeVerificationMatch.js +55 -59
- package/dist/domain/managedNativeVerificationSchemas.js +83 -47
- package/dist/domain/managedReconstruction.js +19 -23
- package/dist/domain/managedRuntimeCorrelation.js +6 -9
- package/dist/domain/nativeApiBoundary.js +2 -7
- package/dist/domain/nativeInspection.js +0 -2
- package/dist/domain/nativeInvestigationGraph.js +351 -0
- package/dist/domain/nativeValueFlow.js +61 -0
- package/dist/domain/nodeRuntimeCharacterization.js +1 -5
- package/dist/domain/objcSwiftMetadata.js +254 -0
- package/dist/domain/peInspection.js +1 -1
- package/dist/domain/permissionPolicy.js +13 -0
- package/dist/domain/processCapture.js +76 -113
- package/dist/domain/processCaptureExample.js +68 -0
- package/dist/domain/processCaptureParsing.js +21 -0
- package/dist/domain/processCaptureReactiveSchema.js +68 -0
- package/dist/domain/processCaptureValidation.js +1 -7
- package/dist/domain/processComparison.js +3 -12
- package/dist/domain/processReactiveMatching.js +29 -50
- package/dist/domain/processReactiveRuntime.js +4 -8
- package/dist/domain/processReactiveScenario.js +28 -94
- package/dist/domain/processReactiveScenarioPreflight.js +5 -30
- package/dist/domain/processReactiveTransition.js +33 -18
- package/dist/domain/processScenario.js +56 -90
- package/dist/domain/processTraceComparison.js +0 -8
- package/dist/domain/processTraceEvaluation.js +14 -4
- package/dist/domain/processTraceSpecification.js +11 -17
- package/dist/domain/protocolCapture.js +3 -3
- package/dist/domain/reconstructionCoverage.js +62 -129
- package/dist/domain/reconstructionCoverageEvaluation.js +17 -17
- package/dist/domain/reconstructionObligationLedgerSchemas.js +45 -72
- package/dist/domain/reconstructionReadiness.js +1 -2
- package/dist/domain/reconstructionReadinessSchemas.js +36 -38
- package/dist/domain/reconstructionUnknowns.js +3 -3
- package/dist/domain/reconstructionVerification.js +13 -47
- package/dist/domain/reconstructionVerificationSchemas.js +50 -38
- package/dist/domain/referenceSourceGraph.js +53 -61
- package/dist/domain/referenceSourceImportParsing.js +1 -5
- package/dist/domain/replayMachine.js +19 -31
- package/dist/domain/replayMachineRun.js +15 -63
- package/dist/domain/replayMachineRuntime.js +41 -41
- package/dist/domain/replayMachineValues.js +84 -0
- package/dist/domain/residualUnknown.js +25 -30
- package/dist/domain/runtimeCharacterization.js +15 -16
- package/dist/domain/runtimeIdentification.js +48 -47
- package/dist/domain/sourceToBundleComparison.js +9 -85
- package/dist/domain/sourceToBundleComparisonSchemas.js +17 -42
- package/dist/domain/sourceToBundleSignals.js +4 -15
- package/dist/domain/staticRuntimeCorrelation.js +37 -49
- package/dist/domain/symbolAnalysis.js +10 -19
- package/dist/domain/unicodeCodePointOrder.js +12 -0
- package/dist/domain/webBundleAnalysis.js +70 -99
- package/dist/domain/webBundleAnalyzer.js +2 -4
- package/dist/domain/webBundleAnalyzerAst.js +0 -13
- package/dist/domain/webBundleAnalyzerInspection.js +26 -52
- package/dist/domain/webBundleAnalyzerResult.js +7 -24
- package/dist/domain/webCaptureDiff.js +33 -73
- package/dist/domain/webCaptureDiffSchemas.js +86 -0
- package/dist/domain/webContentArtifact.js +1 -10
- package/dist/domain/webMcpDiscovery.js +3 -14
- package/dist/domain/webScreenshot.js +58 -34
- package/dist/domain/zipPackageFormat.js +7 -0
- package/dist/dotnet/ManagedArtifactInspector.js +17 -50
- package/dist/dotnet/ManagedMemberInspector.js +27 -58
- package/dist/dotnet/ManagedMemberInspectorCore.js +14 -51
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +2 -2
- package/dist/dotnet/ManagedMemberRows.js +16 -16
- package/dist/dotnet/ManagedMetadataHeaps.js +26 -8
- package/dist/dotnet/ManagedMetadataInventory.js +21 -30
- package/dist/dotnet/ManagedMetadataInventoryRows.js +57 -63
- package/dist/dotnet/ManagedMetadataLayout.js +3 -5
- package/dist/dotnet/ManagedMethodBodyReader.js +5 -30
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +19 -49
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +13 -41
- package/dist/dotnet/ManagedPeReader.js +2 -2
- package/dist/dotnet/ManagedStaticProvider.js +13 -71
- package/dist/generatedMcpToolCatalog.js +1 -1
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraAnalysisProfile.js +3 -8
- package/dist/ghidra/GhidraClient.js +4 -12
- package/dist/ghidra/GhidraClientWire.js +9 -5
- package/dist/ghidra/GhidraDefaults.js +0 -18
- package/dist/ghidra/GhidraDiagnostics.js +0 -2
- package/dist/ghidra/GhidraDoctor.js +16 -12
- package/dist/ghidra/GhidraFunctionValues.js +65 -108
- package/dist/ghidra/GhidraInstallation.js +98 -42
- package/dist/ghidra/GhidraInventoryValues.js +16 -85
- package/dist/ghidra/GhidraLauncher.js +0 -8
- package/dist/ghidra/GhidraProvider.js +15 -22
- package/dist/ghidra/GhidraProviderCapabilities.js +6 -47
- package/dist/ghidra/GhidraRequestQueue.js +6 -30
- package/dist/ghidra/GhidraResponseBuffer.js +1 -7
- package/dist/ghidra/GhidraSessionValues.js +0 -2
- package/dist/ghidra/GhidraTransport.js +4 -7
- package/dist/ghidra/protocol.js +2 -2
- package/dist/hopper/BridgeLauncher.js +112 -36
- package/dist/hopper/HopperAnalysisProfile.js +1 -1
- package/dist/hopper/HopperCleanup.js +6 -3
- package/dist/hopper/HopperClient.js +4 -7
- package/dist/hopper/HopperProcessDiagnostic.js +2 -2
- package/dist/hopper/HopperProvider.js +0 -16
- package/dist/hopper/HopperRequestQueue.js +21 -40
- package/dist/hopper/HopperResponseStream.js +1 -9
- package/dist/hopper/HopperSessionValues.js +3 -2
- package/dist/hopper/HopperTargetLease.js +119 -0
- package/dist/hopper/LinuxPrivateDisplayDiagnostic.js +24 -31
- package/dist/hopper/LinuxPrivateDisplayProbe.js +5 -16
- package/dist/hopper/protocol.js +6 -4
- package/dist/main/reload.js +0 -3
- package/dist/main/shutdown.js +1 -1
- package/dist/main/state.js +0 -9
- package/dist/main/transport.js +0 -5
- package/dist/mcpDoctor.js +25 -45
- package/dist/native/CommandRunner.js +18 -25
- package/dist/native/NativeMacOSProvider.js +13 -38
- package/dist/native/NativeMachoInspection.js +1 -1
- package/dist/process/BoundedFileBytes.js +17 -0
- package/dist/process/ExecFileOutput.js +11 -0
- package/dist/process/PendingOperations.js +8 -6
- package/dist/process/ProcessOwnership.js +3 -2
- package/dist/process/ProcessOwnershipObservation.js +0 -1
- package/dist/process/ProviderProcess.js +7 -28
- package/dist/reference/ReferenceSourceReader.js +8 -24
- package/dist/reference/ReferenceSourceReaderEntries.js +11 -39
- package/dist/reference/ReferenceSourceReaderFile.js +13 -31
- package/dist/reference/ReferenceSourceReaderPaths.js +3 -18
- package/dist/reference/ReferenceSourceReaderValidate.js +3 -6
- package/dist/replay/JavaScriptReplayWorker.js +3 -5
- package/dist/replay/LinuxJavaScriptReplayRunner.js +33 -29
- package/dist/replay/LinuxJavaScriptReplaySandbox.js +0 -19
- package/dist/replay/LinuxRuntimeClosure.js +1 -3
- package/dist/replay/ReplayOutcome.js +1 -3
- package/dist/replay/ReplayProcessLifecycle.js +32 -7
- package/dist/replay/ReplaySeccompFile.js +29 -0
- package/dist/replay/ReplayWorkerProtocol.js +0 -2
- package/dist/replay/SystemJavaScriptReplayHost.js +45 -74
- package/dist/server/ProcessCaptureElicitation.js +4 -8
- package/dist/server/createServer.js +6 -44
- package/dist/server/promptCompletion.js +37 -61
- package/dist/server/recordDerivedEvidence.js +1 -1
- package/dist/server/registerApplicationTools/characterization.js +4 -8
- package/dist/server/registerApplicationTools/compareExportShapes.js +5 -10
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +6 -10
- package/dist/server/registerApplicationTools/compareVersions.js +5 -10
- package/dist/server/registerApplicationTools/controlledReplay.js +3 -5
- package/dist/server/registerApplicationTools/coverage.js +6 -71
- package/dist/server/registerApplicationTools/helpers.js +1 -13
- package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
- package/dist/server/registerApplicationTools/traceFeature.js +5 -9
- package/dist/server/registerApplicationTools/traceSemantics.js +5 -8
- package/dist/server/registerApplicationTools.js +0 -2
- package/dist/server/registerArtifactComparisonTool.js +23 -27
- package/dist/server/registerBrowserScenarioTool.js +4 -4
- package/dist/server/registerBrowserTools.js +5 -8
- package/dist/server/registerBundleComparisonTool.js +5 -7
- package/dist/server/registerCloseLifecycleTool.js +2 -16
- package/dist/server/registerElectronTools.js +10 -29
- package/dist/server/registerEnhancedTools.js +10 -11
- package/dist/server/registerEvidenceTools.js +15 -22
- package/dist/server/registerFunctionComparisonTool.js +30 -25
- package/dist/server/registerInvestigationTools/helpers.js +3 -32
- package/dist/server/registerInvestigationTools.js +20 -116
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +6 -4
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +15 -17
- package/dist/server/registerManagedWorkflowTools/evidence.js +19 -35
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -8
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +3 -8
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +10 -14
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +9 -15
- package/dist/server/registerOfficialTools.js +1 -43
- package/dist/server/registerProcessComparisonTool.js +33 -23
- package/dist/server/registerPrompts.js +19 -17
- package/dist/server/registerSessionRecordTools.js +10 -156
- package/dist/server/registerSessionStatusTool.js +6 -69
- package/dist/server/registerSessionTools.js +10 -51
- package/dist/server/sessionAvailabilityPolicy.js +0 -2
- package/dist/server/sessionEvidence.js +9 -15
- package/dist/server/sessionToolPolicies.js +0 -8
- package/dist/server/toolResult.js +14 -50
- package/dist/serverIdentity.js +0 -20
- package/install.sh +1 -1
- package/package.json +11 -7
- package/scripts/electron-active-hook.cjs +23 -55
- package/scripts/hopper-demo-x11.py +13 -32
- package/skills/reverse-engineer-anything/SKILL.md +47 -12
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +6 -4
- package/skills/reverse-engineer-anything/references/javascript-applications.md +13 -13
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +12 -8
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +0 -188
- package/dist/application/BoundedJsonFiles.js +0 -86
- package/dist/application/CrossVersionInventory.js +0 -129
- package/dist/application/CrossVersionInvestigation.js +0 -301
- package/dist/application/CrossVersionInvestigationCollections.js +0 -23
- package/dist/application/CrossVersionInvestigationEvidence.js +0 -64
- package/dist/application/CrossVersionInvestigationReplay.js +0 -170
- package/dist/application/DeferredFileAuthorization.js +0 -61
- package/dist/application/DoctorProjection.js +0 -43
- package/dist/application/EnhancedToolPagination.js +0 -22
- package/dist/application/EvidenceReferenceResolver.js +0 -26
- package/dist/application/InvestigationWorkspaceStore.js +0 -204
- package/dist/application/ProcessPairedExperiment.js +0 -72
- package/dist/application/ReconstructionCoverageWorkspaceStore.js +0 -31
- package/dist/application/ReconstructionReadinessService.js +0 -48
- package/dist/cliInvestigationCommands.js +0 -173
- package/dist/domain/boundedCartesianProjection.js +0 -15
- package/dist/domain/investigationWorkspace.js +0 -347
- package/dist/domain/jsonLimits.js +0 -26
- package/dist/domain/knownPageCoverage.js +0 -29
- package/dist/domain/processPairedExperiment.js +0 -128
- package/dist/server/javascriptApplicationResult.js +0 -106
- package/dist/server/permissionFailure.js +0 -12
- package/dist/server/registerApplicationTools/readiness.js +0 -50
- package/dist/server/registerEvidenceResources.js +0 -315
- package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -65
- package/dist/server/registerReconstructionObligationLedgerResource.js +0 -32
- package/dist/server/registerReconstructionReadinessResource.js +0 -32
|
@@ -8,15 +8,18 @@ export const ABORTED = Symbol("aborted");
|
|
|
8
8
|
export const waitForAbortable = async (pending, signal) => {
|
|
9
9
|
if (signal === undefined)
|
|
10
10
|
return pending;
|
|
11
|
-
if (signal.aborted)
|
|
12
|
-
return ABORTED;
|
|
13
11
|
let onAbort;
|
|
14
12
|
const cancelled = new Promise((resolve) => {
|
|
13
|
+
if (signal.aborted) {
|
|
14
|
+
resolve(ABORTED);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
15
17
|
onAbort = () => resolve(ABORTED);
|
|
16
18
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
17
19
|
});
|
|
18
20
|
try {
|
|
19
|
-
|
|
21
|
+
// Even an already-cancelled wait must own the producer's eventual rejection.
|
|
22
|
+
return await Promise.race([cancelled, pending]);
|
|
20
23
|
}
|
|
21
24
|
finally {
|
|
22
25
|
if (onAbort !== undefined)
|
|
@@ -76,7 +76,6 @@ export class AnalysisSnapshotCache {
|
|
|
76
76
|
if (target === undefined || profile === undefined)
|
|
77
77
|
return err(new NoBinaryOpenError());
|
|
78
78
|
return ok({
|
|
79
|
-
snapshot_version: 2,
|
|
80
79
|
target: snapshotTarget(target),
|
|
81
80
|
binding: snapshotBinding(profile),
|
|
82
81
|
entries: this.entries(),
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { parseAnalysisSnapshot, serializeAnalysisSnapshot, } from "../domain/analysisSnapshot.js";
|
|
2
2
|
import { EvidenceFileError, EvidenceIntegrityError } from "../domain/errors.js";
|
|
3
3
|
import { err, ok } from "../domain/result.js";
|
|
4
|
-
import {
|
|
5
|
-
/** Read and validate
|
|
6
|
-
export const readAnalysisSnapshot = async (path
|
|
7
|
-
const loaded = await
|
|
4
|
+
import { readJsonFile, writeTextFile } from "./JsonFiles.js";
|
|
5
|
+
/** Read and validate an analysis snapshot from the caller's path. */
|
|
6
|
+
export const readAnalysisSnapshot = async (path) => {
|
|
7
|
+
const loaded = await readJsonFile(path);
|
|
8
8
|
if (!loaded.ok)
|
|
9
9
|
return loaded;
|
|
10
10
|
try {
|
|
@@ -14,8 +14,8 @@ export const readAnalysisSnapshot = async (path, policy) => {
|
|
|
14
14
|
return err(new EvidenceIntegrityError(snapshotValidationMessage(cause), { cause }));
|
|
15
15
|
}
|
|
16
16
|
};
|
|
17
|
-
/** Atomically write a deterministic analysis snapshot
|
|
18
|
-
export const writeAnalysisSnapshot = async (snapshot, path, overwrite
|
|
17
|
+
/** Atomically write a deterministic analysis snapshot to the caller's path. */
|
|
18
|
+
export const writeAnalysisSnapshot = async (snapshot, path, overwrite) => {
|
|
19
19
|
let encoded;
|
|
20
20
|
try {
|
|
21
21
|
encoded = serializeAnalysisSnapshot(snapshot);
|
|
@@ -23,7 +23,7 @@ export const writeAnalysisSnapshot = async (snapshot, path, overwrite, policy) =
|
|
|
23
23
|
catch (cause) {
|
|
24
24
|
return err(new EvidenceIntegrityError(snapshotValidationMessage(cause), { cause }));
|
|
25
25
|
}
|
|
26
|
-
return
|
|
26
|
+
return writeTextFile(encoded, path, overwrite);
|
|
27
27
|
};
|
|
28
28
|
const snapshotValidationMessage = (cause) => cause instanceof TypeError
|
|
29
29
|
? cause.message
|
|
@@ -9,7 +9,7 @@ export const projectAndroidApplicationEvidence = (rawInput) => {
|
|
|
9
9
|
schema: androidApplicationProjectionInputSchema,
|
|
10
10
|
project: projectAndroidApplication,
|
|
11
11
|
operation: OPERATION,
|
|
12
|
-
predicateType: "rea.android-application-graph
|
|
12
|
+
predicateType: "rea.android-application-graph",
|
|
13
13
|
provider: ANDROID_APPLICATION_PROVIDER,
|
|
14
14
|
subjectFormat: () => "apk",
|
|
15
15
|
protocolError: "Android application projection produced an invalid result",
|
|
@@ -9,7 +9,7 @@ export const projectAppleApplicationEvidence = (rawInput) => {
|
|
|
9
9
|
schema: appleApplicationProjectionInputSchema,
|
|
10
10
|
project: projectAppleApplication,
|
|
11
11
|
operation: OPERATION,
|
|
12
|
-
predicateType: "rea.apple-application-graph
|
|
12
|
+
predicateType: "rea.apple-application-graph",
|
|
13
13
|
provider: APPLE_APPLICATION_PROVIDER,
|
|
14
14
|
subjectFormat: () => "ipa",
|
|
15
15
|
protocolError: "Apple application projection produced an invalid result",
|
|
@@ -8,26 +8,35 @@ import { ZipArtifactReader } from "../artifacts/ZipArtifactReader.js";
|
|
|
8
8
|
import { MachOSliceArtifactReader } from "../artifacts/MachOSliceArtifactReader.js";
|
|
9
9
|
import { artifactExtractionResultSchema, } from "../domain/artifactGraph.js";
|
|
10
10
|
import { scanArtifactInventory } from "./ArtifactInventory.js";
|
|
11
|
-
import { digestCanonical
|
|
12
|
-
|
|
13
|
-
/** Extract selected inventory occurrences into an exclusively owned absent root. */
|
|
11
|
+
import { digestCanonical } from "./ArtifactGraphConstruction.js";
|
|
12
|
+
/** Extract every regular inventory occurrence into an exclusively owned absent root. */
|
|
14
13
|
export const extractArtifact = async (input, signal) => {
|
|
15
|
-
validateSelection(input.occurrenceIds);
|
|
16
14
|
const sourcePath = await realpath(input.inputPath);
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
const snapshot = await scanArtifactInventory(sourcePath, {
|
|
16
|
+
signal,
|
|
17
|
+
});
|
|
18
|
+
const selectedOccurrences = snapshot.occurrences.filter((occurrence) => (occurrence.entry_kind === "file" || occurrence.entry_kind === "slice") &&
|
|
19
|
+
occurrence.logical_path !== ".");
|
|
20
|
+
const selectedIds = new Set(selectedOccurrences.map(({ occurrence_id: id }) => id));
|
|
21
|
+
const occurrences = new Map();
|
|
22
|
+
const neededNodes = new Set();
|
|
23
|
+
collectOccurrences(snapshot.occurrences, selectedIds, occurrences, neededNodes);
|
|
24
|
+
const nodes = new Map();
|
|
25
|
+
collectNodes(snapshot.nodes, neededNodes, nodes);
|
|
26
|
+
const inventory = {
|
|
27
|
+
manifest: snapshot.manifest,
|
|
28
|
+
occurrences,
|
|
29
|
+
nodes,
|
|
30
|
+
};
|
|
31
|
+
const selected = selectedOccurrences.map((occurrence) => {
|
|
23
32
|
if ((occurrence.entry_kind !== "file" && occurrence.entry_kind !== "slice") ||
|
|
24
33
|
occurrence.artifact_id === null ||
|
|
25
34
|
occurrence.encrypted ||
|
|
26
35
|
occurrence.logical_path === ".")
|
|
27
|
-
throw new ArtifactReaderFailure("format", `Selected occurrence is not an extractable regular child file: ${
|
|
36
|
+
throw new ArtifactReaderFailure("format", `Selected occurrence is not an extractable regular child file: ${occurrence.occurrence_id}`);
|
|
28
37
|
const node = inventory.nodes.get(occurrence.artifact_id);
|
|
29
38
|
if (node === undefined)
|
|
30
|
-
throw new ArtifactReaderFailure("integrity", `Selected occurrence has no inventory node: ${
|
|
39
|
+
throw new ArtifactReaderFailure("integrity", `Selected occurrence has no inventory node: ${occurrence.occurrence_id}`);
|
|
31
40
|
return { occurrence, node };
|
|
32
41
|
});
|
|
33
42
|
return materializeSelection({
|
|
@@ -41,23 +50,22 @@ export const extractArtifact = async (input, signal) => {
|
|
|
41
50
|
const materializeSelection = async ({ input, sourcePath, inventory, selected, signal, }) => {
|
|
42
51
|
const byPath = new Map(selected.map((item) => [item.occurrence.logical_path, item]));
|
|
43
52
|
const reader = await createReader(sourcePath, input.inputFormat);
|
|
44
|
-
const output = await SafeOutputTree.create(input.outputRoot
|
|
53
|
+
const output = await SafeOutputTree.create(input.outputRoot);
|
|
45
54
|
let readerClosed = false;
|
|
46
55
|
const extracted = [];
|
|
47
56
|
try {
|
|
48
|
-
const
|
|
57
|
+
const materialized = [];
|
|
49
58
|
const registry = new ArtifactPathRegistry();
|
|
50
|
-
let entryCount = 0;
|
|
51
59
|
for await (const entry of reader.entries(signal)) {
|
|
52
|
-
|
|
53
|
-
if (entryCount > input.limits.maxEntries)
|
|
54
|
-
throw new ArtifactReaderFailure("limit", "Artifact entry limit exceeded during extraction");
|
|
55
|
-
const path = normalizeArtifactPath(entry.path, input.limits);
|
|
60
|
+
const path = normalizeArtifactPath(entry.path);
|
|
56
61
|
registry.add(path, entry.kind);
|
|
57
62
|
const selectedItem = byPath.get(path);
|
|
58
|
-
if (selectedItem === undefined)
|
|
63
|
+
if (selectedItem === undefined) {
|
|
64
|
+
if (entry.kind === "file" || entry.kind === "slice")
|
|
65
|
+
throw new ArtifactReaderFailure("integrity", `Regular artifact entry is missing from inventory: ${path}`);
|
|
59
66
|
continue;
|
|
60
|
-
|
|
67
|
+
}
|
|
68
|
+
preflight(entry);
|
|
61
69
|
const stream = await reader.open(entry, signal);
|
|
62
70
|
const written = await output.write(path, stream, selectedItem.node.sha256, signal);
|
|
63
71
|
extracted.push({
|
|
@@ -67,14 +75,12 @@ const materializeSelection = async ({ input, sourcePath, inventory, selected, si
|
|
|
67
75
|
bytes_written: written.bytesWritten,
|
|
68
76
|
created: true,
|
|
69
77
|
});
|
|
70
|
-
|
|
78
|
+
materialized.push(selectedItem);
|
|
71
79
|
}
|
|
72
|
-
if (found.size !== selected.length)
|
|
73
|
-
throw new ArtifactReaderFailure("integrity", "Selected inventory occurrence disappeared before extraction");
|
|
74
80
|
await reader.close();
|
|
75
81
|
readerClosed = true;
|
|
76
82
|
extracted.sort((left, right) => left.relative_path.localeCompare(right.relative_path, "en"));
|
|
77
|
-
const result = createExtractionResult(input, inventory,
|
|
83
|
+
const result = createExtractionResult(input, inventory, materialized, extracted);
|
|
78
84
|
await output.commit();
|
|
79
85
|
return result;
|
|
80
86
|
}
|
|
@@ -87,7 +93,6 @@ const materializeSelection = async ({ input, sourcePath, inventory, selected, si
|
|
|
87
93
|
};
|
|
88
94
|
const createExtractionResult = (input, inventory, selected, extracted) => {
|
|
89
95
|
const extractionSemantic = {
|
|
90
|
-
schema_version: 1,
|
|
91
96
|
source_manifest_id: inventory.manifest.manifest_id,
|
|
92
97
|
selected_occurrence_ids: selected
|
|
93
98
|
.map(({ occurrence }) => occurrence.occurrence_id)
|
|
@@ -101,26 +106,16 @@ const createExtractionResult = (input, inventory, selected, extracted) => {
|
|
|
101
106
|
...extractionSemantic,
|
|
102
107
|
extraction_id: `aex_${digestCanonical(extractionSemantic)}`,
|
|
103
108
|
},
|
|
104
|
-
output_root:
|
|
105
|
-
artifacts:
|
|
109
|
+
output_root: input.outputRoot,
|
|
110
|
+
artifacts: extracted,
|
|
106
111
|
containment_verified: true,
|
|
107
112
|
cleanup: { attempted: false, verified: true, residual_paths: [] },
|
|
108
|
-
limits: toOutputLimits(input.limits),
|
|
109
113
|
provenance: [],
|
|
110
114
|
limitations: [
|
|
111
|
-
"
|
|
115
|
+
"All regular files in the active artifact were materialized; nested archive contents remain represented by their containing file.",
|
|
112
116
|
],
|
|
113
117
|
});
|
|
114
118
|
};
|
|
115
|
-
const loadInventory = async (path, limits, selectedIds, signal) => {
|
|
116
|
-
const snapshot = await scanArtifactInventory(path, limits, { signal });
|
|
117
|
-
const occurrences = new Map();
|
|
118
|
-
const neededNodes = new Set();
|
|
119
|
-
collectOccurrences(snapshot.occurrences, selectedIds, occurrences, neededNodes);
|
|
120
|
-
const nodes = new Map();
|
|
121
|
-
collectNodes(snapshot.nodes, neededNodes, nodes);
|
|
122
|
-
return { manifest: snapshot.manifest, occurrences, nodes };
|
|
123
|
-
};
|
|
124
119
|
const collectOccurrences = (items, selected, output, neededNodes) => {
|
|
125
120
|
for (const item of items) {
|
|
126
121
|
if (!selected.has(item.occurrence_id))
|
|
@@ -150,21 +145,7 @@ const createReader = async (path, format) => {
|
|
|
150
145
|
return new MachOSliceArtifactReader(path);
|
|
151
146
|
throw new ArtifactReaderFailure("unavailable", `Artifact format has no extraction reader: ${format}`);
|
|
152
147
|
};
|
|
153
|
-
const
|
|
154
|
-
if (ids.length === 0 || ids.length > PAGE_SIZE)
|
|
155
|
-
throw new ArtifactReaderFailure("limit", "Extraction requires 1 to 500 explicitly selected occurrences");
|
|
156
|
-
if (new Set(ids).size !== ids.length)
|
|
157
|
-
throw new ArtifactReaderFailure("path", "Extraction occurrence selection contains duplicates");
|
|
158
|
-
};
|
|
159
|
-
const preflight = (entry, limits) => {
|
|
148
|
+
const preflight = (entry) => {
|
|
160
149
|
if ((entry.kind !== "file" && entry.kind !== "slice") || entry.encrypted)
|
|
161
150
|
throw new ArtifactReaderFailure("format", `Selected artifact entry cannot be read: ${entry.path}`);
|
|
162
|
-
if (entry.declaredSize !== null && entry.declaredSize > limits.maxEntryBytes)
|
|
163
|
-
throw new ArtifactReaderFailure("limit", `Selected artifact exceeds byte limit: ${entry.path}`);
|
|
164
|
-
if (entry.declaredSize !== null &&
|
|
165
|
-
entry.compressedSize !== null &&
|
|
166
|
-
(entry.compressedSize === 0
|
|
167
|
-
? entry.declaredSize > 0
|
|
168
|
-
: entry.declaredSize / entry.compressedSize > limits.maxCompressionRatio))
|
|
169
|
-
throw new ArtifactReaderFailure("limit", `Selected artifact exceeds compression ratio limit: ${entry.path}`);
|
|
170
151
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
/** Choose a fresh temporary destination for an artifact extraction. */
|
|
5
|
+
export const createArtifactExtractionDestination = () => join(tmpdir(), `rea-extracted-${randomUUID()}`);
|
|
6
|
+
/** Stable parent scope used to authorize REA-owned extraction destinations. */
|
|
7
|
+
export const artifactExtractionPermissionRoot = () => tmpdir();
|
|
8
|
+
/** Stable filesystem scope for the destination selected internally by REA. */
|
|
9
|
+
export const artifactExtractionPermissionRequest = () => ({
|
|
10
|
+
capability: "artifact_extract",
|
|
11
|
+
roots: [artifactExtractionPermissionRoot()],
|
|
12
|
+
executables: [],
|
|
13
|
+
environment_names: [],
|
|
14
|
+
network: "none",
|
|
15
|
+
mount: false,
|
|
16
|
+
operation_identity: "extract_artifact:temporary_output",
|
|
17
|
+
});
|
|
@@ -19,7 +19,7 @@ export const createOccurrence = (entry, path, parent) => ({
|
|
|
19
19
|
compressed_size: entry.compressedSize,
|
|
20
20
|
executable: entry.executable,
|
|
21
21
|
encrypted: entry.encrypted,
|
|
22
|
-
hash_status: entry.encrypted ? "unavailable" : "not-hashed
|
|
22
|
+
hash_status: entry.encrypted ? "unavailable" : "not-hashed",
|
|
23
23
|
source_location: entry.byteOffset === null || entry.declaredSize === null
|
|
24
24
|
? null
|
|
25
25
|
: { offset: entry.byteOffset, length: entry.declaredSize },
|
|
@@ -82,7 +82,7 @@ export const createRootNode = (input) => createArtifactNode({
|
|
|
82
82
|
contentState: "materialized",
|
|
83
83
|
});
|
|
84
84
|
export const createArtifactNode = (input) => ({
|
|
85
|
-
artifact_id: `art_${digestCanonical({
|
|
85
|
+
artifact_id: `art_${digestCanonical({ sha256: input.sha256 })}`,
|
|
86
86
|
kind: input.kind,
|
|
87
87
|
format: input.format,
|
|
88
88
|
sha256: input.sha256,
|
|
@@ -222,21 +222,6 @@ export const classifyArtifactContent = (path, prefix) => {
|
|
|
222
222
|
};
|
|
223
223
|
return byPath;
|
|
224
224
|
};
|
|
225
|
-
export const pageOf = (items, offset, limit) => ({
|
|
226
|
-
items: items.slice(offset, offset + limit),
|
|
227
|
-
offset,
|
|
228
|
-
limit,
|
|
229
|
-
total: items.length,
|
|
230
|
-
next_offset: offset + limit < items.length ? offset + limit : null,
|
|
231
|
-
});
|
|
232
|
-
export const toOutputLimits = (limits) => ({
|
|
233
|
-
max_entries: limits.maxEntries,
|
|
234
|
-
max_total_bytes: limits.maxTotalBytes,
|
|
235
|
-
max_entry_bytes: limits.maxEntryBytes,
|
|
236
|
-
max_compression_ratio: limits.maxCompressionRatio,
|
|
237
|
-
max_depth: limits.maxDepth,
|
|
238
|
-
max_path_bytes: limits.maxPathBytes,
|
|
239
|
-
});
|
|
240
225
|
export const digestCanonical = (value) => {
|
|
241
226
|
const encoded = canonicalize(value);
|
|
242
227
|
if (encoded === undefined)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { open } from "node:fs/promises";
|
|
2
2
|
import { classifyArtifactPath } from "../ArtifactGraphConstruction.js";
|
|
3
|
-
import { zipPackageFormatForPath } from "../../domain/zipPackageFormat.js";
|
|
3
|
+
import { hasZipSignature, zipPackageFormatForPath, } from "../../domain/zipPackageFormat.js";
|
|
4
4
|
const classifyContainerExtension = (path) => {
|
|
5
5
|
const lower = path.toLowerCase();
|
|
6
6
|
const zipPackage = zipPackageFormatForPath(lower);
|
|
@@ -21,11 +21,7 @@ export const classifyRoot = async (path, directory) => {
|
|
|
21
21
|
try {
|
|
22
22
|
const magic = Buffer.alloc(4);
|
|
23
23
|
const observed = await handle.read(magic, 0, magic.length, 0);
|
|
24
|
-
if (observed.bytesRead
|
|
25
|
-
magic[0] === 0x50 &&
|
|
26
|
-
magic[1] === 0x4b &&
|
|
27
|
-
[0x03, 0x05, 0x07].includes(magic[2] ?? -1) &&
|
|
28
|
-
[0x04, 0x06, 0x08].includes(magic[3] ?? -1))
|
|
24
|
+
if (hasZipSignature(magic.subarray(0, observed.bytesRead)))
|
|
29
25
|
return "zip";
|
|
30
26
|
if (observed.bytesRead === 4) {
|
|
31
27
|
const header = magic.readUInt32BE(0);
|
|
@@ -1,25 +1,11 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { ArtifactReaderFailure
|
|
2
|
+
import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js";
|
|
3
3
|
import { streamChunkToBuffer } from "../../artifacts/StreamBytes.js";
|
|
4
4
|
export const abortIfNeeded = (signal) => {
|
|
5
5
|
if (signal?.aborted === true)
|
|
6
6
|
throw new ArtifactReaderFailure("cancelled", "Artifact inventory cancelled");
|
|
7
7
|
};
|
|
8
|
-
export const
|
|
9
|
-
if (entry.declaredSize !== null && entry.declaredSize > limits.maxEntryBytes)
|
|
10
|
-
throw new ArtifactReaderFailure("limit", `Entry exceeds byte limit: ${entry.path}`);
|
|
11
|
-
if (entry.declaredSize !== null &&
|
|
12
|
-
entry.compressedSize !== null &&
|
|
13
|
-
entry.compressedSize === 0 &&
|
|
14
|
-
entry.declaredSize > 0)
|
|
15
|
-
throw new ArtifactReaderFailure("limit", `Invalid compression ratio: ${entry.path}`);
|
|
16
|
-
if (entry.declaredSize !== null &&
|
|
17
|
-
entry.compressedSize !== null &&
|
|
18
|
-
entry.compressedSize > 0 &&
|
|
19
|
-
entry.declaredSize / entry.compressedSize > limits.maxCompressionRatio)
|
|
20
|
-
throw new ArtifactReaderFailure("limit", `Compression ratio exceeds limit: ${entry.path}`);
|
|
21
|
-
};
|
|
22
|
-
export const hashReadable = async (stream, maximum, signal) => {
|
|
8
|
+
export const hashReadable = async (stream, signal) => {
|
|
23
9
|
const hash = createHash("sha256");
|
|
24
10
|
const prefixes = [];
|
|
25
11
|
let prefixBytes = 0;
|
|
@@ -28,10 +14,6 @@ export const hashReadable = async (stream, maximum, signal) => {
|
|
|
28
14
|
abortIfNeeded(signal);
|
|
29
15
|
const chunk = streamChunkToBuffer(raw);
|
|
30
16
|
bytes += chunk.length;
|
|
31
|
-
if (bytes > maximum) {
|
|
32
|
-
stream.destroy();
|
|
33
|
-
throw new ArtifactReaderFailure("limit", "Observed entry bytes exceed limit");
|
|
34
|
-
}
|
|
35
17
|
hash.update(chunk);
|
|
36
18
|
if (prefixBytes < 16) {
|
|
37
19
|
const selected = chunk.subarray(0, 16 - prefixBytes);
|
|
@@ -2,29 +2,28 @@ import { createReadStream } from "node:fs";
|
|
|
2
2
|
import { lstat } from "node:fs/promises";
|
|
3
3
|
import { ArtifactReaderFailure, } from "../../artifacts/ArtifactReader.js";
|
|
4
4
|
import { artifactInventoryResultSchema, } from "../../domain/artifactGraph.js";
|
|
5
|
-
import { createArtifactEdges, createRootNode, digestCanonical, indexOccurrencesByPath, materializeDirectoryNodes, rekeyOccurrences, rootOccurrenceFor,
|
|
5
|
+
import { createArtifactEdges, createRootNode, digestCanonical, indexOccurrencesByPath, materializeDirectoryNodes, rekeyOccurrences, rootOccurrenceFor, } from "../ArtifactGraphConstruction.js";
|
|
6
6
|
import { classifyRoot } from "./classify.js";
|
|
7
7
|
import { hashReadable } from "./hash.js";
|
|
8
8
|
import { createReader, inventoryLimitations } from "./reader.js";
|
|
9
9
|
import { scanReader, } from "./scanReader.js";
|
|
10
10
|
import { NATIVE_MOUNT_DISABLED, STRICT_INTEGRITY_POLICY, } from "./types.js";
|
|
11
|
-
export const scanCanonicalArtifactInventory = async (path,
|
|
11
|
+
export const scanCanonicalArtifactInventory = async (path, options = {}) => {
|
|
12
12
|
const integrity = options.integrity ?? STRICT_INTEGRITY_POLICY;
|
|
13
13
|
const metadata = await lstat(path);
|
|
14
14
|
const rootFormat = await classifyRoot(path, metadata.isDirectory());
|
|
15
15
|
const rootDigest = metadata.isDirectory()
|
|
16
16
|
? null
|
|
17
|
-
: await hashReadable(createReadStream(path),
|
|
17
|
+
: await hashReadable(createReadStream(path), options.signal);
|
|
18
18
|
const reader = await createReader(path, rootFormat, options.nativeMount ?? NATIVE_MOUNT_DISABLED, options.signal);
|
|
19
19
|
try {
|
|
20
|
-
const { nodes, occurrences, pendingContradictions } = await scanReader(reader,
|
|
20
|
+
const { nodes, occurrences, pendingContradictions } = await scanReader(reader, options.signal, integrity);
|
|
21
21
|
return await buildInventorySnapshot({
|
|
22
22
|
path,
|
|
23
23
|
metadata,
|
|
24
24
|
rootFormat,
|
|
25
25
|
rootDigest,
|
|
26
26
|
reader,
|
|
27
|
-
limits,
|
|
28
27
|
signal: options.signal,
|
|
29
28
|
nodes,
|
|
30
29
|
occurrences,
|
|
@@ -36,7 +35,7 @@ export const scanCanonicalArtifactInventory = async (path, limits, options = {})
|
|
|
36
35
|
}
|
|
37
36
|
};
|
|
38
37
|
const buildInventorySnapshot = async (input) => {
|
|
39
|
-
const { path, metadata, rootFormat, rootDigest, reader,
|
|
38
|
+
const { path, metadata, rootFormat, rootDigest, reader, signal } = input;
|
|
40
39
|
materializeDirectoryNodes(input.occurrences, input.nodes);
|
|
41
40
|
const rootNode = createRootNode({
|
|
42
41
|
path,
|
|
@@ -62,7 +61,7 @@ const buildInventorySnapshot = async (input) => {
|
|
|
62
61
|
const orderedNodes = sortNodes([...input.nodes.values()]);
|
|
63
62
|
const orderedOccurrences = sortOccurrences(input.occurrences);
|
|
64
63
|
const orderedEdges = sortEdges(edges);
|
|
65
|
-
await verifyRootDigest(path, rootDigest,
|
|
64
|
+
await verifyRootDigest(path, rootDigest, signal);
|
|
66
65
|
const graphSha256 = digestCanonical({
|
|
67
66
|
nodes: orderedNodes,
|
|
68
67
|
occurrences: orderedOccurrences,
|
|
@@ -81,7 +80,6 @@ const buildInventorySnapshot = async (input) => {
|
|
|
81
80
|
nodes: orderedNodes,
|
|
82
81
|
occurrences: orderedOccurrences,
|
|
83
82
|
edges: orderedEdges,
|
|
84
|
-
limits: toOutputLimits(limits),
|
|
85
83
|
provenance: reader?.provenance() ?? [],
|
|
86
84
|
integrity_contradictions: integrityContradictions,
|
|
87
85
|
limitations: buildLimitations(rootFormat, reader, integrityContradictions),
|
|
@@ -116,10 +114,10 @@ const buildIntegrityContradictions = (pending, occurrenceByPath, occurrenceById,
|
|
|
116
114
|
],
|
|
117
115
|
};
|
|
118
116
|
});
|
|
119
|
-
const verifyRootDigest = async (path, rootDigest,
|
|
117
|
+
const verifyRootDigest = async (path, rootDigest, signal) => {
|
|
120
118
|
if (rootDigest === null)
|
|
121
119
|
return;
|
|
122
|
-
const verified = await hashReadable(createReadStream(path),
|
|
120
|
+
const verified = await hashReadable(createReadStream(path), signal);
|
|
123
121
|
if (verified.sha256 !== rootDigest.sha256 ||
|
|
124
122
|
verified.bytes !== rootDigest.bytes)
|
|
125
123
|
throw new ArtifactReaderFailure("integrity", "Root artifact changed during inventory");
|
|
@@ -128,9 +126,7 @@ const sortNodes = (nodes) => nodes.sort((left, right) => left.artifact_id.locale
|
|
|
128
126
|
const sortOccurrences = (occurrences) => occurrences.sort((left, right) => left.logical_path.localeCompare(right.logical_path, "en"));
|
|
129
127
|
const sortEdges = (edges) => edges.sort((left, right) => left.edge_id.localeCompare(right.edge_id));
|
|
130
128
|
const buildManifest = ({ rootNode, graphSha256, orderedNodes, orderedOccurrences, orderedEdges, }) => artifactInventoryResultSchema.shape.manifest.parse({
|
|
131
|
-
schema_version: 1,
|
|
132
129
|
manifest_id: `agm_${digestCanonical({
|
|
133
|
-
schema_version: 1,
|
|
134
130
|
root_artifact_id: rootNode.artifact_id,
|
|
135
131
|
graph_sha256: graphSha256,
|
|
136
132
|
})}`,
|
|
@@ -3,16 +3,15 @@ import { ArtifactReaderFailure, } from "../../artifacts/ArtifactReader.js";
|
|
|
3
3
|
import { AsarArtifactReader } from "../../artifacts/AsarArtifactReader.js";
|
|
4
4
|
import { classifyArtifactContent, createArtifactNode, createOccurrence, nearestParent, } from "../ArtifactGraphConstruction.js";
|
|
5
5
|
import { STRICT_INTEGRITY_POLICY, } from "./types.js";
|
|
6
|
-
import { hashReadable
|
|
6
|
+
import { hashReadable } from "./hash.js";
|
|
7
7
|
const UNAVAILABLE_UNPACKED_LIMITATION = "ASAR unpacked companion bytes were unavailable; no content hash or child artifact was produced.";
|
|
8
8
|
const emptyScan = () => ({ nodes: new Map(), occurrences: [], pendingContradictions: [] });
|
|
9
|
-
export const scanReader = async (reader,
|
|
9
|
+
export const scanReader = async (reader, signal, integrity = STRICT_INTEGRITY_POLICY) => {
|
|
10
10
|
const { nodes, occurrences, pendingContradictions } = emptyScan();
|
|
11
11
|
if (reader === undefined)
|
|
12
12
|
return { nodes, occurrences, pendingContradictions };
|
|
13
13
|
const context = {
|
|
14
14
|
reader,
|
|
15
|
-
limits,
|
|
16
15
|
signal,
|
|
17
16
|
integrity,
|
|
18
17
|
nodes,
|
|
@@ -20,54 +19,84 @@ export const scanReader = async (reader, limits, signal, integrity = STRICT_INTE
|
|
|
20
19
|
pendingContradictions,
|
|
21
20
|
occurrenceByPath: new Map(),
|
|
22
21
|
registry: new ArtifactPathRegistry(),
|
|
23
|
-
totalBytes: 0,
|
|
24
22
|
};
|
|
25
23
|
await visitArtifactEntries(context, reader, "");
|
|
26
24
|
return { nodes, occurrences, pendingContradictions };
|
|
27
25
|
};
|
|
28
26
|
const visitArtifactEntries = async (context, currentReader, prefix) => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
27
|
+
const stack = [
|
|
28
|
+
{
|
|
29
|
+
reader: currentReader,
|
|
30
|
+
prefix,
|
|
31
|
+
iterator: currentReader.entries(context.signal)[Symbol.asyncIterator](),
|
|
32
|
+
owned: false,
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
try {
|
|
36
|
+
while (stack.length > 0) {
|
|
37
|
+
const frame = stack.at(-1);
|
|
38
|
+
if (frame === undefined)
|
|
39
|
+
break;
|
|
40
|
+
const next = await frame.iterator.next();
|
|
41
|
+
if (next.done) {
|
|
42
|
+
stack.pop();
|
|
43
|
+
if (frame.owned)
|
|
44
|
+
await frame.reader.close();
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const entry = next.value;
|
|
48
|
+
const logicalPath = normalizeArtifactPath(frame.prefix.length === 0
|
|
49
|
+
? entry.path
|
|
50
|
+
: `${frame.prefix}/${entry.path}`);
|
|
51
|
+
const expandableAsar = isExpandableAsar(entry, logicalPath);
|
|
52
|
+
context.registry.add(logicalPath, expandableAsar ? "directory" : entry.kind);
|
|
53
|
+
const parent = nearestParent(logicalPath, context.occurrenceByPath);
|
|
54
|
+
const occurrence = createOccurrence(entry, logicalPath, parent?.occurrence_id ?? null);
|
|
55
|
+
let digested;
|
|
56
|
+
try {
|
|
57
|
+
digested = await digestArtifactEntry(context, frame.reader, entry, logicalPath);
|
|
58
|
+
}
|
|
59
|
+
catch (cause) {
|
|
60
|
+
if (!isUnavailableUnpackedEntry(cause, entry))
|
|
61
|
+
throw cause;
|
|
62
|
+
occurrence.hash_status = "unavailable";
|
|
63
|
+
occurrence.limitations.push(UNAVAILABLE_UNPACKED_LIMITATION);
|
|
64
|
+
}
|
|
65
|
+
if (digested !== undefined) {
|
|
66
|
+
context.nodes.set(digested.node.artifact_id, digested.node);
|
|
67
|
+
occurrence.artifact_id = digested.node.artifact_id;
|
|
68
|
+
occurrence.hash_status = digested.mismatched
|
|
69
|
+
? "mismatched"
|
|
70
|
+
: "verified";
|
|
71
|
+
if (digested.mismatched)
|
|
72
|
+
occurrence.limitations.push("Declared integrity metadata contradicts observed bytes.");
|
|
73
|
+
}
|
|
74
|
+
context.occurrences.push(occurrence);
|
|
75
|
+
context.occurrenceByPath.set(logicalPath, occurrence);
|
|
76
|
+
if (expandableAsar && digested?.mismatched !== true) {
|
|
77
|
+
const nested = new AsarArtifactReader(entry.adapterKey);
|
|
78
|
+
stack.push({
|
|
79
|
+
reader: nested,
|
|
80
|
+
prefix: logicalPath,
|
|
81
|
+
iterator: nested.entries(context.signal)[Symbol.asyncIterator](),
|
|
82
|
+
owned: true,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
54
85
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
await Promise.allSettled(stack
|
|
89
|
+
.filter(({ owned }) => owned)
|
|
90
|
+
.map(async ({ reader, iterator }) => {
|
|
91
|
+
await iterator.return?.();
|
|
92
|
+
await reader.close();
|
|
93
|
+
}));
|
|
59
94
|
}
|
|
60
95
|
};
|
|
61
96
|
const digestArtifactEntry = async (context, currentReader, entry, logicalPath) => {
|
|
62
97
|
if ((entry.kind !== "file" && entry.kind !== "slice") || entry.encrypted)
|
|
63
98
|
return undefined;
|
|
64
|
-
const
|
|
65
|
-
if (remainingBytes <= 0)
|
|
66
|
-
throw new ArtifactReaderFailure("limit", "Artifact total byte limit exceeded");
|
|
67
|
-
if (entry.declaredSize !== null && entry.declaredSize > remainingBytes)
|
|
68
|
-
throw new ArtifactReaderFailure("limit", "Declared artifact bytes exceed remaining cumulative limit");
|
|
69
|
-
const digest = await hashReadable(await currentReader.open(entry, context.signal), Math.min(context.limits.maxEntryBytes, remainingBytes), context.signal);
|
|
70
|
-
context.totalBytes += digest.bytes;
|
|
99
|
+
const digest = await hashReadable(await currentReader.open(entry, context.signal), context.signal);
|
|
71
100
|
const mismatched = entry.declaredSha256 !== null && entry.declaredSha256 !== digest.sha256;
|
|
72
101
|
if (mismatched && entry.declaredSha256 !== null) {
|
|
73
102
|
if (context.integrity.mode === "fail")
|
|
@@ -77,8 +106,6 @@ const digestArtifactEntry = async (context, currentReader, entry, logicalPath) =
|
|
|
77
106
|
calculatedSha256: digest.sha256,
|
|
78
107
|
unpacked: entry.unpacked,
|
|
79
108
|
});
|
|
80
|
-
if (context.pendingContradictions.length >= context.integrity.maxMismatches)
|
|
81
|
-
throw new ArtifactReaderFailure("limit", "Artifact integrity mismatch limit exceeded");
|
|
82
109
|
context.pendingContradictions.push({
|
|
83
110
|
logicalPath,
|
|
84
111
|
declaredSha256: entry.declaredSha256,
|
|
@@ -107,15 +134,6 @@ const digestArtifactEntry = async (context, currentReader, entry, logicalPath) =
|
|
|
107
134
|
mismatched,
|
|
108
135
|
};
|
|
109
136
|
};
|
|
110
|
-
const visitNestedAsar = async (context, adapterKey, logicalPath) => {
|
|
111
|
-
const nested = new AsarArtifactReader(adapterKey);
|
|
112
|
-
try {
|
|
113
|
-
await visitArtifactEntries(context, nested, logicalPath);
|
|
114
|
-
}
|
|
115
|
-
finally {
|
|
116
|
-
await nested.close();
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
137
|
const isExpandableAsar = (entry, logicalPath) => entry.kind === "file" &&
|
|
120
138
|
logicalPath.toLowerCase().endsWith(".asar") &&
|
|
121
139
|
entry.adapterKey.startsWith("/");
|
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
import { realpath } from "node:fs/promises";
|
|
2
2
|
import { artifactInventoryResultSchema, } from "../domain/artifactGraph.js";
|
|
3
|
-
import { pageOf } from "./ArtifactGraphConstruction.js";
|
|
4
3
|
import { abortIfNeeded } from "./ArtifactInventory/hash.js";
|
|
5
4
|
import { scanCanonicalArtifactInventory } from "./ArtifactInventory/scanCanonical.js";
|
|
6
5
|
export { scanCanonicalArtifactInventory } from "./ArtifactInventory/scanCanonical.js";
|
|
7
|
-
/** Inventory one local artifact
|
|
8
|
-
export const inventoryArtifact = async (inputPath,
|
|
9
|
-
const snapshot = await scanArtifactInventory(inputPath,
|
|
10
|
-
return
|
|
6
|
+
/** Inventory one local artifact and return every graph collection inline. */
|
|
7
|
+
export const inventoryArtifact = async (inputPath, options = {}) => {
|
|
8
|
+
const snapshot = await scanArtifactInventory(inputPath, options);
|
|
9
|
+
return artifactInventoryResultSchema.parse(snapshot);
|
|
11
10
|
};
|
|
12
11
|
/** Scan an artifact once and retain the complete immutable graph for projection. */
|
|
13
|
-
export const scanArtifactInventory = async (inputPath,
|
|
12
|
+
export const scanArtifactInventory = async (inputPath, options = {}) => {
|
|
14
13
|
abortIfNeeded(options.signal);
|
|
15
14
|
const path = await realpath(inputPath);
|
|
16
|
-
return scanCanonicalArtifactInventory(path,
|
|
15
|
+
return scanCanonicalArtifactInventory(path, options);
|
|
17
16
|
};
|
|
18
|
-
/** Project independently paged graph collections from one inventory snapshot. */
|
|
19
|
-
export const paginateArtifactInventory = (snapshot, page) => artifactInventoryResultSchema.parse({
|
|
20
|
-
...snapshot,
|
|
21
|
-
nodes: pageOf(snapshot.nodes, page.nodeOffset, page.nodeLimit),
|
|
22
|
-
occurrences: pageOf(snapshot.occurrences, page.occurrenceOffset, page.occurrenceLimit),
|
|
23
|
-
edges: pageOf(snapshot.edges, page.edgeOffset, page.edgeLimit),
|
|
24
|
-
});
|