rea-agents 1.7.0 → 2.1.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 (333) hide show
  1. package/README.md +112 -59
  2. package/bridge/ghidra/ReaGhidraBridge.java +96 -11
  3. package/dist/application/ArtifactExtraction.js +1 -1
  4. package/dist/application/ArtifactInventory/classify.js +42 -0
  5. package/dist/application/ArtifactInventory/hash.js +43 -0
  6. package/dist/application/ArtifactInventory/reader.js +41 -0
  7. package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
  8. package/dist/application/ArtifactInventory/scanReader.js +124 -0
  9. package/dist/application/ArtifactInventory/types.js +10 -0
  10. package/dist/application/ArtifactInventory.js +9 -351
  11. package/dist/application/AuthorizedArtifactInventory.js +2 -2
  12. package/dist/application/BinarySession.js +47 -270
  13. package/dist/application/BinarySessionExecution.js +28 -0
  14. package/dist/application/BinarySessionOpen.js +39 -0
  15. package/dist/application/BinarySessionRecords.js +149 -0
  16. package/dist/application/BinarySessionStatus.js +75 -0
  17. package/dist/application/CapabilityInventory.js +42 -2
  18. package/dist/application/ClientRegistrationStatus.js +1 -1
  19. package/dist/application/CrossVersionInventory.js +8 -2
  20. package/dist/application/CrossVersionInvestigation.js +11 -29
  21. package/dist/application/CrossVersionInvestigationCollections.js +23 -0
  22. package/dist/application/DirectAnalysis.js +47 -44
  23. package/dist/application/Doctor.js +165 -197
  24. package/dist/application/DoctorDiagnostics.js +180 -0
  25. package/dist/application/ElectronBoundaryAnalysis.js +112 -0
  26. package/dist/application/ElectronBoundaryGraph.js +9 -0
  27. package/dist/application/ElectronBoundaryGraphContext.js +62 -0
  28. package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
  29. package/dist/application/ElectronBoundaryGraphNative.js +86 -0
  30. package/dist/application/ElectronBoundaryGraphWindows.js +223 -0
  31. package/dist/application/EnhancedToolPagination.js +22 -0
  32. package/dist/application/EnhancedToolTypes.js +4 -0
  33. package/dist/application/EnhancedTools.js +58 -50
  34. package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
  35. package/dist/application/InvestigationProviders.js +30 -0
  36. package/dist/application/InvestigationWorkspaceStore.js +24 -10
  37. package/dist/application/JavaScriptApplicationEvidence.js +26 -0
  38. package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
  39. package/dist/application/JavaScriptApplicationService.js +74 -0
  40. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
  41. package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
  42. package/dist/application/JavaScriptArtifactAnalysis.js +52 -7
  43. package/dist/application/JavaScriptArtifactFiles.js +6 -2
  44. package/dist/application/JavaScriptArtifactGraphBuilder.js +82 -17
  45. package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
  46. package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
  47. package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
  48. package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
  49. package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
  50. package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
  51. package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
  52. package/dist/application/JavaScriptArtifactReconstruction.js +4 -1
  53. package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
  54. package/dist/application/JavaScriptJsonModules.js +39 -0
  55. package/dist/application/JavaScriptModuleRelationships.js +262 -0
  56. package/dist/application/JavaScriptReplayPermission.js +16 -0
  57. package/dist/application/JavaScriptReplayPlanning.js +201 -0
  58. package/dist/application/JavaScriptReplayService.js +292 -0
  59. package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
  60. package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
  61. package/dist/application/LinuxHopper.js +10 -0
  62. package/dist/application/MacHopper.js +22 -11
  63. package/dist/application/ManagedApplicationGraphService.js +55 -0
  64. package/dist/application/ManagedMemberComparisonService.js +122 -0
  65. package/dist/application/ManagedNativeVerificationService.js +39 -0
  66. package/dist/application/ManagedReconstructionService.js +58 -0
  67. package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
  68. package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
  69. package/dist/application/PermissionAuthority.js +106 -63
  70. package/dist/application/ProcessCaptureCapability.js +1 -1
  71. package/dist/application/ProcessCapturePermission.js +13 -0
  72. package/dist/application/ProcessCli.js +2 -12
  73. package/dist/application/ProcessHarness.js +1 -1
  74. package/dist/application/ProcessSampling.js +15 -11
  75. package/dist/application/ProjectPermissionStore.js +49 -9
  76. package/dist/application/RealHopperAssertions.js +76 -0
  77. package/dist/application/ReconstructionCoverageService.js +69 -0
  78. package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
  79. package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
  80. package/dist/application/Setup.js +147 -259
  81. package/dist/application/SetupClientConfiguration.js +220 -0
  82. package/dist/application/SetupClients.js +24 -2
  83. package/dist/application/SetupPlan.js +123 -12
  84. package/dist/application/SetupSkill.js +26 -12
  85. package/dist/application/SupportedClients.js +1 -0
  86. package/dist/application/Uninstall.js +6 -3
  87. package/dist/application/WindowsCapabilities.js +86 -0
  88. package/dist/application/runtime.js +2 -0
  89. package/dist/artifacts/AsarArtifactReader.js +11 -0
  90. package/dist/browser/BrowserProcessStartup.js +88 -0
  91. package/dist/browser/CdpCaptureDocuments.js +12 -8
  92. package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
  93. package/dist/browser/CdpCaptureEventHandlers.js +336 -0
  94. package/dist/browser/CdpCaptureEventHelpers.js +71 -0
  95. package/dist/browser/CdpCaptureEventState.js +1 -0
  96. package/dist/browser/CdpCaptureEventTypes.js +1 -0
  97. package/dist/browser/CdpCaptureEvents.js +46 -464
  98. package/dist/browser/CdpElectronInspection.js +106 -162
  99. package/dist/browser/CdpElectronProvider.js +5 -1
  100. package/dist/browser/CdpElectronScriptEvents.js +69 -0
  101. package/dist/browser/CdpElectronScripts.js +94 -0
  102. package/dist/browser/CdpElectronWorkers.js +56 -0
  103. package/dist/browser/CdpObservationSession.js +51 -8
  104. package/dist/browser/CdpPageCapture.js +12 -129
  105. package/dist/browser/CdpPageCaptureScripts.js +97 -0
  106. package/dist/browser/CdpPageCaptureWorkers.js +46 -0
  107. package/dist/browser/CdpWebMcpDiscovery.js +38 -14
  108. package/dist/browser/PngVisualDiff.js +9 -2
  109. package/dist/catalogIdentity.js +8 -1
  110. package/dist/cli/artifactCommands.js +82 -0
  111. package/dist/cli/coreAnalysisCommands.js +232 -0
  112. package/dist/cli/managedCommands.js +397 -0
  113. package/dist/cli/managedProjectGraphCommand.js +24 -0
  114. package/dist/cli/options.js +9 -0
  115. package/dist/cli/setupCommands.js +108 -0
  116. package/dist/cli/types.js +1 -0
  117. package/dist/cli/utilityCommands.js +122 -0
  118. package/dist/cli.js +13 -383
  119. package/dist/cliApplicationCommands.js +176 -0
  120. package/dist/cliBrowserAdvancedCommands.js +73 -16
  121. package/dist/cliBrowserCommands.js +39 -115
  122. package/dist/cliCommandNames.js +17 -0
  123. package/dist/cliElectronCommands.js +100 -27
  124. package/dist/cliEvidenceCommands.js +13 -2
  125. package/dist/cliInvestigationCommands.js +53 -10
  126. package/dist/cliJsonInput.js +54 -0
  127. package/dist/cliObservationOptions.js +137 -0
  128. package/dist/cliPolicyCommands.js +80 -46
  129. package/dist/cliSetup.js +289 -0
  130. package/dist/config/environment.js +107 -0
  131. package/dist/config/parseConfig.js +228 -0
  132. package/dist/config/parsers.js +68 -0
  133. package/dist/config/permissions.js +30 -0
  134. package/dist/config/types.js +1 -0
  135. package/dist/config.js +1 -292
  136. package/dist/contracts/applicationToolContracts.js +225 -0
  137. package/dist/contracts/artifactToolContracts.js +5 -9
  138. package/dist/contracts/browserToolContracts.js +14 -62
  139. package/dist/contracts/electronToolContracts.js +45 -19
  140. package/dist/contracts/errorSchemas.js +1 -0
  141. package/dist/contracts/investigationExamples.js +0 -6
  142. package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
  143. package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
  144. package/dist/contracts/managedToolContracts.js +153 -0
  145. package/dist/contracts/managedWorkflowExamples.js +346 -0
  146. package/dist/contracts/managedWorkflowToolContracts.js +203 -0
  147. package/dist/contracts/nativeToolContracts.js +2 -6
  148. package/dist/contracts/promptContracts.js +18 -2
  149. package/dist/contracts/providerSelection.js +2 -0
  150. package/dist/contracts/toolContractExamples.js +10 -25
  151. package/dist/contracts/toolContracts.js +49 -47
  152. package/dist/contracts/toolEffects.js +174 -0
  153. package/dist/contracts/toolOutputSchemaGroups.js +232 -0
  154. package/dist/contracts/toolOutputSchemaPrimitives.js +327 -0
  155. package/dist/contracts/toolOutputSchemas.js +2 -535
  156. package/dist/doctorRuntime.js +42 -1
  157. package/dist/domain/analysisErrorPresentation.js +234 -0
  158. package/dist/domain/analysisErrorProjection.js +284 -0
  159. package/dist/domain/artifactComparison.js +37 -19
  160. package/dist/domain/binaryTarget.js +87 -37
  161. package/dist/domain/browserObservation.js +1 -282
  162. package/dist/domain/browserObservationSchemas.js +286 -0
  163. package/dist/domain/bundleComparison.js +4 -4
  164. package/dist/domain/electronObservation.js +13 -0
  165. package/dist/domain/electronStaticAnalysis.js +9 -0
  166. package/dist/domain/electronStaticAnalysisBrowser.js +206 -0
  167. package/dist/domain/electronStaticAnalysisIpc.js +171 -0
  168. package/dist/domain/electronStaticAnalysisNative.js +164 -0
  169. package/dist/domain/electronStaticAnalysisTypes.js +1 -0
  170. package/dist/domain/electronStaticAnalysisValues.js +103 -0
  171. package/dist/domain/errors.js +32 -448
  172. package/dist/domain/functionComparison.js +4 -165
  173. package/dist/domain/functionComparisonDimensions.js +164 -0
  174. package/dist/domain/functionComparisonSchemas.js +3 -8
  175. package/dist/domain/inputIssueProjection.js +52 -0
  176. package/dist/domain/javascriptApplicationAnalysis.js +155 -0
  177. package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
  178. package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
  179. package/dist/domain/javascriptApplicationGraph.js +2 -1
  180. package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
  181. package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
  182. package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
  183. package/dist/domain/javascriptApplicationVersionItems.js +233 -0
  184. package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
  185. package/dist/domain/javascriptExportInstrumentation.js +97 -0
  186. package/dist/domain/javascriptFeatureSeed.js +140 -0
  187. package/dist/domain/javascriptFeatureTrace.js +232 -0
  188. package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
  189. package/dist/domain/javascriptFeatureTraversal.js +100 -0
  190. package/dist/domain/javascriptNativeHandoff.js +85 -0
  191. package/dist/domain/javascriptReplay.js +361 -0
  192. package/dist/domain/javascriptRuntimeLoadState.js +106 -0
  193. package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
  194. package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
  195. package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
  196. package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
  197. package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
  198. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
  199. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
  200. package/dist/domain/javascriptRuntimeStaticCandidates.js +193 -0
  201. package/dist/domain/javascriptSemanticAnalysis.js +386 -0
  202. package/dist/domain/javascriptSemanticIr.js +30 -0
  203. package/dist/domain/javascriptSemanticProjection.js +366 -0
  204. package/dist/domain/javascriptSemanticState.js +40 -0
  205. package/dist/domain/javascriptSemanticTraversal.js +22 -0
  206. package/dist/domain/javascriptSemanticValues.js +352 -0
  207. package/dist/domain/javascriptStaticAnalysis.js +26 -254
  208. package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
  209. package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
  210. package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
  211. package/dist/domain/javascriptStaticAnalysisHelpers.js +81 -2
  212. package/dist/domain/javascriptStaticAnalysisState.js +6 -0
  213. package/dist/domain/knownPageCoverage.js +21 -0
  214. package/dist/domain/managedApplicationGraph.js +206 -0
  215. package/dist/domain/managedApplicationGraphCoverage.js +170 -0
  216. package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
  217. package/dist/domain/managedApplicationGraphNodes.js +336 -0
  218. package/dist/domain/managedArtifact.js +452 -0
  219. package/dist/domain/managedMemberComparison.js +211 -0
  220. package/dist/domain/managedMemberComparisonCoverage.js +72 -0
  221. package/dist/domain/managedMemberComparisonMatch.js +356 -0
  222. package/dist/domain/managedNativeVerification.js +46 -0
  223. package/dist/domain/managedNativeVerificationMatch.js +272 -0
  224. package/dist/domain/managedNativeVerificationSchemas.js +141 -0
  225. package/dist/domain/managedReconstruction.js +196 -0
  226. package/dist/domain/managedRuntimeCorrelation.js +184 -0
  227. package/dist/domain/nodeRuntimeCharacterization.js +66 -0
  228. package/dist/domain/permissionPolicy.js +2 -0
  229. package/dist/domain/reconstructionCoverage.js +387 -0
  230. package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
  231. package/dist/domain/reconstructionVerificationSchemas.js +9 -3
  232. package/dist/domain/runtimeCharacterization.js +85 -0
  233. package/dist/domain/webBundleAnalyzer.js +3 -409
  234. package/dist/domain/webBundleAnalyzerAst.js +77 -0
  235. package/dist/domain/webBundleAnalyzerInspection.js +307 -0
  236. package/dist/domain/webBundleAnalyzerResult.js +120 -0
  237. package/dist/dotnet/ManagedArtifactInspector.js +339 -0
  238. package/dist/dotnet/ManagedMemberInspector.js +153 -0
  239. package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
  240. package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
  241. package/dist/dotnet/ManagedMemberRows.js +120 -0
  242. package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
  243. package/dist/dotnet/ManagedMetadataInventory.js +104 -0
  244. package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
  245. package/dist/dotnet/ManagedMetadataLayout.js +259 -0
  246. package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
  247. package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
  248. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
  249. package/dist/dotnet/ManagedNativeBoundaryInspector.js +143 -0
  250. package/dist/dotnet/ManagedPeReader.js +188 -0
  251. package/dist/dotnet/ManagedReaderFailure.js +10 -0
  252. package/dist/dotnet/ManagedStaticProvider.js +203 -0
  253. package/dist/generatedPackageMetadata.js +2 -2
  254. package/dist/ghidra/GhidraClient.js +76 -91
  255. package/dist/ghidra/GhidraClientStartup.js +29 -0
  256. package/dist/ghidra/GhidraClientWire.js +34 -0
  257. package/dist/ghidra/GhidraDefaults.js +1 -1
  258. package/dist/ghidra/GhidraDiagnostics.js +6 -1
  259. package/dist/ghidra/GhidraInstallation.js +20 -15
  260. package/dist/ghidra/GhidraLauncher.js +93 -29
  261. package/dist/ghidra/GhidraProvider.js +67 -161
  262. package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
  263. package/dist/ghidra/GhidraSessionValues.js +2 -0
  264. package/dist/ghidra/GhidraSocketConnection.js +44 -7
  265. package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
  266. package/dist/ghidra/GhidraTransport.js +71 -0
  267. package/dist/identity.js +3 -2
  268. package/dist/main/messages.js +5 -0
  269. package/dist/main/reload.js +49 -0
  270. package/dist/main/shutdown.js +25 -0
  271. package/dist/main/startup.js +14 -0
  272. package/dist/main/state.js +26 -0
  273. package/dist/main/transport.js +61 -0
  274. package/dist/main/types.js +1 -0
  275. package/dist/main.js +35 -132
  276. package/dist/process/PrivateRuntimeRoot.js +3 -2
  277. package/dist/process/ProcessOwnership.js +35 -0
  278. package/dist/process/ProviderProcess.js +2 -0
  279. package/dist/replay/JavaScriptReplayWorker.js +300 -0
  280. package/dist/replay/LinuxJavaScriptReplayRunner.js +217 -0
  281. package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
  282. package/dist/replay/LinuxRuntimeClosure.js +46 -0
  283. package/dist/replay/LinuxSeccompPolicy.js +40 -0
  284. package/dist/replay/ReplayOutcome.js +95 -0
  285. package/dist/replay/ReplayProcessLifecycle.js +71 -0
  286. package/dist/replay/ReplayWorkerProtocol.js +55 -0
  287. package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
  288. package/dist/server/ProcessCaptureElicitation.js +157 -0
  289. package/dist/server/createServer.js +158 -41
  290. package/dist/server/registerApplicationTools/characterization.js +57 -0
  291. package/dist/server/registerApplicationTools/compareVersions.js +34 -0
  292. package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
  293. package/dist/server/registerApplicationTools/coverage.js +84 -0
  294. package/dist/server/registerApplicationTools/helpers.js +42 -0
  295. package/dist/server/registerApplicationTools/traceFeature.js +26 -0
  296. package/dist/server/registerApplicationTools/types.js +1 -0
  297. package/dist/server/registerApplicationTools.js +13 -0
  298. package/dist/server/registerArtifactComparisonTool.js +16 -9
  299. package/dist/server/registerBrowserTools.js +61 -60
  300. package/dist/server/registerBundleComparisonTool.js +17 -20
  301. package/dist/server/registerElectronTools.js +39 -12
  302. package/dist/server/registerEnhancedTools.js +52 -15
  303. package/dist/server/registerEvidenceResources.js +54 -0
  304. package/dist/server/registerEvidenceTools.js +5 -1
  305. package/dist/server/registerFunctionComparisonTool.js +14 -7
  306. package/dist/server/registerInvestigationTools/helpers.js +74 -0
  307. package/dist/server/registerInvestigationTools/types.js +1 -0
  308. package/dist/server/registerInvestigationTools.js +103 -132
  309. package/dist/server/registerManagedTools.js +6 -0
  310. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
  311. package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
  312. package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
  313. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
  314. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
  315. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
  316. package/dist/server/registerManagedWorkflowTools/types.js +1 -0
  317. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
  318. package/dist/server/registerManagedWorkflowTools.js +13 -0
  319. package/dist/server/registerOfficialTools.js +81 -67
  320. package/dist/server/registerProcessComparisonTool.js +25 -47
  321. package/dist/server/registerSessionRecordTools.js +137 -0
  322. package/dist/server/registerSessionStatusTool.js +9 -8
  323. package/dist/server/registerSessionTools.js +77 -216
  324. package/dist/server/sessionAvailabilityPolicy.js +10 -0
  325. package/dist/server/sessionEvidence.js +14 -19
  326. package/dist/server/toolInputValidation.js +77 -0
  327. package/dist/server/toolRegistrationOptions.js +177 -2
  328. package/dist/server/toolResult.js +30 -17
  329. package/package.json +21 -14
  330. package/scripts/rea.mjs +1 -1
  331. package/skills/{rea-analysis → reverse-engineer-anything}/SKILL.md +75 -6
  332. package/scripts/prepare-node-pty.mjs +0 -35
  333. package/scripts/rebuild-native.mjs +0 -22
