rea-agents 6.3.0 → 6.4.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.
Files changed (487) hide show
  1. package/README.md +7 -4
  2. package/bridge/ghidra/ReaGhidraApplySeeds.java +151 -0
  3. package/bridge/ghidra/ReaGhidraBridge.java +597 -209
  4. package/bridge/ghidra/ReaGhidraNoReturnFix.java +123 -0
  5. package/dist/adb/AdbConfiguration.js +88 -0
  6. package/dist/adb/AdbDeviceOutput.js +186 -0
  7. package/dist/adb/AdbProvider.js +1190 -0
  8. package/dist/adb/AdbShellOutput.js +309 -0
  9. package/dist/android/AndroidTargetSnapshot.js +104 -22
  10. package/dist/android/JadxConfiguration.js +44 -24
  11. package/dist/android/JadxProvider.js +51 -19
  12. package/dist/apktool/ApktoolConfiguration.js +84 -0
  13. package/dist/apktool/ApktoolDecodeOutput.js +59 -0
  14. package/dist/apktool/ApktoolProvider.js +506 -0
  15. package/dist/application/AnalysisProvider.js +8 -2
  16. package/dist/application/AppBundleExecutable.js +27 -22
  17. package/dist/application/BinaryTargetResolver.js +22 -2
  18. package/dist/application/CapabilityInventory.js +11 -1
  19. package/dist/application/ClientConfigurationDocument.js +70 -0
  20. package/dist/application/ClientConfigurationFiles.js +91 -0
  21. package/dist/application/ClientRegistrationEnvironment.js +35 -0
  22. package/dist/application/ClientRegistrationStatus.js +66 -31
  23. package/dist/application/DirectAnalysis.js +2 -2
  24. package/dist/application/DirectAnalysisCleanup.js +1 -1
  25. package/dist/application/DirectAnalysisStatus.js +1 -1
  26. package/dist/application/Doctor.js +5 -3
  27. package/dist/application/DoctorDiagnostics.js +1 -1
  28. package/dist/application/EvidenceBundleCommands.js +6 -12
  29. package/dist/application/GeminiClientSettings.js +139 -0
  30. package/dist/application/HermesClientHome.js +115 -0
  31. package/dist/application/HopperDownload.js +39 -0
  32. package/dist/application/InvestigationProviders.js +6 -0
  33. package/dist/application/JsonFiles.js +6 -5
  34. package/dist/{cliJsonFile.js → application/JsonInputFile.js} +108 -35
  35. package/dist/application/LinuxHopper.js +4 -12
  36. package/dist/application/MacHopper.js +172 -149
  37. package/dist/application/MipsElfAbiFlags.js +140 -0
  38. package/dist/application/ProviderOperationExecution.js +31 -0
  39. package/dist/application/ReconstructionObligationCandidates.js +9 -3
  40. package/dist/application/ReferenceSourceImport.js +76 -29
  41. package/dist/application/ReferenceSourceImportEntries.js +18 -9
  42. package/dist/application/ReferenceSourceImportPolicy.js +99 -23
  43. package/dist/application/ReferenceSourceImportTypes.js +30 -22
  44. package/dist/application/ReferenceSourceVcsAdapter.js +145 -30
  45. package/dist/application/RegularFileRead.js +93 -7
  46. package/dist/application/Setup.js +54 -6
  47. package/dist/application/SetupClientConfiguration.js +116 -16
  48. package/dist/application/SetupHost.js +102 -24
  49. package/dist/application/SetupPlan.js +5 -8
  50. package/dist/application/SetupSkill.js +58 -39
  51. package/dist/application/SupportedClients.js +290 -65
  52. package/dist/application/Uninstall.js +158 -10
  53. package/dist/application/UpdateMaintenance.js +17 -21
  54. package/dist/application/Utf8JsonInput.js +7 -0
  55. package/dist/application/WebScriptExportService.js +131 -65
  56. package/dist/application/WebSourceLocationService.js +3 -0
  57. package/dist/application/adb/AdbDeviceAnalysisPort.js +1 -0
  58. package/dist/application/adb/AdbDeviceAnalysisService.js +13 -0
  59. package/dist/application/analysisView/AnalysisViewService.js +40 -2
  60. package/dist/application/apktool/ApktoolResourceAnalysisPort.js +1 -0
  61. package/dist/application/apktool/ApktoolResourceAnalysisService.js +13 -0
  62. package/dist/application/binary/AnalysisClientCleanup.js +0 -24
  63. package/dist/application/binary/BinarySession.js +2 -1
  64. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +2 -1
  65. package/dist/application/binaryDiagnostics/PeResourcesPort.js +1 -0
  66. package/dist/application/binaryDiagnostics/PeResourcesService.js +111 -0
  67. package/dist/application/binaryDiagnostics/RecordedCrashService.js +2 -1
  68. package/dist/application/evm/EvmInterfaceService.js +3 -0
  69. package/dist/application/firmware/FirmwareAnalysisService.js +3 -0
  70. package/dist/application/investigation/InspectEvidenceBundle.js +18 -0
  71. package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
  72. package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
  73. package/dist/application/javascript/ElectronBoundaryGraphNative.js +19 -6
  74. package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
  75. package/dist/application/javascript/JavaScriptApplicationService.js +22 -11
  76. package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
  77. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -30
  78. package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
  79. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +67 -19
  80. package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
  81. package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
  82. package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +19 -16
  83. package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
  84. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +258 -235
  85. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +115 -26
  86. package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -1
  87. package/dist/application/javascript/JavaScriptModuleRelationships.js +6 -4
  88. package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
  89. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +9 -3
  90. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +199 -61
  91. package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +12 -19
  92. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +4 -1
  93. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -3
  94. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +5 -3
  95. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +19 -8
  96. package/dist/application/jeb/JebAnalysisPort.js +1 -0
  97. package/dist/application/jeb/JebAnalysisService.js +13 -0
  98. package/dist/application/managed/ManagedApplicationGraphService.js +1 -1
  99. package/dist/application/native/NativeUiActionTrace.js +16 -8
  100. package/dist/application/native/NativeValueTrace.js +23 -6
  101. package/dist/application/process/ProcessCli.js +25 -20
  102. package/dist/artifacts/ArtifactPaths.js +129 -8
  103. package/dist/artifacts/ArtifactProvider.js +20 -15
  104. package/dist/artifacts/ArtifactReader.js +23 -0
  105. package/dist/artifacts/ArtifactResourceScope.js +100 -0
  106. package/dist/artifacts/AsarArtifactReader.js +176 -102
  107. package/dist/artifacts/AsarHeader.js +24 -0
  108. package/dist/artifacts/DirectoryArtifactReader.js +168 -65
  109. package/dist/artifacts/MachOSliceArtifactReader.js +116 -39
  110. package/dist/artifacts/NativeDmgArtifactReader.js +29 -22
  111. package/dist/artifacts/SafeOutputTree.js +245 -70
  112. package/dist/artifacts/SafeOutputTreeCleanup.js +45 -0
  113. package/dist/artifacts/SafeOutputTreeCreationFailure.js +20 -0
  114. package/dist/artifacts/SafeOutputTreeIdentity.js +42 -0
  115. package/dist/artifacts/SafeOutputTreeReadback.js +33 -0
  116. package/dist/artifacts/ZipArtifactReader.js +77 -27
  117. package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +58 -18
  118. package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +62 -24
  119. package/dist/artifacts/apple/KeyedArchiveReader.js +32 -13
  120. package/dist/artifacts/extraction/ArtifactExtraction.js +110 -86
  121. package/dist/artifacts/inventory/ArtifactGraphConstruction.js +110 -43
  122. package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
  123. package/dist/artifacts/inventory/classify.js +75 -32
  124. package/dist/artifacts/inventory/hashStableRootArtifact.js +48 -15
  125. package/dist/artifacts/inventory/reader.js +13 -5
  126. package/dist/artifacts/inventory/scanCanonical.js +62 -25
  127. package/dist/artifacts/inventory/scanReader.js +38 -11
  128. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +15 -9
  129. package/dist/artifacts/javascript/JavaScriptSourceAnalysis.js +3 -0
  130. package/dist/browser/BrowserScenarioPartialObservation.js +8 -2
  131. package/dist/browser/BrowserScenarioSecrets.js +52 -37
  132. package/dist/browser/CdpBrowserProvider.js +5 -0
  133. package/dist/browser/CdpCaptureDocuments.js +40 -6
  134. package/dist/browser/CdpCaptureDomSvg.js +210 -0
  135. package/dist/browser/CdpCaptureEventBodyShapes.js +4 -8
  136. package/dist/browser/CdpCaptureEventHandlers.js +26 -9
  137. package/dist/browser/CdpCaptureEvents.js +4 -9
  138. package/dist/browser/CdpConnection.js +22 -5
  139. package/dist/browser/CdpPageCapture.js +1 -1
  140. package/dist/browser/CdpTargetSession.js +30 -34
  141. package/dist/browser/CdpWebMcpDiscovery.js +32 -10
  142. package/dist/browser/ElectronFileScope.js +99 -9
  143. package/dist/browser/PlaywrightBrowserScenarioProvider.js +60 -4
  144. package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
  145. package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
  146. package/dist/browser/PlaywrightScenarioBrowser.js +69 -7
  147. package/dist/browser/PlaywrightScenarioSession.js +127 -54
  148. package/dist/browser/PlaywrightScenarioStorage.js +507 -0
  149. package/dist/browser/PngVisualDiff.js +198 -29
  150. package/dist/browser/WebSourceMapFetcher.js +3 -3
  151. package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
  152. package/dist/browser/assets/PublishWebScripts.js +75 -20
  153. package/dist/browser/assets/WebArtifactReads.js +23 -1
  154. package/dist/browser/assets/WebSourceLocationArtifacts.js +1 -0
  155. package/dist/browser/execution/CdpExecutionCapture.js +3 -3
  156. package/dist/browser/execution/CdpPreciseCoverage.js +5 -8
  157. package/dist/browser/history/HarCapture.js +14 -0
  158. package/dist/browser/history/HarCaptureProcess.js +2 -10
  159. package/dist/browser/history/MitmproxyCaptureAdapter.js +3 -1
  160. package/dist/browser/modules/WebModuleArtifacts.js +1 -0
  161. package/dist/cli/adbCommands.js +337 -0
  162. package/dist/cli/analysisViewCommands.js +39 -1
  163. package/dist/cli/apktoolCommands.js +53 -0
  164. package/dist/cli/artifactCommands.js +8 -11
  165. package/dist/cli/binaryDiagnosticsCommands.js +19 -1
  166. package/dist/cli/browserAdvancedCommands.js +65 -36
  167. package/dist/cli/coreBinaryCommands.js +0 -5
  168. package/dist/cli/coreNativeCommands.js +1 -14
  169. package/dist/cli/electronCommands.js +6 -1
  170. package/dist/cli/evmCommands.js +13 -4
  171. package/dist/cli/firmwareCommands.js +7 -2
  172. package/dist/cli/javascriptApplicationAnalysis.js +17 -1
  173. package/dist/cli/javascriptRecoveryCommands.js +22 -15
  174. package/dist/cli/jebCommands.js +99 -0
  175. package/dist/cli/jsonOutput.js +11 -4
  176. package/dist/cli/referenceSourceImportStatus.js +7 -0
  177. package/dist/cli/setupCommands.js +15 -3
  178. package/dist/cli/utilityCommands.js +66 -18
  179. package/dist/cli/webScriptCommands.js +20 -1
  180. package/dist/cli/webSourceLocationCommands.js +21 -9
  181. package/dist/cli.js +6 -0
  182. package/dist/cliBrowserScenarioCommands.js +2 -1
  183. package/dist/cliCommandNames.js +32 -0
  184. package/dist/cliJsonInput.js +2 -2
  185. package/dist/cliObservationOptions.js +3 -0
  186. package/dist/composition/adb.js +3 -0
  187. package/dist/composition/apktool.js +3 -0
  188. package/dist/composition/binaryDiagnostics.js +4 -0
  189. package/dist/composition/directAnalysis.js +12 -4
  190. package/dist/composition/javascriptAnalysisWorkerProcess.js +48 -0
  191. package/dist/composition/jeb.js +6 -0
  192. package/dist/config/environment.js +10 -0
  193. package/dist/config/ghidraLanguageOverride.js +9 -0
  194. package/dist/config/mcpInputSchemaProfile.js +27 -0
  195. package/dist/config/parseConfig.js +28 -1
  196. package/dist/contracts/adb/adbToolContracts.js +353 -0
  197. package/dist/contracts/advertisedInputExamples.js +48 -0
  198. package/dist/contracts/analysisDetail.js +10 -0
  199. package/dist/contracts/analysisViewToolContracts.js +17 -2
  200. package/dist/contracts/apktool/apktoolToolContracts.js +33 -0
  201. package/dist/contracts/artifactToolContracts.js +8 -5
  202. package/dist/contracts/browserToolContracts.js +1 -1
  203. package/dist/contracts/compactInputSchema.js +256 -0
  204. package/dist/contracts/functionWorkflowToolContracts.js +1 -1
  205. package/dist/contracts/inputSchemaPresentation.js +10 -10
  206. package/dist/contracts/javascript/electronToolContracts.js +15 -3
  207. package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
  208. package/dist/contracts/jeb/jebToolContracts.js +64 -0
  209. package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
  210. package/dist/contracts/officialToolContracts.js +5 -5
  211. package/dist/contracts/sessionToolContracts.js +2 -2
  212. package/dist/contracts/sessionToolSchemas.js +6 -2
  213. package/dist/contracts/toolContractExamples.js +6 -0
  214. package/dist/contracts/toolContractTypes.js +3 -0
  215. package/dist/contracts/toolContracts.js +6 -0
  216. package/dist/contracts/toolEffects.js +167 -0
  217. package/dist/contracts/toolOutputSchemaGroups.js +5 -3
  218. package/dist/contracts/toolSchemaMetadata.js +82 -7
  219. package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
  220. package/dist/domain/analysisErrorCleanup.js +29 -0
  221. package/dist/domain/analysisErrorPresentation.js +18 -6
  222. package/dist/domain/analysisErrorProjection.js +4 -1
  223. package/dist/domain/analysisSnapshot.js +2 -1
  224. package/dist/domain/analysisView/analysisView.js +52 -2
  225. package/dist/domain/analysisView/binaryLayoutView.js +2 -0
  226. package/dist/domain/analysisView/javascriptApplicationView.js +2 -0
  227. package/dist/domain/analysisView/nativeFunctionView.js +155 -0
  228. package/dist/domain/android/androidApplication.js +25 -20
  229. package/dist/domain/apktool/apktoolResourceAnalysis.js +77 -0
  230. package/dist/domain/apple/appleApplication.js +40 -23
  231. package/dist/domain/apple/appleBundleAnatomy.js +95 -28
  232. package/dist/domain/apple/dyldPaths.js +9 -1
  233. package/dist/domain/apple/dylibResolution.js +2 -2
  234. package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
  235. package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
  236. package/dist/domain/artifactComparison.js +35 -7
  237. package/dist/domain/artifactGraph.js +5 -3
  238. package/dist/domain/artifactIdentity.js +30 -2
  239. package/dist/domain/artifactInspection.js +3 -43
  240. package/dist/domain/artifactIntegrityPolicy.js +10 -0
  241. package/dist/domain/artifactInventoryEvidence.js +11 -12
  242. package/dist/domain/artifactPathSyntax.js +1 -1
  243. package/dist/domain/binaryTarget.js +16 -0
  244. package/dist/domain/binaryTargetTypes.js +8 -1
  245. package/dist/domain/browserObservationSchemas.js +8 -4
  246. package/dist/domain/canonicalJsonDigestSteps.js +34 -12
  247. package/dist/domain/compactStringIdentity.js +9 -0
  248. package/dist/domain/evidence.js +2 -1
  249. package/dist/domain/evidenceRecordSummary.js +144 -0
  250. package/dist/domain/inputIssueProjection.js +16 -1
  251. package/dist/domain/javascript/electronStaticAnalysisBrowser.js +12 -13
  252. package/dist/domain/javascript/electronStaticAnalysisIpc.js +11 -20
  253. package/dist/domain/javascript/electronStaticAnalysisNative.js +70 -40
  254. package/dist/domain/javascript/electronStaticAnalysisValues.js +16 -0
  255. package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
  256. package/dist/domain/javascript/javascriptApplicationAnalysis.js +4 -1
  257. package/dist/domain/javascript/javascriptApplicationChangeGraph.js +6 -6
  258. package/dist/domain/javascript/javascriptApplicationGraph.js +79 -18
  259. package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
  260. package/dist/domain/javascript/javascriptApplicationVersionItems.js +28 -12
  261. package/dist/domain/javascript/javascriptApplicationVersionKeys.js +9 -1
  262. package/dist/domain/javascript/javascriptAstFingerprint.js +58 -31
  263. package/dist/domain/javascript/javascriptAstValues.js +32 -0
  264. package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
  265. package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
  266. package/dist/domain/javascript/javascriptNativeHandoff.js +6 -1
  267. package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
  268. package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
  269. package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +7 -2
  270. package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +8 -11
  271. package/dist/domain/javascript/javascriptSemanticAnalysis.js +190 -33
  272. package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
  273. package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
  274. package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
  275. package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
  276. package/dist/domain/javascript/javascriptSemanticFingerprints.js +42 -41
  277. package/dist/domain/javascript/javascriptSemanticGraph.js +69 -23
  278. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +2 -10
  279. package/dist/domain/javascript/javascriptSemanticIterationSources.js +40 -7
  280. package/dist/domain/javascript/javascriptSemanticMemberMutations.js +341 -87
  281. package/dist/domain/javascript/javascriptSemanticMutationValues.js +78 -35
  282. package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
  283. package/dist/domain/javascript/javascriptSemanticObjects.js +7 -1
  284. package/dist/domain/javascript/javascriptSemanticProjection.js +52 -14
  285. package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +77 -0
  286. package/dist/domain/javascript/javascriptSemanticQuery.js +27 -29
  287. package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +1 -3
  288. package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
  289. package/dist/domain/javascript/javascriptSemanticReturns.js +13 -23
  290. package/dist/domain/javascript/javascriptSemanticState.js +22 -2
  291. package/dist/domain/javascript/javascriptSemanticTraversal.js +19 -1
  292. package/dist/domain/javascript/javascriptSemanticValues.js +47 -19
  293. package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
  294. package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
  295. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +8 -6
  296. package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
  297. package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
  298. package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
  299. package/dist/domain/jeb/jebAnalysis.js +114 -0
  300. package/dist/domain/jsonShape.js +63 -52
  301. package/dist/domain/jsonValue.js +3 -0
  302. package/dist/domain/managed/managedApplicationGraph.js +37 -0
  303. package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
  304. package/dist/domain/managed/managedApplicationGraphNodes.js +32 -22
  305. package/dist/domain/managed/managedArtifact.js +1 -0
  306. package/dist/domain/managed/managedInspectionEvidence.js +13 -0
  307. package/dist/domain/native/nativeAotPe.js +1408 -0
  308. package/dist/domain/native/nativeInstruction.js +21 -0
  309. package/dist/domain/native/nativeMetadataRecovery.js +79 -6
  310. package/dist/domain/native/peResources.js +94 -0
  311. package/dist/domain/nativeConvention.js +33 -0
  312. package/dist/domain/process/processCapture.js +91 -1
  313. package/dist/domain/process/processCaptureExample.js +24 -0
  314. package/dist/domain/process/processCaptureValidation.js +79 -0
  315. package/dist/domain/process/processScenario.js +59 -7
  316. package/dist/domain/propertyListKeys.js +3 -1
  317. package/dist/domain/referenceSourceGraph.js +25 -16
  318. package/dist/domain/referenceSourceImportParsing.js +6 -3
  319. package/dist/domain/referenceSourcePathIdentity.js +22 -0
  320. package/dist/domain/referenceSourceRequireBindings.js +137 -0
  321. package/dist/domain/webBundleAnalyzerInspection.js +14 -2
  322. package/dist/domain/webCaptureDiff.js +102 -4
  323. package/dist/domain/webScriptExportError.js +10 -4
  324. package/dist/domain/webScriptExportPlan.js +7 -13
  325. package/dist/domain/zipPackageFormat.js +4 -1
  326. package/dist/domain/zodCollectionSteps.js +24 -0
  327. package/dist/dotnet/ManagedArtifactInspector.js +55 -43
  328. package/dist/dotnet/ManagedDecodeBudget.js +80 -0
  329. package/dist/dotnet/ManagedMemberInspector.js +13 -6
  330. package/dist/dotnet/ManagedMemberInspectorCore.js +2 -2
  331. package/dist/dotnet/ManagedMemberInstructionDecoder.js +4 -2
  332. package/dist/dotnet/ManagedMemberRows.js +9 -4
  333. package/dist/dotnet/ManagedMetadataHeaps.js +15 -5
  334. package/dist/dotnet/ManagedMetadataInventoryRows.js +20 -11
  335. package/dist/dotnet/ManagedMetadataLayout.js +10 -4
  336. package/dist/dotnet/ManagedMethodBodyReader.js +8 -3
  337. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +3 -2
  338. package/dist/dotnet/ManagedNativeBoundaryInspector.js +49 -34
  339. package/dist/dotnet/ManagedPeReader.js +41 -25
  340. package/dist/dotnet/ManagedReaderFailure.js +2 -1
  341. package/dist/dotnet/ManagedStaticProvider.js +55 -24
  342. package/dist/evaluation/AgentEvaluationReport.js +9 -5
  343. package/dist/evaluation/CodexAgentEval.js +43 -13
  344. package/dist/evm/EvmoleFailures.js +0 -2
  345. package/dist/evm/EvmoleInterfaceProvider.js +67 -2
  346. package/dist/filesystem/OwnedDirectoryHandle.js +29 -0
  347. package/dist/filesystem/OwnedFileHandle.js +36 -0
  348. package/dist/filesystem/RegularFile.js +33 -1
  349. package/dist/filesystem/StableFileHash.js +46 -0
  350. package/dist/filesystem/readFileHandleChunks.js +26 -0
  351. package/dist/firmware/FirmwareCommand.js +25 -3
  352. package/dist/firmware/FirmwareFiles.js +23 -8
  353. package/dist/firmware/FirmwareProvider.js +156 -32
  354. package/dist/firmware/FirmwarePublication.js +24 -3
  355. package/dist/firmware/FirmwareRelease.js +1 -0
  356. package/dist/generatedPackageMetadata.js +2 -2
  357. package/dist/ghidra/GhidraAnalysisProfile.js +55 -4
  358. package/dist/ghidra/GhidraAnalysisSeeds.js +211 -0
  359. package/dist/ghidra/GhidraClient.js +76 -4
  360. package/dist/ghidra/GhidraDiagnostics.js +11 -8
  361. package/dist/ghidra/GhidraFunctionValues.js +26 -2
  362. package/dist/ghidra/GhidraInstallation.js +1 -1
  363. package/dist/ghidra/GhidraInventoryValues.js +23 -1
  364. package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
  365. package/dist/ghidra/GhidraLauncher.js +80 -39
  366. package/dist/ghidra/GhidraLoadImageAttest.js +49 -2
  367. package/dist/ghidra/GhidraMipsProfile.js +79 -0
  368. package/dist/ghidra/GhidraProvider.js +57 -9
  369. package/dist/ghidra/GhidraProviderCapabilities.js +18 -8
  370. package/dist/ghidra/GhidraProviderClient.js +282 -21
  371. package/dist/ghidra/GhidraSessionValues.js +9 -2
  372. package/dist/hopper/HopperAnalysisProfile.js +2 -0
  373. package/dist/hopper/HopperClient.js +15 -6
  374. package/dist/hopper/HopperMachOImage.js +2 -0
  375. package/dist/hopper/HopperProvider.js +13 -2
  376. package/dist/ida/IdaOperationRunner.js +8 -2
  377. package/dist/ida/IdaProvider.js +7 -0
  378. package/dist/ida/IdaSessionClient.js +3 -1
  379. package/dist/ida/IdaWorkspace.js +4 -2
  380. package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +326 -0
  381. package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +520 -0
  382. package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +63 -0
  383. package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +521 -0
  384. package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +116 -0
  385. package/dist/javascript/recovery/RecoveryFiles.js +18 -7
  386. package/dist/javascript/recovery/WakaruCommand.js +22 -9
  387. package/dist/javascript/recovery/WakaruExecution.js +11 -7
  388. package/dist/javascript/recovery/WakaruProvider.js +139 -16
  389. package/dist/javascript/recovery/WakaruPublication.js +14 -4
  390. package/dist/javascript/recovery/WakaruRelease.js +10 -3
  391. package/dist/javascript/recovery/WakaruReport.js +12 -7
  392. package/dist/javascript/recovery/WakaruVersion.js +24 -0
  393. package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -3
  394. package/dist/javascript/sourceMaps/SourceMapDecoder.js +63 -7
  395. package/dist/javascript/sourceMaps/SourceMapFormat.js +15 -4
  396. package/dist/jeb/JebMcpConnection.js +179 -0
  397. package/dist/jeb/JebMcpEndpoint.js +40 -0
  398. package/dist/jeb/JebProvider.js +299 -0
  399. package/dist/mcpDoctor.js +15 -6
  400. package/dist/native/AppleDispatchCoverage.js +25 -12
  401. package/dist/native/AppleDispatchMetadata.js +14 -7
  402. package/dist/native/AppleMachoFixups.js +71 -15
  403. package/dist/native/AppleMachoSelection.js +23 -3
  404. package/dist/native/NativeMacOSProvider.js +91 -16
  405. package/dist/native/NativeMachoInspection.js +11 -7
  406. package/dist/native/NativeUiHelperRuntime.js +6 -1
  407. package/dist/native/NativeUiObservation.js +4 -3
  408. package/dist/native/pe/PeResourceLayout.js +120 -0
  409. package/dist/native/pe/PeResourceParser.js +286 -0
  410. package/dist/native/pe/PeResourcesProvider.js +63 -0
  411. package/dist/process/BoundedFileBytes.js +30 -7
  412. package/dist/process/DarwinProcessRunTokenReader.js +8 -3
  413. package/dist/process/OwnedCommand.js +4 -3
  414. package/dist/process/ProcessOwnership.js +104 -112
  415. package/dist/process/ProcessOwnershipObservation.js +96 -39
  416. package/dist/process/ProcessOwnershipProcessTree.js +4 -4
  417. package/dist/process/ProcessRunTokenObservations.js +48 -0
  418. package/dist/process/ProviderDiagnosticRedaction.js +17 -0
  419. package/dist/process/ProviderProcess.js +4 -3
  420. package/dist/process/capture/FilesystemSnapshot.js +28 -4
  421. package/dist/process/capture/ProcessCaptureLifecycle.js +350 -59
  422. package/dist/process/capture/ProcessCaptureProgress.js +62 -0
  423. package/dist/process/capture/ProcessHarness.js +194 -26
  424. package/dist/process/capture/ProcessNormalization.js +3 -1
  425. package/dist/process/capture/ProcessScenarioRuntimeValidation.js +5 -2
  426. package/dist/process/capture/TerminalRenderer.js +24 -7
  427. package/dist/reference/ReferenceSourceReader.js +22 -5
  428. package/dist/reference/ReferenceSourceReaderEntries.js +114 -51
  429. package/dist/reference/ReferenceSourceReaderErrors.js +12 -0
  430. package/dist/reference/ReferenceSourceReaderFile.js +50 -10
  431. package/dist/reference/ReferenceSourceReaderValidate.js +4 -4
  432. package/dist/server/EvidenceMcpServer.js +36 -1
  433. package/dist/server/admittedToolOperation.js +9 -0
  434. package/dist/server/contractToolHandler.js +21 -0
  435. package/dist/server/createServer.js +97 -25
  436. package/dist/server/registerAdbTools.js +36 -0
  437. package/dist/server/registerAnalysisViewTool.js +4 -9
  438. package/dist/server/registerAndroidTools.js +3 -12
  439. package/dist/server/registerApktoolTools.js +14 -0
  440. package/dist/server/registerApplicationTools/compareExportShapes.js +4 -6
  441. package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
  442. package/dist/server/registerApplicationTools/compareVersions.js +3 -2
  443. package/dist/server/registerApplicationTools/coverage.js +3 -2
  444. package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
  445. package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -2
  446. package/dist/server/registerApplicationTools/traceFeature.js +3 -2
  447. package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
  448. package/dist/server/registerArtifactComparisonTool.js +5 -2
  449. package/dist/server/registerBinaryDiagnosticsTools.js +16 -4
  450. package/dist/server/registerBrowserScenarioTool.js +10 -7
  451. package/dist/server/registerBrowserTools.js +12 -9
  452. package/dist/server/registerBundleComparisonTool.js +16 -2
  453. package/dist/server/registerCloseLifecycleTool.js +32 -3
  454. package/dist/server/registerElectronTools.js +28 -10
  455. package/dist/server/registerEvmTools.js +4 -9
  456. package/dist/server/registerFirmwareTools.js +3 -11
  457. package/dist/server/registerFunctionComparisonTool.js +5 -2
  458. package/dist/server/registerJavaScriptRecoveryTool.js +4 -9
  459. package/dist/server/registerJavaScriptRuntimeObservationTools.js +9 -6
  460. package/dist/server/registerJebTools.js +16 -0
  461. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -6
  462. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -2
  463. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +3 -2
  464. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +3 -2
  465. package/dist/server/registerPeResourcesTool.js +9 -0
  466. package/dist/server/registerProcessComparisonTool.js +5 -2
  467. package/dist/server/registerRecordedCrashTools.js +4 -9
  468. package/dist/server/registerSessionRecordTools.js +2 -1
  469. package/dist/server/registerSessionTools.js +49 -18
  470. package/dist/server/registerWebModuleTool.js +4 -9
  471. package/dist/server/registerWebNetworkCaptureTool.js +4 -9
  472. package/dist/server/registerWebRuntimeTools.js +6 -5
  473. package/dist/server/registerWebScriptTool.js +6 -3
  474. package/dist/server/registerWebSourceLocationTool.js +4 -9
  475. package/dist/server/toolResult.js +21 -2
  476. package/dist/windows/WindowsPrivateRuntime.js +12 -5
  477. package/install.sh +7 -4
  478. package/licenses/nativeaot-parser-MIT.txt +28 -0
  479. package/native/windows/build/manifest.json +2 -2
  480. package/native/windows/build/rea-windows-x64.node +0 -0
  481. package/package.json +33 -5
  482. package/scripts/rea.mjs +16 -1
  483. package/skills/reverse-engineer-anything/SKILL.md +52 -51
  484. package/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
  485. package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -0
  486. package/skills/reverse-engineer-anything/references/javascript-applications.md +92 -13
  487. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +22 -1
