rea-agents 3.2.1 → 4.0.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 +183 -332
- package/bridge/ghidra/ReaGhidraBridge.java +561 -74
- package/bridge/hopper_bridge.py +70 -27
- package/bridge/native/ReaNativeUI.swift +157 -0
- package/dist/application/AnalysisContextQueries.js +19 -5
- package/dist/application/AnalysisSnapshotCache.js +30 -11
- package/dist/application/AppleAssetCatalogAnalysis.js +171 -0
- package/dist/application/ArtifactExtractionDestination.js +0 -12
- package/dist/application/ArtifactGraphConstruction.js +44 -11
- package/dist/application/ArtifactInventory/classify.js +7 -15
- package/dist/application/ArtifactInventory/hash.js +4 -2
- package/dist/application/ArtifactInventory/policy.js +2 -17
- package/dist/application/ArtifactInventory/reader.js +3 -3
- package/dist/application/ArtifactInventory/scanCanonical.js +2 -2
- package/dist/application/ArtifactInventory/scanReader.js +12 -4
- package/dist/application/ArtifactInventory/types.js +0 -3
- package/dist/application/BinarySession.js +28 -43
- package/dist/application/BinarySessionExecution.js +37 -1
- package/dist/application/BinaryTargetResolver.js +50 -4
- package/dist/application/BrowserEvidence.js +36 -7
- package/dist/application/BrowserObservationService.js +17 -44
- package/dist/application/BrowserScenarioCaptureService.js +2 -35
- package/dist/application/BrowserScenarioEvidence.js +13 -9
- package/dist/application/CapabilityClientRequirements.js +2 -11
- package/dist/application/CapabilityInventory.js +21 -35
- package/dist/application/ClientConfigurationDocument.js +84 -7
- package/dist/application/ClientRegistrationIdentity.js +32 -0
- package/dist/application/ClientRegistrationStatus.js +59 -6
- package/dist/application/DirectAnalysis.js +37 -58
- package/dist/application/DirectAnalysisStatus.js +4 -4
- package/dist/application/Doctor.js +89 -80
- package/dist/application/DoctorDiagnostics.js +2 -26
- package/dist/application/DoctorScope.js +8 -14
- package/dist/application/ElectronActiveEvidence.js +10 -27
- package/dist/application/ElectronActiveObservationService.js +9 -36
- package/dist/application/ElectronBoundaryAnalysis.js +2 -0
- package/dist/application/ElectronBoundaryGraphNative.js +1 -1
- package/dist/application/ElectronEvidence.js +8 -3
- package/dist/application/ElectronObservationService.js +9 -25
- package/dist/application/EnhancedLiteralTracing.js +4 -8
- package/dist/application/EnhancedTools.js +15 -35
- package/dist/application/FilesystemSnapshot.js +7 -8
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +2 -1
- package/dist/application/JavaScriptApplicationWorkflowService.js +31 -7
- package/dist/application/JavaScriptArtifactAnalysis.js +6 -4
- package/dist/application/JavaScriptArtifactFiles.js +5 -0
- package/dist/application/JavaScriptArtifactPathResolution.js +179 -47
- package/dist/application/JavaScriptRuntimeObservationEvidence.js +6 -3
- package/dist/application/JavaScriptRuntimeObservationService.js +9 -25
- package/dist/application/JavaScriptRuntimeReconciliationService.js +45 -4
- package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +11 -0
- package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +11 -0
- package/dist/application/JavaScriptSemanticGraphDataProjection.js +11 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +14 -5
- package/dist/application/JsonFiles.js +1 -1
- package/dist/application/LazyAnalysisProvider.js +27 -6
- package/dist/application/ManagedMemberComparisonService.js +19 -6
- package/dist/application/NativeApiInspection.js +2 -0
- package/dist/application/NativeCallRoutes.js +72 -0
- package/dist/application/NativeDispatchMetadataInspection.js +33 -0
- package/dist/application/NativeUiActionTrace.js +73 -49
- package/dist/application/NativeValueTrace.js +320 -0
- package/dist/application/ProcessCaptureCapability.js +32 -5
- package/dist/application/ProcessCaptureEnvironment.js +9 -26
- package/dist/application/ProcessCaptureError.js +1 -5
- package/dist/application/ProcessCaptureJournal.js +3 -40
- package/dist/application/ProcessCaptureLifecycle.js +102 -111
- package/dist/application/ProcessCli.js +18 -25
- package/dist/application/ProcessEvidence.js +5 -7
- package/dist/application/ProcessFilesystemEffects.js +36 -0
- package/dist/application/ProcessHarness.js +41 -120
- package/dist/application/ProcessNormalization.js +2 -17
- package/dist/application/ProcessScenarioRuntimeValidation.js +76 -0
- package/dist/application/ReferenceSourceImport.js +3 -4
- package/dist/application/Setup.js +236 -84
- package/dist/application/SetupClientConfiguration.js +14 -9
- package/dist/application/SetupPlan.js +138 -86
- package/dist/application/SetupSkill.js +0 -1
- package/dist/application/SupportedClients.js +102 -21
- package/dist/application/Uninstall.js +31 -20
- package/dist/application/Update.js +93 -0
- package/dist/application/UpdateMaintenance.js +108 -0
- package/dist/application/UpdateRuntime.js +126 -0
- package/dist/application/runtime.js +13 -2
- package/dist/artifacts/ArtifactPaths.js +6 -8
- package/dist/artifacts/ArtifactProvider.js +94 -41
- package/dist/artifacts/AsarArtifactReader.js +19 -4
- package/dist/artifacts/KeyedArchiveReader.js +110 -0
- package/dist/artifacts/MachOSliceArtifactReader.js +53 -5
- package/dist/artifacts/ZipArtifactReader.js +18 -1
- package/dist/browser/BrowserScenarioSecrets.js +28 -1
- package/dist/browser/CdpBrowserProvider.js +36 -15
- package/dist/browser/CdpCaptureDocuments.js +22 -8
- package/dist/browser/CdpCaptureEventHandlers.js +14 -5
- package/dist/browser/CdpCaptureEventHelpers.js +13 -0
- package/dist/browser/CdpCaptureEvents.js +10 -1
- package/dist/browser/CdpElectronInspection.js +5 -10
- package/dist/browser/CdpElectronProvider.js +1 -5
- package/dist/browser/CdpElectronScripts.js +1 -1
- package/dist/browser/CdpEndpoint.js +3 -2
- package/dist/browser/CdpObservationSession.js +14 -10
- package/dist/browser/CdpPageCapture.js +1 -1
- package/dist/browser/CdpPageCaptureScripts.js +1 -1
- package/dist/browser/CdpSafeMetadata.js +5 -4
- package/dist/browser/CdpScreenshot.js +16 -5
- package/dist/browser/CdpTargetSession.js +25 -4
- package/dist/browser/CdpWebMcpDiscovery.js +93 -20
- package/dist/browser/JavaScriptRuntimeScope.js +28 -2
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +9 -8
- package/dist/browser/PlaywrightElectronActiveActions.js +3 -10
- package/dist/browser/PlaywrightElectronActiveProvider.js +5 -5
- package/dist/browser/PlaywrightScenarioActions.js +1 -1
- package/dist/browser/PlaywrightScenarioArtifacts.js +13 -25
- package/dist/browser/PlaywrightScenarioBrowser.js +28 -25
- package/dist/browser/PlaywrightScenarioEvents.js +82 -93
- package/dist/browser/PlaywrightScenarioSession.js +27 -123
- package/dist/browser/PngVisualDiff.js +22 -3
- package/dist/browser/V8InspectorCaptureProjection.js +7 -1
- package/dist/browser/V8InspectorProvider.js +60 -7
- package/dist/browser/WebSourceMapFetcher.js +99 -53
- package/dist/cli/artifactCommands.js +56 -12
- package/dist/cli/coreAnalysisCommands.js +110 -0
- package/dist/cli/managedCommands.js +1 -31
- package/dist/cli/setupCommands.js +16 -14
- package/dist/cli/utilityCommands.js +61 -4
- package/dist/cli.js +5 -7
- package/dist/cliApplicationCommands.js +0 -83
- package/dist/cliBrowserAdvancedCommands.js +7 -11
- package/dist/cliBrowserCommands.js +15 -23
- package/dist/cliBrowserContext.js +3 -24
- package/dist/cliBrowserScenarioCommands.js +2 -10
- package/dist/cliCommandNames.js +82 -7
- package/dist/cliElectronCommands.js +10 -36
- package/dist/cliJavaScriptRuntimeCommands.js +6 -30
- package/dist/cliJsonInput.js +4 -2
- package/dist/cliLogging.js +16 -7
- package/dist/cliObservationOptions.js +1 -1
- package/dist/cliOutput.js +2 -4
- package/dist/cliProcessCommands.js +6 -33
- package/dist/cliSetup.js +90 -160
- package/dist/config/environment.js +2 -78
- package/dist/config/parseConfig.js +18 -109
- package/dist/config/parsers.js +0 -23
- package/dist/contracts/applicationToolContracts.js +1 -118
- package/dist/contracts/artifactToolContracts.js +11 -19
- package/dist/contracts/browserScenarioToolContracts.js +1 -5
- package/dist/contracts/browserToolContracts.js +9 -16
- package/dist/contracts/electronToolContracts.js +5 -6
- package/dist/contracts/enhancedInputs.js +3 -2
- package/dist/contracts/errorSchemas.js +16 -40
- package/dist/contracts/functionWorkflowToolContracts.js +2 -2
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +2 -2
- package/dist/contracts/javascriptRuntimeObservationToolContracts.js +4 -4
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +1 -1
- package/dist/contracts/managedToolContracts.js +7 -4
- package/dist/contracts/managedWorkflowExamples.js +0 -22
- package/dist/contracts/managedWorkflowToolContracts.js +16 -31
- package/dist/contracts/nativeToolContracts.js +9 -0
- package/dist/contracts/promptContracts.js +6 -6
- package/dist/contracts/sessionToolSchemas.js +3 -3
- package/dist/contracts/toolContractExamples.js +4 -3
- package/dist/contracts/toolContracts.js +18 -7
- package/dist/contracts/toolEffects.js +34 -21
- package/dist/contracts/toolOutputSchemaGroups.js +18 -5
- package/dist/contracts/toolOutputSchemaPrimitives.js +9 -6
- package/dist/contracts/toolSchemaMetadata.js +5 -8
- package/dist/doctorRuntime.js +0 -41
- package/dist/domain/analysisErrorPresentation.js +4 -28
- package/dist/domain/analysisErrorProjection.js +33 -50
- package/dist/domain/analysisProfile.js +1 -1
- package/dist/domain/analysisSnapshot.js +77 -3
- package/dist/domain/androidApplication.js +5 -4
- package/dist/domain/appleApplication.js +5 -4
- package/dist/domain/appleAssetCatalog.js +127 -0
- package/dist/domain/artifactComparison.js +7 -11
- package/dist/domain/artifactGraph.js +8 -6
- package/dist/domain/artifactInspection.js +13 -12
- package/dist/domain/binaryTarget.js +23 -9
- package/dist/domain/browserObservation.js +43 -24
- package/dist/domain/browserObservationSchemas.js +2 -1
- package/dist/domain/browserScenario.js +7 -107
- package/dist/domain/browserScenarioCapture.js +0 -1
- package/dist/domain/browserScenarioCaptureValues.js +5 -4
- package/dist/domain/browserScenarioDiff.js +1 -3
- package/dist/domain/browserScenarioValues.js +16 -107
- package/dist/domain/bundleComparison.js +18 -17
- package/dist/domain/callPathSchemas.js +17 -7
- package/dist/domain/changedBehavior.js +2 -3
- package/dist/domain/comparisonSemantics.js +19 -0
- package/dist/domain/completionLedgerGeneration.js +3 -2
- package/dist/domain/conformancePackage.js +2 -1
- package/dist/domain/conformanceTrustGate.js +3 -5
- package/dist/domain/customProtocolCapture.js +2 -2
- package/dist/domain/digests.js +30 -0
- package/dist/domain/dosMz.js +83 -0
- package/dist/domain/electronActiveObservation.js +7 -5
- package/dist/domain/electronObservation.js +3 -2
- package/dist/domain/electronStaticAnalysisNative.js +15 -6
- package/dist/domain/emptyArraySchema.js +3 -0
- package/dist/domain/errors.js +10 -28
- package/dist/domain/evidence.js +5 -3
- package/dist/domain/evidenceCompletionLedger.js +3 -2
- package/dist/domain/functionComparisonNormalization.js +24 -18
- package/dist/domain/functionComparisonResults.js +3 -7
- package/dist/domain/functionComparisonSchemas.js +3 -2
- package/dist/domain/hopperValues.js +108 -8
- package/dist/domain/javascriptApplicationAnalysis.js +4 -7
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +4 -3
- package/dist/domain/javascriptApplicationGraphSchemas.js +8 -7
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +9 -7
- package/dist/domain/javascriptApplicationVersionItems.js +12 -18
- package/dist/domain/javascriptAstValues.js +4 -0
- package/dist/domain/javascriptExportShapeComparison.js +1 -6
- package/dist/domain/javascriptExportShapeComparisonSchemas.js +6 -10
- package/dist/domain/javascriptExportShapeVariants.js +15 -2
- package/dist/domain/javascriptFeatureTraceSchemas.js +8 -7
- package/dist/domain/javascriptRuntimeObservation.js +14 -2
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +8 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +4 -2
- package/dist/domain/javascriptRuntimeReconciliationResult.js +6 -4
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +15 -4
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +19 -18
- package/dist/domain/javascriptRuntimeStaticCandidates.js +18 -6
- package/dist/domain/javascriptSemanticAnalysis.js +57 -19
- package/dist/domain/javascriptSemanticAsyncEffects.js +39 -40
- package/dist/domain/javascriptSemanticCalls.js +46 -27
- package/dist/domain/javascriptSemanticChildProcesses.js +43 -50
- package/dist/domain/javascriptSemanticDataEffectHelpers.js +91 -18
- package/dist/domain/javascriptSemanticDataEffects.js +22 -10
- package/dist/domain/javascriptSemanticGraphSchemas.js +8 -6
- package/dist/domain/javascriptSemanticObjects.js +13 -3
- package/dist/domain/javascriptSemanticProjection.js +144 -38
- package/dist/domain/javascriptSemanticPromises.js +14 -27
- package/dist/domain/javascriptSemanticQuerySchemas.js +6 -9
- package/dist/domain/javascriptSemanticResources.js +2 -5
- package/dist/domain/javascriptSemanticState.js +4 -0
- package/dist/domain/javascriptSemanticTraceSchemas.js +2 -1
- package/dist/domain/javascriptSemanticTraversal.js +13 -5
- package/dist/domain/javascriptSemanticValues.js +10 -9
- package/dist/domain/javascriptSourceParser.js +5 -1
- package/dist/domain/javascriptStaticAnalysisCalls.js +8 -5
- package/dist/domain/javascriptStaticAnalysisHelpers.js +16 -7
- package/dist/domain/keyedArchive.js +181 -0
- package/dist/domain/managedApplicationGraph.js +4 -3
- package/dist/domain/managedArtifact.js +2 -1
- package/dist/domain/managedMemberComparison.js +18 -13
- package/dist/domain/managedMemberComparisonCoverage.js +2 -1
- package/dist/domain/managedMemberComparisonItems.js +27 -7
- package/dist/domain/managedMemberComparisonMatch.js +22 -6
- package/dist/domain/managedNativeVerificationMatch.js +2 -2
- package/dist/domain/managedNativeVerificationSchemas.js +7 -5
- package/dist/domain/managedReconstruction.js +6 -5
- package/dist/domain/nativeApiBoundary.js +7 -0
- package/dist/domain/nativeDataType.js +51 -0
- package/dist/domain/nativeInspection.js +0 -1
- package/dist/domain/nativeInstruction.js +82 -0
- package/dist/domain/nativeInvestigationGraph.js +9 -5
- package/dist/domain/nativeUiObservation.js +123 -0
- package/dist/domain/nativeValueFlow.js +17 -0
- package/dist/domain/nativeValueTrace.js +64 -0
- package/dist/domain/objcSwiftMetadata.js +39 -0
- package/dist/domain/peInspection.js +1 -0
- package/dist/domain/processCapture.js +5 -55
- package/dist/domain/processCaptureExample.js +0 -9
- package/dist/domain/processCaptureValidation.js +13 -144
- package/dist/domain/processComparison.js +3 -25
- package/dist/domain/processObservation.js +0 -29
- package/dist/domain/processScenario.js +28 -228
- package/dist/domain/processTraceDimensionProjection.js +0 -15
- package/dist/domain/processTraceEvaluation.js +0 -6
- package/dist/domain/protocolCapture.js +8 -36
- package/dist/domain/reconstructionCoverage.js +3 -2
- package/dist/domain/reconstructionObligationLedgerSchemas.js +4 -12
- package/dist/domain/reconstructionReadinessSchemas.js +4 -3
- package/dist/domain/reconstructionVerification.js +2 -1
- package/dist/domain/reconstructionVerificationSchemas.js +6 -13
- package/dist/domain/referenceSourceClassification.js +0 -110
- package/dist/domain/referenceSourceGraph.js +15 -5
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/runtimeIdentification.js +6 -5
- package/dist/domain/sourceMapContents.js +5 -0
- package/dist/domain/sourceToBundleComparison.js +3 -10
- package/dist/domain/sourceToBundleComparisonSchemas.js +7 -6
- package/dist/domain/sourceToBundleSignals.js +9 -3
- package/dist/domain/staticRuntimeCorrelation.js +5 -11
- package/dist/domain/webBundleAnalysis.js +17 -9
- package/dist/domain/webBundleAnalyzer.js +1 -1
- package/dist/domain/webCaptureDiff.js +5 -11
- package/dist/domain/webCaptureDiffSchemas.js +2 -1
- package/dist/domain/webMcpDiscovery.js +2 -1
- package/dist/dotnet/ManagedMemberInspectorCore.js +15 -7
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +57 -40
- package/dist/dotnet/ManagedMemberRows.js +2 -0
- package/dist/dotnet/ManagedMethodBodyReader.js +15 -8
- package/dist/dotnet/ManagedPeReader.js +2 -0
- package/dist/generatedMcpToolCatalog.js +1 -1
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +15 -5
- package/dist/ghidra/GhidraClient.js +38 -8
- package/dist/ghidra/GhidraFunctionValues.js +56 -20
- package/dist/ghidra/GhidraInstallation.js +7 -4
- package/dist/ghidra/GhidraInventoryValues.js +44 -9
- package/dist/ghidra/GhidraLauncher.js +18 -3
- package/dist/ghidra/GhidraProvider.js +23 -2
- package/dist/ghidra/GhidraRequestQueue.js +45 -4
- package/dist/ghidra/GhidraSessionValues.js +5 -0
- package/dist/hopper/HopperAnalysisProfile.js +2 -0
- package/dist/hopper/HopperProvider.js +29 -6
- package/dist/hopper/HopperTargetLease.js +18 -4
- package/dist/logger.js +0 -13
- package/dist/main/messages.js +0 -1
- package/dist/main/reload.js +3 -32
- package/dist/main/shutdown.js +1 -2
- package/dist/main/transport.js +0 -17
- package/dist/main.js +0 -10
- package/dist/native/AppleDispatchMetadata.js +582 -0
- package/dist/native/AppleObjcProtocols.js +88 -0
- package/dist/native/AppleSwiftVtables.js +86 -0
- package/dist/native/CommandRunner.js +1 -1
- package/dist/native/NativeHostCapabilities.js +23 -0
- package/dist/native/NativeMacOSProvider.js +61 -9
- package/dist/native/NativeMachoInspection.js +39 -6
- package/dist/native/NativeUiHelperRuntime.js +42 -0
- package/dist/native/NativeUiObservation.js +174 -0
- package/dist/native/parsers/codesign.js +4 -1
- package/dist/native/parsers/dyldInfo.js +51 -25
- package/dist/native/parsers/lipo.js +13 -4
- package/dist/native/parsers/otool.js +84 -39
- package/dist/native/parsers/plist.js +2 -1
- package/dist/process/ExecFileOutput.js +5 -1
- package/dist/process/ProcessOwnership.js +69 -33
- package/dist/process/ProcessOwnershipObservation.js +31 -12
- package/dist/process/ProviderProcess.js +4 -2
- package/dist/reference/ReferenceSourceReaderEntries.js +48 -31
- package/dist/reference/ReferenceSourceReaderErrors.js +24 -0
- package/dist/reference/ReferenceSourceReaderFile.js +11 -5
- package/dist/reference/ReferenceSourceReaderValidate.js +22 -8
- package/dist/server/createServer.js +7 -62
- package/dist/server/registerApplicationTools/helpers.js +2 -9
- package/dist/server/registerApplicationTools.js +0 -4
- package/dist/server/registerArtifactComparisonTool.js +1 -1
- package/dist/server/registerBrowserScenarioTool.js +4 -2
- package/dist/server/registerBrowserTools.js +7 -7
- package/dist/server/registerBundleComparisonTool.js +1 -1
- package/dist/server/registerCloseLifecycleTool.js +1 -1
- package/dist/server/registerElectronTools.js +10 -4
- package/dist/server/registerEnhancedTools.js +20 -12
- package/dist/server/registerEvidenceTools.js +4 -28
- package/dist/server/registerFunctionComparisonTool.js +1 -1
- package/dist/server/registerInvestigationTools.js +6 -6
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -2
- package/dist/server/registerManagedTools.js +28 -14
- package/dist/server/registerManagedWorkflowTools.js +0 -2
- package/dist/server/registerProcessComparisonTool.js +1 -3
- package/dist/server/registerSessionRecordTools.js +9 -9
- package/dist/server/registerSessionStatusTool.js +1 -1
- package/dist/server/registerSessionTools.js +28 -57
- package/dist/server/sessionAvailabilityPolicy.js +2 -3
- package/dist/server/sessionToolPolicies.js +0 -4
- package/dist/server/toolResult.js +8 -10
- package/package.json +32 -22
- package/skills/reverse-engineer-anything/SKILL.md +15 -11
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +3 -2
- package/skills/reverse-engineer-anything/references/javascript-applications.md +3 -2
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +8 -6
- package/skills/reverse-engineer-anything/references/runtime-observation.md +15 -11
- package/dist/application/CommandShimReplay.js +0 -152
- package/dist/application/ConfiguredRoots.js +0 -19
- package/dist/application/InstrumentedJavaScriptReplayHost.js +0 -36
- package/dist/application/JavaScriptReplayPermission.js +0 -16
- package/dist/application/JavaScriptReplayPlanning.js +0 -207
- package/dist/application/JavaScriptReplayService.js +0 -274
- package/dist/application/LoopbackReplay.js +0 -389
- package/dist/application/LoopbackReplayRecorder.js +0 -129
- package/dist/application/ManagedRuntimeCorrelationService.js +0 -104
- package/dist/application/NodeRuntimeCharacterizationService.js +0 -191
- package/dist/application/PermissionAuthority.js +0 -268
- package/dist/application/PermissionConfiguration.js +0 -26
- package/dist/application/PermissionFailure.js +0 -5
- package/dist/application/ProcessCaptureAuthority.js +0 -24
- package/dist/application/ProcessCapturePermission.js +0 -13
- package/dist/application/ProcessCheckpoints.js +0 -178
- package/dist/application/ProcessReactiveCoordinator.js +0 -223
- package/dist/application/ProcessReactiveEffects.js +0 -153
- package/dist/application/ProcessReactiveHarness.js +0 -106
- package/dist/application/ProcessReactiveObservations.js +0 -105
- package/dist/application/ProjectPermissionStore.js +0 -199
- package/dist/application/RuntimeExecutableDiagnostics.js +0 -198
- package/dist/application/Upgrade.js +0 -134
- package/dist/browser/SensitiveTextCapture.js +0 -8
- package/dist/cliPolicyCommands.js +0 -185
- package/dist/config/browserScenario.js +0 -77
- package/dist/config/electronAutomation.js +0 -35
- package/dist/config/javascriptReplay.js +0 -41
- package/dist/config/managedRuntime.js +0 -25
- package/dist/config/passiveObservation.js +0 -87
- package/dist/config/permissions.js +0 -23
- package/dist/config/processCapture.js +0 -47
- package/dist/contracts/replayMachineExample.js +0 -37
- package/dist/domain/javascriptExportInstrumentation.js +0 -95
- package/dist/domain/javascriptReplay.js +0 -360
- package/dist/domain/managedRuntimeCorrelation.js +0 -181
- package/dist/domain/nodeRuntimeCharacterization.js +0 -63
- package/dist/domain/permissionPolicy.js +0 -176
- package/dist/domain/processCaptureReactiveSchema.js +0 -68
- package/dist/domain/processCaptureReactiveValidation.js +0 -180
- package/dist/domain/processReactiveCheckpointDataflow.js +0 -32
- package/dist/domain/processReactiveMatching.js +0 -196
- package/dist/domain/processReactiveRuntime.js +0 -116
- package/dist/domain/processReactiveScenario.js +0 -296
- package/dist/domain/processReactiveScenarioPreflight.js +0 -95
- package/dist/domain/processReactiveTransition.js +0 -187
- package/dist/domain/replayMachine.js +0 -320
- package/dist/domain/replayMachineRun.js +0 -168
- package/dist/domain/replayMachineRuntime.js +0 -296
- package/dist/domain/replayMachineValues.js +0 -84
- package/dist/domain/runtimeCharacterization.js +0 -84
- package/dist/replay/JavaScriptReplayWorker.js +0 -382
- package/dist/replay/JavaScriptReplayWorkerTypes.js +0 -1
- package/dist/replay/LinuxJavaScriptReplayRunner.js +0 -216
- package/dist/replay/LinuxJavaScriptReplaySandbox.js +0 -121
- package/dist/replay/LinuxRuntimeClosure.js +0 -44
- package/dist/replay/LinuxSeccompPolicy.js +0 -40
- package/dist/replay/ReplayOutcome.js +0 -104
- package/dist/replay/ReplayProcessLifecycle.js +0 -96
- package/dist/replay/ReplaySeccompFile.js +0 -29
- package/dist/replay/ReplayWorkerProtocol.js +0 -58
- package/dist/replay/SystemJavaScriptReplayHost.js +0 -153
- package/dist/server/ProcessCaptureElicitation.js +0 -153
- package/dist/server/registerApplicationTools/characterization.js +0 -46
- package/dist/server/registerApplicationTools/controlledReplay.js +0 -31
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +0 -29
- package/dist/server/registerReplayMachineTool.js +0 -14
- package/skills/reverse-engineer-anything/references/controlled-replay.md +0 -12
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
5
|
+
import { isOwnedClientRegistrationCommand } from "./ClientRegistrationIdentity.js";
|
|
6
|
+
import { readClientRegistrationStatuses } from "./ClientRegistrationStatus.js";
|
|
7
|
+
import { parseClientConfiguration } from "./ClientConfigurationDocument.js";
|
|
8
|
+
import { supportedClients } from "./SupportedClients.js";
|
|
9
|
+
const setupPlanSchema = z.object({
|
|
10
|
+
status: z.literal("planned"),
|
|
11
|
+
plannedActions: z.array(z.object({
|
|
12
|
+
id: z.string(),
|
|
13
|
+
kind: z.enum(["configure_client", "install_skill"]),
|
|
14
|
+
label: z.string(),
|
|
15
|
+
target: z.string(),
|
|
16
|
+
detail: z.string(),
|
|
17
|
+
external: z.literal(false),
|
|
18
|
+
operation: z.enum(["create", "update", "install"]),
|
|
19
|
+
backupPath: z.string().optional(),
|
|
20
|
+
commands: z.array(z.string()).optional(),
|
|
21
|
+
})),
|
|
22
|
+
});
|
|
23
|
+
/** Discover owned registrations and an existing REA skill without writes. */
|
|
24
|
+
export const existingMaintenanceScope = async (home, entryPoint) => {
|
|
25
|
+
const registrations = await readClientRegistrationStatuses(home, entryPoint);
|
|
26
|
+
const supported = supportedClients(home);
|
|
27
|
+
const clients = [];
|
|
28
|
+
for (const registration of registrations) {
|
|
29
|
+
if ((registration.state !== "aligned" && registration.state !== "stale") ||
|
|
30
|
+
!isOwnedClientRegistrationCommand(registration.command, entryPoint))
|
|
31
|
+
continue;
|
|
32
|
+
const client = supported.find(({ name }) => name === registration.client);
|
|
33
|
+
if (client === undefined)
|
|
34
|
+
continue;
|
|
35
|
+
const { servers } = parseClientConfiguration(await readFile(client.configPath, "utf8"), client.format);
|
|
36
|
+
const enabled = z
|
|
37
|
+
.object({
|
|
38
|
+
enabled: z.boolean().optional(),
|
|
39
|
+
disabled: z.boolean().optional(),
|
|
40
|
+
})
|
|
41
|
+
.parse(servers[PRODUCT_IDENTITY.mcpServerKey]);
|
|
42
|
+
if (enabled.enabled !== false && enabled.disabled !== true)
|
|
43
|
+
clients.push(client.name);
|
|
44
|
+
}
|
|
45
|
+
let skill = false;
|
|
46
|
+
try {
|
|
47
|
+
const content = await readFile(join(home, ".agents", "skills", PRODUCT_IDENTITY.skillName, "SKILL.md"), "utf8");
|
|
48
|
+
skill =
|
|
49
|
+
content.startsWith(`---\nname: ${PRODUCT_IDENTITY.skillName}\n`) ||
|
|
50
|
+
content.startsWith(`---\r\nname: ${PRODUCT_IDENTITY.skillName}\r\n`);
|
|
51
|
+
}
|
|
52
|
+
catch (cause) {
|
|
53
|
+
if (!(cause instanceof Error && "code" in cause && cause.code === "ENOENT"))
|
|
54
|
+
throw cause;
|
|
55
|
+
}
|
|
56
|
+
return { clients, skill };
|
|
57
|
+
};
|
|
58
|
+
/** Ask the verified new executable to plan only existing REA integrations. */
|
|
59
|
+
export const planIntegrationMaintenance = async (home, entryPoint, execute) => {
|
|
60
|
+
try {
|
|
61
|
+
const scope = await existingMaintenanceScope(home, entryPoint);
|
|
62
|
+
if (scope.clients.length === 0 && !scope.skill)
|
|
63
|
+
return { status: "current", plannedActions: [] };
|
|
64
|
+
const command = [
|
|
65
|
+
process.execPath,
|
|
66
|
+
entryPoint,
|
|
67
|
+
"setup",
|
|
68
|
+
...scope.clients.flatMap((client) => ["--client", client]),
|
|
69
|
+
`--skill=${String(scope.skill)}`,
|
|
70
|
+
];
|
|
71
|
+
const execution = await execute([...command, "--dry-run", "--json"]);
|
|
72
|
+
if (!execution.ok)
|
|
73
|
+
return { status: "unavailable", remediation: execution.error };
|
|
74
|
+
const plan = setupPlanSchema.safeParse(JSON.parse(execution.value));
|
|
75
|
+
if (!plan.success)
|
|
76
|
+
return {
|
|
77
|
+
status: "unavailable",
|
|
78
|
+
remediation: `The updated setup executable returned an invalid maintenance plan: ${plan.error.message}`,
|
|
79
|
+
};
|
|
80
|
+
if (plan.data.plannedActions.length === 0)
|
|
81
|
+
return { status: "current", plannedActions: [] };
|
|
82
|
+
const allowedIds = new Set([
|
|
83
|
+
...scope.clients.map((client) => `configure_client:${client}`),
|
|
84
|
+
...(scope.skill ? ["install_skill"] : []),
|
|
85
|
+
]);
|
|
86
|
+
if (plan.data.plannedActions.some(({ id }) => !allowedIds.has(id)))
|
|
87
|
+
return {
|
|
88
|
+
status: "unavailable",
|
|
89
|
+
remediation: "The updated setup plan included an integration outside the existing REA maintenance scope.",
|
|
90
|
+
};
|
|
91
|
+
return {
|
|
92
|
+
status: "planned",
|
|
93
|
+
scope,
|
|
94
|
+
command,
|
|
95
|
+
plannedActions: plan.data.plannedActions.map(({ backupPath, commands, ...action }) => ({
|
|
96
|
+
...action,
|
|
97
|
+
...(backupPath === undefined ? {} : { backupPath }),
|
|
98
|
+
...(commands === undefined ? {} : { commands }),
|
|
99
|
+
})),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
catch (cause) {
|
|
103
|
+
return {
|
|
104
|
+
status: "unavailable",
|
|
105
|
+
remediation: cause instanceof Error ? cause.message : String(cause),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { realpath } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import spawn from "cross-spawn";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
8
|
+
import { err, ok } from "../domain/result.js";
|
|
9
|
+
import { updateInstallCommand, } from "./Update.js";
|
|
10
|
+
import { planIntegrationMaintenance } from "./UpdateMaintenance.js";
|
|
11
|
+
/** Run an updater subprocess with complete diagnostics and isolated machine output. */
|
|
12
|
+
export const runUpdateCommand = (command, output = "structured") => new Promise((resolveResult) => {
|
|
13
|
+
const [executable, ...args] = command;
|
|
14
|
+
if (executable === undefined) {
|
|
15
|
+
resolveResult(err("No executable supplied."));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const environment = { ...process.env };
|
|
19
|
+
// A fresh installed entry point must not inherit npx's invocation identity.
|
|
20
|
+
delete environment.npm_command;
|
|
21
|
+
const child = spawn(executable, args, {
|
|
22
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
23
|
+
env: environment,
|
|
24
|
+
windowsHide: true,
|
|
25
|
+
});
|
|
26
|
+
let stdout = "";
|
|
27
|
+
let stderr = "";
|
|
28
|
+
child.stdout?.setEncoding("utf8");
|
|
29
|
+
child.stderr?.setEncoding("utf8");
|
|
30
|
+
child.stdout?.on("data", (chunk) => {
|
|
31
|
+
stdout += chunk;
|
|
32
|
+
if (output === "human")
|
|
33
|
+
process.stderr.write(chunk);
|
|
34
|
+
});
|
|
35
|
+
child.stderr?.on("data", (chunk) => {
|
|
36
|
+
stderr += chunk;
|
|
37
|
+
if (output === "human")
|
|
38
|
+
process.stderr.write(chunk);
|
|
39
|
+
});
|
|
40
|
+
child.once("error", (cause) => resolveResult(err(cause.message)));
|
|
41
|
+
child.once("close", (code, signal) => resolveResult(code === 0
|
|
42
|
+
? ok(stdout.trim())
|
|
43
|
+
: err(stderr.trim() ||
|
|
44
|
+
stdout.trim() ||
|
|
45
|
+
(signal === null
|
|
46
|
+
? `Process exited with code ${String(code)}.`
|
|
47
|
+
: `Process terminated by ${signal}.`))));
|
|
48
|
+
});
|
|
49
|
+
const requireCommandOutput = async (command) => {
|
|
50
|
+
const result = await runUpdateCommand(command);
|
|
51
|
+
if (!result.ok)
|
|
52
|
+
throw new Error(result.error);
|
|
53
|
+
return result.value;
|
|
54
|
+
};
|
|
55
|
+
/** Resolve the global prefix only when it owns the running package. */
|
|
56
|
+
export const detectNpmInstallation = async (packageRoot, host) => {
|
|
57
|
+
let canonicalPackageRoot;
|
|
58
|
+
try {
|
|
59
|
+
canonicalPackageRoot = await host.canonicalPath(packageRoot);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const npmRoot = await host.globalRoot();
|
|
66
|
+
const globalPackageRoot = await host.canonicalPath(resolve(npmRoot, PRODUCT_IDENTITY.packageName));
|
|
67
|
+
if (canonicalPackageRoot === globalPackageRoot) {
|
|
68
|
+
const prefix = await host.globalPrefix();
|
|
69
|
+
return prefix.length === 0
|
|
70
|
+
? undefined
|
|
71
|
+
: { prefix, packageRoot: canonicalPackageRoot };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// The curl installer uses a Unix prefix that may differ from npm's current default.
|
|
76
|
+
}
|
|
77
|
+
const nodeModules = dirname(canonicalPackageRoot);
|
|
78
|
+
const library = dirname(nodeModules);
|
|
79
|
+
if (basename(canonicalPackageRoot) !== PRODUCT_IDENTITY.packageName ||
|
|
80
|
+
basename(nodeModules) !== "node_modules" ||
|
|
81
|
+
basename(library) !== "lib")
|
|
82
|
+
return undefined;
|
|
83
|
+
return { prefix: dirname(library), packageRoot: canonicalPackageRoot };
|
|
84
|
+
};
|
|
85
|
+
/** Create npm, registry, verification, and read-only maintenance effects. */
|
|
86
|
+
export const systemUpdateHost = (packageRoot = fileURLToPath(new URL("../..", import.meta.url)), home = homedir()) => ({
|
|
87
|
+
installation: () => detectNpmInstallation(packageRoot, {
|
|
88
|
+
canonicalPath: realpath,
|
|
89
|
+
globalRoot: () => requireCommandOutput(["npm", "root", "--global"]),
|
|
90
|
+
globalPrefix: () => requireCommandOutput(["npm", "prefix", "--global"]),
|
|
91
|
+
}),
|
|
92
|
+
latestVersion: async (installation) => {
|
|
93
|
+
const response = await runUpdateCommand([
|
|
94
|
+
"npm",
|
|
95
|
+
"view",
|
|
96
|
+
"--global",
|
|
97
|
+
...(installation === undefined ? [] : ["--prefix", installation.prefix]),
|
|
98
|
+
PRODUCT_IDENTITY.packageName,
|
|
99
|
+
"dist-tags.latest",
|
|
100
|
+
"--json",
|
|
101
|
+
"--fetch-retries=0",
|
|
102
|
+
"--fetch-timeout=10000",
|
|
103
|
+
]);
|
|
104
|
+
if (!response.ok)
|
|
105
|
+
return response;
|
|
106
|
+
try {
|
|
107
|
+
const parsed = z.string().min(1).safeParse(JSON.parse(response.value));
|
|
108
|
+
return parsed.success
|
|
109
|
+
? ok(parsed.data)
|
|
110
|
+
: err(`Invalid npm release metadata: ${parsed.error.message}`);
|
|
111
|
+
}
|
|
112
|
+
catch (cause) {
|
|
113
|
+
return err(cause instanceof Error ? cause.message : String(cause));
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
installVersion: async (installation, version, output) => {
|
|
117
|
+
const result = await runUpdateCommand(updateInstallCommand(installation, version), output);
|
|
118
|
+
return result.ok ? ok(undefined) : result;
|
|
119
|
+
},
|
|
120
|
+
installedVersion: (installation) => runUpdateCommand([
|
|
121
|
+
process.execPath,
|
|
122
|
+
join(installation.packageRoot, "scripts", "rea.mjs"),
|
|
123
|
+
"--version",
|
|
124
|
+
]),
|
|
125
|
+
planMaintenance: (installation) => planIntegrationMaintenance(home, join(installation.packageRoot, "scripts", "rea.mjs"), runUpdateCommand),
|
|
126
|
+
});
|
|
@@ -4,7 +4,10 @@ import { silentLogger } from "../logger.js";
|
|
|
4
4
|
import { GENERATED_AUXILIARY_PROVIDERS } from "../generatedMcpToolCatalog.js";
|
|
5
5
|
import { AnalysisProviderRegistry } from "./AnalysisProviderRegistry.js";
|
|
6
6
|
import { composeBinarySession } from "./BinarySessionComposition.js";
|
|
7
|
+
import { nativeHostCapabilities } from "../native/NativeHostCapabilities.js";
|
|
7
8
|
import { LazyAnalysisProvider } from "./LazyAnalysisProvider.js";
|
|
9
|
+
import { ManagedStaticProvider } from "../dotnet/ManagedStaticProvider.js";
|
|
10
|
+
import { SessionProviderRouter } from "./SessionProviderRouter.js";
|
|
8
11
|
/**
|
|
9
12
|
* Compose the target-switching runtime shared directly by CLI and MCP adapters.
|
|
10
13
|
* This is the sole production wiring point, so both adapters share identical
|
|
@@ -21,12 +24,16 @@ export const createBinarySession = (config, logger = silentLogger) => {
|
|
|
21
24
|
const generated = auxiliary.get(id);
|
|
22
25
|
if (generated === undefined)
|
|
23
26
|
throw new TypeError(`Missing generated provider metadata for ${id}`);
|
|
24
|
-
return new LazyAnalysisProvider({
|
|
27
|
+
return new LazyAnalysisProvider({
|
|
28
|
+
...generated,
|
|
29
|
+
capabilities: nativeHostCapabilities(generated.capabilities),
|
|
30
|
+
load,
|
|
31
|
+
});
|
|
25
32
|
};
|
|
26
33
|
return composeBinarySession(new AnalysisProviderRegistry([hopper, ghidra], config.analysisProvider), [
|
|
27
34
|
lazyProvider("rea-artifact-graph", async () => {
|
|
28
35
|
const { ArtifactProvider } = await import("../artifacts/ArtifactProvider.js");
|
|
29
|
-
return new ArtifactProvider(
|
|
36
|
+
return new ArtifactProvider();
|
|
30
37
|
}),
|
|
31
38
|
lazyProvider("native-macos", async () => {
|
|
32
39
|
const { NativeMacOSProvider } = await import("../native/NativeMacOSProvider.js");
|
|
@@ -38,3 +45,7 @@ export const createBinarySession = (config, logger = silentLogger) => {
|
|
|
38
45
|
}),
|
|
39
46
|
]);
|
|
40
47
|
};
|
|
48
|
+
/** Compose an execution-free managed session without native provider selection. */
|
|
49
|
+
export const createManagedBinarySession = () => composeBinarySession(SessionProviderRouter.selectable(new AnalysisProviderRegistry([]), [
|
|
50
|
+
new ManagedStaticProvider(),
|
|
51
|
+
]));
|
|
@@ -19,20 +19,19 @@ export const normalizeArtifactPath = (input) => {
|
|
|
19
19
|
/** Reject exact, Unicode-normalized, case-folded, and prefix collisions. */
|
|
20
20
|
export class ArtifactPathRegistry {
|
|
21
21
|
#root = { kind: undefined, children: new Map() };
|
|
22
|
-
#folded = new Set();
|
|
23
22
|
add(path, kind) {
|
|
24
|
-
const folded = path.toLocaleLowerCase("en-US");
|
|
25
|
-
if (this.#folded.has(folded))
|
|
26
|
-
throw new ArtifactReaderFailure("path", `Artifact path collision: ${path}`);
|
|
27
23
|
const parts = path.split("/");
|
|
28
24
|
let node = this.#root;
|
|
29
25
|
for (const [index, part] of parts.entries()) {
|
|
30
26
|
if (node.kind !== undefined && node.kind !== "directory")
|
|
31
27
|
throw new ArtifactReaderFailure("path", `Artifact prefix conflict: ${path}`);
|
|
32
|
-
|
|
28
|
+
const foldedPart = part.toLocaleLowerCase("en-US");
|
|
29
|
+
let child = node.children.get(foldedPart);
|
|
30
|
+
if (child !== undefined && child.spelling !== part)
|
|
31
|
+
throw new ArtifactReaderFailure("path", `Artifact path collision: ${path}`);
|
|
33
32
|
if (child === undefined) {
|
|
34
|
-
child = { kind: undefined, children: new Map() };
|
|
35
|
-
node.children.set(
|
|
33
|
+
child = { spelling: part, kind: undefined, children: new Map() };
|
|
34
|
+
node.children.set(foldedPart, child);
|
|
36
35
|
}
|
|
37
36
|
node = child;
|
|
38
37
|
if (index === parts.length - 1) {
|
|
@@ -43,6 +42,5 @@ export class ArtifactPathRegistry {
|
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
44
|
node.kind = kind;
|
|
46
|
-
this.#folded.add(folded);
|
|
47
45
|
}
|
|
48
46
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { createAnalysisExecution, } from "../application/AnalysisProvider.js";
|
|
2
|
+
import { inspectBundleKeyedArchive } from "./KeyedArchiveReader.js";
|
|
3
|
+
import { basename, dirname } from "node:path";
|
|
2
4
|
import { inventoryArtifact } from "../application/ArtifactInventory.js";
|
|
3
5
|
import { extractArtifact } from "../application/ArtifactExtraction.js";
|
|
4
6
|
import { analyzeInterfaceBuilderBundle } from "../application/InterfaceBuilderAnalysis.js";
|
|
7
|
+
import { analyzeAppleAssetCatalogs } from "../application/AppleAssetCatalogAnalysis.js";
|
|
5
8
|
import { ARTIFACT_ANALYSIS_OPERATIONS, artifactInventoryInputSchema, artifactExtractionExecutionSchema, } from "../contracts/artifactToolContracts.js";
|
|
6
9
|
import { AnalysisCapabilityUnavailableError, ArtifactOperationError, } from "../domain/errors.js";
|
|
7
10
|
import { interfaceBuilderLimitsSchema } from "../domain/interfaceBuilderGraph.js";
|
|
@@ -10,35 +13,43 @@ import { ArtifactReaderFailure } from "./ArtifactReader.js";
|
|
|
10
13
|
import { ARTIFACT_GRAPH_PROVIDER } from "../application/InvestigationProviders.js";
|
|
11
14
|
import { createEvidence } from "../domain/evidence.js";
|
|
12
15
|
import { createArtifactInspection } from "../domain/artifactInspection.js";
|
|
13
|
-
import { resolveArtifactIntegrityPolicy
|
|
16
|
+
import { resolveArtifactIntegrityPolicy } from "../application/ArtifactInventory/policy.js";
|
|
14
17
|
const IDENTITY = Object.freeze(ARTIFACT_GRAPH_PROVIDER);
|
|
15
18
|
/** Read-only inventory and exclusively owned extraction provider. */
|
|
16
19
|
export class ArtifactProvider {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
#capabilities;
|
|
21
|
+
constructor(platform = process.platform) {
|
|
22
|
+
this.#capabilities = Object.freeze(ARTIFACT_ANALYSIS_OPERATIONS.map((operation) => {
|
|
23
|
+
const common = {
|
|
24
|
+
provider: IDENTITY,
|
|
25
|
+
operation,
|
|
26
|
+
effects: Object.freeze({
|
|
27
|
+
mutatesArtifact: false,
|
|
28
|
+
launchesProcess: operation !== "decode_interface_builder" &&
|
|
29
|
+
operation !== "inspect_keyed_archive",
|
|
30
|
+
mayShowUi: false,
|
|
31
|
+
mayAccessNetwork: false,
|
|
32
|
+
mayWriteFilesystem: operation === "extract_artifact" ||
|
|
33
|
+
operation === "inspect_artifact" ||
|
|
34
|
+
operation === "inventory_artifact",
|
|
35
|
+
changesPermissions: false,
|
|
36
|
+
requiresRoot: false,
|
|
37
|
+
}),
|
|
38
|
+
limitations: Object.freeze([
|
|
39
|
+
"DMG child inventory automatically uses a read-only native macOS mount; PKG remains root-hash-only.",
|
|
40
|
+
"ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only.",
|
|
41
|
+
]),
|
|
42
|
+
};
|
|
43
|
+
return Object.freeze(operation === "inspect_asset_catalog" && platform !== "darwin"
|
|
44
|
+
? {
|
|
45
|
+
...common,
|
|
46
|
+
available: false,
|
|
47
|
+
availabilityCode: "unsupported_host",
|
|
48
|
+
reason: "Apple asset catalogs require macOS assetutil.",
|
|
49
|
+
}
|
|
50
|
+
: { ...common, available: true, reason: null });
|
|
51
|
+
}));
|
|
22
52
|
}
|
|
23
|
-
#capabilities = Object.freeze(ARTIFACT_ANALYSIS_OPERATIONS.map((operation) => Object.freeze({
|
|
24
|
-
provider: IDENTITY,
|
|
25
|
-
operation,
|
|
26
|
-
available: true,
|
|
27
|
-
reason: null,
|
|
28
|
-
effects: Object.freeze({
|
|
29
|
-
mutatesArtifact: false,
|
|
30
|
-
launchesProcess: operation !== "decode_interface_builder",
|
|
31
|
-
mayShowUi: false,
|
|
32
|
-
mayAccessNetwork: false,
|
|
33
|
-
mayWriteFilesystem: operation === "extract_artifact",
|
|
34
|
-
changesPermissions: false,
|
|
35
|
-
requiresRoot: false,
|
|
36
|
-
}),
|
|
37
|
-
limitations: Object.freeze([
|
|
38
|
-
"DMG child inventory is macOS-only and requires per-call approval plus operator policy; PKG remains root-hash-only.",
|
|
39
|
-
"ASAR files discovered in filesystem-backed inventories are expanded without bulk extraction; other nested containers remain recorded only.",
|
|
40
|
-
]),
|
|
41
|
-
})));
|
|
42
53
|
identity() {
|
|
43
54
|
return IDENTITY;
|
|
44
55
|
}
|
|
@@ -46,17 +57,13 @@ export class ArtifactProvider {
|
|
|
46
57
|
return this.#capabilities;
|
|
47
58
|
}
|
|
48
59
|
createClient(target) {
|
|
49
|
-
return new ArtifactClient(target
|
|
60
|
+
return new ArtifactClient(target);
|
|
50
61
|
}
|
|
51
62
|
}
|
|
52
63
|
class ArtifactClient {
|
|
53
64
|
target;
|
|
54
|
-
|
|
55
|
-
integrityContinueEnabled;
|
|
56
|
-
constructor(target, nativeMountEnabled, integrityContinueEnabled) {
|
|
65
|
+
constructor(target) {
|
|
57
66
|
this.target = target;
|
|
58
|
-
this.nativeMountEnabled = nativeMountEnabled;
|
|
59
|
-
this.integrityContinueEnabled = integrityContinueEnabled;
|
|
60
67
|
}
|
|
61
68
|
async execute(operation, parameters, options) {
|
|
62
69
|
if (operation === "health")
|
|
@@ -88,6 +95,37 @@ class ArtifactClient {
|
|
|
88
95
|
})),
|
|
89
96
|
}));
|
|
90
97
|
}
|
|
98
|
+
if (operation === "inspect_keyed_archive") {
|
|
99
|
+
const standalone = this.target.kind === "artifact" && this.target.format === "plist";
|
|
100
|
+
if (standalone &&
|
|
101
|
+
parameters.path !== undefined &&
|
|
102
|
+
parameters.path !== "." &&
|
|
103
|
+
parameters.path !== basename(this.target.path))
|
|
104
|
+
throw new ArtifactReaderFailure("path", "For an active plist, path must select that archive (omit path or use its basename)");
|
|
105
|
+
const bundlePath = standalone
|
|
106
|
+
? dirname(this.target.path)
|
|
107
|
+
: this.target.sourcePath;
|
|
108
|
+
if (bundlePath === undefined ||
|
|
109
|
+
(!standalone && !bundlePath.toLowerCase().endsWith(".app")))
|
|
110
|
+
throw new ArtifactReaderFailure("unavailable", "inspect_keyed_archive requires an active plist or .app bundle");
|
|
111
|
+
const result = await inspectBundleKeyedArchive({
|
|
112
|
+
bundlePath,
|
|
113
|
+
targetSha256: this.target.sha256,
|
|
114
|
+
parameters: standalone
|
|
115
|
+
? { ...parameters, path: basename(this.target.path) }
|
|
116
|
+
: parameters,
|
|
117
|
+
...(options?.signal === undefined ? {} : { signal: options.signal }),
|
|
118
|
+
});
|
|
119
|
+
if (standalone && result.archive_sha256 !== this.target.sha256)
|
|
120
|
+
throw new ArtifactReaderFailure("integrity", `Active archive digest changed: expected ${this.target.sha256}, observed ${result.archive_sha256}`);
|
|
121
|
+
return ok(createAnalysisExecution(result, IDENTITY, {
|
|
122
|
+
limitations: result.limitations,
|
|
123
|
+
locations: [{ kind: "artifact-path", path: result.archive_path }],
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
126
|
+
if (operation === "inspect_asset_catalog") {
|
|
127
|
+
return await this.inspectAssetCatalog(parameters, options);
|
|
128
|
+
}
|
|
91
129
|
if (operation === "extract_artifact") {
|
|
92
130
|
const parsed = artifactExtractionExecutionSchema.parse(parameters);
|
|
93
131
|
const result = await extractArtifact({
|
|
@@ -124,13 +162,31 @@ class ArtifactClient {
|
|
|
124
162
|
close() {
|
|
125
163
|
return Promise.resolve();
|
|
126
164
|
}
|
|
165
|
+
async inspectAssetCatalog(parameters, options) {
|
|
166
|
+
const bundlePath = this.target.sourcePath;
|
|
167
|
+
if (this.target.kind !== "executable" ||
|
|
168
|
+
bundlePath === undefined ||
|
|
169
|
+
!bundlePath.toLowerCase().endsWith(".app"))
|
|
170
|
+
throw new ArtifactReaderFailure("unavailable", "inspect_asset_catalog requires an active .app bundle target");
|
|
171
|
+
const result = await analyzeAppleAssetCatalogs({
|
|
172
|
+
bundlePath,
|
|
173
|
+
targetSha256: this.target.sha256,
|
|
174
|
+
page: parameters,
|
|
175
|
+
...(options?.signal === undefined ? {} : { signal: options.signal }),
|
|
176
|
+
});
|
|
177
|
+
return ok(createAnalysisExecution(result, IDENTITY, {
|
|
178
|
+
limitations: result.limitations,
|
|
179
|
+
locations: result.catalogs.map(({ path }) => ({
|
|
180
|
+
kind: "artifact-path",
|
|
181
|
+
path,
|
|
182
|
+
})),
|
|
183
|
+
}));
|
|
184
|
+
}
|
|
127
185
|
async inspectArtifact(parameters, options) {
|
|
128
186
|
const parsed = artifactInventoryInputSchema.parse(parameters);
|
|
129
|
-
const inventoryParameters =
|
|
130
|
-
native_mount_approved: parsed.native_mount_approved,
|
|
187
|
+
const inventoryParameters = {
|
|
131
188
|
integrity_policy: parsed.integrity_policy,
|
|
132
|
-
|
|
133
|
-
});
|
|
189
|
+
};
|
|
134
190
|
await options?.progress?.report({
|
|
135
191
|
phase: "inspect_artifact.inventory",
|
|
136
192
|
completed: 0,
|
|
@@ -168,12 +224,9 @@ class ArtifactClient {
|
|
|
168
224
|
inventory(parsed, options) {
|
|
169
225
|
return inventoryArtifact(this.target.sourcePath ?? this.target.path, {
|
|
170
226
|
...(options?.signal === undefined ? {} : { signal: options.signal }),
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
: {
|
|
175
|
-
mode: parsed.integrity_policy,
|
|
176
|
-
}, this.integrityContinueEnabled),
|
|
227
|
+
integrity: resolveArtifactIntegrityPolicy({
|
|
228
|
+
mode: parsed.integrity_policy,
|
|
229
|
+
}),
|
|
177
230
|
});
|
|
178
231
|
}
|
|
179
232
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { sep } from "node:path";
|
|
1
2
|
import { Readable } from "node:stream";
|
|
2
|
-
import { extractFile, listPackage, statFile } from "@electron/asar";
|
|
3
|
+
import { extractFile, listPackage, statFile, uncache } from "@electron/asar";
|
|
3
4
|
import { ArtifactReaderFailure, } from "./ArtifactReader.js";
|
|
4
5
|
/**
|
|
5
6
|
* Official Electron ASAR adapter. Individual files remain caller-bounded.
|
|
@@ -17,6 +18,8 @@ export class AsarArtifactReader {
|
|
|
17
18
|
async *entries(signal) {
|
|
18
19
|
let paths;
|
|
19
20
|
try {
|
|
21
|
+
// ASAR caches headers by path even after the archive has been replaced.
|
|
22
|
+
uncache(this.path);
|
|
20
23
|
paths = listPackage(this.path, { isPack: false }).sort((left, right) => left.localeCompare(right, "en"));
|
|
21
24
|
}
|
|
22
25
|
catch (cause) {
|
|
@@ -24,12 +27,19 @@ export class AsarArtifactReader {
|
|
|
24
27
|
}
|
|
25
28
|
for (const listed of paths) {
|
|
26
29
|
abortIfNeeded(signal);
|
|
27
|
-
|
|
30
|
+
// @electron/asar returns paths assembled with the host path module.
|
|
31
|
+
// Keep that spelling for its API calls, but expose archive paths with
|
|
32
|
+
// portable separators. On POSIX, backslashes can be literal filename
|
|
33
|
+
// characters and must remain untouched.
|
|
34
|
+
const path = toArtifactPath(listed);
|
|
28
35
|
if (path.length === 0)
|
|
29
36
|
continue;
|
|
37
|
+
const providerPath = listed.startsWith(sep)
|
|
38
|
+
? listed.slice(sep.length)
|
|
39
|
+
: listed;
|
|
30
40
|
let metadata;
|
|
31
41
|
try {
|
|
32
|
-
metadata = statFile(this.path,
|
|
42
|
+
metadata = statFile(this.path, providerPath, false);
|
|
33
43
|
}
|
|
34
44
|
catch (cause) {
|
|
35
45
|
throw asarFailure(this.path, `stat ${path}`, cause);
|
|
@@ -58,7 +68,7 @@ export class AsarArtifactReader {
|
|
|
58
68
|
: [
|
|
59
69
|
"Official ASAR extraction buffers each individually bounded file.",
|
|
60
70
|
],
|
|
61
|
-
adapterKey:
|
|
71
|
+
adapterKey: providerPath,
|
|
62
72
|
};
|
|
63
73
|
}
|
|
64
74
|
}
|
|
@@ -81,6 +91,7 @@ export class AsarArtifactReader {
|
|
|
81
91
|
}
|
|
82
92
|
}
|
|
83
93
|
close() {
|
|
94
|
+
uncache(this.path);
|
|
84
95
|
return Promise.resolve();
|
|
85
96
|
}
|
|
86
97
|
provenance() {
|
|
@@ -91,6 +102,10 @@ const abortIfNeeded = (signal) => {
|
|
|
91
102
|
if (signal?.aborted === true)
|
|
92
103
|
throw new ArtifactReaderFailure("cancelled", "ASAR operation cancelled");
|
|
93
104
|
};
|
|
105
|
+
const toArtifactPath = (listed) => {
|
|
106
|
+
const portable = sep === "\\" ? listed.replaceAll("\\", "/") : listed;
|
|
107
|
+
return portable.replace(/^\/+|\/+$/gu, "");
|
|
108
|
+
};
|
|
94
109
|
const asarFailure = (path, operation, cause) => cause instanceof ArtifactReaderFailure
|
|
95
110
|
? cause
|
|
96
111
|
: new ArtifactReaderFailure("format", `Malformed or unreadable ASAR during ${operation}: ${path}`, { cause });
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { TextDecoder } from "node:util";
|
|
3
|
+
import { parse, parseBinary } from "plist";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { keyedArchiveInputSchema, keyedArchiveResultSchema, projectKeyedArchive, } from "../domain/keyedArchive.js";
|
|
6
|
+
import { DirectoryArtifactReader } from "./DirectoryArtifactReader.js";
|
|
7
|
+
import { ArtifactReaderFailure } from "./ArtifactReader.js";
|
|
8
|
+
const MAX_BYTES = 64 * 1024 * 1024;
|
|
9
|
+
/** Parse inert plist bytes, preserving data and dates with explicit typed values. */
|
|
10
|
+
export const decodeKeyedArchiveBytes = (bytes, selection) => {
|
|
11
|
+
if (bytes.length > MAX_BYTES)
|
|
12
|
+
throw new RangeError("Keyed archive exceeds 64 MiB");
|
|
13
|
+
const binary = bytes.subarray(0, 8).toString("ascii") === "bplist00";
|
|
14
|
+
const parsed = binary
|
|
15
|
+
? parseBinary(bytes)
|
|
16
|
+
: parse(decodeXmlPlistText(bytes));
|
|
17
|
+
return {
|
|
18
|
+
archive_format: binary ? "binary-plist" : "xml-plist",
|
|
19
|
+
...projectKeyedArchive(normalizePlist(parsed), selection),
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
const decodeXmlPlistText = (bytes) => {
|
|
23
|
+
const encoding = bytes[0] === 0xff && bytes[1] === 0xfe
|
|
24
|
+
? "utf-16le"
|
|
25
|
+
: bytes[0] === 0xfe && bytes[1] === 0xff
|
|
26
|
+
? "utf-16be"
|
|
27
|
+
: "utf-8";
|
|
28
|
+
const text = new TextDecoder(encoding, { fatal: true }).decode(bytes);
|
|
29
|
+
const declared = /^<\?xml\s[^?]*\bencoding\s*=\s*["']([^"']+)["']/u
|
|
30
|
+
.exec(text)?.[1]
|
|
31
|
+
?.toLowerCase();
|
|
32
|
+
if (declared !== undefined &&
|
|
33
|
+
((encoding !== "utf-8" && declared !== encoding && declared !== "utf-16") ||
|
|
34
|
+
(encoding === "utf-8" && declared.startsWith("utf-16"))))
|
|
35
|
+
throw new TypeError("XML encoding declaration disagrees with its bytes");
|
|
36
|
+
return text;
|
|
37
|
+
};
|
|
38
|
+
const normalizePlist = (value, depth = 0) => {
|
|
39
|
+
if (depth > 128)
|
|
40
|
+
throw new RangeError("Plist exceeds 128 nesting levels");
|
|
41
|
+
if (value instanceof Uint8Array)
|
|
42
|
+
return {
|
|
43
|
+
$plist_type: "data",
|
|
44
|
+
base64: Buffer.from(value).toString("base64"),
|
|
45
|
+
};
|
|
46
|
+
if (value instanceof Date)
|
|
47
|
+
return { $plist_type: "date", iso8601: value.toISOString() };
|
|
48
|
+
if (Array.isArray(value))
|
|
49
|
+
return value.map((item) => normalizePlist(item, depth + 1));
|
|
50
|
+
if (value !== null && typeof value === "object")
|
|
51
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [
|
|
52
|
+
key,
|
|
53
|
+
normalizePlist(item, depth + 1),
|
|
54
|
+
]));
|
|
55
|
+
return z
|
|
56
|
+
.union([z.string(), z.number().finite(), z.boolean(), z.null()])
|
|
57
|
+
.parse(value);
|
|
58
|
+
};
|
|
59
|
+
/** Read exactly one regular, contained bundle entry without following symlinks. */
|
|
60
|
+
export const inspectBundleKeyedArchive = async (input) => {
|
|
61
|
+
const selected = keyedArchiveInputSchema.parse(input.parameters);
|
|
62
|
+
if (selected.path.startsWith("/") ||
|
|
63
|
+
selected.path
|
|
64
|
+
.split("/")
|
|
65
|
+
.some((part) => part === ".." || part === "." || part.length === 0))
|
|
66
|
+
throw new ArtifactReaderFailure("path", "Archive path must be a canonical relative bundle path");
|
|
67
|
+
const reader = new DirectoryArtifactReader(input.bundlePath);
|
|
68
|
+
try {
|
|
69
|
+
for await (const entry of reader.entries(input.signal)) {
|
|
70
|
+
if (entry.path !== selected.path)
|
|
71
|
+
continue;
|
|
72
|
+
if (entry.kind !== "file")
|
|
73
|
+
throw new ArtifactReaderFailure("path", "Archive must be a regular file, not a symlink or directory");
|
|
74
|
+
if ((entry.declaredSize ?? 0) > MAX_BYTES)
|
|
75
|
+
throw new ArtifactReaderFailure("limit", "Keyed archive exceeds 64 MiB");
|
|
76
|
+
const stream = await reader.open(entry, input.signal);
|
|
77
|
+
const chunks = [];
|
|
78
|
+
let size = 0;
|
|
79
|
+
for await (const chunk of stream) {
|
|
80
|
+
if (input.signal?.aborted) {
|
|
81
|
+
stream.destroy();
|
|
82
|
+
throw new ArtifactReaderFailure("cancelled", "Archive inspection cancelled");
|
|
83
|
+
}
|
|
84
|
+
const bytes = z.instanceof(Buffer).parse(chunk);
|
|
85
|
+
size += bytes.length;
|
|
86
|
+
if (size > MAX_BYTES) {
|
|
87
|
+
stream.destroy();
|
|
88
|
+
throw new ArtifactReaderFailure("limit", "Keyed archive exceeds 64 MiB");
|
|
89
|
+
}
|
|
90
|
+
chunks.push(bytes);
|
|
91
|
+
}
|
|
92
|
+
const bytes = Buffer.concat(chunks, size);
|
|
93
|
+
try {
|
|
94
|
+
return keyedArchiveResultSchema.parse({
|
|
95
|
+
target_sha256: input.targetSha256,
|
|
96
|
+
archive_path: entry.path,
|
|
97
|
+
archive_sha256: createHash("sha256").update(bytes).digest("hex"),
|
|
98
|
+
...decodeKeyedArchiveBytes(bytes, selected),
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
catch (cause) {
|
|
102
|
+
throw new ArtifactReaderFailure(cause instanceof RangeError ? "limit" : "format", "Cannot decode selected Foundation keyed archive", { cause });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
throw new ArtifactReaderFailure("path", `Archive not found in bundle: ${selected.path}`);
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
await reader.close();
|
|
109
|
+
}
|
|
110
|
+
};
|