@@ -0,0 +1,289 @@
1
+ import { cancel, confirm, intro, isCancel, multiselect, outro, } from "@clack/prompts";
2
+ import { SUPPORTED_CLIENT_DEFINITIONS } from "./application/SupportedClients.js";
3
+ const clientDisplayNames = new Map(SUPPORTED_CLIENT_DEFINITIONS.map(({ name, displayName }) => [
4
+ name,
5
+ displayName,
6
+ ]));
7
+ const promptStreams = {
8
+ input: process.stdin,
9
+ output: process.stderr,
10
+ withGuide: true,
11
+ };
12
+ const agentAccessCapabilityId = "agent_access";
13
+ /** Run the inline setup picker, exact preflight, and default-No consent. */
14
+ export const confirmInteractiveSetup = async (actions, accessible) => {
15
+ intro("REA setup", promptStreams);
16
+ renderValueIntroduction();
17
+ renderDetectedSummary(actions);
18
+ renderKeyboardHelp(accessible);
19
+ const selectedActionIds = await selectSetupActions(actions, accessible);
20
+ if (selectedActionIds === undefined)
21
+ return cancelledDecision();
22
+ if (selectedActionIds.length === 0) {
23
+ cancel("Nothing selected. No changes were made.", promptStreams);
24
+ return { approved: false, selectedActionIds };
25
+ }
26
+ const selected = new Set(selectedActionIds);
27
+ const selectedActions = actions.filter(({ id }) => selected.has(id));
28
+ renderPreflight(selectedActions);
29
+ const approved = await confirm({
30
+ ...promptStreams,
31
+ message: selectedActions.length === 1
32
+ ? "Apply this change?"
33
+ : `Apply these ${String(selectedActions.length)} changes?`,
34
+ initialValue: false,
35
+ active: "Yes, apply",
36
+ inactive: "No, cancel",
37
+ });
38
+ if (isCancel(approved) || !approved) {
39
+ cancel("Setup cancelled. No changes were made.", promptStreams);
40
+ return { approved: false, selectedActionIds };
41
+ }
42
+ return { approved: true, selectedActionIds };
43
+ };
44
+ /** Render stable, append-only progress for real setup operations. */
45
+ export const renderSetupProgress = (event) => {
46
+ const symbol = event.state === "started"
47
+ ? "◇"
48
+ : event.state === "completed"
49
+ ? "◆"
50
+ : event.state === "warning"
51
+ ? "!"
52
+ : "✗";
53
+ const suffix = event.detail === undefined ? "" : ` · ${event.detail}`;
54
+ writeLine(`${symbol} ${event.label}${suffix}`);
55
+ };
56
+ /** Finish an interactive setup journey without exposing the full doctor catalog. */
57
+ export const renderInteractiveSetupResult = (result) => {
58
+ if (result.status === "ready") {
59
+ const changedClients = Object.entries(result.clients)
60
+ .filter(([, client]) => client.status === "configured")
61
+ .map(([client]) => clientDisplayNames.get(client) ?? client);
62
+ const readyClients = readyAgentClients(result, changedClients);
63
+ renderReadyCapabilities(result, readyClients);
64
+ outro(changedClients.length === 0
65
+ ? "REA is ready for local app analysis."
66
+ : `Restart ${changedClients.join(", ")} to load REA.`, promptStreams);
67
+ return;
68
+ }
69
+ if (result.status === "planned")
70
+ return;
71
+ writeLine(`! ${result.remediation ?? "Setup needs attention."}`);
72
+ outro("Run `rea doctor` for the remaining checks.", promptStreams);
73
+ };
74
+ /** Keep default non-TTY output actionable without emitting the full catalog. */
75
+ export const conciseSetupResult = (result) => ({
76
+ status: result.status,
77
+ plannedActions: result.plannedActions,
78
+ appliedActions: result.appliedActions,
79
+ clients: result.clients,
80
+ doctor: {
81
+ healthy: result.doctor.healthy,
82
+ checks: result.doctor.checks.filter(({ ok }) => !ok),
83
+ },
84
+ ...(result.code === undefined ? {} : { code: result.code }),
85
+ ...(result.remediation === undefined
86
+ ? {}
87
+ : { remediation: result.remediation }),
88
+ });
89
+ const selectSetupActions = async (actions, accessible) => {
90
+ const clientActions = actions.filter(({ kind }) => kind === "configure_client");
91
+ const componentActions = actions.filter(({ kind }) => kind !== "configure_client");
92
+ const capabilities = setupCapabilities(clientActions, componentActions);
93
+ const selectedCapabilities = accessible
94
+ ? await selectCapabilitiesAccessibly(capabilities)
95
+ : await selectCapabilities(capabilities);
96
+ if (selectedCapabilities === undefined)
97
+ return undefined;
98
+ const selectedCapabilityIds = new Set(selectedCapabilities);
99
+ const selectedActionIds = componentActions
100
+ .filter(({ id }) => selectedCapabilityIds.has(id))
101
+ .map(({ id }) => id);
102
+ if (!selectedCapabilityIds.has(agentAccessCapabilityId))
103
+ return selectedActionIds;
104
+ const selectedClients = accessible
105
+ ? await selectClientsAccessibly(clientActions)
106
+ : await selectClients(clientActions);
107
+ return selectedClients === undefined
108
+ ? undefined
109
+ : [...selectedClients, ...selectedActionIds];
110
+ };
111
+ const setupCapabilities = (clientActions, componentActions) => [
112
+ ...(clientActions.length === 0
113
+ ? []
114
+ : [
115
+ {
116
+ id: agentAccessCapabilityId,
117
+ label: "Coding-agent access (MCP)",
118
+ hint: `${String(clientActions.length)} detected ${clientActions.length === 1 ? "agent" : "agents"}`,
119
+ },
120
+ ]),
121
+ ...componentActions.map((action) => ({
122
+ id: action.id,
123
+ label: `${action.label} (${actionModality(action)})`,
124
+ hint: `${action.operation} · ${action.target}`,
125
+ })),
126
+ ];
127
+ const selectCapabilities = async (capabilities) => {
128
+ const selection = await multiselect({
129
+ ...promptStreams,
130
+ message: "What should REA set up?",
131
+ options: capabilities.map((capability) => ({
132
+ value: capability.id,
133
+ label: capability.label,
134
+ hint: capability.hint,
135
+ })),
136
+ required: false,
137
+ maxItems: Math.max(3, Math.min(capabilities.length, (process.stderr.rows ?? 24) - 8)),
138
+ showInstructions: true,
139
+ });
140
+ return isCancel(selection) ? undefined : selection;
141
+ };
142
+ const selectCapabilitiesAccessibly = async (capabilities) => {
143
+ const selected = [];
144
+ for (const capability of capabilities) {
145
+ const included = await confirm({
146
+ ...promptStreams,
147
+ message: `Set up ${capability.label}? ${capability.hint}`,
148
+ initialValue: false,
149
+ vertical: true,
150
+ });
151
+ if (isCancel(included))
152
+ return undefined;
153
+ if (included)
154
+ selected.push(capability.id);
155
+ }
156
+ return selected;
157
+ };
158
+ const selectClients = async (actions) => {
159
+ const selection = await multiselect({
160
+ ...promptStreams,
161
+ message: "Which agents should use REA?",
162
+ options: actions.map((action) => ({
163
+ value: action.id,
164
+ label: `${action.label} (detected)`,
165
+ hint: `${action.operation} · ${action.target}`,
166
+ })),
167
+ required: false,
168
+ maxItems: Math.max(3, Math.min(actions.length, (process.stderr.rows ?? 24) - 8)),
169
+ showInstructions: true,
170
+ });
171
+ return isCancel(selection) ? undefined : selection;
172
+ };
173
+ const selectClientsAccessibly = async (actions) => {
174
+ const selected = [];
175
+ for (const action of actions) {
176
+ const included = await confirm({
177
+ ...promptStreams,
178
+ message: `Configure ${action.label}? ${action.target}`,
179
+ initialValue: false,
180
+ vertical: true,
181
+ });
182
+ if (isCancel(included))
183
+ return undefined;
184
+ if (included)
185
+ selected.push(action.id);
186
+ }
187
+ return selected;
188
+ };
189
+ const renderValueIntroduction = () => {
190
+ writeLine("│ Understand local apps and binaries from your coding agent.");
191
+ writeLine("│");
192
+ writeLine("│ • Trace how a feature works with local evidence.");
193
+ writeLine("│ • Use the same analysis capabilities from REA's CLI and supported agents.");
194
+ writeLine("│ • Keep analyzed targets on this machine instead of uploading them to a hosted service.");
195
+ };
196
+ const renderDetectedSummary = (actions) => {
197
+ const clients = actions.filter(({ kind }) => kind === "configure_client");
198
+ writeLine("│");
199
+ if (clients.length === 0) {
200
+ writeLine("◆ No agent integrations need configuration");
201
+ }
202
+ else {
203
+ writeLine(`◆ Found ${String(clients.length)} supported ${clients.length === 1 ? "agent" : "agents"}`);
204
+ writeLine(`│ ${humanList(clients.map(({ label }) => label))}`);
205
+ }
206
+ };
207
+ const renderKeyboardHelp = (accessible) => {
208
+ writeLine("│");
209
+ writeLine(accessible
210
+ ? "│ Keys: Enter answer · Ctrl-C cancel"
211
+ : "│ Keys: ↑/↓ navigate · Space toggle · Enter confirm · Ctrl-C cancel");
212
+ };
213
+ const renderReadyCapabilities = (result, readyClients) => {
214
+ writeLine("◆ What you can do now");
215
+ const providers = readyProviders(result);
216
+ if (providers.length > 0)
217
+ writeLine(`│ Deep analysis: ${humanList(providers)}`);
218
+ if (readyClients.length > 0)
219
+ writeLine(`│ Agent access: ${humanList(readyClients)}`);
220
+ if (result.doctor.identity?.skill.state === "aligned")
221
+ writeLine("│ Guided reverse-engineering workflows: installed");
222
+ if (providers.length > 0)
223
+ writeLine("│ CLI: rea analyze /path/to/app");
224
+ const firstClient = readyClients[0];
225
+ if (firstClient !== undefined)
226
+ writeLine(`│ Try in ${firstClient}: "Use REA to explain how a feature works in /path/to/app."`);
227
+ };
228
+ const readyAgentClients = (result, changedClients) => {
229
+ const alignedClients = (result.doctor.identity?.registrations ?? [])
230
+ .filter(({ state }) => state === "aligned")
231
+ .map(({ client }) => clientDisplayNames.get(client) ?? client);
232
+ return [...new Set([...alignedClients, ...changedClients])];
233
+ };
234
+ const readyProviders = (result) => {
235
+ const providers = [
236
+ ...(result.doctor.hopperPath === undefined ? [] : ["Hopper"]),
237
+ ...(result.doctor.providerInspections ?? [])
238
+ .filter(({ available }) => available)
239
+ .map(({ id }) => displayProviderId(id)),
240
+ ];
241
+ return [...new Set(providers)];
242
+ };
243
+ const displayProviderId = (id) => id.length === 0 ? id : `${id[0]?.toUpperCase() ?? ""}${id.slice(1)}`;
244
+ const actionModality = (action) => {
245
+ if (action.kind === "configure_client")
246
+ return "MCP";
247
+ if (action.kind === "install_hopper")
248
+ return "provider";
249
+ return "skill";
250
+ };
251
+ const humanList = (values) => {
252
+ if (values.length < 2)
253
+ return values[0] ?? "";
254
+ if (values.length === 2)
255
+ return `${values[0]} and ${values[1]}`;
256
+ return `${values.slice(0, -1).join(", ")}, and ${values.at(-1)}`;
257
+ };
258
+ const renderPreflight = (actions) => {
259
+ writeLine("│");
260
+ writeLine("◆ Ready to review");
261
+ for (const action of actions) {
262
+ writeLine("│");
263
+ writeLine(`│ ${action.operation.toUpperCase()} ${action.label}`);
264
+ writeLine(`│ ${action.target}`);
265
+ if (action.backupPath !== undefined)
266
+ writeLine(`│ backup: ${action.backupPath}`);
267
+ for (const origin of action.networkOrigins ?? [])
268
+ writeLine(`│ network: ${origin}`);
269
+ if (action.integrity !== undefined)
270
+ writeLine(`│ integrity: ${action.integrity}`);
271
+ for (const command of action.commands ?? [])
272
+ writeLine(`│ command: ${command}`);
273
+ writeLine(`│ ${action.detail}`);
274
+ if (action.external)
275
+ writeLine("│ external software");
276
+ }
277
+ writeLine("│");
278
+ writeLine("│ REA will preserve unrelated configuration and will not install or upgrade Node.js, npm, Homebrew, Java, or Ghidra.");
279
+ };
280
+ const cancelledDecision = () => {
281
+ cancel("Setup cancelled. No changes were made.", promptStreams);
282
+ return {
283
+ approved: false,
284
+ selectedActionIds: [],
285
+ };
286
+ };
287
+ const writeLine = (line) => {
288
+ process.stderr.write(`${line}\n`);
289
+ };
@@ -0,0 +1,107 @@
1
+ import { z } from "zod";
2
+ import { isAbsolute } from "node:path";
3
+ import { ConfigurationError } from "../domain/errors.js";
4
+ import { err, ok } from "../domain/result.js";
5
+ import { analysisProviderSelectorSchema } from "../contracts/providerSelection.js";
6
+ const environmentSchema = z
7
+ .object({
8
+ REA_ANALYSIS_PROVIDER: analysisProviderSelectorSchema.default("auto"),
9
+ GHIDRA_INSTALL_DIR: z
10
+ .string()
11
+ .min(1)
12
+ .refine(isAbsolute, "GHIDRA_INSTALL_DIR must be absolute")
13
+ .optional(),
14
+ JAVA_HOME: z
15
+ .string()
16
+ .min(1)
17
+ .refine(isAbsolute, "JAVA_HOME must be absolute")
18
+ .optional(),
19
+ REA_ILSPY_CMD_PATH: z
20
+ .string()
21
+ .min(1)
22
+ .refine(isAbsolute, "REA_ILSPY_CMD_PATH must be absolute")
23
+ .optional(),
24
+ HOPPER_LAUNCHER_PATH: z.string().min(1).optional(),
25
+ HOPPER_TARGET_PATH: z.string().min(1).optional(),
26
+ HOPPER_TARGET_KIND: z
27
+ .enum(["executable", "database"])
28
+ .default("executable"),
29
+ HOPPER_LOADER_ARGS_JSON: z.string().optional(),
30
+ REA_LOG_LEVEL: z
31
+ .enum(["trace", "debug", "info", "warn", "error", "fatal", "silent"])
32
+ .default("info"),
33
+ REA_PROCESS_CAPTURE_ENABLED: z.enum(["true", "false"]).default("false"),
34
+ REA_PROCESS_CAPTURE_AUTO_GRANT: z.enum(["true", "false"]).default("true"),
35
+ REA_ARTIFACT_NATIVE_MOUNT_ENABLED: z
36
+ .enum(["true", "false"])
37
+ .default("false"),
38
+ REA_ARTIFACT_INTEGRITY_CONTINUE_ENABLED: z
39
+ .enum(["true", "false"])
40
+ .default("false"),
41
+ REA_PROCESS_ALLOW_EXTERNAL_NETWORK: z
42
+ .enum(["true", "false"])
43
+ .default("false"),
44
+ REA_PROCESS_EXECUTABLE_ROOTS_JSON: z.string().default("[]"),
45
+ REA_PROCESS_WORKING_ROOTS_JSON: z.string().default("[]"),
46
+ REA_PROCESS_ALLOWED_ENV_JSON: z.string().default("[]"),
47
+ REA_EVIDENCE_ROOTS_JSON: z.string().default("[]"),
48
+ REA_INVESTIGATION_INPUT_ROOTS_JSON: z.string().default("[]"),
49
+ REA_ANALYSIS_SNAPSHOT_ROOTS_JSON: z.string().default("[]"),
50
+ REA_REFERENCE_ROOTS_JSON: z.string().default("[]"),
51
+ REA_REFERENCE_SECRET_PATTERNS_JSON: z.string().default("[]"),
52
+ REA_BROWSER_OBSERVE_ENABLED: z.enum(["true", "false"]).default("false"),
53
+ REA_BROWSER_CDP_ENDPOINTS_JSON: z.string().default("[]"),
54
+ REA_BROWSER_ALLOWED_ORIGINS_JSON: z.string().default("[]"),
55
+ REA_ELECTRON_OBSERVE_ENABLED: z.enum(["true", "false"]).default("false"),
56
+ REA_ELECTRON_CDP_ENDPOINTS_JSON: z.string().default("[]"),
57
+ REA_ELECTRON_FILE_ROOTS_JSON: z.string().default("[]"),
58
+ REA_JAVASCRIPT_REPLAY_ENABLED: z.enum(["true", "false"]).default("false"),
59
+ REA_JAVASCRIPT_REPLAY_ROOTS_JSON: z.string().default("[]"),
60
+ REA_JAVASCRIPT_REPLAY_NODE_PATH: z
61
+ .string()
62
+ .min(1)
63
+ .refine(isAbsolute, "REA_JAVASCRIPT_REPLAY_NODE_PATH must be absolute")
64
+ .default(process.execPath),
65
+ REA_JAVASCRIPT_REPLAY_BWRAP_PATH: z
66
+ .string()
67
+ .min(1)
68
+ .refine(isAbsolute, "REA_JAVASCRIPT_REPLAY_BWRAP_PATH must be absolute")
69
+ .default("/usr/bin/bwrap"),
70
+ REA_JAVASCRIPT_REPLAY_SYSTEMD_RUN_PATH: z
71
+ .string()
72
+ .min(1)
73
+ .refine(isAbsolute, "REA_JAVASCRIPT_REPLAY_SYSTEMD_RUN_PATH must be absolute")
74
+ .default("/usr/bin/systemd-run"),
75
+ REA_JAVASCRIPT_REPLAY_SYSTEMCTL_PATH: z
76
+ .string()
77
+ .min(1)
78
+ .refine(isAbsolute, "REA_JAVASCRIPT_REPLAY_SYSTEMCTL_PATH must be absolute")
79
+ .default("/usr/bin/systemctl"),
80
+ REA_JAVASCRIPT_REPLAY_SHELL_PATH: z
81
+ .string()
82
+ .min(1)
83
+ .refine(isAbsolute, "REA_JAVASCRIPT_REPLAY_SHELL_PATH must be absolute")
84
+ .default("/usr/bin/bash"),
85
+ REA_MANAGED_RUNTIME_ENABLED: z.enum(["true", "false"]).default("false"),
86
+ REA_MANAGED_RUNTIME_ROOTS_JSON: z.string().default("[]"),
87
+ REA_MANAGED_RUNTIME_EXECUTABLE_PATH: z
88
+ .string()
89
+ .min(1)
90
+ .refine(isAbsolute, "REA_MANAGED_RUNTIME_EXECUTABLE_PATH must be absolute")
91
+ .default("/usr/bin/dotnet"),
92
+ REA_PERMISSION_PROJECT_ROOT: z.string().min(1).optional(),
93
+ REA_PERMISSION_PROJECT_STORE: z.string().min(1).optional(),
94
+ })
95
+ .refine((value) => (value.REA_PERMISSION_PROJECT_ROOT === undefined) ===
96
+ (value.REA_PERMISSION_PROJECT_STORE === undefined), {
97
+ message: "REA_PERMISSION_PROJECT_ROOT and REA_PERMISSION_PROJECT_STORE must be configured together",
98
+ });
99
+ export const parseEnvironment = (environment) => {
100
+ const parsed = environmentSchema.safeParse(environment);
101
+ if (!parsed.success) {
102
+ return err(new ConfigurationError("Invalid REA environment configuration", {
103
+ cause: parsed.error,
104
+ }));
105
+ }
106
+ return ok(parsed.data);
107
+ };
@@ -0,0 +1,228 @@
1
+ import { isAbsolute } from "node:path";
2
+ import { ConfigurationError } from "../domain/errors.js";
3
+ import { err, ok } from "../domain/result.js";
4
+ import { parseEnvironment } from "./environment.js";
5
+ import { parseStringArray, parseBrowserArray, parseElectronFileRoots, parseLoaderArgs, } from "./parsers.js";
6
+ import { filePolicy, permissionScope, administratorGrants, browserNetworkScope, } from "./permissions.js";
7
+ import { browserEndpointSchema, browserOriginSchema, } from "../domain/browserObservation.js";
8
+ const DEFAULT_HOPPER_LAUNCHER_PATH = "/Applications/Hopper Disassembler.app/Contents/MacOS/hopper";
9
+ const defaultHopperLauncherPath = () => process.platform === "linux"
10
+ ? "/opt/hopper/bin/Hopper"
11
+ : DEFAULT_HOPPER_LAUNCHER_PATH;
12
+ const parseAllArrays = (env) => {
13
+ const loaderArgs = parseLoaderArgs(env.HOPPER_LOADER_ARGS_JSON);
14
+ if (!loaderArgs.ok)
15
+ return loaderArgs;
16
+ const executableRoots = parseStringArray(env.REA_PROCESS_EXECUTABLE_ROOTS_JSON, "REA_PROCESS_EXECUTABLE_ROOTS_JSON");
17
+ if (!executableRoots.ok)
18
+ return executableRoots;
19
+ const workingRoots = parseStringArray(env.REA_PROCESS_WORKING_ROOTS_JSON, "REA_PROCESS_WORKING_ROOTS_JSON");
20
+ if (!workingRoots.ok)
21
+ return workingRoots;
22
+ const allowedEnvironment = parseStringArray(env.REA_PROCESS_ALLOWED_ENV_JSON, "REA_PROCESS_ALLOWED_ENV_JSON");
23
+ if (!allowedEnvironment.ok)
24
+ return allowedEnvironment;
25
+ const evidenceRoots = parseStringArray(env.REA_EVIDENCE_ROOTS_JSON, "REA_EVIDENCE_ROOTS_JSON");
26
+ if (!evidenceRoots.ok)
27
+ return evidenceRoots;
28
+ const investigationInputRoots = parseStringArray(env.REA_INVESTIGATION_INPUT_ROOTS_JSON, "REA_INVESTIGATION_INPUT_ROOTS_JSON");
29
+ if (!investigationInputRoots.ok)
30
+ return investigationInputRoots;
31
+ const analysisSnapshotRoots = parseStringArray(env.REA_ANALYSIS_SNAPSHOT_ROOTS_JSON, "REA_ANALYSIS_SNAPSHOT_ROOTS_JSON");
32
+ if (!analysisSnapshotRoots.ok)
33
+ return analysisSnapshotRoots;
34
+ const referenceRoots = parseStringArray(env.REA_REFERENCE_ROOTS_JSON, "REA_REFERENCE_ROOTS_JSON");
35
+ if (!referenceRoots.ok)
36
+ return referenceRoots;
37
+ const secretPatterns = parseStringArray(env.REA_REFERENCE_SECRET_PATTERNS_JSON, "REA_REFERENCE_SECRET_PATTERNS_JSON");
38
+ if (!secretPatterns.ok)
39
+ return secretPatterns;
40
+ const browserEndpoints = parseBrowserArray(env.REA_BROWSER_CDP_ENDPOINTS_JSON, "REA_BROWSER_CDP_ENDPOINTS_JSON", browserEndpointSchema, 16);
41
+ if (!browserEndpoints.ok)
42
+ return browserEndpoints;
43
+ const browserOrigins = parseBrowserArray(env.REA_BROWSER_ALLOWED_ORIGINS_JSON, "REA_BROWSER_ALLOWED_ORIGINS_JSON", browserOriginSchema, 32);
44
+ if (!browserOrigins.ok)
45
+ return browserOrigins;
46
+ const electronEndpoints = parseBrowserArray(env.REA_ELECTRON_CDP_ENDPOINTS_JSON, "REA_ELECTRON_CDP_ENDPOINTS_JSON", browserEndpointSchema, 16);
47
+ if (!electronEndpoints.ok)
48
+ return electronEndpoints;
49
+ const electronFileRoots = parseElectronFileRoots(env.REA_ELECTRON_FILE_ROOTS_JSON);
50
+ if (!electronFileRoots.ok)
51
+ return electronFileRoots;
52
+ const javascriptReplayRoots = parseAbsoluteRoots(env.REA_JAVASCRIPT_REPLAY_ROOTS_JSON, "REA_JAVASCRIPT_REPLAY_ROOTS_JSON");
53
+ if (!javascriptReplayRoots.ok)
54
+ return javascriptReplayRoots;
55
+ const managedRuntimeRoots = parseAbsoluteRoots(env.REA_MANAGED_RUNTIME_ROOTS_JSON, "REA_MANAGED_RUNTIME_ROOTS_JSON");
56
+ if (!managedRuntimeRoots.ok)
57
+ return managedRuntimeRoots;
58
+ return ok({
59
+ loaderArgs: loaderArgs.value,
60
+ executableRoots: executableRoots.value,
61
+ workingRoots: workingRoots.value,
62
+ allowedEnvironment: allowedEnvironment.value,
63
+ evidenceRoots: evidenceRoots.value,
64
+ investigationInputRoots: investigationInputRoots.value,
65
+ analysisSnapshotRoots: analysisSnapshotRoots.value,
66
+ referenceRoots: referenceRoots.value,
67
+ secretPatterns: secretPatterns.value,
68
+ browserEndpoints: browserEndpoints.value,
69
+ browserOrigins: browserOrigins.value,
70
+ electronEndpoints: electronEndpoints.value,
71
+ electronFileRoots: electronFileRoots.value,
72
+ javascriptReplayRoots: javascriptReplayRoots.value,
73
+ managedRuntimeRoots: managedRuntimeRoots.value,
74
+ });
75
+ };
76
+ const parseAbsoluteRoots = (value, name) => {
77
+ const parsed = parseStringArray(value, name);
78
+ if (!parsed.ok)
79
+ return parsed;
80
+ return parsed.value.some((root) => !isAbsolute(root))
81
+ ? err(new ConfigurationError(`${name} must encode absolute roots`))
82
+ : parsed;
83
+ };
84
+ const appendProcessCaptureCeiling = (ceilings, env, arrays) => {
85
+ if (env.REA_PROCESS_CAPTURE_ENABLED !== "true")
86
+ return;
87
+ ceilings.push(permissionScope("process_capture", arrays.workingRoots, {
88
+ executables: arrays.executableRoots,
89
+ environment_names: arrays.allowedEnvironment,
90
+ network: env.REA_PROCESS_ALLOW_EXTERNAL_NETWORK === "true" ? "external" : "none",
91
+ }));
92
+ };
93
+ const appendBrowserObservationCeiling = (ceilings, env, arrays) => {
94
+ if (env.REA_BROWSER_OBSERVE_ENABLED !== "true")
95
+ return;
96
+ ceilings.push(permissionScope("browser_observe", [], {
97
+ origins: [...arrays.browserEndpoints, ...arrays.browserOrigins],
98
+ network: browserNetworkScope(arrays.browserOrigins),
99
+ }));
100
+ };
101
+ const appendElectronObservationCeiling = (ceilings, env, arrays) => {
102
+ if (env.REA_ELECTRON_OBSERVE_ENABLED !== "true")
103
+ return;
104
+ ceilings.push(permissionScope("electron_observe", arrays.electronFileRoots, {
105
+ origins: arrays.electronEndpoints,
106
+ network: "loopback",
107
+ }));
108
+ };
109
+ const appendNativeMountCeiling = (ceilings, env) => {
110
+ if (env.REA_ARTIFACT_NATIVE_MOUNT_ENABLED === "true")
111
+ ceilings.push(permissionScope("native_mount", [], { mount: true }));
112
+ };
113
+ const appendJavaScriptReplayCeiling = (ceilings, env, arrays) => {
114
+ if (env.REA_JAVASCRIPT_REPLAY_ENABLED !== "true")
115
+ return;
116
+ ceilings.push(permissionScope("javascript_replay", arrays.javascriptReplayRoots, {
117
+ executables: [
118
+ env.REA_JAVASCRIPT_REPLAY_NODE_PATH,
119
+ env.REA_JAVASCRIPT_REPLAY_BWRAP_PATH,
120
+ env.REA_JAVASCRIPT_REPLAY_SYSTEMD_RUN_PATH,
121
+ env.REA_JAVASCRIPT_REPLAY_SYSTEMCTL_PATH,
122
+ env.REA_JAVASCRIPT_REPLAY_SHELL_PATH,
123
+ ],
124
+ network: "none",
125
+ mount: true,
126
+ }));
127
+ };
128
+ const appendManagedRuntimeCeiling = (ceilings, env, arrays) => {
129
+ if (env.REA_MANAGED_RUNTIME_ENABLED !== "true")
130
+ return;
131
+ ceilings.push(permissionScope("managed_runtime", arrays.managedRuntimeRoots, {
132
+ executables: [env.REA_MANAGED_RUNTIME_EXECUTABLE_PATH],
133
+ network: "none",
134
+ }));
135
+ };
136
+ const buildPermissionCeilings = (env, arrays) => {
137
+ const ceilings = [
138
+ permissionScope("evidence_read", arrays.evidenceRoots),
139
+ permissionScope("evidence_write", arrays.evidenceRoots),
140
+ permissionScope("investigation_input", arrays.investigationInputRoots),
141
+ permissionScope("investigation_workspace_read", arrays.evidenceRoots),
142
+ permissionScope("investigation_workspace_write", arrays.evidenceRoots),
143
+ permissionScope("snapshot_read", arrays.analysisSnapshotRoots),
144
+ permissionScope("snapshot_write", arrays.analysisSnapshotRoots),
145
+ permissionScope("artifact_extract", ["/"]),
146
+ permissionScope("reference_read", arrays.referenceRoots),
147
+ ];
148
+ appendProcessCaptureCeiling(ceilings, env, arrays);
149
+ appendBrowserObservationCeiling(ceilings, env, arrays);
150
+ appendElectronObservationCeiling(ceilings, env, arrays);
151
+ appendNativeMountCeiling(ceilings, env);
152
+ appendJavaScriptReplayCeiling(ceilings, env, arrays);
153
+ appendManagedRuntimeCeiling(ceilings, env, arrays);
154
+ return ceilings;
155
+ };
156
+ const buildAppConfig = (env, arrays, permissionCeilings) => ({
157
+ analysisProvider: env.REA_ANALYSIS_PROVIDER,
158
+ ghidraInstallDir: env.GHIDRA_INSTALL_DIR,
159
+ ghidraJavaHome: env.JAVA_HOME,
160
+ ilspyCmdPath: env.REA_ILSPY_CMD_PATH,
161
+ hopperLauncherPath: env.HOPPER_LAUNCHER_PATH ?? defaultHopperLauncherPath(),
162
+ hopperTargetPath: env.HOPPER_TARGET_PATH,
163
+ hopperTargetKind: env.HOPPER_TARGET_KIND,
164
+ hopperLoaderArgs: arrays.loaderArgs,
165
+ logLevel: env.REA_LOG_LEVEL,
166
+ processExecutionPolicy: {
167
+ enabled: env.REA_PROCESS_CAPTURE_ENABLED === "true",
168
+ executableRoots: arrays.executableRoots,
169
+ workingRoots: arrays.workingRoots,
170
+ allowedEnvironment: arrays.allowedEnvironment,
171
+ allowExternalNetwork: env.REA_PROCESS_ALLOW_EXTERNAL_NETWORK === "true",
172
+ },
173
+ artifactNativeMountEnabled: env.REA_ARTIFACT_NATIVE_MOUNT_ENABLED === "true",
174
+ artifactIntegrityContinueEnabled: env.REA_ARTIFACT_INTEGRITY_CONTINUE_ENABLED === "true",
175
+ evidenceFilePolicy: filePolicy(arrays.evidenceRoots),
176
+ investigationInputRoots: arrays.investigationInputRoots,
177
+ analysisSnapshotFilePolicy: filePolicy(arrays.analysisSnapshotRoots),
178
+ referenceSourcePolicy: {
179
+ roots: arrays.referenceRoots,
180
+ secretPatterns: arrays.secretPatterns,
181
+ maxBytes: 16 * 1024 * 1024,
182
+ maxEntries: 10_000,
183
+ maxDepth: 32,
184
+ maxPathBytes: 4_096,
185
+ },
186
+ browserObservationEnabled: env.REA_BROWSER_OBSERVE_ENABLED === "true",
187
+ browserCdpEndpoints: arrays.browserEndpoints,
188
+ browserAllowedOrigins: arrays.browserOrigins,
189
+ electronObservationEnabled: env.REA_ELECTRON_OBSERVE_ENABLED === "true",
190
+ electronCdpEndpoints: arrays.electronEndpoints,
191
+ electronFileRoots: arrays.electronFileRoots,
192
+ javascriptReplayPolicy: {
193
+ enabled: env.REA_JAVASCRIPT_REPLAY_ENABLED === "true",
194
+ roots: arrays.javascriptReplayRoots,
195
+ nodePath: env.REA_JAVASCRIPT_REPLAY_NODE_PATH,
196
+ bubblewrapPath: env.REA_JAVASCRIPT_REPLAY_BWRAP_PATH,
197
+ systemdRunPath: env.REA_JAVASCRIPT_REPLAY_SYSTEMD_RUN_PATH,
198
+ systemctlPath: env.REA_JAVASCRIPT_REPLAY_SYSTEMCTL_PATH,
199
+ shellPath: env.REA_JAVASCRIPT_REPLAY_SHELL_PATH,
200
+ },
201
+ managedRuntimePolicy: {
202
+ enabled: env.REA_MANAGED_RUNTIME_ENABLED === "true",
203
+ roots: arrays.managedRuntimeRoots,
204
+ executablePath: env.REA_MANAGED_RUNTIME_EXECUTABLE_PATH,
205
+ },
206
+ permissionCeilings,
207
+ administratorPermissionGrants: administratorGrants(env.REA_PROCESS_CAPTURE_AUTO_GRANT === "true"
208
+ ? permissionCeilings
209
+ : permissionCeilings.filter(({ capability }) => capability !== "process_capture")),
210
+ permissionProjectRoot: env.REA_PERMISSION_PROJECT_ROOT,
211
+ permissionProjectStore: env.REA_PERMISSION_PROJECT_STORE,
212
+ });
213
+ /**
214
+ * Parse provider and authority configuration once at the composition root.
215
+ * Explicit loader arguments override REA's header-derived defaults for a
216
+ * supported target, allowing callers to refine Hopper's loader behavior without
217
+ * bypassing REA's path and executable-header checks.
218
+ */
219
+ export const parseConfig = (environment) => {
220
+ const envResult = parseEnvironment(environment);
221
+ if (!envResult.ok)
222
+ return envResult;
223
+ const arraysResult = parseAllArrays(envResult.value);
224
+ if (!arraysResult.ok)
225
+ return arraysResult;
226
+ const permissionCeilings = buildPermissionCeilings(envResult.value, arraysResult.value);
227
+ return ok(buildAppConfig(envResult.value, arraysResult.value, permissionCeilings));
228
+ };