rea-agents 2.0.0 → 2.2.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 (273) hide show
  1. package/README.md +103 -38
  2. package/bridge/ghidra/ReaGhidraBridge.java +96 -11
  3. package/dist/application/AndroidApplicationService.js +17 -0
  4. package/dist/application/AppleApplicationService.js +17 -0
  5. package/dist/application/ArtifactExtraction.js +1 -1
  6. package/dist/application/ArtifactInventory/classify.js +42 -0
  7. package/dist/application/ArtifactInventory/hash.js +43 -0
  8. package/dist/application/ArtifactInventory/reader.js +41 -0
  9. package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
  10. package/dist/application/ArtifactInventory/scanReader.js +124 -0
  11. package/dist/application/ArtifactInventory/types.js +10 -0
  12. package/dist/application/ArtifactInventory.js +9 -351
  13. package/dist/application/AuthorizedArtifactInventory.js +2 -2
  14. package/dist/application/BinarySession.js +47 -270
  15. package/dist/application/BinarySessionExecution.js +28 -0
  16. package/dist/application/BinarySessionOpen.js +39 -0
  17. package/dist/application/BinarySessionRecords.js +149 -0
  18. package/dist/application/BinarySessionStatus.js +75 -0
  19. package/dist/application/CapabilityInventory.js +24 -2
  20. package/dist/application/ClientRegistrationStatus.js +11 -4
  21. package/dist/application/CrossVersionInventory.js +8 -2
  22. package/dist/application/CrossVersionInvestigation.js +1 -23
  23. package/dist/application/CrossVersionInvestigationCollections.js +23 -0
  24. package/dist/application/DirectAnalysis.js +47 -44
  25. package/dist/application/Doctor.js +156 -238
  26. package/dist/application/DoctorDiagnostics.js +180 -0
  27. package/dist/application/ElectronBoundaryAnalysis.js +23 -7
  28. package/dist/application/ElectronBoundaryGraphWindows.js +32 -8
  29. package/dist/application/EnhancedToolPagination.js +22 -0
  30. package/dist/application/EnhancedToolTypes.js +4 -0
  31. package/dist/application/EnhancedTools.js +20 -37
  32. package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
  33. package/dist/application/InventoryProjectionEvidence.js +41 -0
  34. package/dist/application/InvestigationProviders.js +12 -0
  35. package/dist/application/InvestigationWorkspaceStore.js +24 -10
  36. package/dist/application/JavaScriptArtifactAnalysis.js +45 -6
  37. package/dist/application/JavaScriptArtifactFiles.js +6 -2
  38. package/dist/application/JavaScriptArtifactGraphBuilder.js +23 -1
  39. package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
  40. package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
  41. package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
  42. package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
  43. package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
  44. package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
  45. package/dist/application/JavaScriptArtifactReconstruction.js +1 -1
  46. package/dist/application/JavaScriptJsonModules.js +39 -0
  47. package/dist/application/JavaScriptModuleRelationships.js +262 -0
  48. package/dist/application/JavaScriptReplayPermission.js +16 -0
  49. package/dist/application/JavaScriptReplayService.js +182 -156
  50. package/dist/application/LinuxHopper.js +10 -0
  51. package/dist/application/MacHopper.js +22 -11
  52. package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
  53. package/dist/application/PermissionAuthority.js +106 -63
  54. package/dist/application/ProcessCaptureCapability.js +1 -1
  55. package/dist/application/ProcessCapturePermission.js +13 -0
  56. package/dist/application/ProcessCli.js +2 -12
  57. package/dist/application/ProcessHarness.js +1 -1
  58. package/dist/application/ProcessPairedExperiment.js +72 -0
  59. package/dist/application/ProjectPermissionStore.js +48 -9
  60. package/dist/application/RealHopperAssertions.js +76 -0
  61. package/dist/application/ReconstructionCoverageService.js +69 -0
  62. package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
  63. package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
  64. package/dist/application/Setup.js +148 -260
  65. package/dist/application/SetupClientConfiguration.js +224 -0
  66. package/dist/application/SetupClients.js +24 -2
  67. package/dist/application/SetupPlan.js +124 -12
  68. package/dist/application/SetupSkill.js +54 -36
  69. package/dist/application/SupportedClients.js +1 -0
  70. package/dist/application/Uninstall.js +12 -3
  71. package/dist/application/Upgrade.js +16 -1
  72. package/dist/application/WindowsCapabilities.js +86 -0
  73. package/dist/artifacts/AsarArtifactReader.js +11 -0
  74. package/dist/browser/BrowserProcessStartup.js +88 -0
  75. package/dist/browser/CdpCaptureDocuments.js +12 -8
  76. package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
  77. package/dist/browser/CdpCaptureEventHandlers.js +336 -0
  78. package/dist/browser/CdpCaptureEventHelpers.js +71 -0
  79. package/dist/browser/CdpCaptureEventState.js +1 -0
  80. package/dist/browser/CdpCaptureEventTypes.js +1 -0
  81. package/dist/browser/CdpCaptureEvents.js +29 -496
  82. package/dist/browser/CdpObservationSession.js +51 -8
  83. package/dist/browser/CdpPageCapture.js +12 -133
  84. package/dist/browser/CdpPageCaptureScripts.js +97 -0
  85. package/dist/browser/CdpPageCaptureWorkers.js +46 -0
  86. package/dist/browser/CdpWebMcpDiscovery.js +38 -14
  87. package/dist/browser/PngVisualDiff.js +9 -2
  88. package/dist/catalogIdentity.js +4 -0
  89. package/dist/cli/artifactCommands.js +82 -0
  90. package/dist/cli/coreAnalysisCommands.js +232 -0
  91. package/dist/cli/managedCommands.js +397 -0
  92. package/dist/cli/managedProjectGraphCommand.js +24 -0
  93. package/dist/cli/options.js +9 -0
  94. package/dist/cli/setupCommands.js +113 -0
  95. package/dist/cli/types.js +1 -0
  96. package/dist/cli/utilityCommands.js +122 -0
  97. package/dist/cli.js +10 -768
  98. package/dist/cliApplicationCommands.js +118 -4
  99. package/dist/cliBrowserAdvancedCommands.js +73 -16
  100. package/dist/cliBrowserCommands.js +39 -115
  101. package/dist/cliCommandNames.js +4 -0
  102. package/dist/cliElectronCommands.js +33 -62
  103. package/dist/cliEvidenceCommands.js +13 -2
  104. package/dist/cliInvestigationCommands.js +53 -10
  105. package/dist/cliObservationOptions.js +137 -0
  106. package/dist/cliPolicyCommands.js +80 -46
  107. package/dist/cliSetup.js +306 -0
  108. package/dist/config/environment.js +107 -0
  109. package/dist/config/parseConfig.js +228 -0
  110. package/dist/config/parsers.js +68 -0
  111. package/dist/config/permissions.js +30 -0
  112. package/dist/config/types.js +1 -0
  113. package/dist/config.js +1 -375
  114. package/dist/contracts/applicationToolContracts.js +134 -0
  115. package/dist/contracts/electronToolContracts.js +51 -3
  116. package/dist/contracts/managedToolContracts.js +8 -3
  117. package/dist/contracts/managedWorkflowToolContracts.js +3 -3
  118. package/dist/contracts/providerSelection.js +2 -0
  119. package/dist/contracts/sessionStatusContract.js +26 -0
  120. package/dist/contracts/toolContractTypes.js +12 -1
  121. package/dist/contracts/toolContracts.js +5 -12
  122. package/dist/contracts/toolEffects.js +14 -0
  123. package/dist/contracts/toolOutputSchemaGroups.js +274 -0
  124. package/dist/contracts/toolOutputSchemaPrimitives.js +328 -0
  125. package/dist/contracts/toolOutputSchemas.js +2 -550
  126. package/dist/domain/analysisErrorPresentation.js +234 -0
  127. package/dist/domain/analysisErrorProjection.js +284 -0
  128. package/dist/domain/androidApplication.js +206 -0
  129. package/dist/domain/appleApplication.js +221 -0
  130. package/dist/domain/artifactComparison.js +34 -15
  131. package/dist/domain/binaryTarget.js +87 -37
  132. package/dist/domain/boundedCartesianProjection.js +15 -0
  133. package/dist/domain/browserObservation.js +1 -285
  134. package/dist/domain/browserObservationSchemas.js +286 -0
  135. package/dist/domain/electronStaticAnalysisBrowser.js +14 -2
  136. package/dist/domain/errors.js +4 -486
  137. package/dist/domain/functionComparison.js +4 -165
  138. package/dist/domain/functionComparisonDimensions.js +164 -0
  139. package/dist/domain/javascriptApplicationVersionItems.js +18 -6
  140. package/dist/domain/javascriptApplicationVersionKeys.js +8 -8
  141. package/dist/domain/javascriptExportInstrumentation.js +97 -0
  142. package/dist/domain/javascriptFeatureTraversal.js +19 -7
  143. package/dist/domain/javascriptRuntimeStaticCandidates.js +3 -1
  144. package/dist/domain/javascriptSemanticAnalysis.js +386 -0
  145. package/dist/domain/javascriptSemanticIr.js +30 -0
  146. package/dist/domain/javascriptSemanticProjection.js +366 -0
  147. package/dist/domain/javascriptSemanticState.js +40 -0
  148. package/dist/domain/javascriptSemanticTraversal.js +22 -0
  149. package/dist/domain/javascriptSemanticValues.js +352 -0
  150. package/dist/domain/javascriptStaticAnalysis.js +5 -221
  151. package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
  152. package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
  153. package/dist/domain/javascriptStaticAnalysisHelpers.js +71 -2
  154. package/dist/domain/knownPageCoverage.js +21 -0
  155. package/dist/domain/managedApplicationGraph.js +14 -364
  156. package/dist/domain/managedApplicationGraphCoverage.js +170 -0
  157. package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
  158. package/dist/domain/managedApplicationGraphNodes.js +336 -0
  159. package/dist/domain/managedArtifact.js +16 -8
  160. package/dist/domain/managedMemberComparison.js +37 -391
  161. package/dist/domain/managedMemberComparisonCoverage.js +72 -0
  162. package/dist/domain/managedMemberComparisonMatch.js +356 -0
  163. package/dist/domain/managedNativeVerification.js +27 -389
  164. package/dist/domain/managedNativeVerificationMatch.js +272 -0
  165. package/dist/domain/managedNativeVerificationSchemas.js +141 -0
  166. package/dist/domain/managedReconstruction.js +82 -69
  167. package/dist/domain/managedRuntimeCorrelation.js +12 -3
  168. package/dist/domain/nodeRuntimeCharacterization.js +66 -0
  169. package/dist/domain/permissionPolicy.js +2 -0
  170. package/dist/domain/processComparison.js +19 -0
  171. package/dist/domain/processPairedExperiment.js +128 -0
  172. package/dist/domain/reconstructionCoverage.js +387 -0
  173. package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
  174. package/dist/domain/reconstructionVerificationSchemas.js +8 -0
  175. package/dist/domain/replayMachine.js +316 -0
  176. package/dist/domain/replayMachineRuntime.js +215 -0
  177. package/dist/domain/runtimeCharacterization.js +85 -0
  178. package/dist/domain/runtimeIdentification.js +210 -0
  179. package/dist/domain/webBundleAnalyzer.js +3 -409
  180. package/dist/domain/webBundleAnalyzerAst.js +77 -0
  181. package/dist/domain/webBundleAnalyzerInspection.js +307 -0
  182. package/dist/domain/webBundleAnalyzerResult.js +120 -0
  183. package/dist/dotnet/ManagedArtifactInspector.js +50 -29
  184. package/dist/dotnet/ManagedMemberInspector.js +51 -785
  185. package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
  186. package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
  187. package/dist/dotnet/ManagedMemberRows.js +120 -0
  188. package/dist/dotnet/ManagedMetadataInventory.js +42 -306
  189. package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
  190. package/dist/dotnet/ManagedMetadataLayout.js +48 -111
  191. package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
  192. package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
  193. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
  194. package/dist/dotnet/ManagedNativeBoundaryInspector.js +102 -350
  195. package/dist/dotnet/ManagedPeReader.js +59 -28
  196. package/dist/evaluation/CodexAgentEval.js +132 -0
  197. package/dist/generatedPackageMetadata.js +2 -2
  198. package/dist/ghidra/GhidraClient.js +76 -91
  199. package/dist/ghidra/GhidraClientStartup.js +29 -0
  200. package/dist/ghidra/GhidraClientWire.js +34 -0
  201. package/dist/ghidra/GhidraDefaults.js +1 -1
  202. package/dist/ghidra/GhidraDiagnostics.js +6 -1
  203. package/dist/ghidra/GhidraInstallation.js +20 -15
  204. package/dist/ghidra/GhidraLauncher.js +93 -29
  205. package/dist/ghidra/GhidraProvider.js +61 -161
  206. package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
  207. package/dist/ghidra/GhidraSessionValues.js +2 -0
  208. package/dist/ghidra/GhidraSocketConnection.js +44 -7
  209. package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
  210. package/dist/ghidra/GhidraTransport.js +71 -0
  211. package/dist/identity.js +4 -2
  212. package/dist/main/messages.js +5 -0
  213. package/dist/main/reload.js +49 -0
  214. package/dist/main/shutdown.js +25 -0
  215. package/dist/main/startup.js +14 -0
  216. package/dist/main/state.js +26 -0
  217. package/dist/main/transport.js +61 -0
  218. package/dist/main/types.js +1 -0
  219. package/dist/main.js +35 -146
  220. package/dist/process/PrivateRuntimeRoot.js +3 -2
  221. package/dist/process/ProcessOwnership.js +35 -0
  222. package/dist/process/ProviderProcess.js +2 -0
  223. package/dist/replay/JavaScriptReplayWorker.js +64 -50
  224. package/dist/replay/LinuxJavaScriptReplayRunner.js +173 -390
  225. package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
  226. package/dist/replay/ReplayOutcome.js +95 -0
  227. package/dist/replay/ReplayProcessLifecycle.js +71 -0
  228. package/dist/server/ProcessCaptureElicitation.js +157 -0
  229. package/dist/server/createServer.js +124 -56
  230. package/dist/server/javascriptApplicationResult.js +85 -0
  231. package/dist/server/registerApplicationTools/characterization.js +57 -0
  232. package/dist/server/registerApplicationTools/compareVersions.js +34 -0
  233. package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
  234. package/dist/server/registerApplicationTools/coverage.js +84 -0
  235. package/dist/server/registerApplicationTools/helpers.js +42 -0
  236. package/dist/server/registerApplicationTools/traceFeature.js +26 -0
  237. package/dist/server/registerApplicationTools/types.js +1 -0
  238. package/dist/server/registerApplicationTools.js +10 -112
  239. package/dist/server/registerBrowserTools.js +59 -83
  240. package/dist/server/registerElectronTools.js +48 -49
  241. package/dist/server/registerEnhancedTools.js +34 -42
  242. package/dist/server/registerEvidenceResources.js +56 -0
  243. package/dist/server/registerInvestigationTools/helpers.js +74 -0
  244. package/dist/server/registerInvestigationTools/types.js +1 -0
  245. package/dist/server/registerInvestigationTools.js +83 -116
  246. package/dist/server/registerJavaScriptApplicationGraphResource.js +69 -0
  247. package/dist/server/registerManagedTools.js +18 -1
  248. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
  249. package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
  250. package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
  251. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
  252. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
  253. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
  254. package/dist/server/registerManagedWorkflowTools/types.js +1 -0
  255. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
  256. package/dist/server/registerManagedWorkflowTools.js +10 -274
  257. package/dist/server/registerOfficialTools.js +73 -59
  258. package/dist/server/registerSessionRecordTools.js +137 -0
  259. package/dist/server/registerSessionStatusTool.js +97 -26
  260. package/dist/server/registerSessionTools.js +60 -164
  261. package/dist/server/sessionAvailabilityPolicy.js +10 -0
  262. package/dist/server/toolRegistrationOptions.js +101 -3
  263. package/dist/server/toolResult.js +15 -4
  264. package/package.json +11 -11
  265. package/skills/reverse-engineer-anything/SKILL.md +76 -0
  266. package/skills/reverse-engineer-anything/references/controlled-replay.md +12 -0
  267. package/skills/reverse-engineer-anything/references/evidence-workflows.md +33 -0
  268. package/skills/reverse-engineer-anything/references/javascript-applications.md +25 -0
  269. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +36 -0
  270. package/skills/reverse-engineer-anything/references/runtime-observation.md +24 -0
  271. package/scripts/prepare-node-pty.mjs +0 -35
  272. package/scripts/rebuild-native.mjs +0 -22
  273. package/skills/rea-analysis/SKILL.md +0 -222