@@ -7,25 +7,33 @@ import { ArtifactReaderFailure, } from "../ArtifactReader.js";
7
7
  import { abortIfNeeded } from "../ArtifactHash.js";
8
8
  import { DirectoryArtifactReader } from "../DirectoryArtifactReader.js";
9
9
  import { SafeOutputTree } from "../SafeOutputTree.js";
10
+ import { SafeOutputTreeCreationFailure } from "../SafeOutputTreeCreationFailure.js";
10
11
  import { ZipArtifactReader } from "../ZipArtifactReader.js";
11
12
  import { MachOSliceArtifactReader } from "../MachOSliceArtifactReader.js";
12
13
  import { artifactExtractionResultSchema, } from "../../domain/artifactGraph.js";
13
14
  import { AnalysisUnsupportedTargetError } from "../../domain/analysisErrorCore.js";
14
- import { scanArtifactInventory } from "../inventory/ArtifactInventory.js";
15
+ import {} from "../ArtifactResourceScope.js";
16
+ import { scanArtifactInventoryInScope } from "../inventory/ArtifactInventory.js";
15
17
  /** Extract every regular inventory occurrence into an exclusively owned absent root. */
16
- export const extractArtifact = async (input, signal) => {
18
+ export const extractArtifact = async (input, signal) => input.resourceScope.run(() => extractArtifactInScope(input, signal));
19
+ const extractArtifactInScope = async (input, signal) => {
17
20
  // Cancellation wins over every later refusal, including unsupported formats.
18
21
  abortIfNeeded(signal);
19
22
  const sourcePath = await realpath(input.inputPath);
20
23
  await requireExtractableFormat(sourcePath, input);
21
- const snapshot = await scanArtifactInventory(sourcePath, {
24
+ const snapshot = await scanArtifactInventoryInScope(sourcePath, {
25
+ resourceScope: input.resourceScope,
22
26
  signal,
23
27
  environment: input.environment,
28
+ integrity: { mode: input.integrityPolicy },
24
29
  });
25
- return materializeArtifactInventory(input, sourcePath, snapshot, signal);
30
+ return materializeArtifactInventoryInScope(input, sourcePath, snapshot, signal);
26
31
  };
27
32
  /** Materialize a scanned inventory, verifying every current occurrence against it. */
28
33
  export const materializeArtifactInventory = async (input, sourcePath, snapshot, signal) => {
34
+ return input.resourceScope.run(() => materializeArtifactInventoryInScope(input, sourcePath, snapshot, signal));
35
+ };
36
+ const materializeArtifactInventoryInScope = async (input, sourcePath, snapshot, signal) => {
29
37
  abortIfNeeded(signal);
30
38
  const selectedOccurrences = snapshot.occurrences.filter((occurrence) => (occurrence.entry_kind === "file" || occurrence.entry_kind === "slice") &&
31
39
  occurrence.logical_path !== ".");
@@ -42,26 +50,36 @@ export const materializeArtifactInventory = async (input, sourcePath, snapshot,
42
50
  return true;
43
51
  });
44
52
  const selectedIds = new Set(activeOccurrences.map(({ occurrence_id: id }) => id));
45
- const occurrences = new Map();
46
- const neededNodes = new Set();
47
- collectOccurrences(snapshot.occurrences, selectedIds, occurrences, neededNodes);
53
+ const neededNodes = new Set(activeOccurrences.map(({ artifact_id: id }) => id));
48
54
  const nodes = new Map();
49
- collectNodes(snapshot.nodes, neededNodes, nodes);
55
+ for (const node of snapshot.nodes)
56
+ if (neededNodes.has(node.artifact_id))
57
+ nodes.set(node.artifact_id, node);
50
58
  const inventory = {
51
59
  manifest: snapshot.manifest,
52
- occurrences,
53
- nodes,
60
+ integrityContradictions: snapshot.integrity_contradictions.filter(({ occurrence_id: id }) => selectedIds.has(id)),
54
61
  };
55
62
  const selected = activeOccurrences.map((occurrence) => {
56
63
  // REA never decrypts archive entries, so an encrypted entry makes the
57
64
  // complete extraction unsupported rather than the archive invalid.
58
65
  if (occurrence.encrypted)
59
66
  throw new AnalysisUnsupportedTargetError("extract_artifact", input.inputPath, `Archive entry ${occurrence.logical_path} is encrypted; REA does not decrypt archive entries, so the archive cannot be extracted completely`);
67
+ // Inventory keeps an ASAR unpacked entry whose companion file is absent,
68
+ // but extraction cannot materialize bytes it never observed.
69
+ if (occurrence.entry_kind === "file" &&
70
+ occurrence.artifact_id === null &&
71
+ occurrence.hash_status === "unavailable")
72
+ throw new ArtifactReaderFailure("unavailable", `ASAR unpacked companion bytes are unavailable for ${occurrence.logical_path}`, undefined, {
73
+ logicalPath: occurrence.logical_path,
74
+ declaredSha256: null,
75
+ calculatedSha256: null,
76
+ unpacked: true,
77
+ });
60
78
  if ((occurrence.entry_kind !== "file" && occurrence.entry_kind !== "slice") ||
61
79
  occurrence.artifact_id === null ||
62
80
  occurrence.logical_path === ".")
63
81
  throw new ArtifactReaderFailure("format", `Selected occurrence is not an extractable regular child file: ${occurrence.logical_path} (${occurrence.occurrence_id})`);
64
- const node = inventory.nodes.get(occurrence.artifact_id);
82
+ const node = nodes.get(occurrence.artifact_id);
65
83
  if (node === undefined)
66
84
  throw new ArtifactReaderFailure("integrity", `Selected occurrence has no inventory node: ${occurrence.occurrence_id}`);
67
85
  return { occurrence, node };
@@ -77,74 +95,36 @@ export const materializeArtifactInventory = async (input, sourcePath, snapshot,
77
95
  const materializeSelection = async ({ input, sourcePath, inventory, selected, signal, }) => {
78
96
  const byPath = new Map(selected.map((item) => [item.occurrence.logical_path, item]));
79
97
  const reader = await createReader(sourcePath, input);
98
+ const readerOwner = {
99
+ kind: "reader",
100
+ reader,
101
+ resource: `artifact reader for ${sourcePath}`,
102
+ };
103
+ let localReaderOwner = readerOwner;
80
104
  let output;
81
- let readerCloseAttempted = false;
82
- let readerClosed = false;
105
+ let completed;
83
106
  const extracted = [];
84
107
  try {
85
- output = await SafeOutputTree.create(input.outputRoot);
86
- const registry = new ArtifactPathRegistry();
87
- for await (const entry of reader.entries(signal)) {
88
- const path = normalizeArtifactPath(entry.path);
89
- registry.add(path, entry.kind);
90
- const selectedItem = byPath.get(path);
91
- if (selectedItem === undefined) {
92
- if (entry.kind === "file" || entry.kind === "slice")
93
- throw new ArtifactReaderFailure("integrity", `Regular artifact entry is missing from inventory: ${path}`);
94
- continue;
95
- }
96
- preflight(entry);
97
- const stream = await reader.open(entry, signal);
98
- const written = await output.write(path, stream, selectedItem.node.sha256, signal);
99
- extracted.push({
100
- artifact_id: selectedItem.node.artifact_id,
101
- relative_path: written.relativePath,
102
- sha256: written.sha256,
103
- bytes_written: written.bytesWritten,
104
- created: true,
105
- });
106
- byPath.delete(path);
108
+ try {
109
+ output = await SafeOutputTree.create(input.outputRoot);
110
+ }
111
+ catch (cause) {
112
+ if (cause instanceof SafeOutputTreeCreationFailure)
113
+ output = cause.tree;
114
+ throw cause;
107
115
  }
108
- if (byPath.size > 0)
109
- throw new ArtifactReaderFailure("integrity", `Inventoried regular artifact entries were not materialized: ${[...byPath.keys()].sort(compareUnicodeCodePoints).join(", ")}`);
110
- readerCloseAttempted = true;
111
- await reader.close();
112
- readerClosed = true;
116
+ await writeSelectedEntries({ reader, output, byPath, extracted, signal });
117
+ localReaderOwner = undefined;
118
+ const closeAttempt = await input.resourceScope.release(readerOwner);
119
+ if (closeAttempt.kind === "failed")
120
+ throw ArtifactReaderFailure.withCleanup(closeAttempt.cause, ArtifactReaderFailure.cleanupObservation(closeAttempt.cause, readerOwner.resource));
113
121
  extracted.sort((left, right) => compareUnicodeCodePoints(left.relative_path, right.relative_path));
114
- const result = createExtractionResult(input, inventory, selected, extracted);
122
+ completed = createExtractionResult(input, inventory, selected, extracted);
115
123
  await output.commit();
116
- return result;
124
+ return completed;
117
125
  }
118
126
  catch (cause) {
119
- const cleanupFailures = [];
120
- if (readerCloseAttempted && !readerClosed)
121
- cleanupFailures.push({
122
- cause,
123
- resource: `artifact reader for ${sourcePath}`,
124
- });
125
- if (!readerCloseAttempted) {
126
- try {
127
- readerCloseAttempted = true;
128
- await reader.close();
129
- }
130
- catch (cleanupCause) {
131
- cleanupFailures.push({
132
- cause: cleanupCause,
133
- resource: `artifact reader for ${sourcePath}`,
134
- });
135
- }
136
- }
137
- if (output !== undefined) {
138
- try {
139
- await output.rollback();
140
- }
141
- catch (cleanupCause) {
142
- cleanupFailures.push({
143
- cause: cleanupCause,
144
- resource: input.outputRoot,
145
- });
146
- }
147
- }
127
+ const cleanupFailures = await releaseExtractionOwners(input.resourceScope, localReaderOwner, output, input.outputRoot);
148
128
  if (cleanupFailures.length > 0) {
149
129
  const observations = cleanupFailures.map(({ cause: cleanupCause, resource }) => ArtifactReaderFailure.cleanupObservation(cleanupCause, resource));
150
130
  throw ArtifactReaderFailure.withCleanup(cause, {
@@ -152,11 +132,63 @@ const materializeSelection = async ({ input, sourcePath, inventory, selected, si
152
132
  resources: [
153
133
  ...new Set(observations.flatMap(({ resources }) => resources)),
154
134
  ],
155
- });
135
+ }, output?.published === true && completed !== undefined
136
+ ? { kind: "artifact-extraction", extraction: completed }
137
+ : undefined);
156
138
  }
139
+ if (output?.published === true && completed !== undefined)
140
+ return completed;
157
141
  throw cause;
158
142
  }
159
143
  };
144
+ const writeSelectedEntries = async ({ reader, output, byPath, extracted, signal, }) => {
145
+ const registry = new ArtifactPathRegistry();
146
+ for await (const entry of reader.entries(signal)) {
147
+ const path = normalizeArtifactPath(entry.path);
148
+ registry.add(path, entry.kind);
149
+ const selectedItem = byPath.get(path);
150
+ if (selectedItem === undefined) {
151
+ if (entry.kind === "file" || entry.kind === "slice")
152
+ throw new ArtifactReaderFailure("integrity", `Regular artifact entry is missing from inventory: ${path}`);
153
+ continue;
154
+ }
155
+ preflight(entry);
156
+ const stream = await reader.open(entry, signal);
157
+ const written = await output.write(path, stream, {
158
+ sha256: selectedItem.node.sha256,
159
+ bytes: selectedItem.node.size,
160
+ }, signal);
161
+ extracted.push({
162
+ artifact_id: selectedItem.node.artifact_id,
163
+ relative_path: written.relativePath,
164
+ sha256: written.sha256,
165
+ bytes_written: written.bytesWritten,
166
+ created: true,
167
+ });
168
+ byPath.delete(path);
169
+ }
170
+ if (byPath.size > 0)
171
+ throw new ArtifactReaderFailure("integrity", `Inventoried regular artifact entries were not materialized: ${[...byPath.keys()].sort(compareUnicodeCodePoints).join(", ")}`);
172
+ };
173
+ const releaseExtractionOwners = async (resourceScope, readerOwner, output, outputRoot) => {
174
+ const failures = [];
175
+ if (readerOwner !== undefined) {
176
+ const attempt = await resourceScope.release(readerOwner);
177
+ if (attempt.kind === "failed")
178
+ failures.push({ cause: attempt.cause, resource: readerOwner.resource });
179
+ }
180
+ if (output !== undefined) {
181
+ const owner = {
182
+ kind: "output-tree",
183
+ tree: output,
184
+ resource: outputRoot,
185
+ };
186
+ const attempt = await resourceScope.release(owner);
187
+ if (attempt.kind === "failed")
188
+ failures.push({ cause: attempt.cause, resource: owner.resource });
189
+ }
190
+ return failures;
191
+ };
160
192
  const createExtractionResult = (input, inventory, selected, extracted) => {
161
193
  const extractionSemantic = {
162
194
  source_manifest_id: inventory.manifest.manifest_id,
@@ -177,25 +209,17 @@ const createExtractionResult = (input, inventory, selected, extracted) => {
177
209
  containment_verified: true,
178
210
  cleanup: { attempted: false, verified: true, residual_paths: [] },
179
211
  provenance: [],
212
+ integrity_contradictions: inventory.integrityContradictions,
180
213
  limitations: [
181
214
  "All regular files in the active artifact were materialized; nested archive contents remain represented by their containing file.",
215
+ ...(inventory.integrityContradictions.length === 0
216
+ ? []
217
+ : [
218
+ `${String(inventory.integrityContradictions.length)} extracted file(s) contradict declared integrity metadata; their bytes are observed-untrusted.`,
219
+ ]),
182
220
  ],
183
221
  });
184
222
  };
185
- const collectOccurrences = (items, selected, output, neededNodes) => {
186
- for (const item of items) {
187
- if (!selected.has(item.occurrence_id))
188
- continue;
189
- output.set(item.occurrence_id, item);
190
- if (item.artifact_id !== null)
191
- neededNodes.add(item.artifact_id);
192
- }
193
- };
194
- const collectNodes = (items, selected, output) => {
195
- for (const item of items)
196
- if (selected.has(item.artifact_id))
197
- output.set(item.artifact_id, item);
198
- };
199
223
  const ZIP_FORMATS = ["ipa", "apk", "msix", "appx", "zip"];
200
224
  const isZipFormat = (format) => ZIP_FORMATS.includes(format);
201
225
  /**
@@ -11,30 +11,54 @@ export const indexOccurrencesByPath = (occurrences) => {
11
11
  byPath.set(occurrence.logical_path, occurrence);
12
12
  return byPath;
13
13
  };
14
- export const createOccurrence = (entry, path, parent) => ({
15
- occurrence_id: `occ_${digestCanonicalValue({ path, kind: entry.kind }, "Artifact")}`,
16
- artifact_id: null,
17
- parent_occurrence_id: parent,
18
- logical_path: path,
19
- entry_kind: entry.kind,
20
- artifact_kind: entry.kind === "directory"
21
- ? path.toLowerCase().endsWith(".framework")
22
- ? "framework"
23
- : "container"
24
- : classifyArtifactPath(path).kind,
25
- artifact_format: entry.kind === "directory"
26
- ? "directory"
27
- : classifyArtifactPath(path).format,
28
- declared_size: entry.declaredSize,
29
- compressed_size: entry.compressedSize,
30
- executable: entry.executable,
31
- encrypted: entry.encrypted,
32
- hash_status: entry.encrypted ? "unavailable" : "not-hashed",
33
- source_location: entry.byteOffset === null || entry.declaredSize === null
34
- ? null
35
- : { offset: entry.byteOffset, length: entry.declaredSize },
36
- limitations: [...entry.limitations],
37
- });
14
+ /**
15
+ * Create an occurrence before its bytes are read. A container suffix is not a
16
+ * container family until the bytes are classified, so a member named like a
17
+ * container starts with an unknown format.
18
+ */
19
+ export const createOccurrence = (entry, path, parent) => {
20
+ const role = entry.kind === "directory"
21
+ ? {
22
+ kind: path.toLowerCase().endsWith(".framework")
23
+ ? "framework"
24
+ : "container",
25
+ format: "directory",
26
+ }
27
+ : containerSuffixFamily(path) === undefined
28
+ ? classifyArtifactPath(path)
29
+ : { kind: "unknown", format: "unknown" };
30
+ return {
31
+ occurrence_id: `occ_${digestCanonicalValue({ path, kind: entry.kind }, "Artifact")}`,
32
+ artifact_id: null,
33
+ parent_occurrence_id: parent,
34
+ logical_path: path,
35
+ entry_kind: entry.kind,
36
+ artifact_kind: role.kind,
37
+ artifact_format: role.format,
38
+ declared_size: entry.declaredSize,
39
+ compressed_size: entry.compressedSize,
40
+ executable: entry.executable,
41
+ encrypted: entry.encrypted,
42
+ hash_status: entry.encrypted ? "unavailable" : "not-hashed",
43
+ source_location: entry.byteOffset === null || entry.declaredSize === null
44
+ ? null
45
+ : { offset: entry.byteOffset, length: entry.declaredSize },
46
+ limitations: [...entry.limitations],
47
+ };
48
+ };
49
+ /** Record that an unread member's container suffix was not checked against bytes. */
50
+ export const noteUnreadContainerSuffix = (occurrence) => {
51
+ if (occurrence.entry_kind === "directory")
52
+ return;
53
+ const family = containerSuffixFamily(occurrence.logical_path);
54
+ if (family === undefined)
55
+ return;
56
+ occurrence.limitations.push(`The path suffix suggests ${family.toUpperCase()}, but these bytes were not read, so the container family is unknown.`);
57
+ };
58
+ const containerSuffixFamily = (path) => {
59
+ const lower = path.toLowerCase();
60
+ return lower.endsWith(".asar") ? "asar" : zipPackageFormatForPath(lower);
61
+ };
38
62
  /** Compare exact child names independently of host locale and traversal order. */
39
63
  export const materializeDirectoryNodes = (occurrences, nodes) => {
40
64
  const directories = occurrences
@@ -153,15 +177,13 @@ export const createArtifactEdges = (rootArtifactId, occurrences, producer) => {
153
177
  rootArtifactId;
154
178
  const semantic = {
155
179
  parent_artifact_id: parentArtifactId,
156
- child_artifact_id: occurrence.artifact_id,
157
180
  relation: occurrence.entry_kind === "slice"
158
181
  ? "slice-of"
159
182
  : relationFor(occurrence.logical_path),
160
183
  occurrence_id: occurrence.occurrence_id,
161
- logical_path: occurrence.logical_path,
162
184
  };
163
185
  edges.push({
164
- edge_id: artifactEdgeId(semantic),
186
+ edge_id: artifactEdgeId(semantic, occurrence),
165
187
  ...semantic,
166
188
  producer: occurrence.entry_kind === "slice" ? (producer ?? null) : null,
167
189
  ordinal: edges.length,
@@ -169,29 +191,55 @@ export const createArtifactEdges = (rootArtifactId, occurrences, producer) => {
169
191
  }
170
192
  return edges;
171
193
  };
172
- export const nearestParent = (path, occurrences, expandedContainerIds) => {
173
- const parts = path.split("/");
174
- while (parts.length > 1) {
175
- parts.pop();
176
- const candidate = occurrences.get(parts.join("/"));
177
- if (candidate !== undefined &&
178
- (candidate.entry_kind === "directory" ||
179
- expandedContainerIds.has(candidate.occurrence_id)))
180
- return candidate;
194
+ /** Resolve strict observed ancestors without rebuilding every path prefix. */
195
+ export const resolveOccurrenceParents = (occurrences, byPath, expandedContainerIds) => {
196
+ const root = { children: new Map() };
197
+ for (const occurrence of byPath.values()) {
198
+ if (occurrence.entry_kind !== "directory" &&
199
+ !expandedContainerIds.has(occurrence.occurrence_id))
200
+ continue;
201
+ let branch = root;
202
+ for (const segment of occurrence.logical_path.split("/")) {
203
+ let child = branch.children.get(segment);
204
+ if (child === undefined) {
205
+ child = { children: new Map() };
206
+ branch.children.set(segment, child);
207
+ }
208
+ branch = child;
209
+ }
210
+ branch.occurrence = occurrence;
211
+ }
212
+ for (const occurrence of occurrences) {
213
+ const path = occurrence.logical_path;
214
+ let branch = root;
215
+ let parent;
216
+ // Walk parent segments only. Stop scanning the path once no observed
217
+ // directory or expanded container can be an ancestor.
218
+ for (let start = 0;;) {
219
+ const slash = path.indexOf("/", start);
220
+ if (slash < 0)
221
+ break;
222
+ const segment = path.slice(start, slash);
223
+ const child = branch.children.get(segment);
224
+ if (child === undefined)
225
+ break;
226
+ branch = child;
227
+ parent = branch.occurrence ?? parent;
228
+ start = slash + 1;
229
+ }
230
+ occurrence.parent_occurrence_id = parent?.occurrence_id ?? null;
181
231
  }
182
- return undefined;
183
232
  };
233
+ /**
234
+ * Assign a path role hint. Container families are not path roles: ZIP and
235
+ * ASAR families are chosen only after their bytes have been classified.
236
+ */
184
237
  export const classifyArtifactPath = (path) => {
185
238
  const lower = path.toLowerCase();
186
239
  if (lower.endsWith(".map"))
187
240
  return { kind: "source-map", format: "source-map" };
188
241
  if (/\.(?:m?js|cjs)$/u.test(lower))
189
242
  return { kind: "javascript", format: "javascript-bundle" };
190
- if (lower.endsWith(".asar"))
191
- return { kind: "container", format: "asar" };
192
- const archiveFormat = zipPackageFormatForPath(lower);
193
- if (archiveFormat !== undefined)
194
- return { kind: "container", format: archiveFormat };
195
243
  if (/\.framework(?:\/|$)/u.test(lower))
196
244
  return { kind: "framework", format: "file" };
197
245
  if (/\.(?:node|dylib|so)$/u.test(lower))
@@ -207,7 +255,26 @@ export const classifyArtifactPath = (path) => {
207
255
  };
208
256
  /** Classify executable formats from bytes while retaining path-specific roles. */
209
257
  export const classifyArtifactContent = (path, prefix, fileSize = prefix.length) => {
210
- return artifactRoleForFormat(path, classifyArtifactBytes(prefix, fileSize));
258
+ const format = classifyArtifactBytes(prefix, fileSize);
259
+ if (format === "file" &&
260
+ path.toLowerCase().endsWith(".asar") &&
261
+ hasAsarHeader(prefix))
262
+ return { kind: "container", format: "asar" };
263
+ return artifactRoleForFormat(path, format);
264
+ };
265
+ /**
266
+ * Electron ASAR starts with a size pickle whose payload is one uint32, then
267
+ * a header pickle whose payload begins with a JSON object.
268
+ */
269
+ export const hasAsarHeader = (prefix) => {
270
+ if (prefix.length < 17 || prefix.readUInt32LE(0) !== 4)
271
+ return false;
272
+ const headerSize = prefix.readUInt32LE(4);
273
+ const payloadSize = prefix.readUInt32LE(8);
274
+ if (headerSize < 16 || payloadSize !== headerSize - 4)
275
+ return false;
276
+ const stringLength = prefix.readUInt32LE(12);
277
+ return (stringLength >= 2 && stringLength <= payloadSize - 4 && prefix[16] === 0x7b);
211
278
  };
212
279
  const artifactRoleForFormat = (path, format) => {
213
280
  const byPath = classifyArtifactPath(path);
@@ -1,15 +1,16 @@
1
1
  import { realpath } from "node:fs/promises";
2
2
  import { artifactInventoryResultSchema, } from "../../domain/artifactGraph.js";
3
3
  import { abortIfNeeded } from "../ArtifactHash.js";
4
- import { scanCanonicalArtifactInventory } from "./scanCanonical.js";
4
+ import { scanCanonicalArtifactInventoryInScope } from "./scanCanonical.js";
5
5
  /** Inventory one local artifact and return every graph collection inline. */
6
- export const inventoryArtifact = async (inputPath, options = {}) => {
6
+ export const inventoryArtifact = async (inputPath, options) => {
7
7
  const snapshot = await scanArtifactInventory(inputPath, options);
8
8
  return artifactInventoryResultSchema.parse(snapshot);
9
9
  };
10
10
  /** Scan an artifact once and retain the complete immutable graph for projection. */
11
- export const scanArtifactInventory = async (inputPath, options = {}) => {
11
+ export const scanArtifactInventory = async (inputPath, options) => options.resourceScope.run(() => scanArtifactInventoryInScope(inputPath, options));
12
+ export const scanArtifactInventoryInScope = async (inputPath, options) => {
12
13
  abortIfNeeded(options.signal);
13
14
  const path = await realpath(inputPath);
14
- return scanCanonicalArtifactInventory(path, options);
15
+ return scanCanonicalArtifactInventoryInScope(path, options);
15
16
  };
@@ -1,53 +1,96 @@
1
- import { NonRegularFileReadError, openRegularFile, sameRegularFileState, } from "../../filesystem/RegularFile.js";
1
+ import { sameRegularFileState } from "../../filesystem/RegularFile.js";
2
2
  import { classifyArtifactContent } from "./ArtifactGraphConstruction.js";
3
3
  import { ARTIFACT_CLASSIFICATION_PREFIX_BYTES } from "../ArtifactHash.js";
4
4
  import { hasZipSignature, zipPackageFormatForPath, } from "../../domain/zipPackageFormat.js";
5
5
  import { ArtifactReaderFailure } from "../ArtifactReader.js";
6
- import { hashStableRootArtifactHandle } from "./hashStableRootArtifact.js";
7
- const classifyContainerExtension = (path) => {
8
- const lower = path.toLowerCase();
9
- const zipPackage = zipPackageFormatForPath(lower);
10
- if (zipPackage !== undefined)
11
- return zipPackage;
12
- for (const format of ["asar", "dmg", "pkg"])
13
- if (lower.endsWith(`.${format}`))
14
- return format;
15
- return undefined;
16
- };
6
+ import {} from "../ArtifactResourceScope.js";
7
+ import { hashStableRootArtifactHandle, openRootArtifact, } from "./hashStableRootArtifact.js";
17
8
  /** Classify and hash one file root through the same stable open descriptor. */
18
- export const classifyAndHashRoot = async (path, directory, expectedMetadata, signal) => {
9
+ export const classifyAndHashRoot = async (path, directory, expectedMetadata, options) => {
10
+ return options.resourceScope.run(async () => {
11
+ const result = await classifyAndHashRootForInventory(path, directory, expectedMetadata, options);
12
+ const rootSource = result.rootSource;
13
+ if (rootSource !== undefined) {
14
+ const owner = {
15
+ kind: "file-handle",
16
+ handle: rootSource.owner,
17
+ resource: `root artifact descriptor for ${path}`,
18
+ };
19
+ const cleanupAttempt = await options.resourceScope.release(owner);
20
+ if (cleanupAttempt.kind === "failed")
21
+ throw ArtifactReaderFailure.withCleanup(cleanupAttempt.cause, ArtifactReaderFailure.cleanupObservation(cleanupAttempt.cause, owner.resource));
22
+ }
23
+ return { format: result.format, digest: result.digest };
24
+ });
25
+ };
26
+ /** Classify a root and retain its admitted ZIP descriptor for child inventory. */
27
+ export const classifyAndHashRootForInventory = async (path, directory, expectedMetadata, options) => {
19
28
  if (directory)
20
- return { format: "directory", digest: null };
21
- const handle = await openRootFile(path, signal);
29
+ return { format: "directory", digest: null, rootSource: undefined };
30
+ const ownedHandle = await openRootArtifact(path, options.resourceScope, options.signal);
31
+ const handle = ownedHandle.handle;
32
+ const owner = {
33
+ kind: "file-handle",
34
+ handle: ownedHandle,
35
+ resource: `root artifact descriptor for ${path}`,
36
+ };
37
+ let outcome;
22
38
  try {
23
39
  const initial = await handle.stat();
24
40
  if (!sameRegularFileState(expectedMetadata, initial))
25
41
  throw new ArtifactReaderFailure("integrity", `Root artifact changed before inventory: ${path}`);
26
- const format = classifyContainerExtension(path) ??
27
- (await classifyOpenedRoot(path, handle));
28
- const digest = await hashStableRootArtifactHandle(path, handle, initial, signal);
29
- return { format, digest };
30
- }
31
- finally {
32
- await handle.close();
33
- }
34
- };
35
- const openRootFile = async (path, signal) => {
36
- try {
37
- return await openRegularFile(path, { symlinks: "reject", signal });
42
+ const format = await classifyRootFormat(path, handle);
43
+ const digest = await hashStableRootArtifactHandle(path, handle, initial, options.signal);
44
+ const retainSource = isZipFormat(format) || format === "mach-o-universal";
45
+ outcome = {
46
+ kind: "completed",
47
+ value: {
48
+ format,
49
+ digest,
50
+ rootSource: retainSource
51
+ ? { handle, initial, owner: ownedHandle }
52
+ : undefined,
53
+ },
54
+ };
38
55
  }
39
56
  catch (cause) {
40
- if (cause instanceof NonRegularFileReadError)
41
- throw new ArtifactReaderFailure("format", `Artifact root is not a regular file: ${path}`, { cause });
42
- throw cause;
57
+ outcome = { kind: "failed", cause };
58
+ }
59
+ if (outcome.kind === "failed" || outcome.value.rootSource === undefined) {
60
+ const cleanupAttempt = await options.resourceScope.release(owner);
61
+ if (cleanupAttempt.kind === "failed")
62
+ throw ArtifactReaderFailure.withCleanup(outcome.kind === "failed" ? outcome.cause : cleanupAttempt.cause, ArtifactReaderFailure.cleanupObservation(cleanupAttempt.cause, owner.resource));
43
63
  }
64
+ if (outcome.kind === "failed")
65
+ throw outcome.cause;
66
+ return outcome.value;
44
67
  };
45
- const classifyOpenedRoot = async (path, handle) => {
68
+ const isZipFormat = (format) => format === "zip" ||
69
+ format === "ipa" ||
70
+ format === "apk" ||
71
+ format === "msix" ||
72
+ format === "appx";
73
+ const classifyRootFormat = async (path, handle) => {
46
74
  const magic = Buffer.alloc(ARTIFACT_CLASSIFICATION_PREFIX_BYTES);
47
75
  const observed = await handle.read(magic, 0, magic.length, 0);
48
76
  const prefix = magic.subarray(0, observed.bytesRead);
77
+ const lower = path.toLowerCase();
49
78
  if (hasZipSignature(prefix))
50
- return "zip";
79
+ return zipPackageFormatForPath(lower) ?? "zip";
80
+ if (lower.endsWith(".pkg") &&
81
+ prefix.subarray(0, 4).toString("ascii") === "xar!")
82
+ return "pkg";
83
+ if (lower.endsWith(".dmg") && (await hasKolyTrailer(handle)))
84
+ return "dmg";
85
+ // ASAR is chosen from its header pickle; any other suffix is a role hint.
51
86
  return classifyArtifactContent(path, prefix, (await handle.stat()).size)
52
87
  .format;
53
88
  };
89
+ const hasKolyTrailer = async (handle) => {
90
+ const size = (await handle.stat()).size;
91
+ if (size < 512)
92
+ return false;
93
+ const trailer = Buffer.alloc(4);
94
+ const read = await handle.read(trailer, 0, trailer.length, size - 512);
95
+ return read.bytesRead === 4 && trailer.toString("ascii") === "koly";
96
+ };