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,15 +1,31 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { constants } from "node:fs";
3
- import { lstat, mkdir, open, realpath, rm, } from "node:fs/promises";
3
+ import { mkdir, open, readdir, realpath, } from "node:fs/promises";
4
4
  import { basename, dirname, isAbsolute, join, resolve } from "node:path";
5
+ import { OwnedFileHandle } from "../filesystem/OwnedFileHandle.js";
5
6
  import { streamChunkToBuffer } from "./StreamBytes.js";
6
- import { ArtifactPathRegistry, normalizeArtifactPath, } from "./ArtifactPaths.js";
7
+ import { ArtifactPathRegistry, destinationCaseCollisionMessage, normalizeArtifactPath, } from "./ArtifactPaths.js";
7
8
  import { ArtifactReaderFailure } from "./ArtifactReader.js";
8
- /** Symlink-resistant materialization in an exclusively owned, initially absent tree. */
9
+ import { SafeOutputTreeCreationFailure } from "./SafeOutputTreeCreationFailure.js";
10
+ import { hashOutputFile } from "./SafeOutputTreeReadback.js";
11
+ import { removeOwnedTree } from "./SafeOutputTreeCleanup.js";
12
+ import { assertHandleIdentity, assertFilePathIdentity, assertPathIdentity, isAbsent, readDirectoryIdentity, readFileIdentity, replacedDirectory, } from "./SafeOutputTreeIdentity.js";
13
+ /**
14
+ * Materialize files in a tree created by this operation.
15
+ *
16
+ * Path identities are revalidated around operations, but Node has no portable
17
+ * descriptor-relative traversal; a syscall-boundary pathname race remains.
18
+ */
9
19
  export class SafeOutputTree {
10
20
  platform;
11
21
  #registry = new ArtifactPathRegistry();
12
22
  #outputRoot;
23
+ #rootIdentity;
24
+ #nestedDirectories = new Map();
25
+ #unknownDirectories = new Set();
26
+ #ownedFiles = new Map();
27
+ #openFiles = new Map();
28
+ #openHandles = new Set();
13
29
  #published = false;
14
30
  #cleanup = {
15
31
  status: "not-required",
@@ -41,102 +57,180 @@ export class SafeOutputTree {
41
57
  throw new ArtifactReaderFailure("path", "Extraction output root already exists", { cause });
42
58
  throw cause;
43
59
  });
60
+ const tree = new SafeOutputTree(canonicalOutput, platform);
44
61
  try {
62
+ const rootIdentity = await readDirectoryIdentity(canonicalOutput);
63
+ tree.#rootIdentity = rootIdentity;
45
64
  if (platform !== "win32") {
46
- const stagingHandle = await open(canonicalOutput, constants.O_RDONLY | constants.O_DIRECTORY);
65
+ const stagingHandle = tree.#trackHandle(await open(canonicalOutput, constants.O_RDONLY | constants.O_DIRECTORY));
66
+ let setup = { kind: "ready" };
47
67
  try {
48
- await stagingHandle.chmod(0o700);
68
+ await assertHandleIdentity(stagingHandle.handle, rootIdentity, canonicalOutput);
69
+ await stagingHandle.handle.chmod(0o700);
49
70
  }
50
- finally {
51
- await stagingHandle.close();
71
+ catch (cause) {
72
+ setup = { kind: "failed", cause };
52
73
  }
74
+ try {
75
+ await tree.#closeHandle(stagingHandle);
76
+ }
77
+ catch (closeCause) {
78
+ if (setup.kind === "failed")
79
+ throw ArtifactReaderFailure.withCleanup(setup.cause, ArtifactReaderFailure.cleanupObservation(closeCause, canonicalOutput));
80
+ throw closeCause;
81
+ }
82
+ if (setup.kind === "failed")
83
+ throw setup.cause;
53
84
  }
54
- return new SafeOutputTree(canonicalOutput, platform);
85
+ await assertPathIdentity(canonicalOutput, rootIdentity);
86
+ return tree;
55
87
  }
56
88
  catch (cause) {
57
- await rm(canonicalOutput, { recursive: true, force: true });
58
- throw cause;
89
+ throw new SafeOutputTreeCreationFailure(cause, tree);
59
90
  }
60
91
  }
