rea-agents 6.2.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 (636) hide show
  1. package/README.md +24 -23
  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/bridge/hopper_bridge.py +2 -0
  6. package/dist/adb/AdbConfiguration.js +88 -0
  7. package/dist/adb/AdbDeviceOutput.js +186 -0
  8. package/dist/adb/AdbProvider.js +1190 -0
  9. package/dist/adb/AdbShellOutput.js +309 -0
  10. package/dist/android/AndroidTargetSnapshot.js +104 -22
  11. package/dist/android/JadxConfiguration.js +44 -24
  12. package/dist/android/JadxProvider.js +59 -21
  13. package/dist/android/JadxSession.js +51 -9
  14. package/dist/apktool/ApktoolConfiguration.js +84 -0
  15. package/dist/apktool/ApktoolDecodeOutput.js +59 -0
  16. package/dist/apktool/ApktoolProvider.js +506 -0
  17. package/dist/application/AnalysisProvider.js +8 -2
  18. package/dist/application/AppBundleExecutable.js +27 -22
  19. package/dist/application/BinaryTargetResolver.js +85 -19
  20. package/dist/application/BrowserScenarioEvidence.js +2 -2
  21. package/dist/application/CapabilityInventory.js +11 -1
  22. package/dist/application/ClientConfigurationDocument.js +98 -0
  23. package/dist/application/ClientConfigurationFiles.js +91 -0
  24. package/dist/application/ClientRegistrationEnvironment.js +35 -0
  25. package/dist/application/ClientRegistrationStatus.js +75 -27
  26. package/dist/application/DirectAnalysis.js +14 -8
  27. package/dist/application/DirectAnalysisCleanup.js +1 -2
  28. package/dist/application/DirectAnalysisStatus.js +3 -6
  29. package/dist/application/Doctor.js +27 -34
  30. package/dist/application/DoctorDiagnostics.js +1 -1
  31. package/dist/application/EvidenceBundleCommands.js +6 -12
  32. package/dist/application/EvidenceBundleFiles.js +1 -1
  33. package/dist/application/GeminiClientSettings.js +139 -0
  34. package/dist/application/HermesClientHome.js +115 -0
  35. package/dist/application/HopperDownload.js +39 -0
  36. package/dist/application/InvestigationProviders.js +10 -4
  37. package/dist/application/JsonFiles.js +16 -15
  38. package/dist/application/JsonInputFile.js +252 -0
  39. package/dist/application/LinuxHopper.js +6 -13
  40. package/dist/application/MacHopper.js +172 -149
  41. package/dist/application/MipsElfAbiFlags.js +140 -0
  42. package/dist/application/ProviderOperationExecution.js +31 -0
  43. package/dist/application/ReconstructionObligationCandidates.js +16 -3
  44. package/dist/application/ReconstructionObligationLedgerProjection.js +3 -1
  45. package/dist/application/ReferenceSourceImport.js +76 -29
  46. package/dist/application/ReferenceSourceImportEntries.js +18 -9
  47. package/dist/application/ReferenceSourceImportPolicy.js +99 -23
  48. package/dist/application/ReferenceSourceImportTypes.js +30 -22
  49. package/dist/application/ReferenceSourceVcsAdapter.js +145 -30
  50. package/dist/application/RegularFileRead.js +103 -0
  51. package/dist/application/Setup.js +69 -10
  52. package/dist/application/SetupClientConfiguration.js +134 -23
  53. package/dist/application/SetupHost.js +102 -22
  54. package/dist/application/SetupPlan.js +18 -17
  55. package/dist/application/SetupSkill.js +81 -13
  56. package/dist/application/SupportedClients.js +305 -37
  57. package/dist/application/Uninstall.js +172 -8
  58. package/dist/application/UpdateMaintenance.js +23 -23
  59. package/dist/application/Utf8JsonInput.js +71 -0
  60. package/dist/application/WebScriptExportService.js +130 -57
  61. package/dist/application/WebSourceLocationService.js +3 -0
  62. package/dist/application/adb/AdbDeviceAnalysisPort.js +1 -0
  63. package/dist/application/adb/AdbDeviceAnalysisService.js +13 -0
  64. package/dist/application/analysisView/AnalysisViewService.js +40 -2
  65. package/dist/application/android/AndroidAnalysisService.js +1 -1
  66. package/dist/application/apktool/ApktoolResourceAnalysisPort.js +1 -0
  67. package/dist/application/apktool/ApktoolResourceAnalysisService.js +13 -0
  68. package/dist/application/binary/AnalysisClientCleanup.js +0 -24
  69. package/dist/application/binary/AnalysisSnapshotCache.js +5 -4
  70. package/dist/application/binary/BinarySession.js +18 -1
  71. package/dist/application/binary/BinarySessionOpen.js +9 -1
  72. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +2 -1
  73. package/dist/application/binaryDiagnostics/PeResourcesPort.js +1 -0
  74. package/dist/application/binaryDiagnostics/PeResourcesService.js +111 -0
  75. package/dist/application/binaryDiagnostics/RecordedCrashService.js +2 -1
  76. package/dist/application/evm/EvmInterfaceService.js +3 -0
  77. package/dist/application/firmware/FirmwareAnalysisService.js +3 -0
  78. package/dist/application/investigation/InspectEvidenceBundle.js +18 -0
  79. package/dist/application/javascript/ElectronActiveEvidence.js +2 -2
  80. package/dist/application/javascript/ElectronBoundaryAnalysis.js +2 -2
  81. package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
  82. package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
  83. package/dist/application/javascript/ElectronBoundaryGraphNative.js +20 -3
  84. package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
  85. package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -0
  86. package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +107 -46
  87. package/dist/application/javascript/JavaScriptApplicationService.js +23 -11
  88. package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
  89. package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +59 -45
  90. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -36
  91. package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
  92. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +74 -36
  93. package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
  94. package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
  95. package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +53 -42
  96. package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
  97. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +293 -238
  98. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +120 -28
  99. package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -0
  100. package/dist/application/javascript/JavaScriptJsonModules.js +2 -2
  101. package/dist/application/javascript/JavaScriptModuleRelationships.js +10 -20
  102. package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
  103. package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +11 -27
  104. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +11 -5
  105. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +206 -66
  106. package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -1
  107. package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +18 -23
  108. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +5 -2
  109. package/dist/application/javascript/JavaScriptSemanticGraphEvidence.js +1 -1
  110. package/dist/application/javascript/JavaScriptSemanticGraphFingerprintProjection.js +2 -2
  111. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +7 -5
  112. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +6 -4
  113. package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +4 -4
  114. package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +1 -1
  115. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +29 -15
  116. package/dist/application/javascript/JavaScriptSemanticTraceService.js +15 -10
  117. package/dist/application/jeb/JebAnalysisPort.js +1 -0
  118. package/dist/application/jeb/JebAnalysisService.js +13 -0
  119. package/dist/application/managed/ManagedApplicationGraphService.js +1 -1
  120. package/dist/application/native/NativeCallRoutes.js +2 -4
  121. package/dist/application/native/NativeUiActionTrace.js +16 -8
  122. package/dist/application/native/NativeValueTrace.js +23 -6
  123. package/dist/application/process/ProcessCli.js +25 -20
  124. package/dist/artifacts/ArtifactPaths.js +129 -8
  125. package/dist/artifacts/ArtifactProvider.js +34 -31
  126. package/dist/artifacts/ArtifactProviderMetadata.js +1 -4
  127. package/dist/artifacts/ArtifactReader.js +23 -0
  128. package/dist/artifacts/ArtifactResourceScope.js +100 -0
  129. package/dist/artifacts/AsarArtifactReader.js +218 -80
  130. package/dist/artifacts/AsarHeader.js +24 -0
  131. package/dist/artifacts/DirectoryArtifactReader.js +168 -65
  132. package/dist/artifacts/MachOSliceArtifactReader.js +116 -39
  133. package/dist/artifacts/NativeDmgArtifactReader.js +179 -87
  134. package/dist/artifacts/NativeDmgOwnership.js +109 -0
  135. package/dist/artifacts/SafeOutputTree.js +245 -70
  136. package/dist/artifacts/SafeOutputTreeCleanup.js +45 -0
  137. package/dist/artifacts/SafeOutputTreeCreationFailure.js +20 -0
  138. package/dist/artifacts/SafeOutputTreeIdentity.js +42 -0
  139. package/dist/artifacts/SafeOutputTreeReadback.js +33 -0
  140. package/dist/artifacts/ZipArtifactReader.js +77 -27
  141. package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +58 -18
  142. package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +62 -24
  143. package/dist/artifacts/apple/KeyedArchiveReader.js +76 -49
  144. package/dist/artifacts/apple/MachoLoadCommandReader.js +36 -6
  145. package/dist/artifacts/extraction/ArtifactExtraction.js +134 -92
  146. package/dist/artifacts/inventory/ArtifactGraphConstruction.js +116 -50
  147. package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
  148. package/dist/artifacts/inventory/classify.js +87 -25
  149. package/dist/artifacts/inventory/hashStableRootArtifact.js +70 -0
  150. package/dist/artifacts/inventory/reader.js +13 -5
  151. package/dist/artifacts/inventory/scanCanonical.js +73 -30
  152. package/dist/artifacts/inventory/scanReader.js +43 -20
  153. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +72 -28
  154. package/dist/artifacts/javascript/JavaScriptSourceAnalysis.js +3 -0
  155. package/dist/browser/BrowserScenarioPartialObservation.js +8 -2
  156. package/dist/browser/BrowserScenarioSecrets.js +52 -37
  157. package/dist/browser/CdpBrowserProvider.js +9 -3
  158. package/dist/browser/CdpCaptureDocuments.js +40 -6
  159. package/dist/browser/CdpCaptureDomSvg.js +210 -0
  160. package/dist/browser/CdpCaptureEventBodyShapes.js +4 -8
  161. package/dist/browser/CdpCaptureEventHandlers.js +26 -9
  162. package/dist/browser/CdpCaptureEvents.js +4 -9
  163. package/dist/browser/CdpCaptureStorageFingerprints.js +3 -3
  164. package/dist/browser/CdpConnection.js +22 -5
  165. package/dist/browser/CdpElectronInspection.js +2 -2
  166. package/dist/browser/CdpElectronProvider.js +4 -3
  167. package/dist/browser/CdpElectronScripts.js +2 -2
  168. package/dist/browser/CdpPageCapture.js +1 -1
  169. package/dist/browser/CdpTargetSession.js +30 -34
  170. package/dist/browser/CdpWebMcpDiscovery.js +48 -23
  171. package/dist/browser/ElectronFileScope.js +99 -9
  172. package/dist/browser/PlaywrightBrowserScenarioProvider.js +63 -7
  173. package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
  174. package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
  175. package/dist/browser/PlaywrightScenarioBrowser.js +208 -43
  176. package/dist/browser/PlaywrightScenarioSession.js +130 -65
  177. package/dist/browser/PlaywrightScenarioStorage.js +507 -0
  178. package/dist/browser/PngVisualDiff.js +198 -29
  179. package/dist/browser/WebSourceMapFetcher.js +35 -9
  180. package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
  181. package/dist/browser/assets/PublishWebScripts.js +75 -20
  182. package/dist/browser/assets/ScenarioScriptCapture.js +8 -12
  183. package/dist/browser/assets/WebArtifactReads.js +23 -1
  184. package/dist/browser/assets/WebSourceLocationArtifacts.js +1 -0
  185. package/dist/browser/execution/CdpExecutionCapture.js +3 -3
  186. package/dist/browser/execution/CdpPreciseCoverage.js +5 -8
  187. package/dist/browser/history/HarCapture.js +14 -0
  188. package/dist/browser/history/HarCaptureProcess.js +2 -10
  189. package/dist/browser/history/MitmproxyCaptureAdapter.js +3 -1
  190. package/dist/browser/modules/WebModuleArtifacts.js +1 -0
  191. package/dist/cli/adbCommands.js +337 -0
  192. package/dist/cli/analysisViewCommands.js +39 -1
  193. package/dist/cli/apktoolCommands.js +53 -0
  194. package/dist/cli/artifactCommands.js +8 -11
  195. package/dist/cli/binaryDiagnosticsCommands.js +19 -1
  196. package/dist/cli/browserAdvancedCommands.js +65 -36
  197. package/dist/cli/coreAnalysisCommands.js +2 -2
  198. package/dist/cli/coreBinaryCommands.js +12 -13
  199. package/dist/cli/coreNativeCommands.js +1 -14
  200. package/dist/cli/electronCommands.js +14 -10
  201. package/dist/cli/evmCommands.js +13 -4
  202. package/dist/cli/firmwareCommands.js +7 -2
  203. package/dist/cli/javascriptApplicationAnalysis.js +19 -13
  204. package/dist/cli/javascriptRecoveryCommands.js +22 -15
  205. package/dist/cli/jebCommands.js +99 -0
  206. package/dist/cli/jsonOutput.js +12 -4
  207. package/dist/cli/referenceSourceImportStatus.js +7 -0
  208. package/dist/cli/setupCommands.js +15 -3
  209. package/dist/cli/streamedJsonOutput.js +83 -4
  210. package/dist/cli/utilityCommands.js +68 -22
  211. package/dist/cli/webScriptCommands.js +20 -1
  212. package/dist/cli/webSourceLocationCommands.js +21 -9
  213. package/dist/cli.js +11 -2
  214. package/dist/cliBrowserScenarioCommands.js +2 -1
  215. package/dist/cliCommandNames.js +32 -0
  216. package/dist/cliJsonInput.js +47 -34
  217. package/dist/cliObservationOptions.js +7 -0
  218. package/dist/composition/adb.js +3 -0
  219. package/dist/composition/apktool.js +3 -0
  220. package/dist/composition/auxiliaryAnalysisProviders.js +5 -4
  221. package/dist/composition/binaryDiagnostics.js +4 -0
  222. package/dist/composition/browserScenario.js +2 -2
  223. package/dist/composition/directAnalysis.js +14 -7
  224. package/dist/composition/javascriptAnalysisWorkerProcess.js +48 -0
  225. package/dist/composition/jeb.js +6 -0
  226. package/dist/config/environment.js +10 -0
  227. package/dist/config/ghidraLanguageOverride.js +9 -0
  228. package/dist/config/mcpInputSchemaProfile.js +27 -0
  229. package/dist/config/parseConfig.js +28 -1
  230. package/dist/contracts/adb/adbToolContracts.js +353 -0
  231. package/dist/contracts/advertisedInputExamples.js +48 -0
  232. package/dist/contracts/analysisDetail.js +10 -0
  233. package/dist/contracts/analysisViewToolContracts.js +17 -2
  234. package/dist/contracts/apktool/apktoolToolContracts.js +33 -0
  235. package/dist/contracts/artifactComparisonExample.js +5 -5
  236. package/dist/contracts/artifactToolContracts.js +8 -5
  237. package/dist/contracts/browserToolContracts.js +1 -1
  238. package/dist/contracts/compactInputSchema.js +256 -0
  239. package/dist/contracts/errorSchemas.js +3 -1
  240. package/dist/contracts/functionComparisonExample.js +8 -0
  241. package/dist/contracts/functionWorkflowToolContracts.js +1 -1
  242. package/dist/contracts/inputSchemaPresentation.js +104 -13
  243. package/dist/contracts/javascript/electronToolContracts.js +16 -3
  244. package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +3 -2
  245. package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +6 -3
  246. package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
  247. package/dist/contracts/javascript/javascriptRuntimeReconciliationExample.js +8 -7
  248. package/dist/contracts/jeb/jebToolContracts.js +64 -0
  249. package/dist/contracts/managed/managedToolContracts.js +3 -2
  250. package/dist/contracts/mobileApplicationGraphExamples.js +5 -5
  251. package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
  252. package/dist/contracts/native/nativeToolContracts.js +1 -1
  253. package/dist/contracts/officialToolContracts.js +5 -5
  254. package/dist/contracts/sessionLifecycleInputs.js +4 -3
  255. package/dist/contracts/sessionStatusContract.js +3 -2
  256. package/dist/contracts/sessionToolContracts.js +5 -4
  257. package/dist/contracts/sessionToolSchemas.js +9 -4
  258. package/dist/contracts/toolContractExamples.js +6 -0
  259. package/dist/contracts/toolContractTypes.js +3 -0
  260. package/dist/contracts/toolContracts.js +6 -0
  261. package/dist/contracts/toolEffects.js +167 -0
  262. package/dist/contracts/toolOutputSchemaGroups.js +7 -5
  263. package/dist/contracts/toolOutputSchemaPrimitives.js +2 -5
  264. package/dist/contracts/toolSchemaMetadata.js +82 -7
  265. package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
  266. package/dist/domain/analysisErrorBase.js +5 -0
  267. package/dist/domain/analysisErrorCleanup.js +29 -0
  268. package/dist/domain/analysisErrorPresentation.js +18 -4
  269. package/dist/domain/analysisErrorProjection.js +4 -1
  270. package/dist/domain/analysisSnapshot.js +5 -2
  271. package/dist/domain/analysisView/analysisView.js +53 -5
  272. package/dist/domain/analysisView/binaryLayoutView.js +2 -0
  273. package/dist/domain/analysisView/javascriptApplicationView.js +2 -0
  274. package/dist/domain/analysisView/nativeFunctionView.js +155 -0
  275. package/dist/domain/android/androidApplication.js +25 -20
  276. package/dist/domain/android/androidPartialObservation.js +36 -0
  277. package/dist/domain/apktool/apktoolResourceAnalysis.js +77 -0
  278. package/dist/domain/apple/appleApplication.js +40 -23
  279. package/dist/domain/apple/appleBundleAnatomy.js +95 -28
  280. package/dist/domain/apple/dyldPaths.js +9 -1
  281. package/dist/domain/apple/dylibResolution.js +3 -3
  282. package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
  283. package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
  284. package/dist/domain/artifactComparison.js +39 -11
  285. package/dist/domain/artifactGraph.js +6 -4
  286. package/dist/domain/artifactIdentity.js +37 -9
  287. package/dist/domain/artifactInspection.js +10 -50
  288. package/dist/domain/artifactIntegrityPolicy.js +10 -0
  289. package/dist/domain/artifactInventoryEvidence.js +16 -17
  290. package/dist/domain/artifactPathSyntax.js +1 -1
  291. package/dist/domain/binaryTarget.js +16 -0
  292. package/dist/domain/binaryTargetTypes.js +8 -1
  293. package/dist/domain/browserCompleteness.js +3 -2
  294. package/dist/domain/browserObservationSchemas.js +8 -4
  295. package/dist/domain/browserScenarioCaptureValues.js +2 -2
  296. package/dist/domain/browserScenarioNormalization.js +3 -3
  297. package/dist/domain/browserScenarioValues.js +3 -2
  298. package/dist/domain/callPath.js +8 -10
  299. package/dist/domain/canonicalDigest.js +7 -1
  300. package/dist/domain/canonicalJsonDigestSteps.js +34 -12
  301. package/dist/domain/canonicalOrdering.js +1 -13
  302. package/dist/domain/changedBehavior.js +2 -3
  303. package/dist/domain/compactStringIdentity.js +9 -0
  304. package/dist/domain/comparisonSemantics.js +0 -5
  305. package/dist/domain/digests.js +0 -3
  306. package/dist/domain/evidence.js +12 -6
  307. package/dist/domain/evidenceBundle.js +51 -33
  308. package/dist/domain/evidenceRecordSummary.js +144 -0
  309. package/dist/domain/firmware/firmwareAnalysis.js +4 -3
  310. package/dist/domain/functionComparison.js +2 -1
  311. package/dist/domain/functionComparisonNormalization.js +4 -3
  312. package/dist/domain/functionComparisonResults.js +2 -2
  313. package/dist/domain/functionDossierEvidence.js +2 -1
  314. package/dist/domain/hopperValues.js +11 -15
  315. package/dist/domain/inputIssueProjection.js +16 -1
  316. package/dist/domain/javascript/electronActiveObservation.js +4 -3
  317. package/dist/domain/javascript/electronStaticAnalysisBrowser.js +14 -15
  318. package/dist/domain/javascript/electronStaticAnalysisIpc.js +20 -21
  319. package/dist/domain/javascript/electronStaticAnalysisNative.js +73 -41
  320. package/dist/domain/javascript/electronStaticAnalysisValues.js +24 -4
  321. package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
  322. package/dist/domain/javascript/javascriptApplicationAnalysis.js +6 -1
  323. package/dist/domain/javascript/javascriptApplicationChangeGraph.js +18 -14
  324. package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +4 -0
  325. package/dist/domain/javascript/javascriptApplicationGraph.js +91 -28
  326. package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
  327. package/dist/domain/javascript/javascriptApplicationVersionComparison.js +4 -4
  328. package/dist/domain/javascript/javascriptApplicationVersionComparisonSchemas.js +37 -22
  329. package/dist/domain/javascript/javascriptApplicationVersionItems.js +72 -45
  330. package/dist/domain/javascript/javascriptApplicationVersionKeys.js +16 -8
  331. package/dist/domain/javascript/javascriptAstFingerprint.js +60 -33
  332. package/dist/domain/javascript/javascriptAstValues.js +54 -0
  333. package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
  334. package/dist/domain/javascript/javascriptExportShapeComparison.js +3 -2
  335. package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +31 -23
  336. package/dist/domain/javascript/javascriptExportShapeSelection.js +2 -2
  337. package/dist/domain/javascript/javascriptExportShapeVariants.js +3 -2
  338. package/dist/domain/javascript/javascriptFeatureSeed.js +5 -3
  339. package/dist/domain/javascript/javascriptFeatureTrace.js +7 -6
  340. package/dist/domain/javascript/javascriptFeatureTraceSchemas.js +17 -9
  341. package/dist/domain/javascript/javascriptFeatureTraversal.js +4 -4
  342. package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
  343. package/dist/domain/javascript/javascriptNativeHandoff.js +12 -7
  344. package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
  345. package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
  346. package/dist/domain/javascript/javascriptRuntimeObservation.js +8 -5
  347. package/dist/domain/javascript/javascriptRuntimeReconciliation.js +12 -6
  348. package/dist/domain/javascript/javascriptRuntimeReconciliationActive.js +9 -8
  349. package/dist/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.js +212 -0
  350. package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +12 -6
  351. package/dist/domain/javascript/javascriptRuntimeReconciliationInputValidation.js +28 -0
  352. package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +5 -5
  353. package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +12 -223
  354. package/dist/domain/javascript/javascriptRuntimeReconciliationResult.js +2 -2
  355. package/dist/domain/javascript/javascriptRuntimeReconciliationRuntime.js +15 -4
  356. package/dist/domain/javascript/javascriptRuntimeReconciliationSchemas.js +2 -2
  357. package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +15 -17
  358. package/dist/domain/javascript/javascriptSemanticAnalysis.js +379 -30
  359. package/dist/domain/javascript/javascriptSemanticCallResolution.js +9 -7
  360. package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
  361. package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
  362. package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -2
  363. package/dist/domain/javascript/javascriptSemanticCoverage.js +20 -0
  364. package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +7 -9
  365. package/dist/domain/javascript/javascriptSemanticDataEffects.js +4 -11
  366. package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
  367. package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
  368. package/dist/domain/javascript/javascriptSemanticFingerprints.js +43 -42
  369. package/dist/domain/javascript/javascriptSemanticGraph.js +205 -52
  370. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +21 -11
  371. package/dist/domain/javascript/javascriptSemanticIr.js +0 -4
  372. package/dist/domain/javascript/javascriptSemanticIterationSources.js +139 -0
  373. package/dist/domain/javascript/javascriptSemanticMemberMutations.js +774 -136
  374. package/dist/domain/javascript/javascriptSemanticMutationInitializers.js +190 -0
  375. package/dist/domain/javascript/javascriptSemanticMutationValues.js +98 -41
  376. package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
  377. package/dist/domain/javascript/javascriptSemanticObjects.js +9 -7
  378. package/dist/domain/javascript/javascriptSemanticPrimitives.js +7 -2
  379. package/dist/domain/javascript/javascriptSemanticProjection.js +72 -28
  380. package/dist/domain/javascript/javascriptSemanticPromises.js +15 -21
  381. package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +100 -0
  382. package/dist/domain/javascript/javascriptSemanticProvenance.js +3 -3
  383. package/dist/domain/javascript/javascriptSemanticQuery.js +33 -29
  384. package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +4 -5
  385. package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -9
  386. package/dist/domain/javascript/javascriptSemanticRequireOrigin.js +16 -10
  387. package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
  388. package/dist/domain/javascript/javascriptSemanticReturns.js +34 -48
  389. package/dist/domain/javascript/javascriptSemanticState.js +22 -2
  390. package/dist/domain/javascript/javascriptSemanticTraversal.js +25 -2
  391. package/dist/domain/javascript/javascriptSemanticValues.js +169 -30
  392. package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
  393. package/dist/domain/javascript/javascriptSourceMapPaths.js +11 -1
  394. package/dist/domain/javascript/javascriptSourceParser.js +34 -9
  395. package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
  396. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +13 -12
  397. package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
  398. package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
  399. package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +26 -15
  400. package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
  401. package/dist/domain/javascript/sourceToBundleComparison.js +7 -5
  402. package/dist/domain/javascript/sourceToBundleSignals.js +7 -7
  403. package/dist/domain/jeb/jebAnalysis.js +114 -0
  404. package/dist/domain/jsonSerialization.js +109 -55
  405. package/dist/domain/jsonShape.js +69 -31
  406. package/dist/domain/jsonValue.js +3 -0
  407. package/dist/domain/localPath.js +10 -4
  408. package/dist/domain/managed/managedApplicationGraph.js +47 -6
  409. package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
  410. package/dist/domain/managed/managedApplicationGraphNodes.js +94 -59
  411. package/dist/domain/managed/managedArtifact.js +1 -0
  412. package/dist/domain/managed/managedInspectionEvidence.js +13 -0
  413. package/dist/domain/managed/managedMemberComparisonMatch.js +6 -7
  414. package/dist/domain/native/nativeAotPe.js +1408 -0
  415. package/dist/domain/native/nativeCallObservation.js +2 -4
  416. package/dist/domain/native/nativeInstruction.js +21 -0
  417. package/dist/domain/native/nativeMetadataRecovery.js +79 -6
  418. package/dist/domain/native/nativeValueFlow.js +5 -11
  419. package/dist/domain/native/objcSwiftMetadata.js +15 -17
  420. package/dist/domain/native/peResources.js +94 -0
  421. package/dist/domain/nativeConvention.js +33 -0
  422. package/dist/domain/process/processCapture.js +102 -11
  423. package/dist/domain/process/processCaptureCoverage.js +8 -5
  424. package/dist/domain/process/processCaptureExample.js +67 -0
  425. package/dist/domain/process/processCaptureValidation.js +83 -3
  426. package/dist/domain/process/processComparison.js +0 -23
  427. package/dist/domain/process/processScenario.js +62 -10
  428. package/dist/domain/process/processTraceEvaluation.js +4 -4
  429. package/dist/domain/process/processTraceSpecification.js +1 -3
  430. package/dist/domain/propertyListKeys.js +3 -1
  431. package/dist/domain/providerCleanupError.js +6 -2
  432. package/dist/domain/reconstructionCoverage.js +2 -1
  433. package/dist/domain/reconstructionUnknowns.js +4 -3
  434. package/dist/domain/reconstructionVerification.js +3 -2
  435. package/dist/domain/referenceSourceGraph.js +32 -23
  436. package/dist/domain/referenceSourceImportParsing.js +40 -48
  437. package/dist/domain/referenceSourcePathIdentity.js +22 -0
  438. package/dist/domain/referenceSourceRequireBindings.js +137 -0
  439. package/dist/domain/residualUnknown.js +3 -2
  440. package/dist/domain/staticRuntimeCorrelation.js +2 -1
  441. package/dist/domain/swiftSymbolClassification.js +6 -1
  442. package/dist/domain/symbolAnalysis.js +17 -2
  443. package/dist/domain/unicodeCodePointOrder.js +6 -0
  444. package/dist/domain/webBundleAnalyzerInspection.js +23 -3
  445. package/dist/domain/webCaptureDiff.js +170 -30
  446. package/dist/domain/webCaptureDiffSchemas.js +2 -8
  447. package/dist/domain/webInventory.js +3 -2
  448. package/dist/domain/webMcpDiscovery.js +4 -3
  449. package/dist/domain/webScriptExport.js +1 -1
  450. package/dist/domain/webScriptExportError.js +10 -4
  451. package/dist/domain/webScriptExportPlan.js +7 -13
  452. package/dist/domain/zipPackageFormat.js +4 -1
  453. package/dist/domain/zodCollectionSteps.js +24 -0
  454. package/dist/dotnet/ManagedArtifactInspector.js +55 -43
  455. package/dist/dotnet/ManagedDecodeBudget.js +80 -0
  456. package/dist/dotnet/ManagedMemberInspector.js +13 -6
  457. package/dist/dotnet/ManagedMemberInspectorCore.js +2 -2
  458. package/dist/dotnet/ManagedMemberInstructionDecoder.js +5 -4
  459. package/dist/dotnet/ManagedMemberRows.js +9 -4
  460. package/dist/dotnet/ManagedMetadataHeaps.js +15 -5
  461. package/dist/dotnet/ManagedMetadataInventoryRows.js +20 -11
  462. package/dist/dotnet/ManagedMetadataLayout.js +10 -4
  463. package/dist/dotnet/ManagedMethodBodyReader.js +8 -3
  464. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +3 -2
  465. package/dist/dotnet/ManagedNativeBoundaryInspector.js +49 -34
  466. package/dist/dotnet/ManagedPeReader.js +41 -25
  467. package/dist/dotnet/ManagedReaderFailure.js +2 -1
  468. package/dist/dotnet/ManagedStaticProvider.js +65 -31
  469. package/dist/dotnet/ManagedStaticProviderMetadata.js +1 -4
  470. package/dist/evaluation/AgentEvaluationReport.js +9 -5
  471. package/dist/evaluation/CodexAgentEval.js +43 -13
  472. package/dist/evm/EvmoleFailures.js +0 -2
  473. package/dist/evm/EvmoleInterfaceProvider.js +67 -2
  474. package/dist/filesystem/OwnedDirectoryHandle.js +29 -0
  475. package/dist/filesystem/OwnedFileHandle.js +36 -0
  476. package/dist/filesystem/RegularFile.js +73 -0
  477. package/dist/filesystem/StableFileHash.js +46 -0
  478. package/dist/filesystem/readFileHandleChunks.js +26 -0
  479. package/dist/firmware/FirmwareCommand.js +25 -3
  480. package/dist/firmware/FirmwareFiles.js +23 -8
  481. package/dist/firmware/FirmwareProvider.js +156 -32
  482. package/dist/firmware/FirmwarePublication.js +24 -3
  483. package/dist/firmware/FirmwareRelease.js +1 -0
  484. package/dist/generatedPackageMetadata.js +2 -2
  485. package/dist/ghidra/GhidraAnalysisProfile.js +55 -4
  486. package/dist/ghidra/GhidraAnalysisSeeds.js +211 -0
  487. package/dist/ghidra/GhidraClient.js +90 -8
  488. package/dist/ghidra/GhidraDiagnostics.js +11 -8
  489. package/dist/ghidra/GhidraFunctionValues.js +26 -2
  490. package/dist/ghidra/GhidraInstallation.js +111 -10
  491. package/dist/ghidra/GhidraInventoryValues.js +23 -1
  492. package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
  493. package/dist/ghidra/GhidraLauncher.js +123 -58
  494. package/dist/ghidra/GhidraLoadImageAttest.js +49 -2
  495. package/dist/ghidra/GhidraMipsProfile.js +79 -0
  496. package/dist/ghidra/GhidraProvider.js +57 -9
  497. package/dist/ghidra/GhidraProviderCapabilities.js +18 -8
  498. package/dist/ghidra/GhidraProviderClient.js +282 -21
  499. package/dist/ghidra/GhidraSessionValues.js +9 -2
  500. package/dist/hopper/HopperAnalysisProfile.js +2 -0
  501. package/dist/hopper/HopperCleanup.js +1 -1
  502. package/dist/hopper/HopperClient.js +15 -6
  503. package/dist/hopper/HopperMachOImage.js +2 -0
  504. package/dist/hopper/HopperProvider.js +13 -2
  505. package/dist/ida/IdaOperationRunner.js +10 -2
  506. package/dist/ida/IdaProvider.js +7 -0
  507. package/dist/ida/IdaSessionClient.js +7 -3
  508. package/dist/ida/IdaWorkspace.js +4 -2
  509. package/dist/inspector/JavaScriptRuntimeScope.js +9 -5
  510. package/dist/inspector/V8InspectorCaptureProjection.js +46 -13
  511. package/dist/inspector/V8InspectorProvider.js +60 -8
  512. package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +326 -0
  513. package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +520 -0
  514. package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +63 -0
  515. package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +521 -0
  516. package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +116 -0
  517. package/dist/javascript/recovery/RecoveryFiles.js +18 -7
  518. package/dist/javascript/recovery/WakaruCommand.js +22 -9
  519. package/dist/javascript/recovery/WakaruExecution.js +11 -7
  520. package/dist/javascript/recovery/WakaruProvider.js +139 -16
  521. package/dist/javascript/recovery/WakaruPublication.js +14 -4
  522. package/dist/javascript/recovery/WakaruRelease.js +10 -3
  523. package/dist/javascript/recovery/WakaruReport.js +12 -7
  524. package/dist/javascript/recovery/WakaruVersion.js +24 -0
  525. package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -3
  526. package/dist/javascript/sourceMaps/SourceMapDecoder.js +63 -7
  527. package/dist/javascript/sourceMaps/SourceMapFormat.js +15 -4
  528. package/dist/jeb/JebMcpConnection.js +179 -0
  529. package/dist/jeb/JebMcpEndpoint.js +40 -0
  530. package/dist/jeb/JebProvider.js +299 -0
  531. package/dist/main/shutdown.js +76 -32
  532. package/dist/main/transport.js +1 -1
  533. package/dist/mcpDoctor.js +15 -6
  534. package/dist/native/AppleDispatchCoverage.js +25 -12
  535. package/dist/native/AppleDispatchMetadata.js +14 -7
  536. package/dist/native/AppleMachoFixups.js +71 -15
  537. package/dist/native/AppleMachoSelection.js +23 -3
  538. package/dist/native/AppleObjcDispatchFacets.js +3 -3
  539. package/dist/native/AppleObjcProperties.js +17 -7
  540. package/dist/native/LldbCallTracer.js +241 -75
  541. package/dist/native/NativeMacOSProvider.js +100 -20
  542. package/dist/native/NativeMacOSProviderMetadata.js +1 -2
  543. package/dist/native/NativeMachoInspection.js +11 -7
  544. package/dist/native/NativeUiHelperRuntime.js +6 -1
  545. package/dist/native/NativeUiObservation.js +4 -3
  546. package/dist/native/pe/PeResourceLayout.js +120 -0
  547. package/dist/native/pe/PeResourceParser.js +286 -0
  548. package/dist/native/pe/PeResourcesProvider.js +63 -0
  549. package/dist/process/BoundedFileBytes.js +30 -7
  550. package/dist/process/DarwinProcessRunTokenReader.js +8 -3
  551. package/dist/process/OwnedCommand.js +4 -3
  552. package/dist/process/ProcessOwnership.js +104 -112
  553. package/dist/process/ProcessOwnershipObservation.js +104 -51
  554. package/dist/process/ProcessOwnershipProcessTree.js +4 -4
  555. package/dist/process/ProcessRunTokenObservations.js +48 -0
  556. package/dist/process/ProviderDiagnosticRedaction.js +17 -0
  557. package/dist/process/ProviderProcess.js +4 -3
  558. package/dist/process/capture/FilesystemSnapshot.js +116 -22
  559. package/dist/process/capture/ProcessCaptureLifecycle.js +363 -86
  560. package/dist/process/capture/ProcessCaptureProgress.js +62 -0
  561. package/dist/process/capture/ProcessFilesystemEffects.js +19 -4
  562. package/dist/process/capture/ProcessHarness.js +202 -47
  563. package/dist/process/capture/ProcessNormalization.js +3 -1
  564. package/dist/process/capture/ProcessScenarioRuntimeValidation.js +5 -2
  565. package/dist/process/capture/TerminalRenderer.js +24 -7
  566. package/dist/reference/ReferenceSourceReader.js +22 -5
  567. package/dist/reference/ReferenceSourceReaderEntries.js +114 -51
  568. package/dist/reference/ReferenceSourceReaderErrors.js +12 -0
  569. package/dist/reference/ReferenceSourceReaderFile.js +50 -10
  570. package/dist/reference/ReferenceSourceReaderValidate.js +4 -4
  571. package/dist/server/EvidenceMcpServer.js +36 -1
  572. package/dist/server/admittedToolOperation.js +9 -0
  573. package/dist/server/analysisAdmission.js +8 -0
  574. package/dist/server/contractToolHandler.js +21 -0
  575. package/dist/server/createServer.js +118 -47
  576. package/dist/server/registerAdbTools.js +36 -0
  577. package/dist/server/registerAnalysisViewTool.js +4 -9
  578. package/dist/server/registerAndroidTools.js +3 -12
  579. package/dist/server/registerApktoolTools.js +14 -0
  580. package/dist/server/registerApplicationTools/compareExportShapes.js +6 -7
  581. package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
  582. package/dist/server/registerApplicationTools/compareVersions.js +3 -2
  583. package/dist/server/registerApplicationTools/coverage.js +3 -2
  584. package/dist/server/registerApplicationTools/helpers.js +3 -2
  585. package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
  586. package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -2
  587. package/dist/server/registerApplicationTools/traceFeature.js +3 -2
  588. package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
  589. package/dist/server/registerArtifactComparisonTool.js +5 -2
  590. package/dist/server/registerArtifactTools.js +2 -2
  591. package/dist/server/registerBinaryDiagnosticsTools.js +16 -4
  592. package/dist/server/registerBrowserScenarioTool.js +10 -7
  593. package/dist/server/registerBrowserTools.js +12 -9
  594. package/dist/server/registerBundleComparisonTool.js +16 -2
  595. package/dist/server/registerCloseLifecycleTool.js +36 -5
  596. package/dist/server/registerElectronTools.js +28 -10
  597. package/dist/server/registerEnhancedTools.js +78 -73
  598. package/dist/server/registerEvidenceTools.js +54 -46
  599. package/dist/server/registerEvmTools.js +4 -9
  600. package/dist/server/registerFirmwareTools.js +3 -11
  601. package/dist/server/registerFunctionComparisonTool.js +5 -2
  602. package/dist/server/registerJavaScriptRecoveryTool.js +4 -9
  603. package/dist/server/registerJavaScriptRuntimeObservationTools.js +9 -6
  604. package/dist/server/registerJebTools.js +16 -0
  605. package/dist/server/registerManagedTools.js +7 -4
  606. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -6
  607. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -2
  608. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +3 -2
  609. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +3 -2
  610. package/dist/server/registerOfficialTools.js +31 -25
  611. package/dist/server/registerPeResourcesTool.js +9 -0
  612. package/dist/server/registerProcessComparisonTool.js +5 -2
  613. package/dist/server/registerRecordedCrashTools.js +4 -9
  614. package/dist/server/registerSessionRecordTools.js +2 -1
  615. package/dist/server/registerSessionTools.js +58 -21
  616. package/dist/server/registerWebModuleTool.js +4 -9
  617. package/dist/server/registerWebNetworkCaptureTool.js +4 -9
  618. package/dist/server/registerWebRuntimeTools.js +6 -5
  619. package/dist/server/registerWebScriptTool.js +6 -3
  620. package/dist/server/registerWebSourceLocationTool.js +4 -9
  621. package/dist/server/toolResult.js +21 -2
  622. package/dist/windows/WindowsPrivateRuntime.js +12 -5
  623. package/install.sh +7 -4
  624. package/licenses/nativeaot-parser-MIT.txt +28 -0
  625. package/native/windows/build/manifest.json +2 -2
  626. package/native/windows/build/rea-windows-x64.node +0 -0
  627. package/package.json +38 -7
  628. package/scripts/rea.mjs +16 -1
  629. package/skills/reverse-engineer-anything/SKILL.md +52 -51
  630. package/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
  631. package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -0
  632. package/skills/reverse-engineer-anything/references/javascript-applications.md +92 -13
  633. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +31 -1
  634. package/dist/artifacts/inventory/policy.js +0 -2
  635. package/dist/domain/managed/managedApplicationGraphNodeCoverage.js +0 -6
  636. package/dist/server/registerNativeTools.js +0 -6