@@ -36,6 +36,7 @@ const sessionInfoSchema = z
36
36
  compiler_spec_id: z.string().min(1),
37
37
  image_base: z.string().regex(/^0x[0-9a-f]+$/u),
38
38
  default_address_space: z.string().min(1),
39
+ sha256: z.string().regex(/^[a-f0-9]{64}$/u),
39
40
  })
40
41
  .strict(),
41
42
  })
@@ -47,6 +48,7 @@ export const parseGhidraSessionInfo = (value, expected) => {
47
48
  parsed.data.run_id !== expected.runId ||
48
49
  parsed.data.provider.version !== expected.providerVersion ||
49
50
  parsed.data.profile_digest !== expected.profileDigest ||
51
+ parsed.data.target.sha256 !== expected.targetSha256 ||
50
52
  new Set(parsed.data.capabilities).size !==
51
53
  GHIDRA_SESSION_CAPABILITIES.length ||
52
54
  GHIDRA_SESSION_CAPABILITIES.some((capability) => !parsed.data.capabilities.includes(capability)) ||
@@ -1,8 +1,9 @@
1
1
  import { createConnection } from "node:net";
2
2
  import { err, ok } from "../domain/result.js";
3
- import { GhidraSessionError } from "./GhidraSessionError.js";
3
+ import { GhidraSessionError, } from "./GhidraSessionError.js";
4
+ import { observeGhidraEndpoint, } from "./GhidraTransport.js";
4
5
  /** Attach decoded bridge listeners and return an idempotent detach callback. */
5
- export const attachGhidraSocket = (socket, handlers) => {
6
+ const attachGhidraSocket = (socket, handlers) => {
6
7
  socket.setEncoding("utf8");
7
8
  socket.on("data", handlers.data);
8
9
  socket.on("error", handlers.error);
@@ -13,9 +14,40 @@ export const attachGhidraSocket = (socket, handlers) => {
13
14
  socket.off("close", handlers.close);
14
15
  };
15
16
  };
16
- /** Open one abort-aware Ghidra Unix-socket connection attempt. */
17
- export const connectGhidraSocketOnce = (socketPath, signal) => new Promise((resolve) => {
18
- const socket = createConnection(socketPath);
17
+ /** Poll the endpoint and attach the first ready bridge socket. */
18
+ export const connectGhidraSocket = async (options) => {
19
+ while (options.deadline.remainingMs() > 0) {
20
+ if (options.deadline.signal.aborted)
21
+ return err(interruptionFailure(options));
22
+ if (options.isClosed())
23
+ return err(options.failure("cancelled", "Ghidra startup was closed"));
24
+ if (options.processExited())
25
+ return err(options.failure("process", "Ghidra exited before bridge startup"));
26
+ const observed = await observeGhidraEndpoint(options.endpoint);
27
+ if (!observed.ok)
28
+ return observed;
29
+ if (observed.value === null) {
30
+ if ((await options.deadline.wait(50)) === "aborted")
31
+ return err(interruptionFailure(options));
32
+ continue;
33
+ }
34
+ const connected = await connectGhidraSocketOnce(observed.value, options.deadline.signal);
35
+ if (connected.ok) {
36
+ const detach = attachGhidraSocket(connected.value, options.handlers);
37
+ return ok({ socket: connected.value, detach });
38
+ }
39
+ if ((await options.deadline.wait(50)) === "aborted")
40
+ return err(interruptionFailure(options));
41
+ }
42
+ return err(options.failure("timeout", "Ghidra startup deadline elapsed", undefined, {
43
+ timeoutMs: options.startupTimeoutMs,
44
+ }));
45
+ };
46
+ /** Open one abort-aware connection to an observed local Ghidra endpoint. */
47
+ const connectGhidraSocketOnce = (target, signal) => new Promise((resolve) => {
48
+ const socket = "path" in target
49
+ ? createConnection(target.path)
50
+ : createConnection({ host: target.host, port: target.port });
19
51
  const detach = () => {
20
52
  socket.off("connect", onConnect);
21
53
  socket.off("error", onError);
@@ -29,14 +61,14 @@ export const connectGhidraSocketOnce = (socketPath, signal) => new Promise((reso
29
61
  detach();
30
62
  socket.destroy();
31
63
  resolve(err(new GhidraSessionError("start", "Ghidra bridge connection failed", {
32
- socket_path: socketPath,
64
+ endpoint: target,
33
65
  error: cause.message,
34
66
  })));
35
67
  };
36
68
  const onAbort = () => {
37
69
  detach();
38
70
  socket.destroy();
39
- resolve(err(new GhidraSessionError("cancelled", "Ghidra bridge connection was cancelled", { socket_path: socketPath })));
71
+ resolve(err(new GhidraSessionError("cancelled", "Ghidra bridge connection was cancelled", { endpoint: target })));
40
72
  };
41
73
  socket.once("connect", onConnect);
42
74
  socket.once("error", onError);
@@ -44,3 +76,8 @@ export const connectGhidraSocketOnce = (socketPath, signal) => new Promise((reso
44
76
  if (signal.aborted)
45
77
  onAbort();
46
78
  });
79
+ const interruptionFailure = (options) => options.deadline.cancelled
80
+ ? options.failure("cancelled", "Ghidra startup was cancelled")
81
+ : options.failure("timeout", "Ghidra startup deadline elapsed", undefined, {
82
+ timeoutMs: options.startupTimeoutMs,
83
+ });
@@ -0,0 +1,30 @@
1
+ import { createHash } from "node:crypto";
2
+ import { constants, createReadStream } from "node:fs";
3
+ import { chmod, copyFile, rm } from "node:fs/promises";
4
+ import { extname, join } from "node:path";
5
+ /** Copy one target and require its bytes to match the parsed target identity. */
6
+ export const createGhidraTargetSnapshot = async (sourcePath, runtimeRoot, expectedSha256) => {
7
+ if (!/^[a-f0-9]{64}$/u.test(expectedSha256))
8
+ throw new TypeError("Ghidra target SHA-256 commitment is invalid");
9
+ const suffix = safeExtension(sourcePath);
10
+ const snapshotPath = join(runtimeRoot, `target-${expectedSha256.slice(0, 12)}${suffix}`);
11
+ try {
12
+ await copyFile(sourcePath, snapshotPath, constants.COPYFILE_EXCL);
13
+ await chmod(snapshotPath, 0o600);
14
+ const hash = createHash("sha256");
15
+ for await (const chunk of createReadStream(snapshotPath))
16
+ hash.update(chunk);
17
+ const observedSha256 = hash.digest("hex");
18
+ if (observedSha256 !== expectedSha256)
19
+ throw new Error(`Ghidra target snapshot digest mismatch: expected ${expectedSha256}, observed ${observedSha256}`);
20
+ return { path: snapshotPath, sha256: observedSha256 };
21
+ }
22
+ catch (cause) {
23
+ await rm(snapshotPath, { force: true }).catch(() => undefined);
24
+ throw cause;
25
+ }
26
+ };
27
+ const safeExtension = (path) => {
28
+ const extension = extname(path);
29
+ return /^\.[A-Za-z0-9]{1,12}$/u.test(extension) ? extension : ".bin";
30
+ };
@@ -0,0 +1,71 @@
1
+ import { access, open } from "node:fs/promises";
2
+ import { err, ok } from "../domain/result.js";
3
+ import { GhidraSessionError } from "./GhidraSessionError.js";
4
+ const MAX_ENDPOINT_BYTES = 1024;
5
+ /** Observe a ready endpoint, returning null while its bridge is not listening. */
6
+ export const observeGhidraEndpoint = async (endpoint) => {
7
+ if (endpoint.transport === "unix-socket") {
8
+ try {
9
+ await access(endpoint.path);
10
+ return ok({ path: endpoint.path });
11
+ }
12
+ catch (cause) {
13
+ return isMissing(cause)
14
+ ? ok(null)
15
+ : err(endpointFailure(endpoint, "Ghidra socket observation failed", cause));
16
+ }
17
+ }
18
+ let handle;
19
+ try {
20
+ handle = await open(endpoint.path, "r");
21
+ }
22
+ catch (cause) {
23
+ return isMissing(cause)
24
+ ? ok(null)
25
+ : err(endpointFailure(endpoint, "Ghidra endpoint observation failed", cause));
26
+ }
27
+ try {
28
+ const bytes = Buffer.alloc(MAX_ENDPOINT_BYTES + 1);
29
+ const observed = await handle.read(bytes, 0, bytes.length, 0);
30
+ if (observed.bytesRead === 0 || observed.bytesRead > MAX_ENDPOINT_BYTES)
31
+ return err(endpointFailure(endpoint, "Ghidra TCP endpoint is invalid"));
32
+ return parseTcpEndpoint(endpoint, bytes.subarray(0, observed.bytesRead).toString("utf8"));
33
+ }
34
+ catch (cause) {
35
+ return err(endpointFailure(endpoint, "Ghidra endpoint read failed", cause));
36
+ }
37
+ finally {
38
+ await handle.close();
39
+ }
40
+ };
41
+ const parseTcpEndpoint = (endpoint, encoded) => {
42
+ try {
43
+ const value = JSON.parse(encoded);
44
+ if (typeof value !== "object" ||
45
+ value === null ||
46
+ Array.isArray(value) ||
47
+ !hasExactKeys(value, ["host", "port", "schema_version"]) ||
48
+ value.schema_version !== 1 ||
49
+ value.host !== "127.0.0.1" ||
50
+ !Number.isSafeInteger(value.port) ||
51
+ typeof value.port !== "number" ||
52
+ value.port < 1 ||
53
+ value.port > 65_535)
54
+ return err(endpointFailure(endpoint, "Ghidra TCP endpoint is invalid"));
55
+ return ok({ host: "127.0.0.1", port: value.port });
56
+ }
57
+ catch (cause) {
58
+ return err(endpointFailure(endpoint, "Ghidra TCP endpoint is invalid", cause));
59
+ }
60
+ };
61
+ const hasExactKeys = (value, expected) => {
62
+ const keys = Object.keys(value).sort((left, right) => left.localeCompare(right));
63
+ return (keys.length === expected.length &&
64
+ keys.every((key, index) => key === expected[index]));
65
+ };
66
+ const endpointFailure = (endpoint, message, cause) => new GhidraSessionError("start", message, {
67
+ transport: endpoint.transport,
68
+ endpoint_path: endpoint.path,
69
+ ...(cause instanceof Error ? { error: cause.message } : {}),
70
+ }, cause instanceof Error ? { cause } : undefined);
71
+ const isMissing = (cause) => cause instanceof Error && "code" in cause && cause.code === "ENOENT";
package/dist/identity.js CHANGED
@@ -6,11 +6,13 @@
6
6
  export const PRODUCT_IDENTITY = {
7
7
  displayName: "REA",
8
8
  packageName: PACKAGE_METADATA.name,
9
+ packageSpecifier: `${PACKAGE_METADATA.name}@latest`,
10
+ registrationPackageSpecifier: `${PACKAGE_METADATA.name}@${PACKAGE_METADATA.version}`,
9
11
  packageVersion: PACKAGE_METADATA.version,
10
12
  cliBinary: "rea",
11
- mcpCommand: "npx -y rea-agents mcp",
13
+ mcpCommand: `npx -y ${PACKAGE_METADATA.name}@${PACKAGE_METADATA.version} mcp`,
12
14
  mcpServerKey: "rea",
13
- skillName: "rea-analysis",
15
+ skillName: "reverse-engineer-anything",
14
16
  skillVersion: PACKAGE_METADATA.skillVersion,
15
17
  configFileName: "rea.json",
16
18
  };
@@ -0,0 +1,5 @@
1
+ export const MCP_CONNECTION_LOST = "REA lost its MCP client connection. Restart REA from your MCP client.";
2
+ export const MCP_CONNECTION_START_FAILED = "REA could not start its MCP connection. Restart REA from your MCP client; run `rea doctor` if it fails again.";
3
+ export const MCP_SHUTDOWN_FAILED = "REA could not close cleanly. End the REA process before starting it again.";
4
+ export const MCP_PERMISSION_RELOAD_FAILED = "Reloaded permission policy failed unexpectedly";
5
+ export const SERVER_START_FAILED = "REA could not start. Run `rea doctor`, then restart REA from your MCP client.";
@@ -0,0 +1,49 @@
1
+ import { parseConfig } from "../config.js";
2
+ import { readProjectPermissionStore } from "../application/ProjectPermissionStore.js";
3
+ import { MCP_PERMISSION_RELOAD_FAILED } from "./messages.js";
4
+ export const registerConfigReload = (input) => {
5
+ const { dependencies, permissionAuthority, runtimeState, liveServers, serverLogger, } = input;
6
+ let reloadQueue = Promise.resolve();
7
+ return (dependencies.registerReload?.(() => {
8
+ const refreshed = parseConfig(dependencies.env);
9
+ if (!refreshed.ok) {
10
+ serverLogger.error("Reloaded permission policy is invalid");
11
+ return;
12
+ }
13
+ reloadQueue = reloadQueue
14
+ .then(async () => {
15
+ let projectGrants = [];
16
+ if (refreshed.value.permissionProjectRoot !== undefined &&
17
+ refreshed.value.permissionProjectStore !== undefined) {
18
+ const project = await (dependencies.readProjectPermissionStore ??
19
+ readProjectPermissionStore)(refreshed.value.permissionProjectStore, refreshed.value.permissionProjectRoot);
20
+ if (!project.ok) {
21
+ serverLogger.error("Reloaded project grants could not be read");
22
+ return;
23
+ }
24
+ projectGrants = project.value?.grants ?? [];
25
+ }
26
+ const reloaded = await permissionAuthority.replaceConfiguredPolicy({
27
+ ceilings: refreshed.value.permissionCeilings,
28
+ administratorGrants: refreshed.value.administratorPermissionGrants,
29
+ projectGrants,
30
+ });
31
+ if (!reloaded.ok) {
32
+ serverLogger.error("Reloaded permission policy could not be applied");
33
+ return;
34
+ }
35
+ runtimeState.currentConfig = refreshed.value;
36
+ Object.assign(runtimeState.processPolicy, refreshed.value.processExecutionPolicy);
37
+ Object.assign(runtimeState.evidencePolicy, refreshed.value.evidenceFilePolicy);
38
+ Object.assign(runtimeState.snapshotPolicy, refreshed.value.analysisSnapshotFilePolicy);
39
+ runtimeState.investigationRoots.splice(0, runtimeState.investigationRoots.length, ...refreshed.value.investigationInputRoots);
40
+ Object.assign(runtimeState.javascriptReplayPolicy, refreshed.value.javascriptReplayPolicy);
41
+ Object.assign(runtimeState.managedRuntimePolicy, refreshed.value.managedRuntimePolicy);
42
+ for (const server of liveServers)
43
+ server.sendToolListChanged();
44
+ })
45
+ .catch(() => {
46
+ serverLogger.error(MCP_PERMISSION_RELOAD_FAILED);
47
+ });
48
+ }) ?? (() => undefined));
49
+ };
@@ -0,0 +1,25 @@
1
+ import { MCP_SHUTDOWN_FAILED } from "./messages.js";
2
+ export const createShutdown = (input) => {
3
+ const { handle, session, permissionAuthority, unregisterReload, dependencies, serverLogger, } = input;
4
+ let shutdownPromise;
5
+ let unregisterShutdown = () => undefined;
6
+ const shutdown = async () => {
7
+ shutdownPromise ??= (async () => {
8
+ unregisterReload();
9
+ unregisterShutdown();
10
+ await handle.close();
11
+ await session.close();
12
+ permissionAuthority.clearSessionGrants();
13
+ })();
14
+ return shutdownPromise;
15
+ };
16
+ const requestShutdown = () => {
17
+ shutdown().catch(() => {
18
+ dependencies.setExitCode(1);
19
+ serverLogger.error(MCP_SHUTDOWN_FAILED);
20
+ dependencies.writeStderr(`${MCP_SHUTDOWN_FAILED}\n`);
21
+ });
22
+ };
23
+ unregisterShutdown = dependencies.registerShutdown(requestShutdown);
24
+ return { shutdown, request: requestShutdown };
25
+ };
@@ -0,0 +1,14 @@
1
+ import { projectAnalysisError } from "../domain/errors.js";
2
+ export const openInitialTarget = async (session, config, serverLogger, writeStderr) => {
3
+ if (config.hopperTargetPath === undefined)
4
+ return { ok: true };
5
+ const opened = await session.open(config.hopperTargetPath, {
6
+ targetKind: config.hopperTargetKind,
7
+ });
8
+ if (opened.ok)
9
+ return { ok: true };
10
+ await session.close();
11
+ serverLogger.error({ errorTag: opened.error._tag }, "Initial target failed to open");
12
+ writeStderr(`${projectAnalysisError(opened.error).message}\n`);
13
+ return { ok: false, exitCode: 1 };
14
+ };
@@ -0,0 +1,26 @@
1
+ export const createRuntimeState = (config) => ({
2
+ currentConfig: config,
3
+ processPolicy: {
4
+ ...config.processExecutionPolicy,
5
+ executableRoots: [...config.processExecutionPolicy.executableRoots],
6
+ workingRoots: [...config.processExecutionPolicy.workingRoots],
7
+ allowedEnvironment: [...config.processExecutionPolicy.allowedEnvironment],
8
+ },
9
+ evidencePolicy: {
10
+ ...config.evidenceFilePolicy,
11
+ roots: [...config.evidenceFilePolicy.roots],
12
+ },
13
+ snapshotPolicy: {
14
+ ...config.analysisSnapshotFilePolicy,
15
+ roots: [...config.analysisSnapshotFilePolicy.roots],
16
+ },
17
+ investigationRoots: [...config.investigationInputRoots],
18
+ javascriptReplayPolicy: {
19
+ ...config.javascriptReplayPolicy,
20
+ roots: [...config.javascriptReplayPolicy.roots],
21
+ },
22
+ managedRuntimePolicy: {
23
+ ...config.managedRuntimePolicy,
24
+ roots: [...config.managedRuntimePolicy.roots],
25
+ },
26
+ });
@@ -0,0 +1,61 @@
1
+ import { createServer } from "../server/createServer.js";
2
+ import { MCP_CONNECTION_LOST, MCP_CONNECTION_START_FAILED, } from "./messages.js";
3
+ export const startMcpTransport = async (dependencies, session, serverContext) => {
4
+ const liveServers = new Set();
5
+ const { serverLogger } = serverContext;
6
+ let handle;
7
+ try {
8
+ handle = dependencies.serve(() => {
9
+ const server = (dependencies.createServer ?? createServer)(session, session, {
10
+ logger: serverContext.logger,
11
+ processPolicy: serverContext.runtimeState.processPolicy,
12
+ evidenceFilePolicy: serverContext.runtimeState.evidencePolicy,
13
+ investigationInputRoots: serverContext.runtimeState.investigationRoots,
14
+ analysisSnapshotFilePolicy: serverContext.runtimeState.snapshotPolicy,
15
+ permissionAuthority: serverContext.permissionAuthority,
16
+ browserObservation: serverContext.browserObservation,
17
+ electronObservation: serverContext.electronObservation,
18
+ artifactIntegrityContinueEnabled: () => serverContext.runtimeState.currentConfig
19
+ .artifactIntegrityContinueEnabled,
20
+ javascriptReplayPolicy: serverContext.runtimeState.javascriptReplayPolicy,
21
+ managedRuntimePolicy: serverContext.runtimeState.managedRuntimePolicy,
22
+ availabilityPolicy: () => ({
23
+ processCaptureEnabled: serverContext.runtimeState.currentConfig.processExecutionPolicy
24
+ .enabled,
25
+ evidenceFileRoots: serverContext.runtimeState.currentConfig.evidenceFilePolicy
26
+ .roots.length,
27
+ browserObservationEnabled: serverContext.runtimeState.currentConfig
28
+ .browserObservationEnabled &&
29
+ serverContext.runtimeState.currentConfig.browserCdpEndpoints
30
+ .length > 0 &&
31
+ serverContext.runtimeState.currentConfig.browserAllowedOrigins
32
+ .length > 0,
33
+ electronObservationEnabled: serverContext.runtimeState.currentConfig
34
+ .electronObservationEnabled &&
35
+ serverContext.runtimeState.currentConfig.electronCdpEndpoints
36
+ .length > 0 &&
37
+ serverContext.runtimeState.currentConfig.electronFileRoots
38
+ .length > 0,
39
+ javascriptReplayEnabled: serverContext.runtimeState.currentConfig.javascriptReplayPolicy
40
+ .enabled,
41
+ managedRuntimeEnabled: serverContext.runtimeState.currentConfig.managedRuntimePolicy
42
+ .enabled,
43
+ }),
44
+ });
45
+ liveServers.add(server);
46
+ return server;
47
+ }, {
48
+ onerror: () => {
49
+ serverLogger.error(MCP_CONNECTION_LOST);
50
+ dependencies.writeStderr(`${MCP_CONNECTION_LOST}\n`);
51
+ },
52
+ });
53
+ }
54
+ catch {
55
+ await session.close();
56
+ serverLogger.error(MCP_CONNECTION_START_FAILED);
57
+ dependencies.writeStderr(`${MCP_CONNECTION_START_FAILED}\n`);
58
+ return { ok: false };
59
+ }
60
+ return { ok: true, handle, liveServers };
61
+ };
@@ -0,0 +1 @@
1
+ export {};
package/dist/main.js CHANGED
@@ -1,20 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  import { pathToFileURL } from "node:url";
3
3
  import { realpathSync } from "node:fs";
4
- import { serveStdio, } from "@modelcontextprotocol/server/stdio";
4
+ import { serveStdio } from "@modelcontextprotocol/server/stdio";
5
5
  import { parseConfig } from "./config.js";
6
6
  import { createBinarySession } from "./application/runtime.js";
7
- import { createServer } from "./server/createServer.js";
8
7
  import { createLogger } from "./logger.js";
9
8
  import { projectAnalysisError } from "./domain/errors.js";
10
- import { readProjectPermissionStore } from "./application/ProjectPermissionStore.js";
11
9
  import { loadConfiguredPermissionAuthority } from "./application/PermissionConfiguration.js";
12
10
  import { CdpBrowserProvider } from "./browser/CdpBrowserProvider.js";
13
11
  import { CdpElectronProvider } from "./browser/CdpElectronProvider.js";
14
- const MCP_CONNECTION_LOST = "REA lost its MCP client connection. Restart REA from your MCP client.";
15
- const MCP_CONNECTION_START_FAILED = "REA could not start its MCP connection. Restart REA from your MCP client; run `rea doctor` if it fails again.";
16
- const MCP_SHUTDOWN_FAILED = "REA could not close cleanly. End the REA process before starting it again.";
17
- const SERVER_START_FAILED = "REA could not start. Run `rea doctor`, then restart REA from your MCP client.";
12
+ import { SERVER_START_FAILED } from "./main/messages.js";
13
+ import { createRuntimeState } from "./main/state.js";
14
+ import { openInitialTarget } from "./main/startup.js";
15
+ import { startMcpTransport } from "./main/transport.js";
16
+ import { registerConfigReload } from "./main/reload.js";
17
+ import { createShutdown } from "./main/shutdown.js";
18
18
  const runtimeDependencies = () => ({
19
19
  env: process.env,
20
20
  serve: serveStdio,
@@ -60,146 +60,35 @@ export const run = async (dependencies = runtimeDependencies()) => {
60
60
  const session = createBinarySession(config.value, logger);
61
61
  const browserObservation = new CdpBrowserProvider();
62
62
  const electronObservation = new CdpElectronProvider();
63
- if (config.value.hopperTargetPath !== undefined) {
64
- const opened = await session.open(config.value.hopperTargetPath, {
65
- targetKind: config.value.hopperTargetKind,
66
- });
67
- if (!opened.ok) {
68
- await session.close();
69
- serverLogger.error({ errorTag: opened.error._tag }, "Initial target failed to open");
70
- dependencies.writeStderr(`${projectAnalysisError(opened.error).message}\n`);
71
- return 1;
72
- }
73
- }
74
- let currentConfig = config.value;
75
- const runtimeProcessPolicy = {
76
- ...config.value.processExecutionPolicy,
77
- executableRoots: [...config.value.processExecutionPolicy.executableRoots],
78
- workingRoots: [...config.value.processExecutionPolicy.workingRoots],
79
- allowedEnvironment: [
80
- ...config.value.processExecutionPolicy.allowedEnvironment,
81
- ],
82
- };
83
- const runtimeEvidencePolicy = {
84
- ...config.value.evidenceFilePolicy,
85
- roots: [...config.value.evidenceFilePolicy.roots],
86
- };
87
- const runtimeSnapshotPolicy = {
88
- ...config.value.analysisSnapshotFilePolicy,
89
- roots: [...config.value.analysisSnapshotFilePolicy.roots],
90
- };
91
- const runtimeInvestigationRoots = [...config.value.investigationInputRoots];
92
- const runtimeJavascriptReplayPolicy = {
93
- ...config.value.javascriptReplayPolicy,
94
- roots: [...config.value.javascriptReplayPolicy.roots],
95
- };
96
- const runtimeManagedRuntimePolicy = {
97
- ...config.value.managedRuntimePolicy,
98
- roots: [...config.value.managedRuntimePolicy.roots],
99
- };
100
- const liveServers = new Set();
101
- let handle;
102
- try {
103
- handle = dependencies.serve(() => {
104
- const server = (dependencies.createServer ?? createServer)(session, session, {
105
- logger,
106
- processPolicy: runtimeProcessPolicy,
107
- evidenceFilePolicy: runtimeEvidencePolicy,
108
- investigationInputRoots: runtimeInvestigationRoots,
109
- analysisSnapshotFilePolicy: runtimeSnapshotPolicy,
110
- permissionAuthority: permissionAuthority.value,
111
- browserObservation,
112
- electronObservation,
113
- artifactIntegrityContinueEnabled: () => currentConfig.artifactIntegrityContinueEnabled,
114
- javascriptReplayPolicy: runtimeJavascriptReplayPolicy,
115
- managedRuntimePolicy: runtimeManagedRuntimePolicy,
116
- availabilityPolicy: () => ({
117
- processCaptureEnabled: currentConfig.processExecutionPolicy.enabled,
118
- evidenceFileRoots: currentConfig.evidenceFilePolicy.roots.length,
119
- browserObservationEnabled: currentConfig.browserObservationEnabled &&
120
- currentConfig.browserCdpEndpoints.length > 0 &&
121
- currentConfig.browserAllowedOrigins.length > 0,
122
- electronObservationEnabled: currentConfig.electronObservationEnabled &&
123
- currentConfig.electronCdpEndpoints.length > 0 &&
124
- currentConfig.electronFileRoots.length > 0,
125
- javascriptReplayEnabled: currentConfig.javascriptReplayPolicy.enabled,
126
- managedRuntimeEnabled: currentConfig.managedRuntimePolicy.enabled,
127
- }),
128
- });
129
- liveServers.add(server);
130
- return server;
131
- }, {
132
- onerror: () => {
133
- serverLogger.error(MCP_CONNECTION_LOST);
134
- dependencies.writeStderr(`${MCP_CONNECTION_LOST}\n`);
135
- },
136
- });
137
- }
138
- catch {
139
- await session.close();
140
- serverLogger.error(MCP_CONNECTION_START_FAILED);
141
- dependencies.writeStderr(`${MCP_CONNECTION_START_FAILED}\n`);
63
+ const opened = await openInitialTarget(session, config.value, serverLogger, dependencies.writeStderr);
64
+ if (!opened.ok)
65
+ return opened.exitCode;
66
+ const runtimeState = createRuntimeState(config.value);
67
+ const transport = await startMcpTransport(dependencies, session, {
68
+ logger,
69
+ serverLogger,
70
+ browserObservation,
71
+ electronObservation,
72
+ permissionAuthority: permissionAuthority.value,
73
+ runtimeState,
74
+ });
75
+ if (!transport.ok)
142
76
  return 1;
143
- }
144
- let reloadQueue = Promise.resolve();
145
- const unregisterReload = dependencies.registerReload?.(() => {
146
- const refreshed = parseConfig(dependencies.env);
147
- if (!refreshed.ok) {
148
- serverLogger.error("Reloaded permission policy is invalid");
149
- return;
150
- }
151
- reloadQueue = reloadQueue.then(async () => {
152
- let projectGrants = [];
153
- if (refreshed.value.permissionProjectRoot !== undefined &&
154
- refreshed.value.permissionProjectStore !== undefined) {
155
- const project = await (dependencies.readProjectPermissionStore ??
156
- readProjectPermissionStore)(refreshed.value.permissionProjectStore, refreshed.value.permissionProjectRoot);
157
- if (!project.ok) {
158
- serverLogger.error("Reloaded project grants could not be read");
159
- return;
160
- }
161
- projectGrants = project.value?.grants ?? [];
162
- }
163
- const reloaded = await permissionAuthority.value.replaceConfiguredPolicy({
164
- ceilings: refreshed.value.permissionCeilings,
165
- administratorGrants: refreshed.value.administratorPermissionGrants,
166
- projectGrants,
167
- });
168
- if (!reloaded.ok) {
169
- serverLogger.error("Reloaded permission policy could not be applied");
170
- return;
171
- }
172
- currentConfig = refreshed.value;
173
- Object.assign(runtimeProcessPolicy, refreshed.value.processExecutionPolicy);
174
- Object.assign(runtimeEvidencePolicy, refreshed.value.evidenceFilePolicy);
175
- Object.assign(runtimeSnapshotPolicy, refreshed.value.analysisSnapshotFilePolicy);
176
- runtimeInvestigationRoots.splice(0, runtimeInvestigationRoots.length, ...refreshed.value.investigationInputRoots);
177
- Object.assign(runtimeJavascriptReplayPolicy, refreshed.value.javascriptReplayPolicy);
178
- Object.assign(runtimeManagedRuntimePolicy, refreshed.value.managedRuntimePolicy);
179
- for (const server of liveServers)
180
- server.sendToolListChanged();
181
- });
182
- }) ?? (() => undefined);
183
- let shutdownPromise;
184
- let unregisterShutdown = () => undefined;
185
- const shutdown = () => {
186
- shutdownPromise ??= (async () => {
187
- unregisterReload();
188
- unregisterShutdown();
189
- await handle.close();
190
- await session.close();
191
- permissionAuthority.value.clearSessionGrants();
192
- })();
193
- return shutdownPromise;
194
- };
195
- const requestShutdown = () => {
196
- shutdown().catch(() => {
197
- dependencies.setExitCode(1);
198
- serverLogger.error(MCP_SHUTDOWN_FAILED);
199
- dependencies.writeStderr(`${MCP_SHUTDOWN_FAILED}\n`);
200
- });
201
- };
202
- unregisterShutdown = dependencies.registerShutdown(requestShutdown);
77
+ const unregisterReload = registerConfigReload({
78
+ dependencies,
79
+ permissionAuthority: permissionAuthority.value,
80
+ runtimeState,
81
+ liveServers: transport.liveServers,
82
+ serverLogger,
83
+ });
84
+ createShutdown({
85
+ handle: transport.handle,
86
+ session,
87
+ permissionAuthority: permissionAuthority.value,
88
+ unregisterReload,
89
+ dependencies,
90
+ serverLogger,
91
+ });
203
92
  return 0;
204
93
  };
205
94
  /** Run the executable boundary without exposing an unexpected startup cause. */
@@ -2,10 +2,11 @@ import { chmod, mkdtemp, rm } from "node:fs/promises";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  /**
5
- * Owns one mode-0700 temporary runtime root and removes it idempotently.
5
+ * Owns one POSIX mode-0700 temporary runtime root and removes it idempotently.
6
6
  *
7
7
  * Protocol adapters decide what belongs inside the directory; this primitive
8
- * only establishes a private filesystem boundary and deterministic cleanup.
8
+ * establishes a private filesystem boundary on POSIX and deterministic cleanup.
9
+ * Windows privacy requires the separately verified native DACL boundary.
9
10
  */
10
11
  export class PrivateRuntimeRoot {
11
12
  path;