61
92
  get outputRoot() {
62
93
  return this.#outputRoot;
63
94
  }
95
+ /** The output was durably committed, even if descriptor cleanup later failed. */
96
+ get published() {
97
+ return this.#published;
98
+ }
64
99
  get cleanup() {
65
100
  return structuredClone(this.#cleanup);
66
101
  }
67
102
  /** Stream one regular file with exact byte and digest verification. */
68
- async write(relativePath, source, expectedSha256, signal) {
69
- this.#assertWritable();
70
- const path = normalizeArtifactPath(relativePath);
71
- this.#registry.add(path, "file");
72
- const destination = await this.#prepareParent(path);
73
- const handle = await open(destination, constants.O_CREAT |
74
- constants.O_EXCL |
75
- constants.O_WRONLY |
76
- constants.O_NOFOLLOW, 0o600).catch((cause) => {
77
- throw new ArtifactReaderFailure("path", `Could not exclusively create extraction path: ${path}`, { cause });
78
- });
79
- const hash = createHash("sha256");
80
- let bytes = 0;
103
+ async write(relativePath, source, expected, signal) {
81
104
  try {
105
+ this.#assertWritable();
106
+ if (!Number.isSafeInteger(expected.bytes) || expected.bytes < 0)
107
+ throw new ArtifactReaderFailure("format", `Invalid expected extraction size for ${relativePath}`);
108
+ const path = normalizeDestinationPath(relativePath, this.platform);
109
+ this.#registry.add(path, "file");
110
+ const lineage = await this.#prepareParent(path);
111
+ const parent = lineage.at(-1);
112
+ if (parent === undefined)
113
+ throw replacedDirectory(this.#outputRoot);
114
+ const fileName = path.slice(path.lastIndexOf("/") + 1);
115
+ const destination = join(parent.path, fileName);
116
+ const handle = await open(destination, constants.O_CREAT |
117
+ constants.O_EXCL |
118
+ constants.O_WRONLY |
119
+ constants.O_NOFOLLOW, 0o600).catch(async (cause) => {
120
+ await throwIfDestinationCaseCollision(parent.path, path, cause);
121
+ throw new ArtifactReaderFailure("path", `Could not exclusively create extraction path: ${path}`, { cause });
122
+ });
123
+ const ownedHandle = this.#trackHandle(handle);
124
+ this.#openFiles.set(destination, ownedHandle);
125
+ const fileIdentity = await readFileIdentity(ownedHandle.handle, destination);
126
+ await assertFilePathIdentity(destination, fileIdentity);
127
+ this.#ownedFiles.set(destination, fileIdentity);
128
+ const hash = createHash("sha256");
129
+ let bytes = 0;
130
+ await this.#assertLineage(lineage);
82
131
  for await (const raw of source) {
83
132
  abortIfNeeded(signal);
84
133
  const chunk = streamChunkToBuffer(raw);
134
+ if (chunk.length > expected.bytes - bytes)
135
+ throw new ArtifactReaderFailure("integrity", `Extracted content exceeds the inventoried size: ${path}`);
85
136
  bytes += chunk.length;
86
137
  hash.update(chunk);
87
- await writeAll(handle, chunk);
138
+ await writeAll(ownedHandle.handle, chunk);
88
139
  }
140
+ if (bytes !== expected.bytes)
141
+ throw new ArtifactReaderFailure("integrity", `Extracted content size disagrees with inventory: ${path}`);
89
142
  const sha256 = hash.digest("hex");
90
- if (sha256 !== expectedSha256)
143
+ if (sha256 !== expected.sha256)
91
144
  throw new ArtifactReaderFailure("integrity", `Extracted content disagrees with inventory: ${path}`);
92
- await handle.sync();
93
- await handle.close();
94
- const readback = await hashFile(destination, bytes, signal);
145
+ await this.#assertLineage(lineage);
146
+ await assertFilePathIdentity(destination, fileIdentity);
147
+ await ownedHandle.handle.sync();
148
+ await this.#closeFileHandle(destination, ownedHandle);
149
+ const readbackHandle = this.#trackHandle(await open(destination, constants.O_RDONLY | constants.O_NOFOLLOW));
150
+ const readback = await hashOutputFile(readbackHandle, destination, fileIdentity, { maximum: bytes, signal });
151
+ await this.#closeHandle(readbackHandle);
152
+ await this.#assertLineage(lineage);
153
+ await assertFilePathIdentity(destination, fileIdentity);
95
154
  if (readback.sha256 !== sha256 || readback.bytes !== bytes)
96
155
  throw new ArtifactReaderFailure("integrity", `Durable readback verification failed: ${path}`);
97
156
  return { relativePath: path, sha256, bytesWritten: bytes };
98
157
  }
99
158
  catch (cause) {
100
- // best-effort cleanup: file-handle close must not mask the write failure.
101
- await handle.close().catch(() => undefined);
159
+ try {
160
+ source.destroy();
161
+ }
162
+ catch {
163
+ // Preserve the write refusal or failure as the caller-visible error.
164
+ }
102
165
  throw cause;
103
166
  }
104
167
  }
105
168
  /** Sync the owned output tree and prevent further writes through this instance. */
106
169
  async commit() {
107
170
  this.#assertWritable();
171
+ await this.#assertOwnedDirectories();
108
172
  // Windows has no directory fsync; file contents are already synced in write().
109
173
  if (this.platform === "win32") {
110
174
  this.#published = true;
111
175
  return;
112
176
  }
113
- const parent = await open(dirname(this.#outputRoot), constants.O_RDONLY | constants.O_DIRECTORY);
177
+ const parent = this.#trackHandle(await open(dirname(this.#outputRoot), constants.O_RDONLY | constants.O_DIRECTORY));
114
178
  let output;
179
+ let sync = { kind: "synced" };
115
180
  try {
116
- output = await open(this.#outputRoot, constants.O_RDONLY | constants.O_DIRECTORY);
117
- await output.sync();
118
- await parent.sync();
181
+ output = this.#trackHandle(await open(this.#outputRoot, constants.O_RDONLY | constants.O_DIRECTORY));
182
+ await assertHandleIdentity(output.handle, this.#requireRootIdentity(), this.#outputRoot);
183
+ await output.handle.sync();
184
+ await parent.handle.sync();
119
185
  this.#published = true;
120
186
  }
121
187
  catch (cause) {
122
- throw new ArtifactReaderFailure("path", "Could not durably sync extraction output", { cause });
188
+ sync = { kind: "failed", cause };
123
189
  }
124
- finally {
125
- await Promise.allSettled([parent.close(), output?.close()]);
190
+ const closeResults = await Promise.allSettled([parent, output]
191
+ .filter(isDefined)
192
+ .map((handle) => this.#closeHandle(handle)));
193
+ const closeFailures = closeResults
194
+ .filter(isRejected)
195
+ .map(({ reason }) => reason);
196
+ if (closeFailures.length > 0) {
197
+ const closeFailure = new AggregateError(closeFailures, "Extraction output directory handles could not be closed");
198
+ const cleanup = ArtifactReaderFailure.cleanupObservation(closeFailure, this.#outputRoot);
199
+ if (sync.kind === "failed")
200
+ throw ArtifactReaderFailure.withCleanup(new ArtifactReaderFailure("path", "Could not durably sync extraction output", { cause: sync.cause }), cleanup);
201
+ throw ArtifactReaderFailure.withCleanup(closeFailure, cleanup);
126
202
  }
203
+ if (sync.kind === "failed")
204
+ throw new ArtifactReaderFailure("path", "Could not durably sync extraction output", { cause: sync.cause });
127
205
  }
128
206
  /** Remove only this operation's unsealed tree and verify absence. */
129
207
  async rollback() {
130
- if (this.#published)
208
+ if (this.#published) {
209
+ await this.#closePendingHandles();
210
+ return structuredClone(this.#cleanup);
211
+ }
212
+ if (this.#cleanup.status === "complete")
131
213
  return structuredClone(this.#cleanup);
214
+ this.#cleanup = {
215
+ status: "incomplete",
216
+ residualPaths: [basename(this.#outputRoot)],
217
+ };
132
218
  let removalFailure;
133
219
  try {
134
- await rm(this.#outputRoot, { recursive: true, force: true });
220
+ await this.#admitPendingFiles();
221
+ await this.#closePendingHandles();
222
+ await this.#assertOwnedDirectories();
223
+ await removeOwnedTree({
224
+ outputRoot: this.#outputRoot,
225
+ rootIdentity: this.#requireRootIdentity(),
226
+ directories: this.#nestedDirectories,
227
+ files: this.#ownedFiles,
228
+ });
135
229
  }
136
230
  catch (cause) {
137
231
  removalFailure = cause;
138
232
  }
139
- const absent = await isAbsent(this.#outputRoot);
233
+ const absent = removalFailure === undefined && (await isAbsent(this.#outputRoot));
140
234
  this.#cleanup = absent
141
235
  ? { status: "complete", residualPaths: [] }
142
236
  : {
@@ -157,46 +251,117 @@ export class SafeOutputTree {
157
251
  }
158
252
  async #prepareParent(relativePath) {
159
253
  const parts = relativePath.split("/");
160
- const fileName = parts.pop();
161
- if (fileName === undefined)
254
+ if (parts.pop() === undefined)
162
255
  throw new ArtifactReaderFailure("path", "Invalid extraction path");
163
256
  let current = this.#outputRoot;
257
+ let logicalParent = "";
258
+ const lineage = [
259
+ { path: this.#outputRoot, identity: this.#requireRootIdentity() },
260
+ ];
261
+ if (parts.length === 0)
262
+ await assertPathIdentity(this.#outputRoot, this.#requireRootIdentity());
164
263
  for (const part of parts) {
264
+ const parent = lineage.at(-1);
265
+ if (parent === undefined)
266
+ throw replacedDirectory(this.#outputRoot);
267
+ const logicalPath = logicalParent.length === 0 ? part : `${logicalParent}/${part}`;
165
268
  current = join(current, part);
269
+ await assertPathIdentity(parent.path, parent.identity);
270
+ let created = true;
166
271
  await mkdir(current, { mode: 0o700 }).catch((cause) => {
167
272
  if (!isAlreadyExists(cause))
168
273
  throw cause;
274
+ created = false;
169
275
  });
170
- const metadata = await lstat(current);
171
- if (!metadata.isDirectory() || metadata.isSymbolicLink())
172
- throw new ArtifactReaderFailure("path", `Unsafe extraction parent: ${relativePath}`);
276
+ if (!created) {
277
+ await throwIfDestinationCaseCollision(parent.path, logicalPath);
278
+ const identity = this.#nestedDirectories.get(current);
279
+ if (identity === undefined)
280
+ throw replacedDirectory(current);
281
+ await assertPathIdentity(current, identity);
282
+ }
283
+ else {
284
+ try {
285
+ const identity = await readDirectoryIdentity(current);
286
+ this.#nestedDirectories.set(current, identity);
287
+ }
288
+ catch (cause) {
289
+ this.#unknownDirectories.add(current);
290
+ throw cause;
291
+ }
292
+ }
293
+ await assertPathIdentity(parent.path, parent.identity);
294
+ const identity = this.#nestedDirectories.get(current);
295
+ if (identity === undefined)
296
+ throw replacedDirectory(current);
297
+ await assertPathIdentity(current, identity);
298
+ lineage.push({ path: current, identity });
299
+ logicalParent = logicalPath;
173
300
  }
174
- return join(current, fileName);
301
+ return lineage;
302
+ }
303
+ async #assertLineage(lineage) {
304
+ for (const { path, identity } of lineage)
305
+ await assertPathIdentity(path, identity);
306
+ }
307
+ async #assertOwnedDirectories() {
308
+ const rootIdentity = this.#requireRootIdentity();
309
+ await assertPathIdentity(this.#outputRoot, rootIdentity);
310
+ for (const [path, identity] of this.#nestedDirectories)
311
+ await assertPathIdentity(path, identity);
312
+ if (this.#unknownDirectories.size > 0)
313
+ throw new ArtifactReaderFailure("path", `Extraction directory ownership is unknown: ${[...this.#unknownDirectories].join(", ")}`);
314
+ }
315
+ #requireRootIdentity() {
316
+ if (this.#rootIdentity === undefined)
317
+ throw new ArtifactReaderFailure("path", `Extraction output root identity is unknown: ${this.#outputRoot}`);
318
+ return this.#rootIdentity;
175
319
  }
176
320
  #assertWritable() {
177
321
  if (this.#published)
178
322
  throw new ArtifactReaderFailure("integrity", "Extraction tree is already committed");
323
+ if (this.#cleanup.status !== "not-required")
324
+ throw new ArtifactReaderFailure("integrity", "Extraction tree cleanup has already started");
179
325
  }
180
- }
181
- const hashFile = async (path, maximum, signal) => {
182
- const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
183
- const hash = createHash("sha256");
184
- let bytes = 0;
185
- try {
186
- for await (const raw of handle.createReadStream({ autoClose: false })) {
187
- abortIfNeeded(signal);
188
- const chunk = streamChunkToBuffer(raw);
189
- bytes += chunk.length;
190
- if (bytes > maximum)
191
- throw new ArtifactReaderFailure("integrity", "Readback exceeded the bytes written");
192
- hash.update(chunk);
326
+ #trackHandle(handle) {
327
+ const owner = new OwnedFileHandle(handle);
328
+ this.#openHandles.add(owner);
329
+ return owner;
330
+ }
331
+ async #closeHandle(owner) {
332
+ await owner.close();
333
+ this.#openHandles.delete(owner);
334
+ }
335
+ async #closePendingHandles() {
336
+ const failures = [];
337
+ for (const owner of this.#openHandles) {
338
+ try {
339
+ await this.#closeHandle(owner);
340
+ }
341
+ catch (cause) {
342
+ failures.push(cause);
343
+ }
193
344
  }
345
+ if (failures.length > 0)
346
+ throw new AggregateError(failures, "Output tree handles remain open");
194
347
  }
195
- finally {
196
- await handle.close();
348
+ async #closeFileHandle(path, owner) {
349
+ await this.#closeHandle(owner);
350
+ this.#openFiles.delete(path);
197
351
  }
198
- return { sha256: hash.digest("hex"), bytes };
199
- };
352
+ async #admitPendingFiles() {
353
+ for (const [path, owner] of this.#openFiles) {
354
+ let identity = this.#ownedFiles.get(path);
355
+ if (identity === undefined) {
356
+ identity = await readFileIdentity(owner.handle, path);
357
+ await assertFilePathIdentity(path, identity);
358
+ this.#ownedFiles.set(path, identity);
359
+ }
360
+ }
361
+ }
362
+ }
363
+ const isDefined = (value) => value !== undefined;
364
+ const isRejected = (result) => result.status === "rejected";
200
365
  const writeAll = async (handle, chunk) => {
201
366
  let offset = 0;
202
367
  while (offset < chunk.length) {
@@ -206,14 +371,24 @@ const writeAll = async (handle, chunk) => {
206
371
  offset += bytesWritten;
207
372
  }
208
373
  };
209
- const isAbsent = async (path) => lstat(path).then(() => false, (cause) => {
210
- if (isNotFound(cause))
211
- return true;
212
- throw cause;
213
- });
214
- const isNotFound = (cause) => cause instanceof Error && "code" in cause && cause.code === "ENOENT";
215
- const isAlreadyExists = (cause) => cause instanceof Error && "code" in cause && cause.code === "EEXIST";
374
+ const normalizeDestinationPath = (relativePath, platform) => {
375
+ const path = normalizeArtifactPath(relativePath);
376
+ if (platform === "win32" && path.includes(":"))
377
+ throw new ArtifactReaderFailure("path", `Windows destination cannot materialize artifact path as a regular file: ${path}; ':' denotes alternate data stream syntax.`);
378
+ return path;
379
+ };
216
380
  const abortIfNeeded = (signal) => {
217
381
  if (signal?.aborted === true)
218
382
  throw new ArtifactReaderFailure("cancelled", "Artifact extraction cancelled");
219
383
  };
384
+ const isAlreadyExists = (cause) => cause instanceof Error && "code" in cause && cause.code === "EEXIST";
385
+ /** Fail when this directory already holds another spelling of the requested segment. */
386
+ const throwIfDestinationCaseCollision = async (parentDirectory, logicalPath, cause) => {
387
+ const names = await readdir(parentDirectory).catch(() => undefined);
388
+ if (names === undefined)
389
+ return;
390
+ const message = destinationCaseCollisionMessage(logicalPath, names);
391
+ if (message === undefined)
392
+ return;
393
+ throw new ArtifactReaderFailure("path", message, cause === undefined ? undefined : { cause });
394
+ };
@@ -0,0 +1,45 @@
1
+ import { readdir, rmdir, unlink } from "node:fs/promises";
2
+ import { dirname, sep } from "node:path";
3
+ import { ArtifactReaderFailure } from "./ArtifactReader.js";
4
+ import { assertFilePathIdentity, assertPathIdentity, replacedDirectory, } from "./SafeOutputTreeIdentity.js";
5
+ /** Remove only tracked files and empty directories, preserving successful progress. */
6
+ export const removeOwnedTree = async (input) => {
7
+ const { outputRoot, rootIdentity, directories, files } = input;
8
+ const filesByDirectory = new Map();
9
+ for (const entry of files) {
10
+ const directory = dirname(entry[0]);
11
+ const group = filesByDirectory.get(directory) ?? [];
12
+ group.push(entry);
13
+ filesByDirectory.set(directory, group);
14
+ }
15
+ const postorder = [...directories].sort(([left], [right]) => right.slice(outputRoot.length).split(sep).length -
16
+ left.slice(outputRoot.length).split(sep).length);
17
+ for (const [path, identity] of postorder) {
18
+ await removeFiles(path, identity, filesByDirectory.get(path) ?? [], files);
19
+ const parentPath = dirname(path);
20
+ const parentIdentity = parentPath === outputRoot ? rootIdentity : directories.get(parentPath);
21
+ if (parentIdentity === undefined)
22
+ throw replacedDirectory(parentPath);
23
+ await assertPathIdentity(parentPath, parentIdentity);
24
+ await assertPathIdentity(path, identity);
25
+ await requireEmpty(path);
26
+ await rmdir(path);
27
+ directories.delete(path);
28
+ }
29
+ await removeFiles(outputRoot, rootIdentity, filesByDirectory.get(outputRoot) ?? [], files);
30
+ await assertPathIdentity(outputRoot, rootIdentity);
31
+ await requireEmpty(outputRoot);
32
+ await rmdir(outputRoot);
33
+ };
34
+ const removeFiles = async (directory, identity, filesInDirectory, retainedFiles) => {
35
+ for (const [path, fileIdentity] of filesInDirectory) {
36
+ await assertPathIdentity(directory, identity);
37
+ await assertFilePathIdentity(path, fileIdentity);
38
+ await unlink(path);
39
+ retainedFiles.delete(path);
40
+ }
41
+ };
42
+ const requireEmpty = async (directory) => {
43
+ if ((await readdir(directory)).length > 0)
44
+ throw new ArtifactReaderFailure("path", `Unowned entries remain in extraction directory: ${directory}`);
45
+ };
@@ -0,0 +1,20 @@
1
+ import { ArtifactReaderFailure } from "./ArtifactReader.js";
2
+ /** Setup failed after this tree was acquired; callers still own this exact tree. */
3
+ export class SafeOutputTreeCreationFailure extends ArtifactReaderFailure {
4
+ tree;
5
+ constructor(cause, tree) {
6
+ const primary = cause instanceof ArtifactReaderFailure
7
+ ? cause
8
+ : new ArtifactReaderFailure("io", errorMessage(cause), { cause });
9
+ super(primary.reason, primary.message, {
10
+ cause: primary,
11
+ ...(primary.cleanup === undefined ? {} : { cleanup: primary.cleanup }),
12
+ ...(primary.partialObservation === undefined
13
+ ? {}
14
+ : { partialObservation: primary.partialObservation }),
15
+ }, primary.details);
16
+ this.name = "SafeOutputTreeCreationFailure";
17
+ this.tree = tree;
18
+ }
19
+ }
20
+ const errorMessage = (cause) => cause instanceof Error ? cause.message : String(cause);
@@ -0,0 +1,42 @@
1
+ import { lstat } from "node:fs/promises";
2
+ import { ArtifactReaderFailure } from "./ArtifactReader.js";
3
+ export const readDirectoryIdentity = async (path) => {
4
+ const metadata = await lstat(path, { bigint: true });
5
+ if (!metadata.isDirectory())
6
+ throw replacedDirectory(path);
7
+ return { dev: metadata.dev, ino: metadata.ino };
8
+ };
9
+ export const assertPathIdentity = async (path, expected) => {
10
+ const metadata = await lstat(path, { bigint: true });
11
+ if (!metadata.isDirectory() ||
12
+ metadata.dev !== expected.dev ||
13
+ metadata.ino !== expected.ino)
14
+ throw replacedDirectory(path);
15
+ };
16
+ export const assertHandleIdentity = async (handle, expected, path) => {
17
+ const metadata = await handle.stat({ bigint: true });
18
+ if (!metadata.isDirectory() ||
19
+ metadata.dev !== expected.dev ||
20
+ metadata.ino !== expected.ino)
21
+ throw replacedDirectory(path);
22
+ };
23
+ export const readFileIdentity = async (handle, path) => {
24
+ const metadata = await handle.stat({ bigint: true });
25
+ if (!metadata.isFile())
26
+ throw new ArtifactReaderFailure("path", `Extraction file identity changed: ${path}`);
27
+ return { dev: metadata.dev, ino: metadata.ino };
28
+ };
29
+ export const assertFilePathIdentity = async (path, expected) => {
30
+ const metadata = await lstat(path, { bigint: true });
31
+ if (!metadata.isFile() ||
32
+ metadata.dev !== expected.dev ||
33
+ metadata.ino !== expected.ino)
34
+ throw new ArtifactReaderFailure("path", `Extraction file identity changed: ${path}`);
35
+ };
36
+ export const isAbsent = async (path) => lstat(path).then(() => false, (cause) => {
37
+ if (isNotFound(cause))
38
+ return true;
39
+ throw cause;
40
+ });
41
+ export const replacedDirectory = (path) => new ArtifactReaderFailure("path", `Extraction directory identity changed: ${path}`);
42
+ const isNotFound = (cause) => cause instanceof Error && "code" in cause && cause.code === "ENOENT";
@@ -0,0 +1,33 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFileHandleChunks } from "../filesystem/readFileHandleChunks.js";
3
+ import { streamChunkToBuffer } from "./StreamBytes.js";
4
+ import { ArtifactReaderFailure } from "./ArtifactReader.js";
5
+ import { assertFilePathIdentity, readFileIdentity, } from "./SafeOutputTreeIdentity.js";
6
+ /** Hash one retained readback descriptor and confirm it still names the output file. */
7
+ export const hashOutputFile = async (owner, path, identity, options) => {
8
+ const admittedIdentity = await readFileIdentity(owner.handle, path);
9
+ await assertFilePathIdentity(path, identity);
10
+ if (admittedIdentity.dev !== identity.dev ||
11
+ admittedIdentity.ino !== identity.ino)
12
+ throw new ArtifactReaderFailure("path", `Extraction file identity changed: ${path}`);
13
+ const hash = createHash("sha256");
14
+ let bytes = 0;
15
+ try {
16
+ for await (const raw of readFileHandleChunks(owner.handle, options)) {
17
+ if (options.signal?.aborted === true)
18
+ throw new ArtifactReaderFailure("cancelled", "Artifact extraction cancelled");
19
+ const chunk = streamChunkToBuffer(raw);
20
+ bytes += chunk.length;
21
+ if (bytes > options.maximum)
22
+ throw new ArtifactReaderFailure("integrity", "Readback exceeded the bytes written");
23
+ hash.update(chunk);
24
+ }
25
+ }
26
+ catch (cause) {
27
+ if (options.signal?.aborted === true)
28
+ throw new ArtifactReaderFailure("cancelled", "Artifact extraction cancelled", { cause });
29
+ throw cause;
30
+ }
31
+ await assertFilePathIdentity(path, identity);
32
+ return { sha256: hash.digest("hex"), bytes };
33
+ };