rea-agents 3.1.0 → 3.2.1
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
package/dist/mcpDoctor.js
CHANGED
|
@@ -2,19 +2,18 @@ import { Client } from "@modelcontextprotocol/client";
|
|
|
2
2
|
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
|
|
3
3
|
import { Formatter } from "incur";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
|
-
import { CATALOG_IDENTITY
|
|
5
|
+
import { CATALOG_IDENTITY } from "./catalogIdentity.js";
|
|
6
6
|
import { PROMPT_CONTRACTS } from "./contracts/promptContracts.js";
|
|
7
7
|
import { TOOL_CONTRACTS } from "./contracts/toolContracts.js";
|
|
8
8
|
import { PRODUCT_IDENTITY } from "./identity.js";
|
|
9
9
|
import { MCP_STARTUP_POLICY } from "./mcpStartupPolicy.js";
|
|
10
|
-
const STDERR_LIMIT_BYTES = 64 * 1_024;
|
|
11
10
|
const OUTPUT_FORMATS = ["toon", "json", "yaml", "md", "jsonl"];
|
|
12
|
-
/** Diagnose the actual production stdio adapter with one bounded SDK session. */
|
|
11
|
+
/** Diagnose the actual production stdio adapter with one startup-bounded SDK session. */
|
|
13
12
|
export const runProductionMcpDoctor = async (options) => {
|
|
14
13
|
const deadline = Date.now() + (options.deadlineMs ?? MCP_STARTUP_POLICY.doctorDeadlineMs);
|
|
15
14
|
const controller = new AbortController();
|
|
16
15
|
const timer = setTimeout(() => controller.abort(new Error("Production MCP doctor deadline expired")), Math.max(1, deadline - Date.now()));
|
|
17
|
-
const stderr =
|
|
16
|
+
const stderr = captureStderr();
|
|
18
17
|
const transport = new TrackedStdioClientTransport({
|
|
19
18
|
command: options.command,
|
|
20
19
|
args: [...options.args],
|
|
@@ -56,21 +55,16 @@ export const runProductionMcpDoctor = async (options) => {
|
|
|
56
55
|
};
|
|
57
56
|
const inspectProductionMcpSession = async (client, deadline, signal) => {
|
|
58
57
|
const request = requestOptions(deadline, signal);
|
|
59
|
-
const [tools, prompts,
|
|
58
|
+
const [tools, prompts, requestFlow] = await Promise.all([
|
|
60
59
|
client.listTools(undefined, request),
|
|
61
60
|
client.listPrompts(undefined, request),
|
|
62
|
-
client.
|
|
63
|
-
client.listResourceTemplates(undefined, request),
|
|
64
|
-
client.readResource({ uri: "rea://server/identity" }, request),
|
|
65
|
-
client.callTool({ name: "binary_session", arguments: { detail: "full" } }, request),
|
|
61
|
+
client.callTool({ name: "binary_session", arguments: {} }, request),
|
|
66
62
|
]);
|
|
67
63
|
const inventory = {
|
|
68
64
|
tools: compareInventory(TOOL_CONTRACTS.map(({ name }) => name), tools.tools.map(({ name }) => name)),
|
|
69
65
|
prompts: compareInventory(PROMPT_CONTRACTS.map(({ name }) => name), prompts.prompts.map(({ name }) => name)),
|
|
70
|
-
resources: compareInventory(MCP_RESOURCE_CATALOG.map(({ name }) => name), resources.resources.map(({ name }) => name)),
|
|
71
|
-
resource_templates: compareInventory(MCP_RESOURCE_TEMPLATE_CATALOG.map(({ name }) => name), templates.resourceTemplates.map(({ name }) => name)),
|
|
72
66
|
};
|
|
73
|
-
const observedIdentity =
|
|
67
|
+
const observedIdentity = parseIdentityToolResult(requestFlow.structuredContent);
|
|
74
68
|
const serverVersion = client.getServerVersion();
|
|
75
69
|
const protocolVersion = client.getNegotiatedProtocolVersion();
|
|
76
70
|
const checks = [
|
|
@@ -161,29 +155,23 @@ const inventoryCheck = (name, comparison) => ({
|
|
|
161
155
|
comparison.duplicates.length === 0,
|
|
162
156
|
detail: `expected=${String(comparison.expected)} observed=${String(comparison.observed)} missing=${comparison.missing.join(",") || "none"} unexpected=${comparison.unexpected.join(",") || "none"} duplicates=${comparison.duplicates.join(",") || "none"}`,
|
|
163
157
|
});
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
if (!isRecord(first) || typeof first.text !== "string")
|
|
158
|
+
const parseIdentityToolResult = (input) => {
|
|
159
|
+
if (!isRecord(input) || !isRecord(input.result))
|
|
167
160
|
return { packageVersion: null, catalogDigest: null };
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (!isRecord(identity))
|
|
171
|
-
return { packageVersion: null, catalogDigest: null };
|
|
172
|
-
const packageIdentity = identity.package;
|
|
173
|
-
const catalog = identity.catalog;
|
|
174
|
-
const digests = isRecord(catalog) ? catalog.digests : undefined;
|
|
175
|
-
return {
|
|
176
|
-
packageVersion: isRecord(packageIdentity) && typeof packageIdentity.version === "string"
|
|
177
|
-
? packageIdentity.version
|
|
178
|
-
: null,
|
|
179
|
-
catalogDigest: isRecord(digests) && typeof digests.combined_sha256 === "string"
|
|
180
|
-
? digests.combined_sha256
|
|
181
|
-
: null,
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
catch {
|
|
161
|
+
const identity = input.result.server_identity;
|
|
162
|
+
if (!isRecord(identity))
|
|
185
163
|
return { packageVersion: null, catalogDigest: null };
|
|
186
|
-
|
|
164
|
+
const packageIdentity = identity.package;
|
|
165
|
+
const catalog = identity.catalog;
|
|
166
|
+
const digests = isRecord(catalog) ? catalog.digests : undefined;
|
|
167
|
+
return {
|
|
168
|
+
packageVersion: isRecord(packageIdentity) && typeof packageIdentity.version === "string"
|
|
169
|
+
? packageIdentity.version
|
|
170
|
+
: null,
|
|
171
|
+
catalogDigest: isRecord(digests) && typeof digests.combined_sha256 === "string"
|
|
172
|
+
? digests.combined_sha256
|
|
173
|
+
: null,
|
|
174
|
+
};
|
|
187
175
|
};
|
|
188
176
|
const parseOutputArguments = (arguments_) => {
|
|
189
177
|
let format = "toon";
|
|
@@ -234,28 +222,20 @@ const targetFreeEnvironment = (environment) => {
|
|
|
234
222
|
delete result[name];
|
|
235
223
|
return result;
|
|
236
224
|
};
|
|
237
|
-
const
|
|
238
|
-
|
|
225
|
+
const captureStderr = () => {
|
|
226
|
+
const chunks = [];
|
|
239
227
|
let bytes = 0;
|
|
240
|
-
let truncated = false;
|
|
241
228
|
return {
|
|
242
229
|
append(chunk) {
|
|
243
230
|
const buffer = Buffer.isBuffer(chunk)
|
|
244
231
|
? chunk
|
|
245
232
|
: Buffer.from(String(chunk), "utf8");
|
|
246
233
|
bytes += buffer.byteLength;
|
|
247
|
-
|
|
248
|
-
if (retained < STDERR_LIMIT_BYTES)
|
|
249
|
-
text += buffer
|
|
250
|
-
.subarray(0, STDERR_LIMIT_BYTES - retained)
|
|
251
|
-
.toString("utf8");
|
|
252
|
-
if (bytes > STDERR_LIMIT_BYTES)
|
|
253
|
-
truncated = true;
|
|
234
|
+
chunks.push(Buffer.from(buffer));
|
|
254
235
|
},
|
|
255
236
|
value: () => ({
|
|
256
|
-
stderr:
|
|
237
|
+
stderr: Buffer.concat(chunks, bytes).toString("utf8"),
|
|
257
238
|
stderr_bytes: bytes,
|
|
258
|
-
stderr_truncated: truncated,
|
|
259
239
|
}),
|
|
260
240
|
};
|
|
261
241
|
};
|
|
@@ -14,17 +14,17 @@ export class NativeCommandFailure extends Error {
|
|
|
14
14
|
this.exitCode = exitCode;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
/** Run allowlisted Xcode tools directly
|
|
17
|
+
/** Run allowlisted Xcode tools directly without a shell. */
|
|
18
18
|
export class XcrunCommandRunner {
|
|
19
19
|
resolveTool;
|
|
20
20
|
#resolved = new Map();
|
|
21
|
-
constructor(resolveTool = (tool) => resolveXcrunTool(tool)) {
|
|
21
|
+
constructor(resolveTool = (tool, signal) => resolveXcrunTool(tool, signal)) {
|
|
22
22
|
this.resolveTool = resolveTool;
|
|
23
23
|
}
|
|
24
24
|
run(tool, arguments_, options) {
|
|
25
25
|
if (!ALLOWED_TOOLS.has(tool))
|
|
26
26
|
return Promise.resolve(err(new NativeCommandFailure(tool, "unavailable")));
|
|
27
|
-
return this.#resolve(tool).then(async (resolved) => {
|
|
27
|
+
return this.#resolve(tool, options.signal).then(async (resolved) => {
|
|
28
28
|
if (!resolved.ok)
|
|
29
29
|
return resolved;
|
|
30
30
|
const captured = await captureProcess(resolved.value.path, arguments_, tool, options);
|
|
@@ -41,15 +41,13 @@ export class XcrunCommandRunner {
|
|
|
41
41
|
: captured;
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
|
-
async #resolve(tool) {
|
|
44
|
+
async #resolve(tool, signal) {
|
|
45
45
|
const existing = this.#resolved.get(tool);
|
|
46
46
|
if (existing !== undefined)
|
|
47
|
-
return existing;
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (!resolved.ok && this.#resolved.get(tool) === pending)
|
|
52
|
-
this.#resolved.delete(tool);
|
|
47
|
+
return ok(existing);
|
|
48
|
+
const resolved = await this.resolveTool(tool, signal);
|
|
49
|
+
if (resolved.ok)
|
|
50
|
+
this.#resolved.set(tool, resolved.value);
|
|
53
51
|
return resolved;
|
|
54
52
|
}
|
|
55
53
|
}
|
|
@@ -66,9 +64,14 @@ const ALLOWED_TOOLS = new Set([
|
|
|
66
64
|
"swift-demangle",
|
|
67
65
|
"vtool",
|
|
68
66
|
]);
|
|
69
|
-
const resolveXcrunTool = async (tool) => {
|
|
70
|
-
const found = await captureProcess("/usr/bin/xcrun", ["--find", tool], "xcrun",
|
|
71
|
-
if (!found.ok
|
|
67
|
+
const resolveXcrunTool = async (tool, signal) => {
|
|
68
|
+
const found = await captureProcess("/usr/bin/xcrun", ["--find", tool], "xcrun", signal === undefined ? {} : { signal });
|
|
69
|
+
if (!found.ok) {
|
|
70
|
+
if (found.error.reason === "cancelled")
|
|
71
|
+
return err(new NativeCommandFailure(tool, "cancelled"));
|
|
72
|
+
return err(new NativeCommandFailure(tool, "unavailable"));
|
|
73
|
+
}
|
|
74
|
+
if (found.value.exitCode !== 0)
|
|
72
75
|
return err(new NativeCommandFailure(tool, "unavailable"));
|
|
73
76
|
const candidate = found.value.stdout.trim();
|
|
74
77
|
if (!candidate.startsWith("/"))
|
|
@@ -107,7 +110,6 @@ const captureProcess = (executable, arguments_, tool, options) => new Promise((r
|
|
|
107
110
|
if (settled)
|
|
108
111
|
return;
|
|
109
112
|
settled = true;
|
|
110
|
-
clearTimeout(timeout);
|
|
111
113
|
options.signal?.removeEventListener("abort", onAbort);
|
|
112
114
|
resolve(result);
|
|
113
115
|
};
|
|
@@ -117,20 +119,13 @@ const captureProcess = (executable, arguments_, tool, options) => new Promise((r
|
|
|
117
119
|
};
|
|
118
120
|
const onAbort = () => stop("cancelled");
|
|
119
121
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
120
|
-
const timeout = setTimeout(() => stop("timeout"), options.timeoutMs);
|
|
121
122
|
child.stdout.on("data", (chunk) => {
|
|
122
123
|
stdoutBytes += chunk.length;
|
|
123
|
-
|
|
124
|
-
stop("output-limit");
|
|
125
|
-
else
|
|
126
|
-
stdout.push(chunk);
|
|
124
|
+
stdout.push(chunk);
|
|
127
125
|
});
|
|
128
126
|
child.stderr.on("data", (chunk) => {
|
|
129
127
|
stderrBytes += chunk.length;
|
|
130
|
-
|
|
131
|
-
stop("output-limit");
|
|
132
|
-
else
|
|
133
|
-
stderr.push(chunk);
|
|
128
|
+
stderr.push(chunk);
|
|
134
129
|
});
|
|
135
130
|
child.once("error", (cause) => finish(err(new NativeCommandFailure(tool, "io", null, { cause }))));
|
|
136
131
|
child.once("close", (code, signal) => {
|
|
@@ -147,8 +142,6 @@ const captureProcess = (executable, arguments_, tool, options) => new Promise((r
|
|
|
147
142
|
stderr: Buffer.concat(stderr).toString("utf8"),
|
|
148
143
|
stdoutBytes,
|
|
149
144
|
stderrBytes,
|
|
150
|
-
stdoutTruncated: false,
|
|
151
|
-
stderrTruncated: false,
|
|
152
145
|
exitCode: code,
|
|
153
146
|
signal,
|
|
154
147
|
}));
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { dirname, isAbsolute,
|
|
2
|
-
import {
|
|
1
|
+
import { dirname, isAbsolute, resolve } from "node:path";
|
|
2
|
+
import { stat } from "node:fs/promises";
|
|
3
3
|
import { parse as parseXmlPlist } from "plist";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { createAnalysisExecution, } from "../application/AnalysisProvider.js";
|
|
6
6
|
import { NATIVE_TOOL_CONTRACTS, } from "../contracts/nativeToolContracts.js";
|
|
7
|
-
import { AnalysisCancelledError, AnalysisCapabilityUnavailableError, AnalysisOutputError,
|
|
7
|
+
import { AnalysisCancelledError, AnalysisCapabilityUnavailableError, AnalysisOutputError, ProviderAdapterError, } from "../domain/errors.js";
|
|
8
8
|
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
9
9
|
import { demangleSwiftSchema, inspectPlistSchema, inspectSignatureSchema, listArchitecturesSchema, } from "../domain/nativeInspection.js";
|
|
10
10
|
import { err, ok } from "../domain/result.js";
|
|
@@ -21,8 +21,6 @@ export const NATIVE_MACOS_PROVIDER_IDENTITY = Object.freeze({
|
|
|
21
21
|
version: null,
|
|
22
22
|
});
|
|
23
23
|
const IDENTITY = NATIVE_MACOS_PROVIDER_IDENTITY;
|
|
24
|
-
const TIMEOUT_MS = 30_000;
|
|
25
|
-
const OUTPUT_LIMIT = 4 * 1024 * 1024;
|
|
26
24
|
/** Read-only semantic provider composed from Xcode command-line utilities. */
|
|
27
25
|
export class NativeMacOSProvider {
|
|
28
26
|
runner;
|
|
@@ -41,11 +39,7 @@ export class NativeMacOSProvider {
|
|
|
41
39
|
return Object.freeze({
|
|
42
40
|
provider: IDENTITY,
|
|
43
41
|
operation: contract.name,
|
|
44
|
-
inputContractVersion: 1,
|
|
45
|
-
outputContractVersion: 1,
|
|
46
42
|
...availability,
|
|
47
|
-
pagination: "none",
|
|
48
|
-
exhaustive: contract.name !== "inspect_macho",
|
|
49
43
|
effects: Object.freeze({
|
|
50
44
|
mutatesArtifact: false,
|
|
51
45
|
launchesProcess: true,
|
|
@@ -55,11 +49,6 @@ export class NativeMacOSProvider {
|
|
|
55
49
|
changesPermissions: false,
|
|
56
50
|
requiresRoot: false,
|
|
57
51
|
}),
|
|
58
|
-
limits: Object.freeze({
|
|
59
|
-
maxResults: contract.name === "demangle_swift" ? 500 : null,
|
|
60
|
-
maxPayloadBytes: OUTPUT_LIMIT,
|
|
61
|
-
timeoutMs: TIMEOUT_MS,
|
|
62
|
-
}),
|
|
63
52
|
limitations: Object.freeze([
|
|
64
53
|
"Availability and textual formats depend on the installed macOS/Xcode toolchain.",
|
|
65
54
|
]),
|
|
@@ -199,9 +188,9 @@ class NativeMacOSClient {
|
|
|
199
188
|
});
|
|
200
189
|
}
|
|
201
190
|
async #inspectPlist(parameters, signal) {
|
|
202
|
-
const requested = parameters.
|
|
203
|
-
if (typeof requested !== "string")
|
|
204
|
-
return err(new AnalysisOutputError("inspect_plist", "
|
|
191
|
+
const requested = parameters.path;
|
|
192
|
+
if (requested !== undefined && typeof requested !== "string")
|
|
193
|
+
return err(new AnalysisOutputError("inspect_plist", "path was not a string"));
|
|
205
194
|
const plist = await resolvePlistPath(this.target, requested);
|
|
206
195
|
if (!plist.ok)
|
|
207
196
|
return plist;
|
|
@@ -220,7 +209,7 @@ class NativeMacOSClient {
|
|
|
220
209
|
? "xml"
|
|
221
210
|
: "unknown",
|
|
222
211
|
...parsed,
|
|
223
|
-
source_path:
|
|
212
|
+
source_path: plist.value,
|
|
224
213
|
provenance,
|
|
225
214
|
limitations: [],
|
|
226
215
|
});
|
|
@@ -228,7 +217,7 @@ class NativeMacOSClient {
|
|
|
228
217
|
result: jsonValueSchema.parse(result),
|
|
229
218
|
provenance,
|
|
230
219
|
limitations: [],
|
|
231
|
-
locations: [{ kind: "artifact-path", path:
|
|
220
|
+
locations: [{ kind: "artifact-path", path: plist.value }],
|
|
232
221
|
});
|
|
233
222
|
}
|
|
234
223
|
async #inspectMacho(signal) {
|
|
@@ -246,8 +235,6 @@ class NativeMacOSClient {
|
|
|
246
235
|
async #run(operation, tool, arguments_, options = {}) {
|
|
247
236
|
const captured = await this.runner.run(tool, arguments_, {
|
|
248
237
|
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
249
|
-
timeoutMs: TIMEOUT_MS,
|
|
250
|
-
maxOutputBytes: OUTPUT_LIMIT,
|
|
251
238
|
acceptNonZero: options.acceptNonZero ?? false,
|
|
252
239
|
});
|
|
253
240
|
if (captured.ok)
|
|
@@ -261,8 +248,6 @@ const translateCommandFailure = (operation, failure) => {
|
|
|
261
248
|
return new AnalysisCapabilityUnavailableError(IDENTITY.id, operation, `${failure.tool} is unavailable through xcrun.`);
|
|
262
249
|
if (failure.reason === "cancelled")
|
|
263
250
|
return new AnalysisCancelledError(operation);
|
|
264
|
-
if (failure.reason === "timeout")
|
|
265
|
-
return new AnalysisTimeoutError(operation, TIMEOUT_MS);
|
|
266
251
|
return new ProviderAdapterError(IDENTITY.id, operation, { cause: failure });
|
|
267
252
|
};
|
|
268
253
|
const invocation = (capture, artifactPath, alias = "$ARTIFACT") => ({
|
|
@@ -277,8 +262,6 @@ const invocation = (capture, artifactPath, alias = "$ARTIFACT") => ({
|
|
|
277
262
|
exit: { code: capture.exitCode, signal: capture.signal },
|
|
278
263
|
stdout_bytes: capture.stdoutBytes,
|
|
279
264
|
stderr_bytes: capture.stderrBytes,
|
|
280
|
-
stdout_truncated: capture.stdoutTruncated,
|
|
281
|
-
stderr_truncated: capture.stderrTruncated,
|
|
282
265
|
});
|
|
283
266
|
const parseEntitlements = (output) => {
|
|
284
267
|
const start = output.indexOf("<?xml");
|
|
@@ -290,23 +273,15 @@ const parseEntitlements = (output) => {
|
|
|
290
273
|
const resolvePlistPath = async (target, requested) => {
|
|
291
274
|
try {
|
|
292
275
|
const source = target.sourcePath ?? target.path;
|
|
276
|
+
if (requested !== undefined && isAbsolute(requested))
|
|
277
|
+
return ok(resolve(requested));
|
|
293
278
|
const sourceMetadata = await stat(source);
|
|
294
279
|
const root = sourceMetadata.isDirectory() ? source : dirname(target.path);
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const canonicalRoot = await realpath(root);
|
|
299
|
-
const canonical = await realpath(candidate);
|
|
300
|
-
if (!within(canonicalRoot, canonical))
|
|
301
|
-
return err(new ProviderAdapterError(IDENTITY.id, "inspect_plist"));
|
|
302
|
-
return ok(canonical);
|
|
280
|
+
return ok(requested === undefined
|
|
281
|
+
? resolve(root, "Contents/Info.plist")
|
|
282
|
+
: resolve(root, requested));
|
|
303
283
|
}
|
|
304
284
|
catch (cause) {
|
|
305
285
|
return err(new ProviderAdapterError(IDENTITY.id, "inspect_plist", { cause }));
|
|
306
286
|
}
|
|
307
287
|
};
|
|
308
|
-
const within = (root, candidate) => {
|
|
309
|
-
const child = relative(root, candidate);
|
|
310
|
-
return (child === "" ||
|
|
311
|
-
(!child.startsWith(`..${sep}`) && child !== ".." && !isAbsolute(child)));
|
|
312
|
-
};
|
|
@@ -15,7 +15,7 @@ const REQUIRED_COMMANDS = [
|
|
|
15
15
|
];
|
|
16
16
|
const OPTIONAL_VTOOL_COMMAND = ["vtool", ["-show-build"]];
|
|
17
17
|
const VTOOL_UNAVAILABLE_LIMITATION = "vtool is unavailable; build metadata is normalized from otool only.";
|
|
18
|
-
/** Inspect one Mach-O with
|
|
18
|
+
/** Inspect one Mach-O with the required native commands and normalized output. */
|
|
19
19
|
export const inspectNativeMacho = async (context) => {
|
|
20
20
|
const captures = [];
|
|
21
21
|
for (const [tool, prefix] of REQUIRED_COMMANDS) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Read through EOF, returning undefined on overflow; consume at most maxBytes + 1 bytes without closing the handle. */
|
|
2
|
+
export const readBoundedFileBytes = async (handle, maxBytes) => {
|
|
3
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0)
|
|
4
|
+
throw new RangeError("File byte limit must be a nonnegative safe integer");
|
|
5
|
+
const chunks = [];
|
|
6
|
+
const buffer = Buffer.allocUnsafe(Math.min(64 * 1_024, maxBytes + 1));
|
|
7
|
+
let total = 0;
|
|
8
|
+
for (;;) {
|
|
9
|
+
const { bytesRead } = await handle.read(buffer, 0, Math.min(buffer.length, maxBytes - total + 1), null);
|
|
10
|
+
if (bytesRead === 0)
|
|
11
|
+
return Buffer.concat(chunks, total);
|
|
12
|
+
total += bytesRead;
|
|
13
|
+
if (total > maxBytes)
|
|
14
|
+
return undefined;
|
|
15
|
+
chunks.push(Buffer.from(buffer.subarray(0, bytesRead)));
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { execFile, } from "node:child_process";
|
|
2
|
+
/** Run a shell-free command while capturing its complete UTF-8 output. */
|
|
3
|
+
export const execFileOutput = (command, arguments_, options = {}) => new Promise((resolve, reject) => {
|
|
4
|
+
execFile(command, [...arguments_], { ...options, encoding: "utf8", maxBuffer: Number.POSITIVE_INFINITY }, (error, stdout, stderr) => {
|
|
5
|
+
if (error !== null) {
|
|
6
|
+
reject(error);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
resolve({ stdout, stderr });
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Correlates event-driven provider replies with bounded waits.
|
|
3
3
|
*
|
|
4
|
-
* The registry owns
|
|
5
|
-
* out, cancelling, or failing
|
|
6
|
-
* late protocol replies can be ignored without retaining request resources.
|
|
4
|
+
* The registry owns optional request timers and cancellation listeners.
|
|
5
|
+
* Settling, timing out, cancelling, or failing removes these before resolution.
|
|
7
6
|
*/
|
|
8
7
|
export class PendingOperations {
|
|
9
8
|
#pending = new Map();
|
|
@@ -15,7 +14,7 @@ export class PendingOperations {
|
|
|
15
14
|
has(key) {
|
|
16
15
|
return this.#pending.has(key);
|
|
17
16
|
}
|
|
18
|
-
/** Register one unique operation key and
|
|
17
|
+
/** Register one unique operation key and await its reply or cancellation. */
|
|
19
18
|
wait(key, options) {
|
|
20
19
|
if (this.#pending.has(key))
|
|
21
20
|
throw new Error("Pending operation key is already registered");
|
|
@@ -25,7 +24,9 @@ export class PendingOperations {
|
|
|
25
24
|
const onAbort = options.signal === undefined
|
|
26
25
|
? undefined
|
|
27
26
|
: () => this.#finish(key, options.cancelledValue());
|
|
28
|
-
const timer =
|
|
27
|
+
const timer = options.timeoutMs === undefined
|
|
28
|
+
? undefined
|
|
29
|
+
: setTimeout(() => this.#finish(key, options.timeoutValue()), options.timeoutMs);
|
|
29
30
|
this.#pending.set(key, {
|
|
30
31
|
resolve,
|
|
31
32
|
timer,
|
|
@@ -50,7 +51,8 @@ export class PendingOperations {
|
|
|
50
51
|
if (pending === undefined)
|
|
51
52
|
return false;
|
|
52
53
|
this.#pending.delete(key);
|
|
53
|
-
|
|
54
|
+
if (pending.timer !== undefined)
|
|
55
|
+
clearTimeout(pending.timer);
|
|
54
56
|
if (pending.signal !== undefined && pending.onAbort !== undefined)
|
|
55
57
|
pending.signal.removeEventListener("abort", pending.onAbort);
|
|
56
58
|
pending.resolve(value);
|
|
@@ -4,6 +4,7 @@ import { promisify } from "node:util";
|
|
|
4
4
|
import { observeOwnedProcessGroupWithHost, observeOwnedProcessLineageWithHost, } from "./ProcessOwnershipObservation.js";
|
|
5
5
|
import { launcherIdentityFailure } from "./ProcessOwnershipIdentity.js";
|
|
6
6
|
import { descendantsOf, liveProcesses } from "./ProcessOwnershipProcessTree.js";
|
|
7
|
+
import { execFileOutput } from "./ExecFileOutput.js";
|
|
7
8
|
const execFileAsync = promisify(execFile);
|
|
8
9
|
/**
|
|
9
10
|
* Terminate one Windows process tree through the platform utility.
|
|
@@ -51,7 +52,7 @@ const systemHost = {
|
|
|
51
52
|
async listProcesses() {
|
|
52
53
|
if (process.platform === "win32")
|
|
53
54
|
return [];
|
|
54
|
-
const { stdout } = await
|
|
55
|
+
const { stdout } = await execFileOutput("ps", [
|
|
55
56
|
"-axo",
|
|
56
57
|
"pid=,ppid=,pgid=,stat=,command=",
|
|
57
58
|
]);
|
|
@@ -71,7 +72,7 @@ const systemHost = {
|
|
|
71
72
|
if (process.platform === "linux") {
|
|
72
73
|
return parseProcessEnvironment(await readFile(`/proc/${pid}/environ`, "utf8"));
|
|
73
74
|
}
|
|
74
|
-
const { stdout } = await
|
|
75
|
+
const { stdout } = await execFileOutput("ps", ["eww", "-p", String(pid)]);
|
|
75
76
|
const environment = {};
|
|
76
77
|
for (const match of stdout.matchAll(/(?:^|\s)([A-Za-z_][A-Za-z0-9_]*)=([^\s]*)/gu)) {
|
|
77
78
|
const name = match[1];
|
|
@@ -63,7 +63,6 @@ export const observeOwnedProcessLineageWithHost = async (ownership, host) => {
|
|
|
63
63
|
status: "verified",
|
|
64
64
|
observedAt: new Date().toISOString(),
|
|
65
65
|
lineage: {
|
|
66
|
-
schemaVersion: 1,
|
|
67
66
|
runId: ownership.runId,
|
|
68
67
|
launcherPid: launcher.pid,
|
|
69
68
|
launcherParentPid: launcher.parentPid,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
-
const DEFAULT_OUTPUT_BYTES = 64 * 1024;
|
|
3
2
|
const DEFAULT_TERMINATION_GRACE_MS = 250;
|
|
4
3
|
const DEFAULT_KILL_GRACE_MS = 1_000;
|
|
5
4
|
/**
|
|
@@ -47,8 +46,8 @@ export const spawnOwnedProviderProcess = async (options) => {
|
|
|
47
46
|
export class ProviderProcessSupervisor {
|
|
48
47
|
launch;
|
|
49
48
|
#options;
|
|
50
|
-
#stdout;
|
|
51
|
-
#stderr;
|
|
49
|
+
#stdout = new ProcessOutputCapture();
|
|
50
|
+
#stderr = new ProcessOutputCapture();
|
|
52
51
|
#exit = deferred();
|
|
53
52
|
#onStdout = (chunk) => {
|
|
54
53
|
this.#capture("stdout", this.#stdout, chunk);
|
|
@@ -71,11 +70,6 @@ export class ProviderProcessSupervisor {
|
|
|
71
70
|
constructor(launch, options = {}) {
|
|
72
71
|
this.launch = launch;
|
|
73
72
|
this.#options = options;
|
|
74
|
-
const limit = options.maxOutputBytesPerStream ?? DEFAULT_OUTPUT_BYTES;
|
|
75
|
-
if (!Number.isSafeInteger(limit) || limit <= 0)
|
|
76
|
-
throw new RangeError("Provider output limit must be a positive integer");
|
|
77
|
-
this.#stdout = new BoundedByteCapture(limit);
|
|
78
|
-
this.#stderr = new BoundedByteCapture(limit);
|
|
79
73
|
this.#attach(launch.process.stdout, "stdout");
|
|
80
74
|
this.#attach(launch.process.stderr, "stderr");
|
|
81
75
|
launch.process.once("exit", this.#onExit);
|
|
@@ -84,7 +78,7 @@ export class ProviderProcessSupervisor {
|
|
|
84
78
|
if (launch.process.exitCode !== null || launch.process.signalCode !== null)
|
|
85
79
|
this.#recordExit(launch.process.exitCode, launch.process.signalCode);
|
|
86
80
|
}
|
|
87
|
-
/** Latest
|
|
81
|
+
/** Latest complete output and exit observation. */
|
|
88
82
|
snapshot() {
|
|
89
83
|
return {
|
|
90
84
|
stdout: this.#stdout.snapshot(),
|
|
@@ -203,7 +197,6 @@ export class ProviderProcessSupervisor {
|
|
|
203
197
|
stream,
|
|
204
198
|
bytes: bytes.byteLength,
|
|
205
199
|
totalBytes: capture.bytes,
|
|
206
|
-
truncated: capture.truncated,
|
|
207
200
|
});
|
|
208
201
|
}
|
|
209
202
|
#recordExit(code, signal) {
|
|
@@ -219,35 +212,21 @@ export class ProviderProcessSupervisor {
|
|
|
219
212
|
});
|
|
220
213
|
}
|
|
221
214
|
}
|
|
222
|
-
class
|
|
223
|
-
limit;
|
|
215
|
+
class ProcessOutputCapture {
|
|
224
216
|
#chunks = [];
|
|
225
217
|
#bytes = 0;
|
|
226
|
-
#retainedBytes = 0;
|
|
227
|
-
constructor(limit) {
|
|
228
|
-
this.limit = limit;
|
|
229
|
-
}
|
|
230
218
|
get bytes() {
|
|
231
219
|
return this.#bytes;
|
|
232
220
|
}
|
|
233
|
-
get truncated() {
|
|
234
|
-
return this.#bytes > this.#retainedBytes;
|
|
235
|
-
}
|
|
236
221
|
append(chunk) {
|
|
237
222
|
this.#bytes += chunk.byteLength;
|
|
238
|
-
|
|
239
|
-
if (remaining <= 0)
|
|
240
|
-
return;
|
|
241
|
-
const retained = Buffer.from(chunk.subarray(0, remaining));
|
|
242
|
-
this.#chunks.push(retained);
|
|
243
|
-
this.#retainedBytes += retained.byteLength;
|
|
223
|
+
this.#chunks.push(Buffer.from(chunk));
|
|
244
224
|
}
|
|
245
225
|
snapshot() {
|
|
226
|
+
const text = Buffer.concat(this.#chunks, this.#bytes).toString("utf8");
|
|
246
227
|
return {
|
|
247
|
-
text
|
|
228
|
+
text,
|
|
248
229
|
bytes: this.#bytes,
|
|
249
|
-
retainedBytes: this.#retainedBytes,
|
|
250
|
-
truncated: this.truncated,
|
|
251
230
|
};
|
|
252
231
|
}
|
|
253
232
|
}
|
|
@@ -1,61 +1,45 @@
|
|
|
1
|
+
import { compareUnicodeCodePoints } from "../domain/unicodeCodePointOrder.js";
|
|
1
2
|
import { err, ok } from "../domain/result.js";
|
|
2
3
|
import { traverseDirectory } from "./ReferenceSourceReaderEntries.js";
|
|
3
|
-
import { compareNames } from "./ReferenceSourceReaderPaths.js";
|
|
4
4
|
import {} from "./ReferenceSourceReaderTypes.js";
|
|
5
5
|
import { isAborted, noFollowOpenSupported, prepareRoot, } from "./ReferenceSourceReaderValidate.js";
|
|
6
|
-
const DEFAULT_LIMITS = {
|
|
7
|
-
maxBytes: 16 * 1024 * 1024,
|
|
8
|
-
maxEntries: 10_000,
|
|
9
|
-
maxDepth: 32,
|
|
10
|
-
maxPathBytes: 4_096,
|
|
11
|
-
};
|
|
12
6
|
const PATH_RACE_LIMITATION = "Path identity is revalidated around operations; Node lacks portable descriptor-relative openat traversal, so a syscall-boundary pathname race remains.";
|
|
13
|
-
/** Read a
|
|
14
|
-
export const readReferenceSource = async (root,
|
|
7
|
+
/** Read a source tree without intentionally following symbolic links. */
|
|
8
|
+
export const readReferenceSource = async (root, options = {}) => {
|
|
15
9
|
if (!noFollowOpenSupported())
|
|
16
10
|
return err({
|
|
17
11
|
tag: "reference-source-reader",
|
|
18
12
|
code: "unsupported",
|
|
19
13
|
message: "Safe no-follow file opens are unavailable",
|
|
20
14
|
});
|
|
21
|
-
const prepared = await prepareRoot(root,
|
|
15
|
+
const prepared = await prepareRoot(root, options.signal);
|
|
22
16
|
if (!prepared.ok)
|
|
23
17
|
return prepared;
|
|
24
18
|
const { canonicalRoot, rootIdentity } = prepared.value;
|
|
25
19
|
const state = {
|
|
26
20
|
root: canonicalRoot,
|
|
27
21
|
rootIdentity,
|
|
28
|
-
limits,
|
|
29
22
|
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
30
23
|
...(options.shouldExclude === undefined
|
|
31
24
|
? {}
|
|
32
25
|
: { shouldExclude: options.shouldExclude }),
|
|
33
26
|
entries: [],
|
|
34
|
-
pending: [{ path: canonicalRoot
|
|
27
|
+
pending: [{ path: canonicalRoot }],
|
|
35
28
|
bytesRead: 0,
|
|
36
|
-
filesSeen: 0,
|
|
37
|
-
truncated: false,
|
|
38
|
-
stopReason: undefined,
|
|
39
29
|
};
|
|
40
30
|
const traversal = await traverse(state);
|
|
41
31
|
if (!traversal.ok)
|
|
42
32
|
return traversal;
|
|
43
|
-
state.entries.sort((left, right) =>
|
|
33
|
+
state.entries.sort((left, right) => compareUnicodeCodePoints(left.path, right.path));
|
|
44
34
|
return ok({
|
|
45
35
|
root: canonicalRoot,
|
|
46
36
|
entries: state.entries,
|
|
47
37
|
bytesRead: state.bytesRead,
|
|
48
|
-
|
|
49
|
-
limitations: [
|
|
50
|
-
PATH_RACE_LIMITATION,
|
|
51
|
-
...(state.stopReason === "entry-limit"
|
|
52
|
-
? ["Traversal stopped because the entry limit was reached."]
|
|
53
|
-
: []),
|
|
54
|
-
],
|
|
38
|
+
limitations: [PATH_RACE_LIMITATION],
|
|
55
39
|
});
|
|
56
40
|
};
|
|
57
41
|
const traverse = async (state) => {
|
|
58
|
-
while (state.pending.length > 0
|
|
42
|
+
while (state.pending.length > 0) {
|
|
59
43
|
if (isAborted(state.signal))
|
|
60
44
|
return err({
|
|
61
45
|
tag: "reference-source-reader",
|