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,58 @@
1
+ import { z } from "zod";
2
+ import { AnalysisInputError, AnalysisProtocolError, } from "../domain/errors.js";
3
+ import { createEvidence } from "../domain/evidence.js";
4
+ import { jsonValueSchema } from "../domain/jsonValue.js";
5
+ import { importManagedReconstruction, managedReconstructionImportInputSchema, } from "../domain/managedReconstruction.js";
6
+ import { err, ok } from "../domain/result.js";
7
+ import { MANAGED_WORKFLOW_PROVIDER } from "./InvestigationProviders.js";
8
+ const OPERATION = "import_managed_reconstruction";
9
+ /** Authenticate and import managed decompiler reconstruction as Evidence. */
10
+ export const importManagedReconstructionEvidence = (rawInput) => {
11
+ const parsed = managedReconstructionImportInputSchema.safeParse(rawInput);
12
+ if (!parsed.success)
13
+ return err(new AnalysisInputError(OPERATION, { cause: parsed.error }));
14
+ return importManagedReconstructionEvidenceValidated(parsed.data);
15
+ };
16
+ /** Import reconstruction from input parsed by a trusted adapter. */
17
+ export const importManagedReconstructionEvidenceValidated = (input) => {
18
+ try {
19
+ const result = importManagedReconstruction(input);
20
+ return ok(createManagedReconstructionEvidence(input, result));
21
+ }
22
+ catch (cause) {
23
+ return err(cause instanceof TypeError || cause instanceof z.ZodError
24
+ ? new AnalysisInputError(OPERATION, { cause })
25
+ : new AnalysisProtocolError("Managed reconstruction import produced an invalid result", { cause }));
26
+ }
27
+ };
28
+ const createManagedReconstructionEvidence = (input, result) => createEvidence({
29
+ path: result.static_observation.artifact_path,
30
+ sha256: result.static_observation.artifact_sha256,
31
+ format: "pe",
32
+ }, MANAGED_WORKFLOW_PROVIDER, {
33
+ predicateType: "rea.managed-reconstruction-import/v1",
34
+ operation: OPERATION,
35
+ parameters: {
36
+ static_members_evidence_id: input.static_members.evidence_id,
37
+ decompiler: jsonValueSchema.parse(result.decompiler),
38
+ method_locks: jsonValueSchema.parse(input.methods.map(({ token, signature_sha256, normalized_il_sha256 }) => ({
39
+ token,
40
+ signature_sha256,
41
+ normalized_il_sha256,
42
+ }))),
43
+ notes: jsonValueSchema.parse(input.notes),
44
+ },
45
+ result: jsonValueSchema.parse(result),
46
+ rawResult: null,
47
+ confidence: "inferred",
48
+ authority: "analyst-inference",
49
+ environment: null,
50
+ limitations: result.limitations,
51
+ locations: [
52
+ {
53
+ kind: "artifact-path",
54
+ path: result.static_observation.artifact_path,
55
+ },
56
+ ],
57
+ evidenceLinks: result.evidence_links,
58
+ });
@@ -0,0 +1,103 @@
1
+ import { AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisProtocolError, PermissionRequiredError, } from "../domain/errors.js";
2
+ import { createEvidence, parseEvidence, } from "../domain/evidence.js";
3
+ import { jsonValueSchema } from "../domain/jsonValue.js";
4
+ import { managedRuntimeCorrelationInputSchema, planManagedRuntimeCorrelation, } from "../domain/managedRuntimeCorrelation.js";
5
+ import { err, ok } from "../domain/result.js";
6
+ import { MANAGED_WORKFLOW_PROVIDER } from "./InvestigationProviders.js";
7
+ import { digestJson } from "./JavaScriptReplayPlanning.js";
8
+ const OPERATION = "plan_managed_runtime_correlation";
9
+ /** Create a separately authorized, non-executing managed runtime plan Evidence. */
10
+ export const planManagedRuntimeCorrelationEvidence = async (dependencies, rawInput) => {
11
+ const parsed = managedRuntimeCorrelationInputSchema.safeParse(rawInput);
12
+ if (!parsed.success)
13
+ return err(new AnalysisInputError(OPERATION, { cause: parsed.error }));
14
+ return planManagedRuntimeCorrelationEvidenceValidated(dependencies, parsed.data);
15
+ };
16
+ /** Plan runtime correlation from input parsed by a trusted adapter. */
17
+ export const planManagedRuntimeCorrelationEvidenceValidated = async (dependencies, input) => {
18
+ if (!dependencies.policy.enabled)
19
+ return err(new AnalysisCapabilityUnavailableError(MANAGED_WORKFLOW_PROVIDER.id, OPERATION, "managed runtime correlation is disabled; configure exact roots and runtime executable before enabling it"));
20
+ if (dependencies.authority === undefined)
21
+ return err(new AnalysisCapabilityUnavailableError(MANAGED_WORKFLOW_PROVIDER.id, OPERATION, "managed runtime permission policy is not configured"));
22
+ let staticEvidence;
23
+ let artifactPath;
24
+ try {
25
+ staticEvidence = parseEvidence(input.static_members);
26
+ artifactPath = artifactPathFor(staticEvidence);
27
+ }
28
+ catch (cause) {
29
+ return err(new AnalysisInputError(OPERATION, { cause }));
30
+ }
31
+ const authorized = await dependencies.authority.explain({
32
+ capability: "managed_runtime",
33
+ roots: [artifactPath],
34
+ executables: [dependencies.policy.executablePath],
35
+ environment_names: [],
36
+ network: "none",
37
+ mount: false,
38
+ operation_identity: operationIdentity(input, staticEvidence),
39
+ }, "read", { restartRequired: true });
40
+ if (!authorized.ok)
41
+ return err(authorized.error instanceof PermissionRequiredError
42
+ ? authorized.error
43
+ : new AnalysisProtocolError(authorized.error.message, {
44
+ cause: authorized.error,
45
+ }));
46
+ try {
47
+ const result = planManagedRuntimeCorrelation(input, dependencies.policy.executablePath, authorized.value.grant_id);
48
+ return ok(createEvidence({
49
+ path: result.static_observation.artifact_path,
50
+ sha256: result.static_observation.artifact_sha256,
51
+ format: "pe",
52
+ }, MANAGED_WORKFLOW_PROVIDER, {
53
+ predicateType: "rea.managed-runtime-correlation-plan/v1",
54
+ operation: OPERATION,
55
+ parameters: {
56
+ static_members_evidence_id: staticEvidence.evidence_id,
57
+ method: jsonValueSchema.parse(input.method),
58
+ requested_effect: input.requested_effect,
59
+ host: jsonValueSchema.parse(input.host),
60
+ bounds: jsonValueSchema.parse(input.bounds),
61
+ },
62
+ result: jsonValueSchema.parse(result),
63
+ rawResult: null,
64
+ confidence: "derived",
65
+ authority: "analyst-inference",
66
+ environment: null,
67
+ limitations: result.limitations,
68
+ locations: [
69
+ {
70
+ kind: "artifact-path",
71
+ path: result.static_observation.artifact_path,
72
+ },
73
+ ],
74
+ evidenceLinks: result.evidence_links,
75
+ }));
76
+ }
77
+ catch (cause) {
78
+ return err(cause instanceof TypeError
79
+ ? new AnalysisInputError(OPERATION, { cause })
80
+ : new AnalysisProtocolError("Managed runtime correlation planning produced an invalid result", { cause }));
81
+ }
82
+ };
83
+ const artifactPathFor = (evidence) => {
84
+ const result = evidence.normalized_result;
85
+ if (typeof result === "object" &&
86
+ result !== null &&
87
+ "artifact" in result &&
88
+ typeof result.artifact === "object" &&
89
+ result.artifact !== null &&
90
+ "path" in result.artifact &&
91
+ typeof result.artifact.path === "string")
92
+ return result.artifact.path;
93
+ throw new AnalysisInputError(OPERATION, {
94
+ cause: new TypeError("Managed member Evidence does not expose an artifact path"),
95
+ });
96
+ };
97
+ const operationIdentity = (input, evidence) => `${OPERATION}:${digestJson({
98
+ evidence_id: evidence.evidence_id,
99
+ method: input.method,
100
+ requested_effect: input.requested_effect,
101
+ host: input.host,
102
+ bounds: input.bounds,
103
+ })}`;
@@ -0,0 +1,196 @@
1
+ import { createHash } from "node:crypto";
2
+ import { z } from "zod";
3
+ import { nodeCharacterizationExecutionInputSchema, nodeCharacterizationExecutionOutputSchema, nodeCharacterizationPreparationInputSchema, nodeCharacterizationPreparationOutputSchema, } from "../domain/nodeRuntimeCharacterization.js";
4
+ import { AnalysisInputError, AnalysisProtocolError, ReplayPlanStaleError, } from "../domain/errors.js";
5
+ import { createEvidence } from "../domain/evidence.js";
6
+ import { controlledReplayOutputSchema } from "../domain/javascriptReplay.js";
7
+ import { createRuntimeCharacterizationPlan, } from "../domain/runtimeCharacterization.js";
8
+ import { err, ok } from "../domain/result.js";
9
+ import { jsonValueSchema } from "../domain/jsonValue.js";
10
+ import { InstrumentedJavaScriptReplayHost } from "./InstrumentedJavaScriptReplayHost.js";
11
+ import { runControlledReplayValidated, } from "./JavaScriptReplayService.js";
12
+ const PREPARE_OPERATION = "prepare_node_characterization";
13
+ const EXECUTE_OPERATION = "execute_node_characterization";
14
+ const PROVIDER = {
15
+ id: "rea-node-characterization",
16
+ name: "REA Node runtime characterization",
17
+ version: "1",
18
+ };
19
+ /** Prepare exact Node/JavaScript characterization without executing target code. */
20
+ export const prepareNodeCharacterization = async (dependencies, rawInput, options = {}) => {
21
+ const parsed = nodeCharacterizationPreparationInputSchema.safeParse(rawInput);
22
+ if (!parsed.success)
23
+ return err(new AnalysisInputError(PREPARE_OPERATION, { cause: parsed.error }));
24
+ const prepared = await prepareValidated(dependencies, parsed.data, options);
25
+ return prepared.ok
26
+ ? ok(jsonValueSchema.parse(nodeCharacterizationPreparationOutputSchema.parse(prepared.value)))
27
+ : prepared;
28
+ };
29
+ /** Execute only a freshly recomputed and separately approved characterization plan. */
30
+ export const executeNodeCharacterization = async (dependencies, rawInput, options = {}) => {
31
+ const parsed = nodeCharacterizationExecutionInputSchema.safeParse(rawInput);
32
+ if (!parsed.success)
33
+ return err(new AnalysisInputError(EXECUTE_OPERATION, { cause: parsed.error }));
34
+ const prepared = await prepareValidated(dependencies, parsed.data.preparation, options);
35
+ if (!prepared.ok)
36
+ return prepared;
37
+ if (prepared.value.plan.plan_sha256 !== parsed.data.approved_plan_sha256)
38
+ return err(new ReplayPlanStaleError(parsed.data.approved_plan_sha256, prepared.value.plan.plan_sha256));
39
+ const plannedReplay = controlledReplayOutputSchema.parse(prepared.value.replay);
40
+ if (plannedReplay.phase !== "plan" || plannedReplay.plan === null)
41
+ return err(new AnalysisProtocolError("Node characterization preparation did not produce a replay plan"));
42
+ const host = new InstrumentedJavaScriptReplayHost(dependencies.host, parsed.data.preparation.instrumentation);
43
+ const executed = await runControlledReplayValidated({ ...dependencies, host }, {
44
+ ...parsed.data.preparation.replay,
45
+ mode: "execute",
46
+ approved: true,
47
+ plan_digest: plannedReplay.plan.plan_digest,
48
+ }, options);
49
+ if (!executed.ok)
50
+ return executed;
51
+ if (host.instrumentation === null)
52
+ return err(new AnalysisProtocolError("Node characterization execution omitted instrumentation evidence"));
53
+ return ok(jsonValueSchema.parse(nodeCharacterizationExecutionOutputSchema.parse({
54
+ schema_version: 1,
55
+ phase: "execution",
56
+ plan: prepared.value.plan,
57
+ transformation: host.instrumentation.manifest,
58
+ transformation_evidence: prepared.value.transformation_evidence,
59
+ evidence: createCharacterizationEvidence(prepared.value, controlledReplayOutputSchema.parse(executed.value)),
60
+ replay: controlledReplayOutputSchema.parse(executed.value),
61
+ })));
62
+ };
63
+ const prepareValidated = async (dependencies, input, options) => {
64
+ const host = new InstrumentedJavaScriptReplayHost(dependencies.host, input.instrumentation);
65
+ const replay = await runControlledReplayValidated({ ...dependencies, host }, input.replay, options);
66
+ if (!replay.ok)
67
+ return replay;
68
+ const output = controlledReplayOutputSchema.parse(replay.value);
69
+ if (output.phase !== "plan" ||
70
+ output.plan === null ||
71
+ host.instrumentation === null)
72
+ return err(new AnalysisProtocolError("Node characterization preparation omitted committed plan evidence"));
73
+ const module = output.plan.left.modules.find(({ alias }) => alias === input.selected_alias);
74
+ if (module === undefined)
75
+ return err(new AnalysisProtocolError("Node characterization replay plan omitted selected module"));
76
+ const plan = createCharacterizationPlan(input, host.instrumentation, output.plan);
77
+ return ok({
78
+ schema_version: 1,
79
+ phase: "preparation",
80
+ plan,
81
+ transformation: host.instrumentation.manifest,
82
+ transformation_evidence: createTransformationEvidence(input, host.instrumentation),
83
+ replay: output,
84
+ });
85
+ };
86
+ const createTransformationEvidence = (input, instrumentation) => createEvidence({
87
+ path: input.instrumentation.artifact_path,
88
+ sha256: input.instrumentation.artifact_sha256,
89
+ format: "javascript-bundle",
90
+ }, PROVIDER, {
91
+ predicateType: "rea.javascript-export-transformation/v1",
92
+ operation: PREPARE_OPERATION,
93
+ parameters: {
94
+ selected_alias: input.selected_alias,
95
+ selected_sha256: input.instrumentation.selection.selected_sha256,
96
+ },
97
+ result: jsonValueSchema.parse(instrumentation.manifest),
98
+ confidence: "derived",
99
+ authority: "shipped-artifact",
100
+ locations: [
101
+ {
102
+ kind: "file-offset-range",
103
+ start: input.instrumentation.selection.byte_start,
104
+ end: input.instrumentation.selection.byte_end,
105
+ },
106
+ ],
107
+ limitations: [
108
+ "The transformation is deterministic derived evidence; execution authority is established only by a separately approved characterization run.",
109
+ ],
110
+ });
111
+ const createCharacterizationEvidence = (prepared, replay) => {
112
+ if (replay.phase !== "execute" || replay.evidence === null)
113
+ throw new AnalysisProtocolError("Node characterization execution omitted replay Evidence");
114
+ return createEvidence({
115
+ path: prepared.plan.artifact.path,
116
+ sha256: prepared.plan.artifact.sha256,
117
+ format: "javascript-bundle",
118
+ }, PROVIDER, {
119
+ predicateType: "rea.runtime-characterization/v1",
120
+ operation: EXECUTE_OPERATION,
121
+ parameters: {
122
+ plan_sha256: prepared.plan.plan_sha256,
123
+ replay_evidence_id: replay.evidence.evidence_id,
124
+ },
125
+ result: jsonValueSchema.parse({
126
+ plan: prepared.plan,
127
+ transformation_evidence_id: prepared.transformation_evidence.evidence_id,
128
+ replay_evidence_id: replay.evidence.evidence_id,
129
+ execution: replay.evidence.normalized_result,
130
+ }),
131
+ confidence: "observed",
132
+ authority: "controlled-replay",
133
+ environment: replay.evidence.environment,
134
+ limitations: [
135
+ "This Evidence proves only the finite approved characterization plan and transformed controlled-replay authority, not unmodified shipped-runtime equivalence.",
136
+ ...replay.evidence.limitations,
137
+ ],
138
+ evidenceLinks: [
139
+ prepared.transformation_evidence.evidence_id,
140
+ replay.evidence.evidence_id,
141
+ ],
142
+ });
143
+ };
144
+ const createCharacterizationPlan = (input, instrumentation, replayPlan) => createRuntimeCharacterizationPlan({
145
+ schema_version: 1,
146
+ preparation_sha256: digestPreparation(instrumentation.manifest.instrumented_sha256, replayPlan.plan_digest),
147
+ artifact: {
148
+ path: input.instrumentation.artifact_path,
149
+ sha256: input.instrumentation.artifact_sha256,
150
+ byte_length: instrumentation.manifest.original_byte_length,
151
+ },
152
+ runtime: {
153
+ family: "ecmascript",
154
+ provider_id: "node-javascript",
155
+ executable_path: replayPlan.runtime.executable.path,
156
+ executable_sha256: replayPlan.runtime.executable.sha256,
157
+ version: replayPlan.runtime.executable.version,
158
+ profile_sha256: replayPlan.policy_sha256,
159
+ },
160
+ callable: {
161
+ callable_id: `callable/${input.instrumentation.selection.selected_sha256}`,
162
+ module_id: stableModuleId(input.selected_alias),
163
+ export_name: input.instrumentation.selection.export_name,
164
+ semantic_evidence_id: null,
165
+ selector_sha256: input.instrumentation.selection.selected_sha256,
166
+ },
167
+ working_directory: "/work",
168
+ isolated_home: "/work",
169
+ expected_effect: input.expected_effect,
170
+ allowed_boundaries: [],
171
+ limits: {
172
+ max_calls: replayPlan.cases.length,
173
+ max_processes: 0,
174
+ max_files: 0,
175
+ max_bytes: replayPlan.limits.output_bytes,
176
+ max_handles: replayPlan.limits.tasks,
177
+ timeout_ms: replayPlan.limits.wall_time_ms,
178
+ idle_timeout_ms: replayPlan.limits.wall_time_ms,
179
+ },
180
+ determinism: {
181
+ clock: "fixed",
182
+ randomness: "seeded",
183
+ identifiers: "deterministic",
184
+ seed: replayPlan.determinism.random_seed,
185
+ },
186
+ authority: {
187
+ preparation_approved: true,
188
+ execution_approved: false,
189
+ network: "none",
190
+ provider_owned_process_only: true,
191
+ },
192
+ });
193
+ const digestPreparation = (instrumentedSha256, replayPlanDigest) => createHash("sha256")
194
+ .update(`rea.node-characterization-preparation/v1\0${instrumentedSha256}\0${replayPlanDigest}`)
195
+ .digest("hex");
196
+ const stableModuleId = (alias) => `module/${createHash("sha256").update(alias).digest("hex")}`;
@@ -73,31 +73,52 @@ const errorReason = (error) => isNotFound(error) ? "not_found" : "io";
73
73
  /** Stateful owner for permission evaluation, consumption, reload, and revoke. */
