rea-agents 3.0.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 +83 -108
- package/bridge/ghidra/ReaGhidraBridge.java +609 -841
- package/bridge/hopper_bridge.py +99 -344
- package/dist/application/AbortablePromise.js +6 -3
- package/dist/application/AnalysisContextQueries.js +21 -9
- 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/policy.js +17 -0
- package/dist/application/ArtifactInventory/reader.js +1 -4
- package/dist/application/ArtifactInventory/scanCanonical.js +8 -15
- package/dist/application/ArtifactInventory/scanReader.js +76 -58
- package/dist/application/ArtifactInventory/types.js +1 -5
- package/dist/application/ArtifactInventory.js +6 -14
- package/dist/application/AuthorizedArtifactInventory.js +3 -13
- package/dist/application/BinarySession.js +54 -28
- package/dist/application/BinarySessionComposition.js +0 -11
- package/dist/application/BinarySessionOpen.js +2 -1
- package/dist/application/BinarySessionRecords.js +24 -86
- package/dist/application/BinarySessionStatus.js +16 -21
- package/dist/application/BinaryTargetResolver.js +216 -0
- package/dist/application/BrowserEvidence.js +39 -57
- 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/CapabilityClientRequirements.js +26 -0
- package/dist/application/CapabilityInventory.js +143 -77
- 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 +50 -0
- package/dist/application/ElectronActiveObservationPort.js +1 -0
- package/dist/application/ElectronActiveObservationService.js +78 -0
- 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 +98 -64
- package/dist/application/EvidenceBundleCommands.js +16 -12
- package/dist/application/EvidenceBundleFiles.js +9 -15
- package/dist/application/EvidenceLedger.js +14 -42
- 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/JavaScriptReplayPermission.js +1 -1
- package/dist/application/JavaScriptReplayPlanning.js +9 -3
- package/dist/application/JavaScriptReplayService.js +29 -47
- 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 +14 -13
- package/dist/application/NativeApiInspection.js +2 -7
- package/dist/application/NativeUiActionTrace.js +394 -0
- package/dist/application/NodeRuntimeCharacterizationService.js +11 -16
- 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 +10 -12
- package/dist/application/ProcessCheckpoints.js +29 -11
- package/dist/application/ProcessCli.js +8 -17
- package/dist/application/ProcessEvidence.js +5 -7
- package/dist/application/ProcessHarness.js +60 -20
- package/dist/application/ProcessNormalization.js +2 -1
- 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 -95
- 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 +21 -47
- 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 -88
- 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/application/WindowsCapabilities.js +5 -4
- package/dist/artifacts/ArtifactPaths.js +2 -5
- package/dist/artifacts/ArtifactProvider.js +43 -67
- 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 +21 -31
- 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 -95
- package/dist/browser/CdpCaptureValues.js +21 -21
- package/dist/browser/CdpConnection.js +10 -25
- package/dist/browser/CdpElectronInspection.js +29 -51
- 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 +10 -10
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +31 -64
- package/dist/browser/PlaywrightElectronActiveActions.js +309 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +274 -0
- 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 +7 -9
- package/dist/browser/PlaywrightScenarioEvents.js +45 -94
- package/dist/browser/PlaywrightScenarioSession.js +18 -34
- package/dist/browser/PngVisualDiff.js +22 -14
- package/dist/browser/SensitiveTextCapture.js +1 -18
- package/dist/browser/V8InspectorCaptureProjection.js +7 -7
- 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 +12 -60
- 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 +6 -271
- package/dist/cli/setupCommands.js +3 -12
- package/dist/cli/utilityCommands.js +7 -41
- package/dist/cli.js +0 -2
- package/dist/cliApplicationCommands.js +44 -114
- package/dist/cliBrowserAdvancedCommands.js +12 -102
- package/dist/cliBrowserCommands.js +19 -124
- package/dist/cliBrowserContext.js +30 -0
- package/dist/cliCommandNames.js +5 -5
- package/dist/cliElectronCommands.js +49 -71
- package/dist/cliEvidenceCommands.js +8 -77
- package/dist/cliJavaScriptRuntimeCommands.js +18 -92
- package/dist/cliJsonInput.js +4 -14
- package/dist/cliObservationOptions.js +11 -92
- package/dist/cliPolicyCommands.js +2 -16
- package/dist/cliProcessCommands.js +3 -3
- package/dist/cliSetup.js +0 -13
- package/dist/config/browserScenario.js +77 -0
- package/dist/config/electronAutomation.js +35 -0
- package/dist/config/environment.js +6 -9
- package/dist/config/javascriptReplay.js +41 -0
- package/dist/config/managedRuntime.js +25 -0
- package/dist/config/parseConfig.js +56 -232
- package/dist/config/parsers.js +16 -28
- package/dist/config/passiveObservation.js +87 -0
- package/dist/config/permissions.js +0 -7
- package/dist/config/processCapture.js +47 -0
- package/dist/contracts/analysisSearchContract.js +2 -5
- package/dist/contracts/applicationToolContracts.js +58 -114
- package/dist/contracts/applicationWorkflowInputContracts.js +29 -114
- package/dist/contracts/artifactComparisonExample.js +58 -60
- package/dist/contracts/artifactToolContracts.js +37 -91
- package/dist/contracts/browserScenarioToolContracts.js +6 -51
- package/dist/contracts/browserToolContracts.js +10 -75
- package/dist/contracts/electronToolContracts.js +27 -98
- package/dist/contracts/enhancedInputs.js +31 -78
- 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 +4 -5
- 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 +10 -104
- package/dist/contracts/managedWorkflowExamples.js +77 -125
- package/dist/contracts/managedWorkflowToolContracts.js +51 -74
- package/dist/contracts/nativeToolContracts.js +9 -14
- 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 +52 -0
- package/dist/contracts/toolContractExamples.js +11 -10
- package/dist/contracts/toolContractHelpers.js +19 -0
- package/dist/contracts/toolContracts.js +60 -143
- package/dist/contracts/toolEffects.js +16 -9
- package/dist/contracts/toolOutputSchemaGroups.js +47 -86
- package/dist/contracts/toolOutputSchemaPrimitives.js +72 -62
- package/dist/contracts/toolSchemaMetadata.js +117 -0
- package/dist/contracts/unknownContractExamples.js +0 -2
- package/dist/doctorRuntime.js +1 -1
- 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 -52
- package/dist/domain/appleApplication.js +24 -65
- 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 -219
- package/dist/domain/binaryTargetTypes.js +1 -0
- package/dist/domain/browserCaptureComparison.js +35 -60
- package/dist/domain/browserObservation.js +45 -197
- 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 +53 -54
- package/dist/domain/callPath.js +50 -169
- 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 +39 -11
- package/dist/domain/conformanceTrustGate.js +174 -30
- package/dist/domain/customProtocolCapture.js +4 -4
- package/dist/domain/electronActiveObservation.js +244 -0
- package/dist/domain/electronObservation.js +21 -83
- 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 +14 -18
- package/dist/domain/errors.js +33 -54
- package/dist/domain/eventProcessTree.js +101 -90
- 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 +8 -8
- package/dist/domain/functionComparisonResults.js +25 -15
- package/dist/domain/functionComparisonSchemas.js +49 -33
- package/dist/domain/functionDossierEvidence.js +31 -151
- package/dist/domain/hopperStartupFailure.js +1 -1
- package/dist/domain/hopperValues.js +17 -141
- package/dist/domain/inputIssueProjection.js +4 -1
- 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 +70 -77
- 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 +100 -101
- package/dist/domain/javascriptRuntimeLoadState.js +3 -8
- package/dist/domain/javascriptRuntimeObservation.js +43 -103
- package/dist/domain/javascriptRuntimeReconciliation.js +1 -3
- package/dist/domain/javascriptRuntimeReconciliationActive.js +80 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +21 -33
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +75 -61
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +21 -46
- package/dist/domain/javascriptRuntimeReconciliationResult.js +25 -19
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +8 -12
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +34 -49
- 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 +17 -14
- 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 +15 -18
- 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/processCaptureReactiveValidation.js +8 -3
- package/dist/domain/processCaptureValidation.js +8 -10
- package/dist/domain/processComparison.js +12 -16
- package/dist/domain/processObservation.js +5 -6
- package/dist/domain/processReactiveMatching.js +32 -46
- 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 +42 -21
- package/dist/domain/processScenario.js +62 -93
- package/dist/domain/processTraceComparison.js +0 -7
- package/dist/domain/processTraceEvaluation.js +14 -4
- package/dist/domain/processTraceSpecification.js +11 -17
- package/dist/domain/protocolCapture.js +11 -9
- 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 +66 -40
- 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 +3 -7
- package/dist/domain/replayMachine.js +19 -31
- package/dist/domain/replayMachineRun.js +15 -63
- package/dist/domain/replayMachineRuntime.js +46 -44
- 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 +11 -87
- package/dist/domain/sourceToBundleComparisonSchemas.js +25 -50
- package/dist/domain/sourceToBundleSignals.js +11 -16
- package/dist/domain/staticRuntimeCorrelation.js +44 -54
- 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 +48 -85
- 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 -42
- 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 +5 -13
- package/dist/ghidra/GhidraClientStartup.js +1 -1
- 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 +67 -108
- package/dist/ghidra/GhidraInstallation.js +98 -42
- package/dist/ghidra/GhidraInventoryValues.js +18 -77
- package/dist/ghidra/GhidraLauncher.js +0 -8
- package/dist/ghidra/GhidraProvider.js +32 -31
- package/dist/ghidra/GhidraProviderCapabilities.js +11 -48
- package/dist/ghidra/GhidraRequestQueue.js +6 -30
- package/dist/ghidra/GhidraResponseBuffer.js +1 -7
- package/dist/ghidra/GhidraSessionValues.js +0 -2
- package/dist/ghidra/GhidraSocketConnection.js +1 -1
- package/dist/ghidra/GhidraTransport.js +4 -7
- package/dist/ghidra/protocol.js +19 -42
- package/dist/hopper/BridgeLauncher.js +115 -37
- package/dist/hopper/HopperAnalysisProfile.js +3 -5
- package/dist/hopper/HopperCleanup.js +11 -9
- package/dist/hopper/HopperClient.js +5 -8
- package/dist/hopper/HopperProcessDiagnostic.js +2 -2
- package/dist/hopper/HopperProvider.js +0 -30
- 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 +21 -26
- package/dist/hopper/protocol.js +6 -4
- package/dist/main/reload.js +1 -9
- package/dist/main/shutdown.js +1 -1
- package/dist/main/state.js +0 -23
- package/dist/main/transport.js +27 -39
- package/dist/main.js +17 -15
- package/dist/mcpDoctor.js +27 -69
- 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/PrivateRuntimeRoot.js +17 -0
- package/dist/process/ProcessOwnership.js +67 -130
- package/dist/process/ProcessOwnershipIdentity.js +13 -0
- package/dist/process/ProcessOwnershipObservation.js +87 -0
- package/dist/process/ProcessOwnershipProcessTree.js +22 -0
- package/dist/process/ProviderDeadline.js +8 -12
- package/dist/process/ProviderProcess.js +7 -28
- package/dist/process/WindowsAuthority.js +32 -0
- 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 +95 -13
- package/dist/replay/JavaScriptReplayWorkerTypes.js +1 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +42 -43
- package/dist/replay/LinuxJavaScriptReplaySandbox.js +0 -19
- package/dist/replay/LinuxRuntimeClosure.js +1 -3
- package/dist/replay/ReplayOutcome.js +27 -18
- package/dist/replay/ReplayProcessLifecycle.js +32 -7
- package/dist/replay/ReplaySeccompFile.js +29 -0
- package/dist/replay/ReplayWorkerProtocol.js +33 -30
- package/dist/replay/SystemJavaScriptReplayHost.js +45 -74
- package/dist/server/ProcessCaptureElicitation.js +4 -8
- package/dist/server/createServer.js +145 -119
- package/dist/server/mcpClientMetadata.js +32 -0
- package/dist/server/promptCompletion.js +37 -61
- package/dist/server/recordDerivedEvidence.js +1 -1
- package/dist/server/registerApplicationTools/characterization.js +10 -21
- package/dist/server/registerApplicationTools/compareExportShapes.js +6 -16
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +6 -15
- package/dist/server/registerApplicationTools/compareVersions.js +6 -16
- package/dist/server/registerApplicationTools/controlledReplay.js +8 -15
- package/dist/server/registerApplicationTools/coverage.js +7 -78
- package/dist/server/registerApplicationTools/helpers.js +1 -13
- package/dist/server/registerApplicationTools/obligationLedger.js +4 -8
- package/dist/server/registerApplicationTools/traceFeature.js +6 -15
- package/dist/server/registerApplicationTools/traceSemantics.js +5 -13
- package/dist/server/registerApplicationTools.js +0 -2
- package/dist/server/registerArtifactComparisonTool.js +27 -35
- package/dist/server/registerBrowserScenarioTool.js +3 -8
- package/dist/server/registerBrowserTools.js +36 -81
- package/dist/server/registerBundleComparisonTool.js +10 -16
- package/dist/server/registerCloseLifecycleTool.js +5 -27
- package/dist/server/registerElectronTools.js +29 -65
- package/dist/server/registerEnhancedTools.js +118 -127
- package/dist/server/registerEvidenceTools.js +19 -30
- package/dist/server/registerFunctionComparisonTool.js +35 -34
- package/dist/server/registerInvestigationTools/helpers.js +3 -32
- package/dist/server/registerInvestigationTools.js +36 -148
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +15 -27
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +16 -23
- package/dist/server/registerManagedWorkflowTools/contract.js +2 -3
- package/dist/server/registerManagedWorkflowTools/evidence.js +19 -35
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +4 -14
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +4 -14
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +11 -20
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +10 -21
- package/dist/server/registerOfficialTools.js +8 -51
- package/dist/server/registerProcessComparisonTool.js +43 -38
- package/dist/server/registerPrompts.js +19 -17
- package/dist/server/registerReplayMachineTool.js +4 -10
- package/dist/server/registerSessionRecordTools.js +36 -153
- package/dist/server/registerSessionStatusTool.js +18 -96
- package/dist/server/registerSessionTools.js +34 -91
- package/dist/server/sessionAvailabilityPolicy.js +2 -3
- package/dist/server/sessionEvidence.js +9 -15
- package/dist/server/sessionToolPolicies.js +1 -13
- package/dist/server/toolRegistrationOptions.js +4 -192
- package/dist/server/toolResult.js +15 -67
- package/dist/serverIdentity.js +0 -20
- package/install.sh +1 -1
- package/package.json +27 -15
- package/scripts/electron-active-hook-boundaries.cjs +394 -0
- package/scripts/electron-active-hook.cjs +469 -0
- package/scripts/hopper-demo-x11.py +13 -32
- package/scripts/rea.mjs +1 -11
- package/skills/reverse-engineer-anything/SKILL.md +46 -11
- 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 -180
- package/dist/application/BoundedJsonFiles.js +0 -86
- package/dist/application/CrossVersionInventory.js +0 -128
- 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 -346
- package/dist/domain/jsonLimits.js +0 -26
- package/dist/domain/knownPageCoverage.js +0 -21
- package/dist/domain/processPairedExperiment.js +0 -128
- package/dist/server/DynamicToolAvailability.js +0 -70
- package/dist/server/LazyToolCatalog.js +0 -134
- package/dist/server/hydrateServerTools.js +0 -191
- package/dist/server/javascriptApplicationResult.js +0 -106
- package/dist/server/permissionFailure.js +0 -12
- package/dist/server/registerApplicationTools/readiness.js +0 -55
- 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/server/toolInputValidation.js +0 -77
- package/scripts/package-runner-bootstrap.mjs +0 -72
|
@@ -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);
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import { chmod, mkdtemp, rm } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { windowsNativeCapabilities, } from "./WindowsAuthority.js";
|
|
5
|
+
/** Report whether this process can establish a private runtime root. */
|
|
6
|
+
export const privateRuntimeRootCapability = (platform = process.platform) => platform === "win32"
|
|
7
|
+
? windowsNativeCapabilities(platform).private_runtime_dacl
|
|
8
|
+
: { available: true, reason: null, proof: "posix-mode-0700" };
|
|
9
|
+
/** Expected failure when a runtime root's privacy boundary is unavailable. */
|
|
10
|
+
export class PrivateRuntimeRootUnavailableError extends Error {
|
|
11
|
+
code = "private-runtime-root-authority-unavailable";
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "PrivateRuntimeRootUnavailableError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
4
17
|
/**
|
|
5
18
|
* Owns one POSIX mode-0700 temporary runtime root and removes it idempotently.
|
|
6
19
|
*
|
|
@@ -16,6 +29,10 @@ export class PrivateRuntimeRoot {
|
|
|
16
29
|
}
|
|
17
30
|
/** Allocate a new private runtime root without performing protocol work. */
|
|
18
31
|
static async create(options = {}) {
|
|
32
|
+
const platform = options.platform ?? process.platform;
|
|
33
|
+
const capability = privateRuntimeRootCapability(platform);
|
|
34
|
+
if (!capability.available)
|
|
35
|
+
throw new PrivateRuntimeRootUnavailableError(capability.reason);
|
|
19
36
|
const path = await mkdtemp(join(options.parent ?? tmpdir(), options.prefix ?? "rea-provider-"));
|
|
20
37
|
try {
|
|
21
38
|
await chmod(path, 0o700);
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { promisify } from "node:util";
|
|
4
|
-
import {
|
|
4
|
+
import { observeOwnedProcessGroupWithHost, observeOwnedProcessLineageWithHost, } from "./ProcessOwnershipObservation.js";
|
|
5
|
+
import { launcherIdentityFailure } from "./ProcessOwnershipIdentity.js";
|
|
6
|
+
import { descendantsOf, liveProcesses } from "./ProcessOwnershipProcessTree.js";
|
|
7
|
+
import { execFileOutput } from "./ExecFileOutput.js";
|
|
5
8
|
const execFileAsync = promisify(execFile);
|
|
6
9
|
/**
|
|
7
10
|
* Terminate one Windows process tree through the platform utility.
|
|
8
11
|
*
|
|
9
12
|
* This is a bounded P0 cleanup mechanism, not Job Object ownership proof. The
|
|
10
|
-
* caller-visible Windows
|
|
13
|
+
* caller-visible Windows capability report remains unavailable until a native
|
|
14
|
+
* authority verifies Job Object creation, membership, and cleanup semantics.
|
|
11
15
|
*/
|
|
12
16
|
export const cleanupWindowsProcessTree = async (rootPid, host = systemWindowsProcessTreeHost) => {
|
|
13
17
|
if (!Number.isSafeInteger(rootPid) || rootPid <= 0)
|
|
@@ -48,7 +52,7 @@ const systemHost = {
|
|
|
48
52
|
async listProcesses() {
|
|
49
53
|
if (process.platform === "win32")
|
|
50
54
|
return [];
|
|
51
|
-
const { stdout } = await
|
|
55
|
+
const { stdout } = await execFileOutput("ps", [
|
|
52
56
|
"-axo",
|
|
53
57
|
"pid=,ppid=,pgid=,stat=,command=",
|
|
54
58
|
]);
|
|
@@ -68,10 +72,13 @@ const systemHost = {
|
|
|
68
72
|
if (process.platform === "linux") {
|
|
69
73
|
return parseProcessEnvironment(await readFile(`/proc/${pid}/environ`, "utf8"));
|
|
70
74
|
}
|
|
71
|
-
const { stdout } = await
|
|
75
|
+
const { stdout } = await execFileOutput("ps", ["eww", "-p", String(pid)]);
|
|
72
76
|
const environment = {};
|
|
73
|
-
for (const match of stdout.matchAll(/(?:^|\s)([A-Za-z_][A-Za-z0-9_]*)=([^\s]*)/gu))
|
|
74
|
-
|
|
77
|
+
for (const match of stdout.matchAll(/(?:^|\s)([A-Za-z_][A-Za-z0-9_]*)=([^\s]*)/gu)) {
|
|
78
|
+
const name = match[1];
|
|
79
|
+
if (name !== undefined)
|
|
80
|
+
environment[name] = match[2] ?? "";
|
|
81
|
+
}
|
|
75
82
|
return environment;
|
|
76
83
|
},
|
|
77
84
|
signalGroup(processGroupId, signal) {
|
|
@@ -97,13 +104,9 @@ const systemWindowsProcessTreeHost = {
|
|
|
97
104
|
export const readProcessRunId = async (pid, host = systemHost) => (await host.environment(pid)).REA_PROCESS_RUN_ID;
|
|
98
105
|
/** Token-validate every rooted POSIX process group before signaling any. */
|
|
99
106
|
export const cleanupOwnedProcessGroup = async (ownership, host = systemHost) => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
processes = liveProcesses(await host.listProcesses());
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
107
|
+
const processes = await readLiveProcessTable(host);
|
|
108
|
+
if (processes === undefined)
|
|
105
109
|
return { cleaned: false, reason: "process table could not be inspected" };
|
|
106
|
-
}
|
|
107
110
|
const plan = await createOwnedCleanupPlan(ownership, processes, host);
|
|
108
111
|
if ("cleaned" in plan)
|
|
109
112
|
return plan;
|
|
@@ -126,10 +129,38 @@ export const cleanupOwnedProcessGroup = async (ownership, host = systemHost) =>
|
|
|
126
129
|
}
|
|
127
130
|
return { cleaned: true, signaled };
|
|
128
131
|
};
|
|
132
|
+
/** Verify that no live process still carries an owned capture run token. */
|
|
133
|
+
export const verifyNoTokenOwnedProcesses = async (runId, host = systemHost) => {
|
|
134
|
+
const processes = await readLiveProcessTable(host);
|
|
135
|
+
if (processes === undefined)
|
|
136
|
+
return { cleaned: false, reason: "process table could not be inspected" };
|
|
137
|
+
const scan = await scanTokenOwnedProcesses(processes, runId, host);
|
|
138
|
+
if (scan.failures.length > 0)
|
|
139
|
+
return cleanupValidationFailure(scan.failures);
|
|
140
|
+
return scan.owned.length === 0
|
|
141
|
+
? { cleaned: true, signaled: false }
|
|
142
|
+
: { cleaned: false, reason: "token-owned process remained after cleanup" };
|
|
143
|
+
};
|
|
144
|
+
const readLiveProcessTable = async (host) => {
|
|
145
|
+
try {
|
|
146
|
+
return liveProcesses(await host.listProcesses());
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
129
152
|
const createOwnedCleanupPlan = async (ownership, processes, host) => {
|
|
153
|
+
const tokenOwned = ownership.sweepTokenOwnedProcesses === true
|
|
154
|
+
? await scanTokenOwnedProcesses(processes, ownership.runId, host)
|
|
155
|
+
: { owned: [], failures: [] };
|
|
156
|
+
if (tokenOwned.failures.length > 0)
|
|
157
|
+
return cleanupValidationFailure(tokenOwned.failures);
|
|
158
|
+
const tokenOwnedGroupIds = new Set(tokenOwned.owned.map(({ processGroupId }) => processGroupId));
|
|
130
159
|
const launcher = processes.find(({ pid }) => pid === ownership.leaderPid);
|
|
131
160
|
const rootMembers = processes.filter(({ processGroupId }) => processGroupId === ownership.processGroupId);
|
|
132
|
-
if (launcher === undefined &&
|
|
161
|
+
if (launcher === undefined &&
|
|
162
|
+
rootMembers.length === 0 &&
|
|
163
|
+
tokenOwned.owned.length === 0)
|
|
133
164
|
return { cleaned: true, signaled: false };
|
|
134
165
|
let descendants = [];
|
|
135
166
|
if (launcher !== undefined) {
|
|
@@ -142,11 +173,14 @@ const createOwnedCleanupPlan = async (ownership, processes, host) => {
|
|
|
142
173
|
const processGroupIds = new Set([ownership.processGroupId]);
|
|
143
174
|
for (const descendant of descendants)
|
|
144
175
|
processGroupIds.add(descendant.processGroupId);
|
|
176
|
+
for (const process of tokenOwned.owned)
|
|
177
|
+
processGroupIds.add(process.processGroupId);
|
|
145
178
|
for (const processGroupId of processGroupIds) {
|
|
146
179
|
if (processGroupId === ownership.processGroupId)
|
|
147
180
|
continue;
|
|
148
181
|
const groupLeader = processes.find(({ pid, processGroupId: observedGroupId }) => pid === processGroupId && observedGroupId === processGroupId);
|
|
149
|
-
if (groupLeader === undefined || !descendantPids.has(groupLeader.pid))
|
|
182
|
+
if ((groupLeader === undefined || !descendantPids.has(groupLeader.pid)) &&
|
|
183
|
+
!tokenOwnedGroupIds.has(processGroupId))
|
|
150
184
|
return {
|
|
151
185
|
cleaned: false,
|
|
152
186
|
reason: "descendant process-group leader identity could not be verified",
|
|
@@ -162,17 +196,6 @@ const createOwnedCleanupPlan = async (ownership, processes, host) => {
|
|
|
162
196
|
.sort((left, right) => left - right)),
|
|
163
197
|
};
|
|
164
198
|
};
|
|
165
|
-
const launcherIdentityFailure = (launcher, ownership) => {
|
|
166
|
-
if (launcher.processGroupId !== ownership.processGroupId)
|
|
167
|
-
return "owned launcher process-group identity did not match";
|
|
168
|
-
if (ownership.expectedParentPid !== undefined &&
|
|
169
|
-
launcher.parentPid !== ownership.expectedParentPid)
|
|
170
|
-
return "owned launcher parent identity did not match";
|
|
171
|
-
if (ownership.expectedCommand !== undefined &&
|
|
172
|
-
!matchesOwnedProcessCommand(launcher.command, ownership.expectedCommand))
|
|
173
|
-
return `owned launcher command identity did not match (observed=${launcher.command}; expected=${ownership.expectedCommand})`;
|
|
174
|
-
return null;
|
|
175
|
-
};
|
|
176
199
|
const revalidateOwnedProcessGroup = async (processGroupId, ownership, host) => {
|
|
177
200
|
let members;
|
|
178
201
|
try {
|
|
@@ -197,7 +220,8 @@ const revalidateOwnedProcessGroup = async (processGroupId, ownership, host) => {
|
|
|
197
220
|
}
|
|
198
221
|
if (processGroupId !== ownership.processGroupId &&
|
|
199
222
|
members.length > 0 &&
|
|
200
|
-
!members.some(({ pid }) => pid === processGroupId)
|
|
223
|
+
!members.some(({ pid }) => pid === processGroupId) &&
|
|
224
|
+
ownership.sweepTokenOwnedProcesses !== true)
|
|
201
225
|
return {
|
|
202
226
|
cleaned: false,
|
|
203
227
|
reason: "descendant process-group leader identity could not be revalidated",
|
|
@@ -230,39 +254,28 @@ const processOwnershipFailures = async (members, runId, host) => {
|
|
|
230
254
|
}
|
|
231
255
|
return failures;
|
|
232
256
|
};
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
members = (await host.listProcesses()).filter(({ processGroupId }) => processGroupId === ownership.processGroupId);
|
|
238
|
-
}
|
|
239
|
-
catch {
|
|
240
|
-
return {
|
|
241
|
-
state: "unverifiable",
|
|
242
|
-
reason: "process group could not be inspected",
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
const liveMembers = liveProcesses(members);
|
|
246
|
-
if (liveMembers.length === 0)
|
|
247
|
-
return { state: "empty" };
|
|
248
|
-
for (const member of liveMembers) {
|
|
257
|
+
const scanTokenOwnedProcesses = async (processes, runId, host) => {
|
|
258
|
+
const owned = [];
|
|
259
|
+
const failures = [];
|
|
260
|
+
for (const process of processes) {
|
|
249
261
|
try {
|
|
250
|
-
if ((await host.environment(
|
|
251
|
-
|
|
252
|
-
return {
|
|
253
|
-
state: "unverifiable",
|
|
254
|
-
reason: "process ownership did not match",
|
|
255
|
-
};
|
|
262
|
+
if ((await host.environment(process.pid)).REA_PROCESS_RUN_ID === runId)
|
|
263
|
+
owned.push(process);
|
|
256
264
|
}
|
|
257
265
|
catch {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
266
|
+
try {
|
|
267
|
+
const live = liveProcesses(await host.listProcesses());
|
|
268
|
+
if (!live.some(({ pid }) => pid === process.pid))
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
catch { }
|
|
272
|
+
failures.push({ pid: process.pid, reason: "environment-unreadable" });
|
|
262
273
|
}
|
|
263
274
|
}
|
|
264
|
-
return {
|
|
275
|
+
return { owned, failures };
|
|
265
276
|
};
|
|
277
|
+
/** Observe one group without signaling it, failing closed on identity doubt. */
|
|
278
|
+
export const observeOwnedProcessGroup = async (ownership, host = systemHost) => observeOwnedProcessGroupWithHost(ownership, host);
|
|
266
279
|
/**
|
|
267
280
|
* Record the live launcher and descendant lineage after run-token validation.
|
|
268
281
|
*
|
|
@@ -270,80 +283,4 @@ export const observeOwnedProcessGroup = async (ownership, host = systemHost) =>
|
|
|
270
283
|
* list means no descendants were live during this observation, not that the
|
|
271
284
|
* run never created a short-lived child.
|
|
272
285
|
*/
|
|
273
|
-
export const observeOwnedProcessLineage = async (ownership, host = systemHost) =>
|
|
274
|
-
let processes;
|
|
275
|
-
try {
|
|
276
|
-
processes = liveProcesses(await host.listProcesses());
|
|
277
|
-
}
|
|
278
|
-
catch {
|
|
279
|
-
return unavailableLineage(ownership, "process table could not be inspected");
|
|
280
|
-
}
|
|
281
|
-
const launcher = processes.find(({ pid }) => pid === ownership.leaderPid);
|
|
282
|
-
if (launcher === undefined)
|
|
283
|
-
return unavailableLineage(ownership, "owned launcher is not live");
|
|
284
|
-
if (launcher.processGroupId !== ownership.processGroupId)
|
|
285
|
-
return unavailableLineage(ownership, "owned launcher process-group identity did not match");
|
|
286
|
-
if (ownership.expectedParentPid !== undefined &&
|
|
287
|
-
launcher.parentPid !== ownership.expectedParentPid)
|
|
288
|
-
return unavailableLineage(ownership, "owned launcher parent identity did not match");
|
|
289
|
-
if (ownership.expectedCommand !== undefined &&
|
|
290
|
-
!matchesOwnedProcessCommand(launcher.command, ownership.expectedCommand))
|
|
291
|
-
return unavailableLineage(ownership, `owned launcher command identity did not match (observed=${launcher.command}; expected=${ownership.expectedCommand})`);
|
|
292
|
-
const descendants = descendantsOf(launcher.pid, processes);
|
|
293
|
-
for (const member of [launcher, ...descendants]) {
|
|
294
|
-
try {
|
|
295
|
-
if ((await host.environment(member.pid)).REA_PROCESS_RUN_ID !==
|
|
296
|
-
ownership.runId)
|
|
297
|
-
return unavailableLineage(ownership, "process lineage contains an unowned or PID-reused process");
|
|
298
|
-
}
|
|
299
|
-
catch {
|
|
300
|
-
return unavailableLineage(ownership, "process ownership could not be revalidated");
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
return {
|
|
304
|
-
status: "verified",
|
|
305
|
-
observedAt: new Date().toISOString(),
|
|
306
|
-
lineage: {
|
|
307
|
-
schemaVersion: 1,
|
|
308
|
-
runId: ownership.runId,
|
|
309
|
-
launcherPid: launcher.pid,
|
|
310
|
-
launcherParentPid: launcher.parentPid,
|
|
311
|
-
processGroupId: launcher.processGroupId,
|
|
312
|
-
descendants: descendants
|
|
313
|
-
.sort((left, right) => left.pid - right.pid)
|
|
314
|
-
.map(({ pid, parentPid, processGroupId }) => ({
|
|
315
|
-
pid,
|
|
316
|
-
parentPid,
|
|
317
|
-
processGroupId,
|
|
318
|
-
})),
|
|
319
|
-
},
|
|
320
|
-
};
|
|
321
|
-
};
|
|
322
|
-
const descendantsOf = (launcherPid, processes) => {
|
|
323
|
-
const childrenByParent = new Map();
|
|
324
|
-
for (const process of processes) {
|
|
325
|
-
const siblings = childrenByParent.get(process.parentPid) ?? [];
|
|
326
|
-
siblings.push(process);
|
|
327
|
-
childrenByParent.set(process.parentPid, siblings);
|
|
328
|
-
}
|
|
329
|
-
const descendants = [];
|
|
330
|
-
const pending = [...(childrenByParent.get(launcherPid) ?? [])];
|
|
331
|
-
const visited = new Set([launcherPid]);
|
|
332
|
-
for (const process of pending) {
|
|
333
|
-
if (visited.has(process.pid))
|
|
334
|
-
continue;
|
|
335
|
-
visited.add(process.pid);
|
|
336
|
-
descendants.push(process);
|
|
337
|
-
pending.push(...(childrenByParent.get(process.pid) ?? []));
|
|
338
|
-
}
|
|
339
|
-
return descendants;
|
|
340
|
-
};
|
|
341
|
-
const unavailableLineage = (ownership, reason) => ({
|
|
342
|
-
status: "unavailable",
|
|
343
|
-
observedAt: new Date().toISOString(),
|
|
344
|
-
runId: ownership.runId,
|
|
345
|
-
launcherPid: ownership.leaderPid,
|
|
346
|
-
processGroupId: ownership.processGroupId,
|
|
347
|
-
reason,
|
|
348
|
-
});
|
|
349
|
-
const liveProcesses = (members) => members.filter(({ state }) => !state.startsWith("Z"));
|
|
286
|
+
export const observeOwnedProcessLineage = async (ownership, host = systemHost) => observeOwnedProcessLineageWithHost(ownership, host);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { matchesOwnedProcessCommand } from "./ProcessCommandIdentity.js";
|
|
2
|
+
/** Compare a live launcher against the identity committed at process launch. */
|
|
3
|
+
export const launcherIdentityFailure = (launcher, ownership) => {
|
|
4
|
+
if (launcher.processGroupId !== ownership.processGroupId)
|
|
5
|
+
return "owned launcher process-group identity did not match";
|
|
6
|
+
if (ownership.expectedParentPid !== undefined &&
|
|
7
|
+
launcher.parentPid !== ownership.expectedParentPid)
|
|
8
|
+
return "owned launcher parent identity did not match";
|
|
9
|
+
if (ownership.expectedCommand !== undefined &&
|
|
10
|
+
!matchesOwnedProcessCommand(launcher.command, ownership.expectedCommand))
|
|
11
|
+
return `owned launcher command identity did not match (observed=${launcher.command}; expected=${ownership.expectedCommand})`;
|
|
12
|
+
return null;
|
|
13
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { launcherIdentityFailure } from "./ProcessOwnershipIdentity.js";
|
|
2
|
+
import { descendantsOf, liveProcesses } from "./ProcessOwnershipProcessTree.js";
|
|
3
|
+
/** Observe one group without signaling it, failing closed on identity doubt. */
|
|
4
|
+
export const observeOwnedProcessGroupWithHost = async (ownership, host) => {
|
|
5
|
+
let members;
|
|
6
|
+
try {
|
|
7
|
+
members = (await host.listProcesses()).filter(({ processGroupId }) => processGroupId === ownership.processGroupId);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return {
|
|
11
|
+
state: "unverifiable",
|
|
12
|
+
reason: "process group could not be inspected",
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const liveMembers = liveProcesses(members);
|
|
16
|
+
if (liveMembers.length === 0)
|
|
17
|
+
return { state: "empty" };
|
|
18
|
+
for (const member of liveMembers) {
|
|
19
|
+
try {
|
|
20
|
+
if ((await host.environment(member.pid)).REA_PROCESS_RUN_ID !==
|
|
21
|
+
ownership.runId)
|
|
22
|
+
return {
|
|
23
|
+
state: "unverifiable",
|
|
24
|
+
reason: "process ownership did not match",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return {
|
|
29
|
+
state: "unverifiable",
|
|
30
|
+
reason: "process ownership could not be revalidated",
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return { state: "alive" };
|
|
35
|
+
};
|
|
36
|
+
/** Record the live launcher and descendant lineage after run-token validation. */
|
|
37
|
+
export const observeOwnedProcessLineageWithHost = async (ownership, host) => {
|
|
38
|
+
let processes;
|
|
39
|
+
try {
|
|
40
|
+
processes = liveProcesses(await host.listProcesses());
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return unavailableLineage(ownership, "process table could not be inspected");
|
|
44
|
+
}
|
|
45
|
+
const launcher = processes.find(({ pid }) => pid === ownership.leaderPid);
|
|
46
|
+
if (launcher === undefined)
|
|
47
|
+
return unavailableLineage(ownership, "owned launcher is not live");
|
|
48
|
+
const identityFailure = launcherIdentityFailure(launcher, ownership);
|
|
49
|
+
if (identityFailure !== null)
|
|
50
|
+
return unavailableLineage(ownership, identityFailure);
|
|
51
|
+
const descendants = descendantsOf(launcher.pid, processes);
|
|
52
|
+
for (const member of [launcher, ...descendants]) {
|
|
53
|
+
try {
|
|
54
|
+
if ((await host.environment(member.pid)).REA_PROCESS_RUN_ID !==
|
|
55
|
+
ownership.runId)
|
|
56
|
+
return unavailableLineage(ownership, "process lineage contains an unowned or PID-reused process");
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return unavailableLineage(ownership, "process ownership could not be revalidated");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
status: "verified",
|
|
64
|
+
observedAt: new Date().toISOString(),
|
|
65
|
+
lineage: {
|
|
66
|
+
runId: ownership.runId,
|
|
67
|
+
launcherPid: launcher.pid,
|
|
68
|
+
launcherParentPid: launcher.parentPid,
|
|
69
|
+
processGroupId: launcher.processGroupId,
|
|
70
|
+
descendants: descendants
|
|
71
|
+
.sort((left, right) => left.pid - right.pid)
|
|
72
|
+
.map(({ pid, parentPid, processGroupId }) => ({
|
|
73
|
+
pid,
|
|
74
|
+
parentPid,
|
|
75
|
+
processGroupId,
|
|
76
|
+
})),
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
const unavailableLineage = (ownership, reason) => ({
|
|
81
|
+
status: "unavailable",
|
|
82
|
+
observedAt: new Date().toISOString(),
|
|
83
|
+
runId: ownership.runId,
|
|
84
|
+
launcherPid: ownership.leaderPid,
|
|
85
|
+
processGroupId: ownership.processGroupId,
|
|
86
|
+
reason,
|
|
87
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Exclude process-table entries that the operating system has already reaped. */
|
|
2
|
+
export const liveProcesses = (members) => members.filter(({ state }) => !state.startsWith("Z"));
|
|
3
|
+
/** Return every live-table descendant of a launcher in breadth-first order. */
|
|
4
|
+
export const descendantsOf = (launcherPid, processes) => {
|
|
5
|
+
const childrenByParent = new Map();
|
|
6
|
+
for (const process of processes) {
|
|
7
|
+
const siblings = childrenByParent.get(process.parentPid) ?? [];
|
|
8
|
+
siblings.push(process);
|
|
9
|
+
childrenByParent.set(process.parentPid, siblings);
|
|
10
|
+
}
|
|
11
|
+
const descendants = [];
|
|
12
|
+
const pending = [...(childrenByParent.get(launcherPid) ?? [])];
|
|
13
|
+
const visited = new Set([launcherPid]);
|
|
14
|
+
for (const process of pending) {
|
|
15
|
+
if (visited.has(process.pid))
|
|
16
|
+
continue;
|
|
17
|
+
visited.add(process.pid);
|
|
18
|
+
descendants.push(process);
|
|
19
|
+
pending.push(...(childrenByParent.get(process.pid) ?? []));
|
|
20
|
+
}
|
|
21
|
+
return descendants;
|
|
22
|
+
};
|