@@ -1,34 +1,96 @@
1
- import { open } from "node:fs/promises";
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
- const classifyContainerExtension = (path) => {
6
- const lower = path.toLowerCase();
7
- const zipPackage = zipPackageFormatForPath(lower);
8
- if (zipPackage !== undefined)
9
- return zipPackage;
10
- for (const format of ["asar", "dmg", "pkg"])
11
- if (lower.endsWith(`.${format}`))
12
- return format;
13
- return undefined;
5
+ import { ArtifactReaderFailure } from "../ArtifactReader.js";
6
+ import {} from "../ArtifactResourceScope.js";
7
+ import { hashStableRootArtifactHandle, openRootArtifact, } from "./hashStableRootArtifact.js";
8
+ /** Classify and hash one file root through the same stable open descriptor. */
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
+ });
14
25
  };
15
- export const classifyRoot = async (path, directory) => {
26
+ /** Classify a root and retain its admitted ZIP descriptor for child inventory. */
27
+ export const classifyAndHashRootForInventory = async (path, directory, expectedMetadata, options) => {
16
28
  if (directory)
17
- return "directory";
18
- const extensionFormat = classifyContainerExtension(path);
19
- if (extensionFormat !== undefined)
20
- return extensionFormat;
21
- const handle = await open(path, "r");
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
- const magic = Buffer.alloc(ARTIFACT_CLASSIFICATION_PREFIX_BYTES);
24
- const observed = await handle.read(magic, 0, magic.length, 0);
25
- const prefix = magic.subarray(0, observed.bytesRead);
26
- if (hasZipSignature(prefix))
27
- return "zip";
28
- return classifyArtifactContent(path, prefix, (await handle.stat()).size)
29
- .format;
39
+ const initial = await handle.stat();
40
+ if (!sameRegularFileState(expectedMetadata, initial))
41
+ throw new ArtifactReaderFailure("integrity", `Root artifact changed before inventory: ${path}`);
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
+ };
55
+ }
56
+ catch (cause) {
57
+ outcome = { kind: "failed", cause };
30
58
  }
