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,9 +1,17 @@
1
- import { inflateSync } from "node:zlib";
1
+ import { constants as zlibConstants, crc32, inflateSync } from "node:zlib";
2
+ import { AnalysisResourceConstraintError, AnalysisUnsupportedTargetError, } from "../domain/analysisErrorCore.js";
2
3
  import { decodeCanonicalBase64 } from "../domain/webScreenshot.js";
4
+ /** Conservative allowance for the simultaneously live PNG comparison buffers. */
5
+ const PNG_COMPARISON_WORKING_MEMORY_BYTES = 256 * 1024 * 1024;
6
+ const PNG_INFLATE_CHUNK_BYTES = zlibConstants.Z_DEFAULT_CHUNK;
3
7
  /** Compare two validated screenshots using deterministic RGBA metrics. */
4
8
  export const comparePngScreenshots = (input) => {
5
- const before = decodePng(input.before);
6
- const after = decodePng(input.after);
9
+ admitEncodedInputPair(input.before, input.after);
10
+ const beforePlan = parsePng(input.before, "before");
11
+ const afterPlan = parsePng(input.after, "after");
12
+ admitPngPair(beforePlan, afterPlan);
13
+ const before = decodePng(beforePlan);
14
+ const after = decodePng(afterPlan);
7
15
  if (before.width !== after.width || before.height !== after.height)
8
16
  return {
9
17
  status: "dimension_mismatch",
@@ -57,7 +65,7 @@ export const comparePngScreenshots = (input) => {
57
65
  changed_ratio: changedPixels / pixels,
58
66
  };
59
67
  };
60
- const decodePng = (artifact) => {
68
+ const parsePng = (artifact, field) => {
61
69
  const bytes = decodeCanonicalBase64(artifact.data_base64);
62
70
  if (bytes === undefined || !bytes.subarray(0, 8).equals(PNG_SIGNATURE))
63
71
  throw new TypeError("Invalid PNG signature");
@@ -65,68 +73,229 @@ const decodePng = (artifact) => {
65
73
  let header;
66
74
  const compressed = [];
67
75
  let sawEnd = false;
76
+ let sawPalette = false;
77
+ let imageDataEnded = false;
78
+ let paletteEntries = 0;
68
79
  let transparentColor;
80
+ let sawTransparency = false;
81
+ let unsupportedReason;
69
82
  while (offset < bytes.length) {
70
83
  if (offset + 12 > bytes.length)
71
84
  throw new TypeError("Truncated PNG chunk");
72
85
  const length = bytes.readUInt32BE(offset);
73
- const type = bytes.subarray(offset + 4, offset + 8).toString("ascii");
86
+ if (length > 0x7fffffff)
87
+ throw new TypeError("Invalid PNG chunk length");
88
+ const type = bytes.subarray(offset + 4, offset + 8).toString("latin1");
74
89
  const dataStart = offset + 8;
75
90
  const dataEnd = dataStart + length;
76
91
  if (dataEnd + 4 > bytes.length)
77
92
  throw new TypeError("Truncated PNG data");
78
93
  const data = bytes.subarray(dataStart, dataEnd);
79
- if (type === "IHDR")
94
+ if (crc32(bytes.subarray(offset + 4, dataEnd)) !== bytes.readUInt32BE(dataEnd))
95
+ throw new TypeError("Invalid PNG chunk checksum");
96
+ if (!/^[A-Za-z]{4}$/u.test(type) || type[2] !== type[2]?.toUpperCase())
97
+ throw new TypeError("Invalid PNG chunk type");
98
+ if (type !== "IDAT" && compressed.length > 0)
99
+ imageDataEnded = true;
100
+ if (type === "IHDR") {
101
+ if (offset !== 8 || header !== undefined)
102
+ throw new TypeError("Invalid PNG header order");
80
103
  header = parseHeader(data);
104
+ }
105
+ else if (header === undefined)
106
+ throw new TypeError("Invalid PNG header order");
81
107
  else if (type === "tRNS") {
82
- if (header?.channels !== 3 || data.length !== 6)
108
+ if (sawTransparency || compressed.length > 0)
109
+ throw new TypeError("Invalid PNG transparency order");
110
+ sawTransparency = true;
111
+ if (header.colorType === 2 && data.length === 6) {
112
+ transparentColor = [
113
+ data.readUInt16BE(0),
114
+ data.readUInt16BE(2),
115
+ data.readUInt16BE(4),
116
+ ];
117
+ }
118
+ else if ((header.colorType === 0 && data.length === 2) ||
119
+ (header.colorType === 3 &&
120
+ sawPalette &&
121
+ data.length > 0 &&
122
+ data.length <= paletteEntries)) {
123
+ unsupportedReason ??=
124
+ "PNG transparency for this color type is not supported.";
125
+ }
126
+ else {
83
127
  throw new TypeError("Unsupported PNG transparency");
84
- transparentColor = [
85
- data.readUInt16BE(0),
86
- data.readUInt16BE(2),
87
- data.readUInt16BE(4),
88
- ];
128
+ }
129
+ }
130
+ else if (type === "PLTE") {
131
+ if (sawPalette ||
132
+ sawTransparency ||
133
+ compressed.length > 0 ||
134
+ length === 0 ||
135
+ length > 768 ||
136
+ length % 3 !== 0 ||
137
+ (header.colorType === 3 && length / 3 > 2 ** header.bitDepth) ||
138
+ (header.colorType !== 2 &&
139
+ header.colorType !== 3 &&
140
+ header.colorType !== 6))
141
+ throw new TypeError("Invalid PNG palette");
142
+ sawPalette = true;
143
+ paletteEntries = length / 3;
89
144
  }
90
- else if (type === "IDAT")
145
+ else if (type === "IDAT") {
146
+ if (imageDataEnded)
147
+ throw new TypeError("Nonconsecutive PNG image data");
91
148
  compressed.push(data);
149
+ }
92
150
  else if (type === "IEND") {
151
+ if (length !== 0 || dataEnd + 4 !== bytes.length)
152
+ throw new TypeError("Invalid PNG end chunk");
93
153
  sawEnd = true;
94
154
  break;
95
155
  }
156
+ else if (/^[A-Z]/u.test(type)) {
157
+ unsupportedReason ??= `Unsupported critical PNG chunk ${type}.`;
158
+ }
96
159
  offset = dataEnd + 4;
97
160
  }
98
161
  if (header === undefined || !sawEnd || compressed.length === 0)
99
162
  throw new TypeError("Incomplete PNG");
100
- const rowBytes = header.width * header.channels;
101
- const expected = (rowBytes + 1) * header.height;
102
- const raw = inflateSync(Buffer.concat(compressed), {
103
- maxOutputLength: expected + 1,
104
- });
105
- if (raw.byteLength !== expected)
106
- throw new TypeError("Unexpected PNG size");
163
+ if (header.colorType === 3 && !sawPalette)
164
+ throw new TypeError("Missing PNG palette");
165
+ if (unsupportedReason !== undefined)
166
+ throw new AnalysisUnsupportedTargetError("compare_web_screenshots", field, unsupportedReason);
167
+ if (!header.supported)
168
+ throw new AnalysisUnsupportedTargetError("compare_web_screenshots", field, "PNG encoding is not supported for pixel comparison.");
169
+ const pixels = BigInt(header.width) * BigInt(header.height);
170
+ const expectedRawBytes = (BigInt(header.width) * BigInt(header.channels) + 1n) *
171
+ BigInt(header.height);
107
172
  return {
173
+ bytes,
108
174
  width: header.width,
109
175
  height: header.height,
110
- rgba: expandRgba(unfilter(raw, header.width, header.height, header.channels), header.channels, transparentColor),
176
+ channels: header.channels,
177
+ compressed,
178
+ transparentColor,
179
+ expectedRawBytes,
180
+ unfilteredBytes: pixels * BigInt(header.channels),
181
+ rgbaBytes: pixels * 4n,
182
+ };
183
+ };
184
+ const decodePng = (plan) => {
185
+ const expected = Number(plan.expectedRawBytes);
186
+ const raw = inflatePng(Buffer.concat(plan.compressed), expected + 1);
187
+ if (raw.byteLength !== expected)
188
+ throw new TypeError("Unexpected PNG size");
189
+ return {
190
+ width: plan.width,
191
+ height: plan.height,
192
+ rgba: expandRgba(unfilter(raw, plan.width, plan.height, plan.channels), plan.channels, plan.transparentColor),
111
193
  };
112
194
  };
195
+ const admitEncodedInputPair = (before, after) => {
196
+ const sourceBytes = BigInt(before.bytes) + BigInt(after.bytes);
197
+ if (sourceBytes > BigInt(PNG_COMPARISON_WORKING_MEMORY_BYTES))
198
+ throw pngWorkingMemoryError(sourceBytes, null, null);
199
+ };
200
+ const admitPngPair = (before, after) => {
201
+ // Input buffers remain live for both plans. For each decode, count the
202
+ // concatenated IDAT, rounded zlib output chunks, any concatenated output and
203
+ // unfiltered rows, plus RGB-to-RGBA output. The first completed RGBA image
204
+ // remains live while the second is decoded.
205
+ const inputBytes = BigInt(before.bytes.byteLength + after.bytes.byteLength);
206
+ const estimate = (current, retained) => {
207
+ const compressedBytes = current.compressed.reduce((total, chunk) => total + BigInt(chunk.byteLength), 0n);
208
+ const rgbaExpansion = current.channels === 3 ? current.rgbaBytes : 0n;
209
+ return (inputBytes +
210
+ (retained?.rgbaBytes ?? 0n) +
211
+ compressedBytes +
212
+ inflateBufferAllowance(current.expectedRawBytes) +
213
+ current.unfilteredBytes +
214
+ rgbaExpansion);
215
+ };
216
+ const estimateBytes = [
217
+ estimate(before, undefined),
218
+ estimate(after, before),
219
+ ].reduce((maximum, value) => (value > maximum ? value : maximum), 0n);
220
+ if (estimateBytes > BigInt(PNG_COMPARISON_WORKING_MEMORY_BYTES))
221
+ throw pngWorkingMemoryError(estimateBytes, before, after);
222
+ };
223
+ const inflateBufferAllowance = (expectedRawBytes) => {
224
+ const chunkBytes = BigInt(PNG_INFLATE_CHUNK_BYTES);
225
+ const maximumOutputBytes = expectedRawBytes + 1n;
226
+ const roundUpToChunk = (bytes) => ((bytes + chunkBytes - 1n) / chunkBytes) * chunkBytes;
227
+ // Node checks maxOutputLength after writing a chunk, so a rejected stream can
228
+ // retain one chunk's worth of output past the limit before it throws.
229
+ const rejectedOutputChunks = roundUpToChunk(maximumOutputBytes + chunkBytes - 1n);
230
+ // Sync zlib retains each output chunk while Buffer.concat creates the final
231
+ // result. A full final chunk also allocates the next scratch chunk first.
232
+ const returnedOutputChunks = roundUpToChunk(maximumOutputBytes);
233
+ const scratchChunk = expectedRawBytes % chunkBytes === 0n ||
234
+ maximumOutputBytes % chunkBytes === 0n
235
+ ? chunkBytes
236
+ : 0n;
237
+ const concatenatedOutput = maximumOutputBytes > chunkBytes ? maximumOutputBytes : 0n;
238
+ const returnedOutput = returnedOutputChunks + scratchChunk + concatenatedOutput;
239
+ return rejectedOutputChunks > returnedOutput
240
+ ? rejectedOutputChunks
241
+ : returnedOutput;
242
+ };
243
+ const pngWorkingMemoryError = (estimateBytes, before, after) => new AnalysisResourceConstraintError("compare_web_screenshots", "memory", "Screenshot comparison exceeds REA's 256 MiB estimated working-memory budget.", {
244
+ boundary: "png-screenshot-comparison",
245
+ estimated_working_memory_bytes: estimateBytes.toString(),
246
+ maximum_working_memory_bytes: PNG_COMPARISON_WORKING_MEMORY_BYTES,
247
+ before_dimensions: before === null ? null : { width: before.width, height: before.height },
248
+ after_dimensions: after === null ? null : { width: after.width, height: after.height },
249
+ }, {
250
+ remediationAction: "Compare smaller screenshots or reduce their viewport dimensions before capture.",
251
+ });
252
+ const inflatePng = (compressed, maxOutputLength) => {
253
+ try {
254
+ return inflateSync(compressed, {
255
+ maxOutputLength,
256
+ chunkSize: PNG_INFLATE_CHUNK_BYTES,
257
+ });
258
+ }
259
+ catch (cause) {
260
+ if (cause instanceof Error &&
261
+ "code" in cause &&
262
+ (cause.code === "Z_DATA_ERROR" ||
263
+ cause.code === "Z_BUF_ERROR" ||
264
+ cause.code === "ERR_BUFFER_TOO_LARGE"))
265
+ throw new TypeError("Invalid PNG image data", { cause });
266
+ throw cause;
267
+ }
268
+ };
113
269
  const parseHeader = (data) => {
114
270
  if (data.byteLength !== 13)
115
271
  throw new TypeError("Invalid PNG header");
116
272
  const width = data.readUInt32BE(0);
117
273
  const height = data.readUInt32BE(4);
118
- const bitDepth = data[8];
119
- const colorType = data[9];
274
+ const bitDepth = data[8] ?? 0;
275
+ const colorType = data[9] ?? -1;
276
+ const validDepth = (colorType === 0 && [1, 2, 4, 8, 16].includes(bitDepth)) ||
277
+ (colorType === 2 && [8, 16].includes(bitDepth)) ||
278
+ (colorType === 3 && [1, 2, 4, 8].includes(bitDepth)) ||
279
+ (colorType === 4 && [8, 16].includes(bitDepth)) ||
280
+ (colorType === 6 && [8, 16].includes(bitDepth));
120
281
  if (width === 0 ||
121
282
  height === 0 ||
122
- !Number.isSafeInteger(width * height) ||
123
- bitDepth !== 8 ||
124
- (colorType !== 2 && colorType !== 6) ||
283
+ width > 0x7fffffff ||
284
+ height > 0x7fffffff ||
285
+ !validDepth ||
125
286
  data[10] !== 0 ||
126
287
  data[11] !== 0 ||
127
- data[12] !== 0)
128
- throw new TypeError("Unsupported PNG");
129
- return { width, height, channels: colorType === 6 ? 4 : 3 };
288
+ (data[12] !== 0 && data[12] !== 1))
289
+ throw new TypeError("Invalid PNG header");
290
+ return {
291
+ width,
292
+ height,
293
+ colorType,
294
+ bitDepth,
295
+ interlace: data[12],
296
+ channels: colorType === 6 ? 4 : 3,
297
+ supported: bitDepth === 8 && (colorType === 2 || colorType === 6) && data[12] === 0,
298
+ };
130
299
  };
131
300
  const unfilter = (raw, width, height, channels) => {
132
301
  const rowBytes = width * channels;
@@ -9,7 +9,7 @@ import { webSourceMapsSchema } from "../domain/webBundleAnalysis.js";
9
9
  import { createWebTextArtifact } from "../domain/webContentArtifact.js";
10
10
  import { safeParseJson } from "../domain/safeJson.js";
11
11
  import { jsonParts } from "../domain/jsonSerialization.js";
12
- import { inspectSourceMapValue, SourceMapFormatFailure, } from "../javascript/sourceMaps/SourceMapFormat.js";
12
+ import { inspectSourceMapValue, sourceMapJsonText, SourceMapFormatFailure, } from "../javascript/sourceMaps/SourceMapFormat.js";
13
13
  import { WEB_SOURCE_MAP_LIMITS } from "../domain/webSourceLocation.js";
14
14
  // Source maps are normally fetched as a small part of a larger inspection.
15
15
  // Bound a stalled server to 30 seconds and bound raw map input retained for
@@ -106,6 +106,12 @@ class SourceMapEncodingError extends Error {
106
106
  this.name = "SourceMapEncodingError";
107
107
  }
108
108
  }
109
+ class SourceMapRedirectLocationError extends Error {
110
+ constructor(url, location) {
111
+ super(`Source-map redirect from ${JSON.stringify(url)} supplied an invalid Location URL: ${JSON.stringify(location)}.`);
112
+ this.name = "SourceMapRedirectLocationError";
113
+ }
114
+ }
109
115
  const fetchOne = async (request, input, signal, host, budget) => {
110
116
  if (!approvedUrl(request.fetchUrl, input.allowed_origins))
111
117
  return emptySourceMapItem(request, "policy_filtered", "Declared source-map URL is outside the approved exact origins.");
@@ -131,13 +137,25 @@ const fetchOne = async (request, input, signal, host, budget) => {
131
137
  throw cause;
132
138
  if (cause instanceof SourceMapEncodingError)
133
139
  return emptySourceMapItem(request, "invalid", cause.message);
134
- return emptySourceMapItem(request, "fetch_failed", cause instanceof SourceMapSizeLimitError
140
+ return emptySourceMapItem(request, "fetch_failed", cause instanceof SourceMapRedirectLocationError ||
141
+ cause instanceof SourceMapSizeLimitError ||
142
+ cause instanceof SourceMapDeadlineError
135
143
  ? cause.message
136
- : cause instanceof SourceMapDeadlineError
137
- ? cause.message
138
- : "Source-map fetch or validation failed.");
144
+ : "Source-map fetch or validation failed.");
139
145
  }
140
146
  };
147
+ /**
148
+ * Fetch redirect statuses per WHATWG Fetch (redirect status list:
149
+ * 301, 302, 303, 307, 308). Single owner for redirect decisions.
150
+ * 300/304/305/306 carry `Location` without being redirects — following
151
+ * them would replace the observed failure with an unrelated map.
152
+ * See https://fetch.spec.whatwg.org/#redirect-status
153
+ */
154
+ export const isFetchRedirectStatus = (status) => status === 301 ||
155
+ status === 302 ||
156
+ status === 303 ||
157
+ status === 307 ||
158
+ status === 308;
141
159
  const fetchFollowingApprovedRedirects = async (initialUrl, allowedOrigins, signal, host) => {
142
160
  let current = initialUrl;
143
161
  const visited = new Set();
@@ -163,13 +181,21 @@ const fetchFollowingApprovedRedirects = async (initialUrl, allowedOrigins, signa
163
181
  await response.body?.cancel(signal.reason).catch(() => undefined);
164
182
  throw signal.reason;
165
183
  }
166
- if (response.status < 300 || response.status >= 400)
184
+ // `Location` is a redirect target only for Fetch redirect statuses.
185
+ // Other 3xx responses retain their own HTTP failure (strict identity:
186
+ // never replace the observed failure with an unrelated map).
187
+ if (!isFetchRedirectStatus(response.status))
167
188
  return { response, fetchedUrl: current };
168
189
  const location = response.headers.get("location");
169
190
  if (location === null)
170
191
  return { response, fetchedUrl: current };
171
192
  await response.body?.cancel();
172
- current = new URL(location, current).href;
193
+ try {
194
+ current = new URL(location, current).href;
195
+ }
196
+ catch {
197
+ throw new SourceMapRedirectLocationError(current, location);
198
+ }
173
199
  }
174
200
  };
175
201
  const readBoundedText = async (response, budget, maxBytes, signal) => {
@@ -209,7 +235,7 @@ const readBoundedText = async (response, budget, maxBytes, signal) => {
209
235
  offset += chunk.byteLength;
210
236
  }
211
237
  try {
212
- return new TextDecoder("utf-8", { fatal: true }).decode(joined);
238
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(joined);
213
239
  }
214
240
  catch {
215
241
  throw new SourceMapEncodingError();
@@ -288,7 +314,7 @@ const promiseWithAbort = (promise, signal) => {
288
314
  });
289
315
  };
290
316
  const normalizeSourceMap = (request, text, fetchedUrl, context) => {
291
- const parsedJson = safeParseJson(text);
317
+ const parsedJson = safeParseJson(sourceMapJsonText(text));
292
318
  if (!parsedJson.ok)
293
319
  return emptySourceMapItem(request, "invalid", "Source-map JSON is not a version 3 map.");
294
320
  const retainedBytesBeforeMap = context.budget.expandedBytes;
@@ -17,6 +17,7 @@ export class LocalWebScriptArtifacts {
17
17
  async load(input, options) {
18
18
  let field = ["manifest_path"];
19
19
  let targetPath = input.manifest_path;
20
+ let callerSelected = true;
20
21
  try {
21
22
  const manifestBytes = await readWebArtifactJson(input.manifest_path, 32 * 1024 * 1024, options?.signal);
22
23
  const manifest = webScriptExportManifestSchema.parse(manifestBytes.value);
@@ -34,6 +35,7 @@ export class LocalWebScriptArtifacts {
34
35
  const root = resolve(dirname(input.manifest_path));
35
36
  const sourcePath = join(root, "files", portable);
36
37
  targetPath = sourcePath;
38
+ callerSelected = false;
37
39
  await assertContained(root, sourcePath);
38
40
  const sourceBytes = await readStableArtifact(sourcePath, 16 * 1024 * 1024, options?.signal);
39
41
  await assertContained(root, sourcePath);
@@ -62,7 +64,7 @@ export class LocalWebScriptArtifacts {
62
64
  });
63
65
  }
64
66
  catch (cause) {
65
- return err(webArtifactReadError(cause, { operation: this.operation, field, targetPath }, options?.signal));
67
+ return err(webArtifactReadError(cause, { operation: this.operation, field, targetPath, callerSelected }, options?.signal));
66
68
  }
67
69
  }
68
70
  }
@@ -1,24 +1,34 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { join } from "node:path";
3
3
  import { Readable } from "node:stream";
4
+ import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js";
5
+ import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js";
6
+ import { DESTINATION_CASE_COLLISION_PREFIX } from "../../artifacts/ArtifactPaths.js";
4
7
  import { SafeOutputTree } from "../../artifacts/SafeOutputTree.js";
8
+ import { SafeOutputTreeCreationFailure } from "../../artifacts/SafeOutputTreeCreationFailure.js";
5
9
  import { webScriptExportManifestSchema, webScriptExportResultSchema, } from "../../domain/webScriptExport.js";
6
- import { planWebScriptExport } from "../../domain/webScriptExportPlan.js";
10
+ import { planWebScriptExport, } from "../../domain/webScriptExportPlan.js";
7
11
  import { WebScriptExportError } from "../../domain/webScriptExportError.js";
8
12
  const LIMITATIONS = [
9
13
  "Only script bytes retained in this capture are exported. Sources are not refetched or executed, and a response or Debugger source does not prove execution.",
10
- "Ordinary unambiguous URL paths preserve relative module layouts by origin. Query variants, collisions, inline sources, and unrepresentable paths are isolated; their browser module relationships remain unknown.",
14
+ "Ordinary unambiguous URL paths preserve relative module layouts by origin, including case-distinct spellings. Query variants, exact path collisions, file/directory prefixes, inline sources, and unrepresentable paths are isolated. A case-distinct pair is isolated only when the destination filesystem cannot store both spellings; the record names that pair. Browser module relationships of isolated paths remain unknown.",
11
15
  "Local JavaScript analysis does not implement browser import maps, root-relative URL resolution, remote URL loading, or browser runtime behavior. It may strip import queries and fragments; isolated variants are not canonical targets.",
12
16
  "Source-map declarations are retained as metadata. No source maps or missing dependencies are fetched or reconstructed.",
13
17
  "Captured response bytes are browser-decoded bytes; Debugger sources are the exposed text encoded as UTF-8. Redacted bytes are exported exactly as retained, and may no longer parse as JavaScript.",
14
18
  ];
15
19
  /** Exclusively publish verified bytes and a manifest, rolling back partial work. */
16
- export const publishWebScripts = async (input, capture, captureSha256, signal) => {
20
+ export const publishWebScripts = async (input, capture, captureSha256, options) => options.resources.run(async () => {
17
21
  const planned = planWebScriptExport(capture.scripts);
18
- const tree = await SafeOutputTree.create(input.output_directory);
22
+ let tree;
23
+ let result;
19
24
  try {
20
- signal?.throwIfAborted();
21
- const records = planned.map(({ record }) => record);
25
+ tree = await SafeOutputTree.create(input.output_directory);
26
+ options.signal?.throwIfAborted();
27
+ const records = [];
28
+ for (const [index, item] of planned.entries()) {
29
+ options.signal?.throwIfAborted();
30
+ records.push(await publishPlannedScript(tree, item, index, options.signal));
31
+ }
22
32
  const manifest = webScriptExportManifestSchema.parse({
23
33
  capture_path: input.capture_path,
24
34
  capture_sha256: captureSha256,
@@ -42,7 +52,7 @@ export const publishWebScripts = async (input, capture, captureSha256, signal) =
42
52
  });
43
53
  const bytes = Buffer.from(`${JSON.stringify(manifest, null, 2)}\n`);
44
54
  const digest = createHash("sha256").update(bytes).digest("hex");
45
- const result = webScriptExportResultSchema.parse({
55
+ result = webScriptExportResultSchema.parse({
46
56
  ...manifest,
47
57
  manifest: {
48
58
  path: join(tree.outputRoot, "manifest.json"),
@@ -50,25 +60,70 @@ export const publishWebScripts = async (input, capture, captureSha256, signal) =
50
60
  bytes: bytes.length,
51
61
  },
52
62
  });
53
- for (const { script, record } of planned) {
54
- signal?.throwIfAborted();
55
- if (script.content.state === "captured" &&
56
- record.content.state === "exported")
57
- await tree.write(`files/${record.content.relative_path}`, Readable.from([script.content.bytes]), script.content.sha256, signal);
58
- }
59
- await tree.write("manifest.json", Readable.from([bytes]), digest, signal);
60
- signal?.throwIfAborted();
63
+ await tree.write("manifest.json", Readable.from([bytes]), { sha256: digest, bytes: bytes.byteLength }, options.signal);
64
+ options.signal?.throwIfAborted();
61
65
  await tree.commit();
62
66
  return result;
63
67
  }
64
68
  catch (cause) {
65
- try {
66
- await tree.rollback();
67
- }
68
- catch (cleanupCause) {
69
- throw new WebScriptExportError("io", tree.outputRoot, `Publication failed (${message(cause)}); rollback failed (${message(cleanupCause)}). Remove the residual output directory before retrying.`, [tree.outputRoot]);
69
+ if (cause instanceof SafeOutputTreeCreationFailure)
70
+ tree = cause.tree;
71
+ if (tree !== undefined) {
72
+ const cleanup = await options.resources.release({
73
+ kind: "output-tree",
74
+ resource: tree.outputRoot,
75
+ tree,
76
+ });
77
+ if (cleanup.kind === "failed") {
78
+ const cleanupCause = cleanup.cause;
79
+ const diagnostic = tree.published
80
+ ? `Publication completed, but descriptor cleanup failed (${message(cleanupCause)}). The published output remains available.`
81
+ : `Publication failed (${message(cause)}); rollback failed (${message(cleanupCause)}). Remove the residual output directory before retrying.`;
82
+ const error = new WebScriptExportError(cause instanceof ArtifactReaderFailure ? cause.reason : "io", tree.outputRoot, diagnostic, { residualPaths: [tree.outputRoot] });
83
+ if (tree.published && result !== undefined)
84
+ error.retainPartialObservation({
85
+ kind: "web-script-export",
86
+ result,
87
+ });
88
+ throw error;
89
+ }
90
+ if (tree.published && result !== undefined)
91
+ return result;
70
92
  }
71
93
  throw cause;
72
94
  }
95
+ });
96
+ const publishPlannedScript = async (tree, item, index, signal) => {
97
+ const { script, record } = item;
98
+ const content = script.content;
99
+ if (content.state !== "captured" || record.content.state !== "exported")
100
+ return record;
101
+ const write = (relativePath) => tree.write(`files/${relativePath}`, Readable.from([content.bytes]), { sha256: content.sha256, bytes: content.bytes.byteLength }, signal);
102
+ try {
103
+ await write(record.content.relative_path);
104
+ return record;
105
+ }
106
+ catch (cause) {
107
+ const collision = destinationCollisionReason(cause);
108
+ if (collision === undefined || record.content.layout !== "url-path")
109
+ throw cause;
110
+ const relativePath = isolatedScriptPath(script, index);
111
+ await write(relativePath);
112
+ return {
113
+ ...record,
114
+ content: {
115
+ ...record.content,
116
+ relative_path: relativePath,
117
+ layout: "isolated",
118
+ layout_reason: collision,
119
+ },
120
+ };
121
+ }
73
122
  };
123
+ const isolatedScriptPath = (script, index) => `isolated/source-${index + 1}-${createHash("sha256").update(JSON.stringify(script.source)).digest("hex")}.js`;
124
+ const destinationCollisionReason = (cause) => cause instanceof ArtifactReaderFailure &&
125
+ cause.reason === "path" &&
126
+ cause.message.startsWith(DESTINATION_CASE_COLLISION_PREFIX)
127
+ ? cause.message
128
+ : undefined;
74
129
  const message = (cause) => cause instanceof Error ? cause.message : "Unknown publication failure";
@@ -14,9 +14,9 @@ const indexResponses = (events) => {
14
14
  requests: new Map(),
15
15
  };
16
16
  for (const event of events) {
17
- if (event.kind === "request" && event.transaction_id !== undefined)
17
+ if (event.kind === "request")
18
18
  index.requests.set(event.transaction_id, (index.requests.get(event.transaction_id) ?? 0) + 1);
19
- if (event.kind === "response" && event.transaction_id !== undefined)
19
+ if (event.kind === "response")
20
20
  append(index.responses, event.transaction_id, event);
21
21
  if (event.kind === "network-content" && event.phase === "response")
22
22
  append(index.contents, event.source_event_sequence, event);
@@ -25,33 +25,29 @@ const indexResponses = (events) => {
25
25
  };
26
26
  const projectRequest = (request, index) => {
27
27
  const id = request.transaction_id;
28
- const matches = id === undefined ? [] : (index.responses.get(id) ?? []);
28
+ const matches = index.responses.get(id) ?? [];
29
29
  const response = matches.length === 1 ? matches[0] : undefined;
30
30
  const bodies = response === undefined ? [] : (index.contents.get(response.sequence) ?? []);
31
31
  const body = bodies.length === 1 ? bodies[0]?.body : undefined;
32
- const ambiguous = (id !== undefined && index.requests.get(id) !== 1) ||
33
- matches.length > 1 ||
34
- bodies.length > 1;
32
+ const ambiguous = index.requests.get(id) !== 1 || matches.length > 1 || bodies.length > 1;
35
33
  return {
36
34
  source: {
37
35
  kind: "scenario-response",
38
- transaction_id: id ?? null,
36
+ transaction_id: id,
39
37
  request_sequence: request.sequence,
40
38
  response_sequence: ambiguous ? null : (response?.sequence ?? null),
41
39
  status: ambiguous ? null : (response?.status ?? null),
42
40
  },
43
41
  url: request.url.url,
44
- content: projectBody(body, id, ambiguous),
42
+ content: projectBody(body, ambiguous),
45
43
  };
46
44
  };
47
45
  const unavailable = (reason, message) => ({ state: "unavailable", reason, message });
48
- const projectBody = (body, transactionId, ambiguous) => {
46
+ const projectBody = (body, ambiguous) => {
49
47
  if (ambiguous)
50
48
  return unavailable("ambiguous-transaction", "The capture does not identify one request, response, and content record for this transaction.");
51
49
  if (body === undefined)
52
- return unavailable(transactionId === undefined
53
- ? "transaction-identity-unavailable"
54
- : "response-content-not-retained", "No selected, completed script response bytes were retained for this request.");
50
+ return unavailable("response-content-not-retained", "No selected, completed script response bytes were retained for this request.");
55
51
  if (body.state === "unavailable")
56
52
  return unavailable(body.reason, body.message);
57
53
  if (body.state !== "captured")
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js";
3
3
  import { readStableArtifact } from "../../artifacts/readStableArtifact.js";
4
- import { AnalysisCancelledError, AnalysisInputError, } from "../../domain/analysisErrorCore.js";
4
+ import { AnalysisAccessDeniedError, AnalysisCancelledError, AnalysisInputError, } from "../../domain/analysisErrorCore.js";
5
5
  import { ArtifactOperationError } from "../../domain/artifactOperationError.js";
6
6
  import { ProviderAdapterError } from "../../domain/providerAdapterError.js";
7
7
  import { safeParseJson } from "../../domain/safeJson.js";
@@ -29,6 +29,11 @@ export const readWebArtifactJson = async (path, maximumBytes, signal) => {
29
29
  export const webArtifactReadError = (cause, context, signal) => {
30
30
  if (signal?.aborted === true)
31
31
  return new AnalysisCancelledError(context.operation);
32
+ const selection = context.callerSelected
33
+ ? selectedFileError(cause, context)
34
+ : undefined;
35
+ if (selection !== undefined)
36
+ return selection;
32
37
  if (cause instanceof ArtifactReaderFailure)
33
38
  return new ArtifactOperationError(context.operation, cause.reason, cause.details, cause.message);
34
39
  if (cause instanceof Error &&
@@ -54,3 +59,20 @@ export const webArtifactReadError = (cause, context, signal) => {
54
59
  },
55
60
  });
56
61
  };
62
+ /**
63
+ * Report a missing, non-regular or unreadable caller-selected file as the
64
+ * caller's selection or a host permission denial, not an artifact fault.
65
+ */
66
+ const selectedFileError = (cause, context) => {
67
+ const selected = (message) => new AnalysisInputError(context.operation, { cause }, [
68
+ { path: context.field, reason: "invalid_value", message },
69
+ ]);
70
+ if (cause instanceof ArtifactReaderFailure)
71
+ return cause.reason === "path" ? selected(cause.message) : undefined;
72
+ const code = cause instanceof Error && "code" in cause ? String(cause.code) : "";
73
+ if (code === "EACCES" || code === "EPERM")
74
+ return new AnalysisAccessDeniedError(context.operation, context.targetPath, code, { cause });
75
+ if (code === "ENOENT" || code === "ENOTDIR")
76
+ return selected(`Selected file could not be read (${code}): ${context.targetPath}`);
77
+ return undefined;
78
+ };
@@ -34,6 +34,7 @@ export class LocalWebSourceLocationArtifacts {
34
34
  operation: "trace_web_source_location",
35
35
  field: ["source_map", "path"],
36
36
  targetPath: input.source_map.path,
37
+ callerSelected: true,
37
38
  }, options?.signal));
38
39
  }
39
40
  }
@@ -69,9 +69,9 @@ export const captureWebExecution = async (input, sources) => {
69
69
  sources.check();
70
70
  const verifiedRequests = requests.result();
71
71
  const verifiedMainScripts = mainScripts.filter((id) => sources.belongsToDocument(id));
72
- const sample = raw === undefined
73
- ? undefined
74
- : normalizePreciseCoverage(raw, sources, retained);
72
+ const sample = parsed?.success === true
73
+ ? normalizePreciseCoverage(parsed.data, sources, retained)
74
+ : undefined;
75
75
  await session.options.progress?.report({
76
76
  phase: "browser_execution",
77
77
  completed: 2,