74
74
  export class PermissionAuthority {
75
75
  policy;
76
- constructor(policy) {
76
+ configuredAuthority;
77
+ constructor(policy, configuredAuthority) {
77
78
  this.policy = policy;
79
+ this.configuredAuthority = configuredAuthority;
80
+ }
81
+ /** Create a connection-owned overlay for once and session grants. */
82
+ createConnectionAuthority() {
83
+ return new PermissionAuthority(createPermissionPolicy([]), this.configuredAuthority ?? this);
78
84
  }
79
85
  /** Canonicalize and authorize one exact operation before its side effect. */
80
86
  async authorize(request, access, options = {}) {
81
- const evaluated = await this.explain(request, access, options);
87
+ const evaluated = await this.evaluateRequest(request, access, options);
82
88
  if (!evaluated.ok)
83
89
  return evaluated;
84
- const decision = evaluated.value;
85
- this.policy = consumePermission(this.policy, decision);
86
- return ok(decision);
90
+ const { decision, owner, request: canonicalRequest } = evaluated.value;
91
+ owner.policy = consumePermission(owner.policy, decision);
92
+ return ok({ ...decision, request: canonicalRequest });
87
93
  }
88
94
  /** Dry-run the exact shared evaluation without consuming a once grant. */
89
95
  async explain(request, access, options = {}) {
96
+ const evaluated = await this.evaluateRequest(request, access, options);
97
+ return evaluated.ok
98
+ ? ok({
99
+ ...evaluated.value.decision,
100
+ request: evaluated.value.request,
101
+ })
102
+ : evaluated;
103
+ }
104
+ async evaluateRequest(request, access, options) {
90
105
  const canonical = await canonicalizePermissionRequest(request, access);
91
106
  if (!canonical.ok)
92
107
  return canonical;
93
- const decision = evaluatePermission(this.policy, canonical.value);
94
- if (!decision.allowed)
95
- return err(new PermissionRequiredError(canonical.value, decision.missing, ceilingFor(this.policy, canonical.value.capability), options.elicitationSupported ?? false, options.restartRequired ?? false));
96
- return ok(decision);
108
+ const evaluated = this.evaluateCanonical(canonical.value, options);
109
+ return evaluated.ok
110
+ ? ok({ ...evaluated.value, request: canonical.value })
111
+ : evaluated;
97
112
  }
98
113
  /** Add authority beneath the administrator ceiling. */
99
114
  grant(grant) {
100
- const result = grantPermission(this.policy, grant);
115
+ const policy = this.configuredAuthority === undefined
116
+ ? this.policy
117
+ : {
118
+ ...this.policy,
119
+ ceilings: this.configuredAuthority.effectivePolicy().ceilings,
120
+ };
121
+ const result = grantPermission(policy, grant);
101
122
  if (result.ok)
102
123
  this.policy = result.value;
103
124
  return result;
@@ -110,44 +131,61 @@ export class PermissionAuthority {
110
131
  clearSessionGrants() {
111
132
  this.policy = clearSessionPermissions(this.policy);
112
133
  }
113
- /** Atomically replace optional persisted project grants. */
114
- async replaceProjectGrants(grants) {
115
- let candidate = {
116
- ...this.policy,
117
- grants: this.policy.grants.filter(({ lifetime }) => lifetime !== "project"),
134
+ effectivePolicy() {
135
+ if (this.configuredAuthority === undefined)
136
+ return this.policy;
137
+ const configured = this.configuredAuthority.effectivePolicy();
138
+ return {
139
+ ceilings: configured.ceilings,
140
+ grants: [...configured.grants, ...this.policy.grants],
141
+ revoked_grant_ids: new Set([
142
+ ...configured.revoked_grant_ids,
143
+ ...this.policy.revoked_grant_ids,
144
+ ]),
145
+ consumed_grant_ids: new Set([
146
+ ...configured.consumed_grant_ids,
147
+ ...this.policy.consumed_grant_ids,
148
+ ]),
118
149
  };
119
- for (const grant of grants) {
120
- const canonical = await canonicalizeGrant(grant);
121
- if (!canonical.ok)
122
- return canonical;
123
- const added = grantPermission(candidate, canonical.value);
124
- if (!added.ok)
125
- return err(new PermissionPathError(grant.grant_id, "io", {
126
- cause: added.error,
127
- }));
128
- candidate = added.value;
150
+ }
151
+ evaluateCanonical(request, options) {
152
+ const configured = this.configuredAuthority;
153
+ if (configured !== undefined) {
154
+ const configuredDecision = evaluatePermission(configured.effectivePolicy(), request);
155
+ if (configuredDecision.allowed)
156
+ return ok({ decision: configuredDecision, owner: configured });
129
157
  }
130
- this.policy = candidate;
131
- return ok(null);
158
+ const localPolicy = configured === undefined
159
+ ? this.policy
160
+ : { ...this.policy, ceilings: configured.effectivePolicy().ceilings };
161
+ const localDecision = evaluatePermission(localPolicy, request);
162
+ if (localDecision.allowed)
163
+ return ok({ decision: localDecision, owner: this });
164
+ const effective = this.effectivePolicy();
165
+ const denied = evaluatePermission(effective, request);
166
+ if (denied.allowed)
167
+ return ok({ decision: denied, owner: this });
168
+ return err(new PermissionRequiredError(request, denied.missing, ceilingFor(effective, request.capability), options.elicitationSupported ?? false, options.restartRequired ?? false));
169
+ }
170
+ /** Atomically replace optional persisted project grants. */
171
+ async replaceProjectGrants(grants) {
172
+ return this.replaceGrants(grants, "project");
132
173
  }
133
174
  /** Replace grants derived from the currently loaded administrator ceiling. */
134
175
  async replaceAdministratorGrants(grants) {
135
- let candidate = {
176
+ return this.replaceGrants(grants, "administrator");
177
+ }
178
+ async replaceGrants(grants, lifetime) {
179
+ const canonical = await canonicalizeGrants(grants);
180
+ if (!canonical.ok)
181
+ return canonical;
182
+ const replaced = addGrantsToPolicy({
136
183
  ...this.policy,
137
- grants: this.policy.grants.filter(({ lifetime }) => lifetime !== "administrator"),
138
- };
139
- for (const grant of grants) {
140
- const canonical = await canonicalizeGrant(grant);
141
- if (!canonical.ok)
142
- return canonical;
143
- const added = grantPermission(candidate, canonical.value);
144
- if (!added.ok)
145
- return err(new PermissionPathError(grant.grant_id, "io", {
146
- cause: added.error,
147
- }));
148
- candidate = added.value;
149
- }
150
- this.policy = candidate;
184
+ grants: this.policy.grants.filter((grant) => grant.lifetime !== lifetime),
185
+ }, canonical.value);
186
+ if (!replaced.ok)
187
+ return replaced;
188
+ this.policy = replaced.value;
151
189
  return ok(null);
152
190
  }
153
191
  /** Atomically replace reloadable ceilings and persisted grants. */
@@ -155,29 +193,20 @@ export class PermissionAuthority {
155
193
  const ceilings = await canonicalizePermissionCeilings(configuration.ceilings);
156
194
  if (!ceilings.ok)
157
195
  return ceilings;
158
- const grants = [];
159
- for (const grant of [
196
+ const grants = await canonicalizeGrants([
160
197
  ...configuration.administratorGrants,
161
198
  ...configuration.projectGrants,
162
- ]) {
163
- const canonical = await canonicalizeGrant(grant);
164
- if (!canonical.ok)
165
- return canonical;
166
- grants.push(canonical.value);
167
- }
168
- let candidate = {
199
+ ]);
200
+ if (!grants.ok)
201
+ return grants;
202
+ const candidate = {
169
203
  ...reloadPermissionCeilings(this.policy, ceilings.value),
170
204
  grants: this.policy.grants.filter(({ lifetime }) => lifetime !== "administrator" && lifetime !== "project"),
171
205
  };
172
- for (const grant of grants) {
173
- const added = grantPermission(candidate, grant);
174
- if (!added.ok)
175
- return err(new PermissionPathError(grant.grant_id, "io", {
176
- cause: added.error,
177
- }));
178
- candidate = added.value;
179
- }
180
- this.policy = candidate;
206
+ const replaced = addGrantsToPolicy(candidate, grants.value);
207
+ if (!replaced.ok)
208
+ return replaced;
209
+ this.policy = replaced.value;
181
210
  return ok(null);
182
211
  }
183
212
  /** Replace ceilings without restarting the MCP process. */
@@ -194,17 +223,31 @@ export const createPermissionAuthority = async (ceilings, grants = []) => {
194
223
  const canonical = await canonicalizePermissionCeilings(ceilings);
195
224
  if (!canonical.ok)
196
225
  return canonical;
197
- let policy = createPermissionPolicy(canonical.value);
226
+ const canonicalGrants = await canonicalizeGrants(grants);
227
+ if (!canonicalGrants.ok)
228
+ return canonicalGrants;
229
+ const policy = addGrantsToPolicy(createPermissionPolicy(canonical.value), canonicalGrants.value);
230
+ return policy.ok ? ok(new PermissionAuthority(policy.value)) : policy;
231
+ };
232
+ const canonicalizeGrants = async (grants) => {
233
+ const canonical = [];
198
234
  for (const grant of grants) {
199
235
  const canonicalGrant = await canonicalizeGrant(grant);
200
236
  if (!canonicalGrant.ok)
201
237
  return canonicalGrant;
202
- const added = grantPermission(policy, canonicalGrant.value);
238
+ canonical.push(canonicalGrant.value);
239
+ }
240
+ return ok(canonical);
241
+ };
242
+ const addGrantsToPolicy = (initial, grants) => {
243
+ let policy = initial;
244
+ for (const grant of grants) {
245
+ const added = grantPermission(policy, grant);
203
246
  if (!added.ok)
204
247
  return err(new PermissionPathError(grant.grant_id, "io", { cause: added.error }));
205
248
  policy = added.value;
206
249
  }
207
- return ok(new PermissionAuthority(policy));
250
+ return ok(policy);
208
251
  };
209
252
  const canonicalizeGrant = async (grant) => {
210
253
  const scope = await canonicalizeScope(grant, "read");
@@ -1,8 +1,8 @@
1
1
  import { tmpdir } from "node:os";
2
- import { spawn } from "node-pty";
3
2
  /** Probe the actual native PTY seam instead of inferring support from the OS name. */
4
3
  export const probeProcessCaptureCapability = async () => {
5
4
  try {
5
+ const { spawn } = await import("@lydell/node-pty");
6
6
  const terminal = spawn(process.platform === "win32" ? "cmd.exe" : "/bin/sh", process.platform === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
7
7
  cwd: tmpdir(),
8
8
  env: { HOME: tmpdir(), TERM: "xterm-256color" },
@@ -0,0 +1,13 @@
1
+ /** Build the exact permission request shared by process-capture adapters. */
2
+ export const processCapturePermissionRequest = (scenario) => ({
3
+ capability: "process_capture",
4
+ roots: [scenario.working_directory, ...scenario.filesystem_roots],
5
+ executables: [scenario.executable],
6
+ environment_names: [
7
+ ...Object.keys(scenario.environment),
8
+ ...scenario.inherit_environment,
9
+ ],
10
+ network: scenario.network_access === "host" ? "external" : "none",
11
+ mount: false,
12
+ operation_identity: `capture_process_scenario:${scenario.executable}`,
13
+ });
@@ -5,6 +5,7 @@ import { createEvidence, parseEvidence } from "../domain/evidence.js";
5
5
  import { jsonValueSchema } from "../domain/jsonValue.js";
6
6
  import { compareProcessCaptures, LEGACY_PROCESS_CAPTURE_MESSAGE, parseProcessScenario, parseProcessCapture, } from "../domain/processCapture.js";
7
7
  import { captureProcessScenario } from "./ProcessHarness.js";
8
+ import { processCapturePermissionRequest } from "./ProcessCapturePermission.js";
8
9
  import { PROCESS_PROVIDER, createProcessCaptureEvidence, } from "./ProcessEvidence.js";
9
10
  import { loadConfiguredPermissionAuthority } from "./PermissionConfiguration.js";
10
11
  const MAX_INPUT_BYTES = 64 * 1024 * 1024;
@@ -25,18 +26,7 @@ export const captureProcessScenarioFile = async (path) => {
25
26
  const authority = await loadConfiguredPermissionAuthority(config.value);
26
27
  if (!authority.ok)
27
28
  return cliAnalysisError(authority.error);
28
- const authorized = await authority.value.authorize({
29
- capability: "process_capture",
30
- roots: [scenario.working_directory, ...scenario.filesystem_roots],
31
- executables: [scenario.executable],
32
- environment_names: [
33
- ...Object.keys(scenario.environment),
34
- ...scenario.inherit_environment,
35
- ],
36
- network: scenario.network_access === "host" ? "external" : "none",
37
- mount: false,
38
- operation_identity: `capture_process_scenario:${scenario.executable}`,
39
- }, "read");
29
+ const authorized = await authority.value.authorize(processCapturePermissionRequest(scenario), "read");
40
30
  if (!authorized.ok)
41
31
  return cliAnalysisError(authorized.error instanceof PermissionRequiredError
42
32
  ? authorized.error
@@ -1,4 +1,3 @@
1
- import { spawn } from "node-pty";
2
1
  import { validateProcessCapture } from "../domain/processCapture.js";
3
2
  import { err, ok } from "../domain/result.js";
4
3
  import { ProcessCaptureError, processCaptureCancelled, } from "./ProcessCaptureError.js";
@@ -111,6 +110,7 @@ const startCaptureRuntime = async (options) => {
111
110
  let shimReplay;
112
111
  let terminal;
113
112
  try {
113
+ const { spawn } = await import("@lydell/node-pty");
114
114
  replay = await startLoopbackReplay(scenario);
115
115
  const startedAt = new Date();
116
116
  const started = Date.now();