31
- finally {
32
- await handle.close();
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));
33
63
  }
64
+ if (outcome.kind === "failed")
65
+ throw outcome.cause;
66
+ return outcome.value;
67
+ };
68
+ const isZipFormat = (format) => format === "zip" ||
69
+ format === "ipa" ||
70
+ format === "apk" ||
71
+ format === "msix" ||
72
+ format === "appx";
73
+ const classifyRootFormat = async (path, handle) => {
74
+ const magic = Buffer.alloc(ARTIFACT_CLASSIFICATION_PREFIX_BYTES);
75
+ const observed = await handle.read(magic, 0, magic.length, 0);
76
+ const prefix = magic.subarray(0, observed.bytesRead);
77
+ const lower = path.toLowerCase();
78
+ if (hasZipSignature(prefix))
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.
86
+ return classifyArtifactContent(path, prefix, (await handle.stat()).size)
87
+ .format;
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";
34
96
  };
@@ -0,0 +1,70 @@
1
+ import { lstat } from "node:fs/promises";
2
+ import { readFileHandleChunks } from "../../filesystem/readFileHandleChunks.js";
3
+ import { OwnedFileHandle } from "../../filesystem/OwnedFileHandle.js";
4
+ import { ArtifactReaderFailure } from "../ArtifactReader.js";
5
+ import { NonRegularFileReadError, RegularFileAdmissionFailure, openRegularFile, sameRegularFileState, } from "../../filesystem/RegularFile.js";
6
+ import { abortIfNeeded, hashReadable, } from "../ArtifactHash.js";
7
+ /** Admit a root descriptor without losing ownership when validation cleanup fails. */
8
+ export const openRootArtifact = async (path, resourceScope, signal) => {
9
+ try {
10
+ return new OwnedFileHandle(await openRegularFile(path, { symlinks: "reject", signal }));
11
+ }
12
+ catch (cause) {
13
+ const primary = cause instanceof RegularFileAdmissionFailure ? cause.cause : cause;
14
+ const failure = primary instanceof NonRegularFileReadError
15
+ ? new ArtifactReaderFailure("format", `Artifact root is not a regular file: ${path}`, { cause: primary })
16
+ : primary;
17
+ if (cause instanceof RegularFileAdmissionFailure) {
18
+ const resource = `root artifact descriptor for ${path}`;
19
+ const cleanup = await resourceScope.release({
20
+ kind: "file-handle",
21
+ resource,
22
+ handle: cause.owner,
23
+ });
24
+ if (cleanup.kind === "failed")
25
+ throw ArtifactReaderFailure.withCleanup(failure, ArtifactReaderFailure.cleanupObservation(cleanup.cause, resource));
26
+ }
27
+ throw failure;
28
+ }
29
+ };
30
+ /** Hash one stable regular root file from the same descriptor that was checked. */
31
+ export const hashStableRootArtifact = async (path, resourceScope, signal) => {
32
+ const owner = await openRootArtifact(path, resourceScope, signal);
33
+ const handle = owner.handle;
34
+ let outcome;
35
+ try {
36
+ const initial = await handle.stat();
37
+ outcome = {
38
+ kind: "completed",
39
+ value: await hashStableRootArtifactHandle(path, handle, initial, signal),
40
+ };
41
+ }
42
+ catch (cause) {
43
+ outcome = { kind: "failed", cause };
44
+ }
45
+ const resource = `root artifact descriptor for ${path}`;
46
+ const cleanup = await resourceScope.release({
47
+ kind: "file-handle",
48
+ resource,
49
+ handle: owner,
50
+ });
51
+ if (cleanup.kind === "failed")
52
+ throw ArtifactReaderFailure.withCleanup(outcome.kind === "failed" ? outcome.cause : cleanup.cause, ArtifactReaderFailure.cleanupObservation(cleanup.cause, resource));
53
+ if (outcome.kind === "failed")
54
+ throw outcome.cause;
55
+ return outcome.value;
56
+ };
57
+ /** Hash and revalidate the same open descriptor used for root classification. */
58
+ export const hashStableRootArtifactHandle = async (path, handle, initial, signal) => {
59
+ const digest = await hashReadable(
60
+ // Read at most the admitted extent plus one byte to detect growth without
61
+ // following an actively appended file indefinitely.
62
+ readFileHandleChunks(handle, { start: 0, end: initial.size }), signal);
63
+ abortIfNeeded(signal);
64
+ const [opened, currentPath] = await Promise.all([handle.stat(), lstat(path)]);
65
+ if (!sameRegularFileState(initial, opened) ||
66
+ !sameRegularFileState(initial, currentPath) ||
67
+ digest.bytes !== initial.size)
68
+ throw new ArtifactReaderFailure("integrity", `Root artifact changed during inventory: ${path}`);
69
+ return digest;
70
+ };
@@ -3,7 +3,8 @@ import { DirectoryArtifactReader } from "../DirectoryArtifactReader.js";
3
3
  import { MachOSliceArtifactReader } from "../MachOSliceArtifactReader.js";
4
4
  import { NativeDmgArtifactReader } from "../NativeDmgArtifactReader.js";
5
5
  import { ZipArtifactReader } from "../ZipArtifactReader.js";
6
- export const createReader = async (path, format, environment, signal) => {
6
+ import { ZIP_NON_ENTRY_TAIL_LIMITATION } from "../../domain/zipPackageFormat.js";
7
+ export const createReader = (path, format, environment, rootSource) => {
7
8
  switch (format) {
8
9
  case "directory":
9
10
  return new DirectoryArtifactReader(path);
@@ -12,24 +13,31 @@ export const createReader = async (path, format, environment, signal) => {
12
13
  case "apk":
13
14
  case "msix":
14
15
  case "appx":
15
- return new ZipArtifactReader(path, format);
16
+ return new ZipArtifactReader(path, format, undefined, rootSource);
16
17
  case "asar":
17
18
  return new AsarArtifactReader(path);
18
19
  case "mach-o-universal":
19
20
  return process.platform === "darwin"
20
- ? new MachOSliceArtifactReader(path, environment)
21
+ ? new MachOSliceArtifactReader(path, environment, undefined, rootSource)
21
22
  : undefined;
22
23
  case "dmg":
23
24
  if (process.platform !== "darwin")
24
25
  return undefined;
25
- return NativeDmgArtifactReader.create(path, environment, signal);
26
+ return new NativeDmgArtifactReader(path, environment);
26
27
  default:
27
28
  return undefined;
28
29
  }
29
30
  };
30
31
  export const inventoryLimitations = (format, reader) => {
31
32
  if (reader !== undefined)
32
- return [];
33
+ return reader.format === "zip" ||
34
+ reader.format === "ipa" ||
35
+ reader.format === "apk" ||
36
+ reader.format === "msix" ||
37
+ reader.format === "appx"
38
+ ? [ZIP_NON_ENTRY_TAIL_LIMITATION]
39
+ : [];
40
+ // dmg and pkg reach here only after classifyRootFormat matched their bytes.
33
41
  if (format === "dmg" || format === "pkg")
34
42
  return [
35
43
  `${format.toUpperCase()} root hash is observed; child inventory requires a native macOS adapter.`,
@@ -1,26 +1,37 @@
1
- import { compareCodePoints } from "../../domain/canonicalOrdering.js";
2
- import { createReadStream } from "node:fs";
1
+ import { compareUnicodeCodePoints } from "../../domain/unicodeCodePointOrder.js";
2
+ import { AsarArtifactReader } from "../AsarArtifactReader.js";
3
3
  import { lstat } from "node:fs/promises";
4
4
  import { ArtifactReaderFailure, } from "../ArtifactReader.js";
5
5
  import { artifactInventoryResultSchema, } from "../../domain/artifactGraph.js";
6
6
  import { createArtifactEdges, createRootNode, indexOccurrencesByPath, materializeDirectoryNodes, rekeyOccurrences, rootOccurrenceFor, } from "./ArtifactGraphConstruction.js";
7
7
  import { artifactContradictionId, artifactGraphDigest, artifactManifestId, } from "../../domain/artifactIdentity.js";
8
- import { classifyRoot } from "./classify.js";
9
- import { hashReadable } from "../ArtifactHash.js";
8
+ import { classifyAndHashRootForInventory } from "./classify.js";
9
+ import {} from "../ArtifactHash.js";
10
+ import { hashStableRootArtifact, hashStableRootArtifactHandle, } from "./hashStableRootArtifact.js";
10
11
  import { createReader, inventoryLimitations } from "./reader.js";
11
12
  import { scanReader, } from "./scanReader.js";
12
13
  import { STRICT_INTEGRITY_POLICY, } from "./types.js";
13
- export const scanCanonicalArtifactInventory = async (path, options = {}, readerFactory = createReader) => {
14
+ export const scanCanonicalArtifactInventory = async (path, options, readerFactory = createReader) => options.resourceScope.run(() => scanCanonicalArtifactInventoryInScope(path, options, readerFactory));
15
+ export const scanCanonicalArtifactInventoryInScope = async (path, options, readerFactory = createReader) => {
14
16
  const integrity = options.integrity ?? STRICT_INTEGRITY_POLICY;
15
17
  const metadata = await lstat(path);
16
- const rootFormat = await classifyRoot(path, metadata.isDirectory());
17
- const rootDigest = metadata.isDirectory()
18
- ? null
19
- : await hashReadable(createReadStream(path), options.signal);
20
- const reader = await readerFactory(path, rootFormat, options.environment ?? {}, options.signal);
18
+ const { format: rootFormat, digest: rootDigest, rootSource, } = await classifyAndHashRootForInventory(path, metadata.isDirectory(), metadata, options);
19
+ let reader;
20
+ let readerCreationFailure;
21
+ try {
22
+ reader = readerFactory(path, rootFormat, options.environment ?? {}, rootSource);
23
+ }
24
+ catch (cause) {
25
+ readerCreationFailure = { cause };
26
+ }
27
+ const ownedReaders = reader === undefined ? [] : [reader];
21
28
  let outcome;
22
29
  try {
23
- const { nodes, occurrences, pendingContradictions } = await scanReader(reader, options.signal, integrity);
30
+ if (readerCreationFailure !== undefined)
31
+ throw readerCreationFailure.cause;
32
+ if (reader instanceof AsarArtifactReader)
33
+ await reader.prepareContainer(rootDigest?.sha256, options.signal);
34
+ const { nodes, occurrences, pendingContradictions, caseCollisionLimitation, } = await scanReader(reader, ownedReaders, options.signal, integrity);
24
35
  outcome = {
25
36
  kind: "completed",
26
37
  snapshot: await buildInventorySnapshot({
@@ -28,33 +39,62 @@ export const scanCanonicalArtifactInventory = async (path, options = {}, readerF
28
39
  metadata,
29
40
  rootFormat,
30
41
  rootDigest,
42
+ rootSource,
43
+ resourceScope: options.resourceScope,
31
44
  reader,
32
45
  signal: options.signal,
33
46
  nodes,
34
47
  occurrences,
35
48
  pendingContradictions,
49
+ caseCollisionLimitation,
36
50
  }),
37
51
  };
38
52
  }
39
53
  catch (cause) {
40
54
  outcome = { kind: "failed", cause };
41
55
  }
42
- try {
43
- await reader?.close();
44
- }
45
- catch (cleanupCause) {
46
- const cleanup = ArtifactReaderFailure.cleanupObservation(cleanupCause, `artifact reader for ${path}`);
47
- const primary = outcome.kind === "failed" ? outcome.cause : cleanupCause;
48
- throw ArtifactReaderFailure.withCleanup(primary, cleanup, outcome.kind === "completed"
49
- ? { kind: "artifact-inventory", inventory: outcome.snapshot }
50
- : undefined);
51
- }
56
+ const cleanupFailure = await cleanupInventoryOwners({
57
+ path,
58
+ options,
59
+ rootSource,
60
+ ownedReaders,
61
+ outcome,
62
+ });
63
+ if (cleanupFailure !== undefined)
64
+ throw cleanupFailure;
52
65
  if (outcome.kind === "failed")
53
66
  throw outcome.cause;
54
67
  return outcome.snapshot;
55
68
  };
69
+ const cleanupInventoryOwners = async ({ path, options, rootSource, ownedReaders, outcome, }) => {
70
+ let cleanupFailure;
71
+ const owners = [...ownedReaders]
72
+ .reverse()
73
+ .map((reader) => ({
74
+ kind: "reader",
75
+ reader,
76
+ resource: `artifact reader for ${path}`,
77
+ }));
78
+ if (rootSource !== undefined)
79
+ owners.push({
80
+ kind: "file-handle",
81
+ handle: rootSource.owner,
82
+ resource: `root artifact descriptor for ${path}`,
83
+ });
84
+ for (const owner of owners) {
85
+ const attempt = await options.resourceScope.release(owner);
86
+ if (attempt.kind === "released")
87
+ continue;
88
+ const primary = cleanupFailure ??
89
+ (outcome.kind === "failed" ? outcome.cause : attempt.cause);
90
+ cleanupFailure = ArtifactReaderFailure.withCleanup(primary, ArtifactReaderFailure.cleanupObservation(attempt.cause, owner.resource), outcome.kind === "completed"
91
+ ? { kind: "artifact-inventory", inventory: outcome.snapshot }
92
+ : undefined);
93
+ }
94
+ return cleanupFailure;
95
+ };
56
96
  const buildInventorySnapshot = async (input) => {
57
- const { path, metadata, rootFormat, rootDigest, reader, signal } = input;
97
+ const { path, metadata, rootFormat, rootDigest, rootSource, reader, signal } = input;
58
98
  materializeDirectoryNodes(input.occurrences, input.nodes);
59
99
  const rootNode = createRootNode({
60
100
  digest: rootDigest,
@@ -85,7 +125,7 @@ const buildInventorySnapshot = async (input) => {
85
125
  ...edge,
86
126
  ordinal,
87
127
  }));
88
- await verifyRootDigest(path, rootDigest, signal);
128
+ await verifyRootDigest(path, rootDigest, rootSource, input.resourceScope, signal);
89
129
  const graphSha256 = artifactGraphDigest({
90
130
  nodes: orderedNodes,
91
131
  occurrences: orderedOccurrences,
@@ -107,7 +147,7 @@ const buildInventorySnapshot = async (input) => {
107
147
  edges: orderedEdges,
108
148
  provenance: reader?.provenance() ?? [],
109
149
  integrity_contradictions: integrityContradictions,
110
- limitations: buildLimitations(rootFormat, reader, integrityContradictions),
150
+ limitations: buildLimitations(rootFormat, reader, integrityContradictions, input.caseCollisionLimitation),
111
151
  };
112
152
  };
113
153
  const buildIntegrityContradictions = (pending, occurrenceByPath, occurrenceById, rootNode) => pending.map((contradiction) => {
@@ -139,17 +179,19 @@ const buildIntegrityContradictions = (pending, occurrenceByPath, occurrenceById,
139
179
  ],
140
180
  };
141
181
  });
142
- const verifyRootDigest = async (path, rootDigest, signal) => {
182
+ const verifyRootDigest = async (path, rootDigest, rootSource, resourceScope, signal) => {
143
183
  if (rootDigest === null)
144
184
  return;
145
- const verified = await hashReadable(createReadStream(path), signal);
185
+ const verified = rootSource === undefined
186
+ ? await hashStableRootArtifact(path, resourceScope, signal)
187
+ : await hashStableRootArtifactHandle(path, rootSource.handle, rootSource.initial, signal);
146
188
  if (verified.sha256 !== rootDigest.sha256 ||
147
189
  verified.bytes !== rootDigest.bytes)
148
190
  throw new ArtifactReaderFailure("integrity", "Root artifact changed during inventory");
149
191
  };
150
- const sortNodes = (nodes) => nodes.sort((left, right) => compareCodePoints(left.artifact_id, right.artifact_id));
151
- const sortOccurrences = (occurrences) => occurrences.sort((left, right) => compareCodePoints(left.logical_path, right.logical_path));
152
- const sortEdges = (edges) => edges.sort((left, right) => compareCodePoints(left.edge_id, right.edge_id));
192
+ const sortNodes = (nodes) => nodes.sort((left, right) => compareUnicodeCodePoints(left.artifact_id, right.artifact_id));
193
+ const sortOccurrences = (occurrences) => occurrences.sort((left, right) => compareUnicodeCodePoints(left.logical_path, right.logical_path));
194
+ const sortEdges = (edges) => edges.sort((left, right) => compareUnicodeCodePoints(left.edge_id, right.edge_id));
153
195
  const buildManifest = ({ rootNode, rootFormat, graphSha256, orderedNodes, orderedOccurrences, orderedEdges, }) => artifactInventoryResultSchema.shape.manifest.parse({
154
196
  manifest_id: artifactManifestId(rootNode.artifact_id, graphSha256),
155
197
  root_artifact_id: rootNode.artifact_id,
@@ -160,8 +202,9 @@ const buildManifest = ({ rootNode, rootFormat, graphSha256, orderedNodes, ordere
160
202
  occurrence_count: orderedOccurrences.length,
161
203
  edge_count: orderedEdges.length,
162
204
  });
163
- const buildLimitations = (rootFormat, reader, integrityContradictions) => [
205
+ const buildLimitations = (rootFormat, reader, integrityContradictions, caseCollisionLimitation) => [
164
206
  ...inventoryLimitations(rootFormat, reader),
207
+ ...(caseCollisionLimitation === undefined ? [] : [caseCollisionLimitation]),
165
208
  ...(integrityContradictions.length === 0
166
209
  ? []
167
210
  : [
@@ -1,16 +1,21 @@
1
1
  import { isAbsolute } from "node:path";
2
- import { ArtifactPathRegistry, normalizeArtifactPath, } from "../ArtifactPaths.js";
2
+ import { annotateEnglishUnicodeCaseCollisions, ArtifactPathRegistry, normalizeArtifactPath, } from "../ArtifactPaths.js";
3
3
  import { ArtifactReaderFailure, } from "../ArtifactReader.js";
4
4
  import { AsarArtifactReader } from "../AsarArtifactReader.js";
5
- import { classifyArtifactContent, classifyArtifactBytes, createArtifactNode, createOccurrence, nearestParent, } from "./ArtifactGraphConstruction.js";
5
+ import { classifyArtifactContent, classifyArtifactBytes, createArtifactNode, createOccurrence, noteUnreadContainerSuffix, resolveOccurrenceParents, } from "./ArtifactGraphConstruction.js";
6
6
  import { STRICT_INTEGRITY_POLICY, } from "./types.js";
7
7
  import { hashReadable } from "../ArtifactHash.js";
8
8
  const UNAVAILABLE_UNPACKED_LIMITATION = "ASAR unpacked companion bytes were unavailable; no content hash or child artifact was produced.";
9
9
  const emptyScan = () => ({ nodes: new Map(), occurrences: [], pendingContradictions: [] });
10
- export const scanReader = async (reader, signal, integrity = STRICT_INTEGRITY_POLICY) => {
10
+ export const scanReader = async (reader, ownedReaders, signal, integrity = STRICT_INTEGRITY_POLICY) => {
11
11
  const { nodes, occurrences, pendingContradictions } = emptyScan();
12
12
  if (reader === undefined)
13
- return { nodes, occurrences, pendingContradictions };
13
+ return {
14
+ nodes,
15
+ occurrences,
16
+ pendingContradictions,
17
+ caseCollisionLimitation: undefined,
18
+ };
14
19
  const context = {
15
20
  reader,
16
21
  signal,
@@ -21,14 +26,18 @@ export const scanReader = async (reader, signal, integrity = STRICT_INTEGRITY_PO
21
26
  occurrenceByPath: new Map(),
22
27
  registry: new ArtifactPathRegistry(),
23
28
  expandedContainerIds: new Set(),
29
+ ownedReaders,
24
30
  };
25
31
  await visitArtifactEntries(context, reader, "");
26
32
  // Archive directories may appear after their children. Resolve containment
27
33
  // against the complete index before directory identities are materialized.
28
- for (const occurrence of occurrences)
29
- occurrence.parent_occurrence_id =
30
- nearestParent(occurrence.logical_path, context.occurrenceByPath, context.expandedContainerIds)?.occurrence_id ?? null;
31
- return { nodes, occurrences, pendingContradictions };
34
+ resolveOccurrenceParents(occurrences, context.occurrenceByPath, context.expandedContainerIds);
35
+ return {
36
+ nodes,
37
+ occurrences,
38
+ pendingContradictions,
39
+ caseCollisionLimitation: annotateEnglishUnicodeCaseCollisions(occurrences),
40
+ };
32
41
  };
33
42
  const visitArtifactEntries = async (context, currentReader, prefix) => {
34
43
  const stack = [
@@ -36,9 +45,9 @@ const visitArtifactEntries = async (context, currentReader, prefix) => {
36
45
  reader: currentReader,
37
46
  prefix,
38
47
  iterator: currentReader.entries(context.signal)[Symbol.asyncIterator](),
39
- owned: false,
40
48
  },
41
49
  ];
50
+ let failure;
42
51
  try {
43
52
  while (stack.length > 0) {
44
53
  const frame = stack.at(-1);
@@ -47,8 +56,6 @@ const visitArtifactEntries = async (context, currentReader, prefix) => {
47
56
  const next = await frame.iterator.next();
48
57
  if (next.done) {
49
58
  stack.pop();
50
- if (frame.owned)
51
- await frame.reader.close();
52
59
  continue;
53
60
  }
54
61
  const entry = next.value;
@@ -68,7 +75,9 @@ const visitArtifactEntries = async (context, currentReader, prefix) => {
68
75
  occurrence.hash_status = "unavailable";
69
76
  occurrence.limitations.push(UNAVAILABLE_UNPACKED_LIMITATION);
70
77
  }
71
- if (digested !== undefined) {
78
+ if (digested === undefined)
79
+ noteUnreadContainerSuffix(occurrence);
80
+ else {
72
81
  context.nodes.set(digested.node.artifact_id, digested.node);
73
82
  occurrence.artifact_id = digested.node.artifact_id;
74
83
  occurrence.artifact_kind = digested.classification.kind;
@@ -81,27 +90,41 @@ const visitArtifactEntries = async (context, currentReader, prefix) => {
81
90
  }
82
91
  context.occurrences.push(occurrence);
83
92
  context.occurrenceByPath.set(logicalPath, occurrence);
84
- if (expandableAsar && digested?.mismatched !== true) {
93
+ if (expandableAsar &&
94
+ digested !== undefined &&
95
+ digested.classification.format === "asar" &&
96
+ !digested.mismatched) {
85
97
  const nested = new AsarArtifactReader(entry.adapterKey);
98
+ context.ownedReaders.push(nested);
99
+ await nested.prepareContainer(digested.node.sha256, context.signal);
86
100
  // Only traversed containers can own members, not opaque ASAR-named files.
87
101
  context.expandedContainerIds.add(occurrence.occurrence_id);
88
102
  stack.push({
89
103
  reader: nested,
90
104
  prefix: logicalPath,
91
105
  iterator: nested.entries(context.signal)[Symbol.asyncIterator](),
92
- owned: true,
93
106
  });
94
107
  }
95
108
  }
96
109
  }
110
+ catch (cause) {
111
+ failure = { cause };
112
+ }
97
113
  finally {
98
- await Promise.allSettled(stack
99
- .filter(({ owned }) => owned)
100
- .map(async ({ reader, iterator }) => {
101
- await iterator.return?.();
102
- await reader.close();
103
- }));
114
+ // Readers remain owned by the inventory until its complete observation is built.
115
+ for (const { iterator, prefix, reader } of stack.reverse()) {
116
+ try {
117
+ await iterator.return?.();
118
+ }
119
+ catch (cause) {
120
+ failure = {
121
+ cause: ArtifactReaderFailure.withCleanup(failure === undefined ? cause : failure.cause, ArtifactReaderFailure.cleanupObservation(cause, `artifact traversal for ${prefix || reader.format}`)),
122
+ };
123
+ }
124
+ }
104
125
  }
126
+ if (failure !== undefined)
127
+ throw failure.cause;
105
128
  };
106
129
  const digestArtifactEntry = async (context, currentReader, entry, logicalPath) => {
107
130
  if ((entry.kind !== "file" && entry.kind !== "slice") || entry.encrypted)