rea-agents 1.6.0 → 2.0.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 (238) hide show
  1. package/README.md +157 -66
  2. package/bridge/ghidra/ReaGhidraBridge.java +2075 -0
  3. package/bridge/hopper_bridge.py +13 -3
  4. package/dist/application/AbortablePromise.js +25 -0
  5. package/dist/application/AnalysisProvider.js +3 -0
  6. package/dist/application/AnalysisProviderEvaluation.js +60 -0
  7. package/dist/application/AnalysisProviderRegistry.js +228 -0
  8. package/dist/application/AnalysisSnapshotCache.js +41 -21
  9. package/dist/application/AnalysisSnapshotFiles.js +5 -6
  10. package/dist/application/BinarySession.js +218 -101
  11. package/dist/application/CapabilityInventory.js +18 -0
  12. package/dist/application/CompositeProvider.js +20 -8
  13. package/dist/application/CrossVersionInvestigation.js +10 -6
  14. package/dist/application/DirectAnalysis.js +49 -35
  15. package/dist/application/Doctor.js +110 -8
  16. package/dist/application/ElectronBoundaryAnalysis.js +96 -0
  17. package/dist/application/ElectronBoundaryGraph.js +9 -0
  18. package/dist/application/ElectronBoundaryGraphContext.js +62 -0
  19. package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
  20. package/dist/application/ElectronBoundaryGraphNative.js +86 -0
  21. package/dist/application/ElectronBoundaryGraphWindows.js +199 -0
  22. package/dist/application/EnhancedTools.js +39 -14
  23. package/dist/application/InvestigationProviders.js +41 -0
  24. package/dist/application/JavaScriptApplicationEvidence.js +26 -0
  25. package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
  26. package/dist/application/JavaScriptApplicationService.js +74 -0
  27. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
  28. package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
  29. package/dist/application/JavaScriptArtifactAnalysis.js +305 -0
  30. package/dist/application/JavaScriptArtifactAnalysisTypes.js +1 -0
  31. package/dist/application/JavaScriptArtifactFiles.js +231 -0
  32. package/dist/application/JavaScriptArtifactGraphAccumulator.js +54 -0
  33. package/dist/application/JavaScriptArtifactGraphBuilder.js +144 -0
  34. package/dist/application/JavaScriptArtifactGraphContext.js +205 -0
  35. package/dist/application/JavaScriptArtifactGraphDocuments.js +108 -0
  36. package/dist/application/JavaScriptArtifactGraphEvidence.js +99 -0
  37. package/dist/application/JavaScriptArtifactGraphFindings.js +271 -0
  38. package/dist/application/JavaScriptArtifactGraphStructure.js +409 -0
  39. package/dist/application/JavaScriptArtifactReconstruction.js +77 -0
  40. package/dist/application/JavaScriptArtifactReconstructionInput.js +18 -0
  41. package/dist/application/JavaScriptReplayPlanning.js +201 -0
  42. package/dist/application/JavaScriptReplayService.js +266 -0
  43. package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
  44. package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
  45. package/dist/application/MacHopper.js +20 -4
  46. package/dist/application/ManagedApplicationGraphService.js +55 -0
  47. package/dist/application/ManagedMemberComparisonService.js +122 -0
  48. package/dist/application/ManagedNativeVerificationService.js +39 -0
  49. package/dist/application/ManagedReconstructionService.js +58 -0
  50. package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
  51. package/dist/application/PermissionAuthority.js +1 -1
  52. package/dist/application/ProcessCaptureLifecycle.js +1 -1
  53. package/dist/application/ProcessHarness.js +1 -1
  54. package/dist/application/ProcessSampling.js +16 -12
  55. package/dist/application/ProjectPermissionStore.js +1 -0
  56. package/dist/application/SessionProviderRouter.js +219 -0
  57. package/dist/application/Setup.js +84 -60
  58. package/dist/application/SetupClients.js +1 -1
  59. package/dist/application/SetupPlan.js +9 -2
  60. package/dist/application/SupportedClients.js +40 -16
  61. package/dist/application/Upgrade.js +1 -1
  62. package/dist/application/runtime.js +11 -6
  63. package/dist/artifacts/AsarArtifactReader.js +23 -3
  64. package/dist/browser/CdpBrowserProvider.js +4 -2
  65. package/dist/browser/CdpCaptureEvents.js +49 -0
  66. package/dist/browser/CdpElectronInspection.js +106 -162
  67. package/dist/browser/CdpElectronProvider.js +9 -3
  68. package/dist/browser/CdpElectronScriptEvents.js +69 -0
  69. package/dist/browser/CdpElectronScripts.js +94 -0
  70. package/dist/browser/CdpElectronWorkers.js +56 -0
  71. package/dist/browser/CdpEndpoint.js +14 -1
  72. package/dist/browser/CdpPageCapture.js +8 -4
  73. package/dist/catalogIdentity.js +6 -42
  74. package/dist/cli.js +446 -34
  75. package/dist/cliApplicationCommands.js +62 -0
  76. package/dist/cliBrowserAdvancedCommands.js +5 -4
  77. package/dist/cliBrowserCommands.js +5 -4
  78. package/dist/cliCommandNames.js +56 -0
  79. package/dist/cliElectronCommands.js +106 -3
  80. package/dist/cliEvidenceCommands.js +4 -3
  81. package/dist/cliInvestigationCommands.js +2 -1
  82. package/dist/cliJsonInput.js +54 -0
  83. package/dist/cliPolicyCommands.js +2 -1
  84. package/dist/cliProcessCommands.js +3 -2
  85. package/dist/config.js +101 -2
  86. package/dist/contracts/applicationToolContracts.js +91 -0
  87. package/dist/contracts/artifactToolContracts.js +5 -9
  88. package/dist/contracts/browserToolContracts.js +14 -62
  89. package/dist/contracts/electronToolContracts.js +45 -19
  90. package/dist/contracts/enhancedInputs.js +2 -2
  91. package/dist/contracts/errorSchemas.js +1 -0
  92. package/dist/contracts/investigationExamples.js +0 -6
  93. package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
  94. package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
  95. package/dist/contracts/managedToolContracts.js +153 -0
  96. package/dist/contracts/managedWorkflowExamples.js +346 -0
  97. package/dist/contracts/managedWorkflowToolContracts.js +203 -0
  98. package/dist/contracts/nativeToolContracts.js +2 -6
  99. package/dist/contracts/promptContracts.js +18 -2
  100. package/dist/contracts/providerSelection.js +28 -0
  101. package/dist/contracts/sessionLifecycleInputs.js +2 -0
  102. package/dist/contracts/toolContractExamples.js +10 -25
  103. package/dist/contracts/toolContracts.js +69 -65
  104. package/dist/contracts/toolEffects.js +160 -0
  105. package/dist/contracts/toolOutputSchemas.js +152 -42
  106. package/dist/doctorRuntime.js +47 -0
  107. package/dist/domain/analysisProfile.js +78 -0
  108. package/dist/domain/analysisSnapshot.js +92 -46
  109. package/dist/domain/artifactComparison.js +3 -4
  110. package/dist/domain/artifactGraph.js +1 -0
  111. package/dist/domain/binaryTarget.js +4 -29
  112. package/dist/domain/browserObservation.js +3 -0
  113. package/dist/domain/bundleComparison.js +4 -4
  114. package/dist/domain/electronObservation.js +13 -0
  115. package/dist/domain/electronStaticAnalysis.js +9 -0
  116. package/dist/domain/electronStaticAnalysisBrowser.js +194 -0
  117. package/dist/domain/electronStaticAnalysisIpc.js +171 -0
  118. package/dist/domain/electronStaticAnalysisNative.js +164 -0
  119. package/dist/domain/electronStaticAnalysisTypes.js +1 -0
  120. package/dist/domain/electronStaticAnalysisValues.js +103 -0
  121. package/dist/domain/errors.js +148 -7
  122. package/dist/domain/evidence.js +44 -5
  123. package/dist/domain/evidenceBundle.js +9 -7
  124. package/dist/domain/functionComparison.js +9 -3
  125. package/dist/domain/functionComparisonNormalization.js +37 -0
  126. package/dist/domain/functionComparisonSchemas.js +3 -8
  127. package/dist/domain/functionDossierEvidence.js +4 -1
  128. package/dist/domain/hopperValues.js +66 -9
  129. package/dist/domain/inputIssueProjection.js +52 -0
  130. package/dist/domain/investigationWorkspace.js +2 -1
  131. package/dist/domain/javascriptApplicationAnalysis.js +155 -0
  132. package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
  133. package/dist/domain/javascriptApplicationEvidenceSchemas.js +379 -0
  134. package/dist/domain/javascriptApplicationGraph.js +282 -0
  135. package/dist/domain/javascriptApplicationGraphSchemas.js +139 -0
  136. package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
  137. package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
  138. package/dist/domain/javascriptApplicationVersionItems.js +221 -0
  139. package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
  140. package/dist/domain/javascriptAstFingerprint.js +143 -0
  141. package/dist/domain/javascriptFeatureSeed.js +140 -0
  142. package/dist/domain/javascriptFeatureTrace.js +232 -0
  143. package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
  144. package/dist/domain/javascriptFeatureTraversal.js +88 -0
  145. package/dist/domain/javascriptNativeHandoff.js +85 -0
  146. package/dist/domain/javascriptReplay.js +361 -0
  147. package/dist/domain/javascriptRuntimeLoadState.js +106 -0
  148. package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
  149. package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
  150. package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
  151. package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
  152. package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
  153. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
  154. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
  155. package/dist/domain/javascriptRuntimeStaticCandidates.js +191 -0
  156. package/dist/domain/javascriptStaticAnalysis.js +346 -0
  157. package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
  158. package/dist/domain/javascriptStaticAnalysisHelpers.js +274 -0
  159. package/dist/domain/javascriptStaticAnalysisState.js +23 -0
  160. package/dist/domain/javascriptStaticAnalysisTypes.js +1 -0
  161. package/dist/domain/managedApplicationGraph.js +556 -0
  162. package/dist/domain/managedArtifact.js +444 -0
  163. package/dist/domain/managedMemberComparison.js +565 -0
  164. package/dist/domain/managedNativeVerification.js +408 -0
  165. package/dist/domain/managedReconstruction.js +183 -0
  166. package/dist/domain/managedRuntimeCorrelation.js +175 -0
  167. package/dist/domain/reconstructionVerificationSchemas.js +1 -3
  168. package/dist/dotnet/ManagedArtifactInspector.js +318 -0
  169. package/dist/dotnet/ManagedMemberInspector.js +887 -0
  170. package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
  171. package/dist/dotnet/ManagedMetadataInventory.js +368 -0
  172. package/dist/dotnet/ManagedMetadataLayout.js +322 -0
  173. package/dist/dotnet/ManagedNativeBoundaryInspector.js +391 -0
  174. package/dist/dotnet/ManagedPeReader.js +157 -0
  175. package/dist/dotnet/ManagedReaderFailure.js +10 -0
  176. package/dist/dotnet/ManagedStaticProvider.js +203 -0
  177. package/dist/generatedPackageMetadata.js +2 -2
  178. package/dist/ghidra/GhidraAnalysisProfile.js +37 -0
  179. package/dist/ghidra/GhidraClient.js +400 -0
  180. package/dist/ghidra/GhidraClientTypes.js +1 -0
  181. package/dist/ghidra/GhidraDefaults.js +20 -0
  182. package/dist/ghidra/GhidraDiagnostics.js +43 -0
  183. package/dist/ghidra/GhidraDoctor.js +59 -0
  184. package/dist/ghidra/GhidraFunctionValues.js +264 -0
  185. package/dist/ghidra/GhidraInstallation.js +239 -0
  186. package/dist/ghidra/GhidraInventoryValues.js +217 -0
  187. package/dist/ghidra/GhidraLauncher.js +139 -0
  188. package/dist/ghidra/GhidraProvider.js +366 -0
  189. package/dist/ghidra/GhidraRequestQueue.js +98 -0
  190. package/dist/ghidra/GhidraResponseBuffer.js +31 -0
  191. package/dist/ghidra/GhidraResponseRouter.js +24 -0
  192. package/dist/ghidra/GhidraSessionError.js +39 -0
  193. package/dist/ghidra/GhidraSessionValues.js +62 -0
  194. package/dist/ghidra/GhidraSocketConnection.js +46 -0
  195. package/dist/ghidra/protocol.js +69 -0
  196. package/dist/hopper/BridgeLauncher.js +19 -54
  197. package/dist/hopper/HopperAnalysisProfile.js +106 -0
  198. package/dist/hopper/HopperClient.js +154 -162
  199. package/dist/hopper/HopperProvider.js +99 -7
  200. package/dist/hopper/HopperSessionValues.js +27 -0
  201. package/dist/hopper/HopperSocketConnection.js +31 -0
  202. package/dist/main.js +14 -0
  203. package/dist/native/NativeMacOSProvider.js +3 -1
  204. package/dist/process/PendingOperations.js +59 -0
  205. package/dist/process/PrivateRuntimeRoot.js +33 -0
  206. package/dist/process/ProviderDeadline.js +95 -0
  207. package/dist/process/ProviderProcess.js +275 -0
  208. package/dist/replay/JavaScriptReplayWorker.js +286 -0
  209. package/dist/replay/LinuxJavaScriptReplayRunner.js +434 -0
  210. package/dist/replay/LinuxRuntimeClosure.js +46 -0
  211. package/dist/replay/LinuxSeccompPolicy.js +40 -0
  212. package/dist/replay/ReplayWorkerProtocol.js +55 -0
  213. package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
  214. package/dist/server/createServer.js +53 -0
  215. package/dist/server/promptCompletion.js +9 -3
  216. package/dist/server/registerApplicationTools.js +115 -0
  217. package/dist/server/registerArtifactComparisonTool.js +16 -9
  218. package/dist/server/registerBrowserTools.js +33 -8
  219. package/dist/server/registerBundleComparisonTool.js +17 -20
  220. package/dist/server/registerElectronTools.js +45 -3
  221. package/dist/server/registerEnhancedTools.js +67 -19
  222. package/dist/server/registerEvidenceTools.js +5 -1
  223. package/dist/server/registerFunctionComparisonTool.js +14 -7
  224. package/dist/server/registerInvestigationTools.js +21 -17
  225. package/dist/server/registerManagedTools.js +6 -0
  226. package/dist/server/registerManagedWorkflowTools.js +277 -0
  227. package/dist/server/registerOfficialTools.js +11 -8
  228. package/dist/server/registerProcessComparisonTool.js +25 -47
  229. package/dist/server/registerSessionStatusTool.js +7 -7
  230. package/dist/server/registerSessionTools.js +57 -87
  231. package/dist/server/sessionEvidence.js +14 -19
  232. package/dist/server/toolInputValidation.js +77 -0
  233. package/dist/server/toolRegistrationOptions.js +79 -2
  234. package/dist/server/toolResult.js +25 -17
  235. package/package.json +17 -7
  236. package/scripts/rea.mjs +36 -2
  237. package/skills/rea-analysis/SKILL.md +59 -3
  238. /package/dist/{application → process}/ProcessOwnership.js +0 -0
@@ -0,0 +1,122 @@
1
+ import { readFile, stat } from "node:fs/promises";
2
+ import { z } from "zod";
3
+ import { compareManagedMembers, managedMemberComparisonResultSchema, parseManagedMemberEvidence, } from "../domain/managedMemberComparison.js";
4
+ import { AnalysisInputError, AnalysisProtocolError, } from "../domain/errors.js";
5
+ import { createEvidence } from "../domain/evidence.js";
6
+ import { jsonValueSchema } from "../domain/jsonValue.js";
7
+ import { parseBinaryTarget } from "../domain/binaryTarget.js";
8
+ import { err, ok } from "../domain/result.js";
9
+ import { inspectManagedMembersBytes } from "../dotnet/ManagedMemberInspector.js";
10
+ import { MANAGED_STATIC_PROVIDER } from "./InvestigationProviders.js";
11
+ import { MANAGED_WORKFLOW_PROVIDER } from "./InvestigationProviders.js";
12
+ /** Compare managed members from input parsed by a trusted adapter. */
13
+ export const compareManagedMembersEvidenceValidated = (input) => {
14
+ const operation = "compare_managed_members";
15
+ try {
16
+ const left = parseManagedMemberEvidence(input.left);
17
+ const right = parseManagedMemberEvidence(input.right);
18
+ const result = compareManagedMembers({ evidenceId: left.evidenceId, result: left.result }, { evidenceId: right.evidenceId, result: right.result }, input.limits);
19
+ return ok(createManagedMemberComparisonEvidence(input, result));
20
+ }
21
+ catch (cause) {
22
+ return workflowFailure(operation, cause);
23
+ }
24
+ };
25
+ /** Inspect two local PE artifacts and return one derived comparison Evidence. */
26
+ export const compareManagedMemberPaths = async (input) => {
27
+ const operation = "compare_managed_members";
28
+ try {
29
+ const [leftTarget, rightTarget] = await Promise.all([
30
+ parseBinaryTarget(input.leftPath),
31
+ parseBinaryTarget(input.rightPath),
32
+ ]);
33
+ if (!leftTarget.ok)
34
+ return err(new AnalysisInputError(operation, { cause: leftTarget.error }));
35
+ if (!rightTarget.ok)
36
+ return err(new AnalysisInputError(operation, { cause: rightTarget.error }));
37
+ const [leftStat, rightStat] = await Promise.all([
38
+ stat(leftTarget.value.path),
39
+ stat(rightTarget.value.path),
40
+ ]);
41
+ if (leftStat.size > input.memberLimits.maxFileBytes ||
42
+ rightStat.size > input.memberLimits.maxFileBytes)
43
+ return err(new AnalysisInputError(operation, {
44
+ cause: new RangeError(`Managed comparison input exceeds max_file_bytes ${String(input.memberLimits.maxFileBytes)}`),
45
+ }));
46
+ const [leftBytes, rightBytes] = await Promise.all([
47
+ readFile(leftTarget.value.path),
48
+ readFile(rightTarget.value.path),
49
+ ]);
50
+ const leftInspection = inspectManagedMembersBytes(leftBytes, leftTarget.value, input.memberLimits);
51
+ const rightInspection = inspectManagedMembersBytes(rightBytes, rightTarget.value, input.memberLimits);
52
+ const leftEvidence = createEvidence(leftTarget.value, MANAGED_STATIC_PROVIDER, {
53
+ operation: "inspect_managed_members",
54
+ parameters: memberLimitParameters(input.memberLimits),
55
+ result: jsonValueSchema.parse(leftInspection),
56
+ rawResult: null,
57
+ limitations: leftInspection.limitations,
58
+ locations: [{ kind: "artifact-path", path: leftTarget.value.path }],
59
+ });
60
+ const rightEvidence = createEvidence(rightTarget.value, MANAGED_STATIC_PROVIDER, {
61
+ operation: "inspect_managed_members",
62
+ parameters: memberLimitParameters(input.memberLimits),
63
+ result: jsonValueSchema.parse(rightInspection),
64
+ rawResult: null,
65
+ limitations: rightInspection.limitations,
66
+ locations: [{ kind: "artifact-path", path: rightTarget.value.path }],
67
+ });
68
+ const result = compareManagedMembers({
69
+ evidenceId: leftEvidence.evidence_id,
70
+ result: leftInspection,
71
+ }, {
72
+ evidenceId: rightEvidence.evidence_id,
73
+ result: rightInspection,
74
+ }, input.comparisonLimits);
75
+ return ok(createManagedMemberComparisonEvidence({
76
+ left: leftEvidence,
77
+ right: rightEvidence,
78
+ limits: input.comparisonLimits,
79
+ }, result));
80
+ }
81
+ catch (cause) {
82
+ return workflowFailure(operation, cause);
83
+ }
84
+ };
85
+ const createManagedMemberComparisonEvidence = (parameters, result) => createEvidence(undefined, MANAGED_WORKFLOW_PROVIDER, {
86
+ predicateType: "rea.managed-member-comparison/v1",
87
+ operation: "compare_managed_members",
88
+ parameters: {
89
+ left_evidence_id: parameters.left.evidence_id,
90
+ right_evidence_id: parameters.right.evidence_id,
91
+ limits: jsonValueSchema.parse(parameters.limits),
92
+ },
93
+ result: jsonValueSchema.parse(result),
94
+ rawResult: null,
95
+ confidence: "inferred",
96
+ authority: "analyst-inference",
97
+ environment: null,
98
+ limitations: result.limitations,
99
+ evidenceLinks: result.evidence_links,
100
+ });
101
+ const memberLimitParameters = (limits) => ({
102
+ type_offset: limits.typeOffset,
103
+ type_limit: limits.typeLimit,
104
+ method_offset: limits.methodOffset,
105
+ method_limit: limits.methodLimit,
106
+ field_offset: limits.fieldOffset,
107
+ field_limit: limits.fieldLimit,
108
+ member_ref_offset: limits.memberRefOffset,
109
+ member_ref_limit: limits.memberRefLimit,
110
+ edge_offset: limits.edgeOffset,
111
+ edge_limit: limits.edgeLimit,
112
+ instruction_anchor_limit: limits.instructionAnchorLimit,
113
+ max_file_bytes: limits.maxFileBytes,
114
+ max_metadata_bytes: limits.maxMetadataBytes,
115
+ max_table_rows: limits.maxTableRows,
116
+ max_heap_item_bytes: limits.maxHeapItemBytes,
117
+ max_method_body_bytes: limits.maxMethodBodyBytes,
118
+ max_method_instructions: limits.maxMethodInstructions,
119
+ });
120
+ const workflowFailure = (operation, cause) => err(cause instanceof z.ZodError || cause instanceof TypeError
121
+ ? new AnalysisInputError(operation, { cause })
122
+ : new AnalysisProtocolError("Managed member comparison produced an invalid result", { cause }));
@@ -0,0 +1,39 @@
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 { managedNativeVerificationInputSchema, verifyManagedNativeBoundaries, } from "../domain/managedNativeVerification.js";
6
+ import { err, ok } from "../domain/result.js";
7
+ import { MANAGED_WORKFLOW_PROVIDER } from "./InvestigationProviders.js";
8
+ const OPERATION = "verify_managed_native_boundaries";
9
+ /** Verify managed/native boundary declarations against native Evidence. */
10
+ export const verifyManagedNativeBoundariesEvidence = (rawInput) => {
11
+ const parsed = managedNativeVerificationInputSchema.safeParse(rawInput);
12
+ if (!parsed.success)
13
+ return err(new AnalysisInputError(OPERATION, { cause: parsed.error }));
14
+ try {
15
+ const result = verifyManagedNativeBoundaries(parsed.data);
16
+ return ok(createManagedNativeVerificationEvidence(parsed.data, result));
17
+ }
18
+ catch (cause) {
19
+ return err(cause instanceof TypeError || cause instanceof z.ZodError
20
+ ? new AnalysisInputError(OPERATION, { cause })
21
+ : new AnalysisProtocolError("Managed/native verification produced an invalid result", { cause }));
22
+ }
23
+ };
24
+ const createManagedNativeVerificationEvidence = (input, result) => createEvidence(undefined, MANAGED_WORKFLOW_PROVIDER, {
25
+ predicateType: "rea.managed-native-verification/v1",
26
+ operation: OPERATION,
27
+ parameters: {
28
+ managed_boundaries_evidence_id: input.managed_boundaries.evidence_id,
29
+ native_evidence_ids: jsonValueSchema.parse(input.native_observations.map(({ evidence_id: id }) => id)),
30
+ limits: jsonValueSchema.parse(input.limits),
31
+ },
32
+ result: jsonValueSchema.parse(result),
33
+ rawResult: null,
34
+ confidence: "inferred",
35
+ authority: "analyst-inference",
36
+ environment: null,
37
+ limitations: result.limitations,
38
+ evidenceLinks: result.evidence_links,
39
+ });
@@ -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
+ })}`;
@@ -93,7 +93,7 @@ export class PermissionAuthority {
93
93
  const decision = evaluatePermission(this.policy, canonical.value);
94
94
  if (!decision.allowed)
95
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);
96
+ return ok({ ...decision, request: canonical.value });
97
97
  }
98
98
  /** Add authority beneath the administrator ceiling. */
99
99
  grant(grant) {
@@ -6,7 +6,7 @@ import { join } from "node:path";
6
6
  import { authorizeProcessScenario, digestProcessCommitment, processComparisonContract, processScenarioCommitment, } from "../domain/processCapture.js";
7
7
  import { PRODUCT_IDENTITY } from "../identity.js";
8
8
  import { snapshotRoots } from "./FilesystemSnapshot.js";
9
- import { cleanupOwnedProcessGroup, observeOwnedProcessGroup, } from "./ProcessOwnership.js";
9
+ import { cleanupOwnedProcessGroup, observeOwnedProcessGroup, } from "../process/ProcessOwnership.js";
10
10
  import { classifyFilesystemEffects, ProcessCheckpoints, } from "./ProcessCheckpoints.js";
11
11
  import { ProcessCaptureError } from "./ProcessCaptureError.js";
12
12
  import { assertNotCancelled, assertRealPathAuthority, } from "./ProcessCaptureAuthority.js";
@@ -10,7 +10,7 @@ import { ProcessCheckpoints } from "./ProcessCheckpoints.js";
10
10
  import { TerminalRenderer } from "./TerminalRenderer.js";
11
11
  import { startCommandShimReplay, } from "./CommandShimReplay.js";
12
12
  import { normalizeProcessText } from "./ProcessNormalization.js";
13
- import { selectCapturedProcessGroupIds } from "./ProcessOwnership.js";
13
+ import { selectCapturedProcessGroupIds } from "../process/ProcessOwnership.js";
14
14
  import { awaitTerminalExit, buildCaptureResult, captureTerminalFrames, createRunManifest, observeSettlement, prepareProcessCapture, releaseProcessResources, resolveProcessResult, } from "./ProcessCaptureLifecycle.js";
15
15
  import { assertNotCancelled } from "./ProcessCaptureAuthority.js";
16
16
  export { probeProcessCaptureCapability } from "./ProcessCaptureCapability.js";
@@ -1,19 +1,23 @@
1
1
  import { execFile } from "node:child_process";
2
2
  import { readFile, readdir } from "node:fs/promises";
3
3
  import { promisify } from "node:util";
4
- import { readProcessRunId } from "./ProcessOwnership.js";
4
+ import { readProcessRunId } from "../process/ProcessOwnership.js";
5
5
  const execFileAsync = promisify(execFile);
6
6
  const PROC_READ_CONCURRENCY = 64;
7
7
  /** Prove that forkpty completed session setup and installed the run token. */
8
- export const isInitializedPtyRoot = (options) => options.before.pid === options.rootPid &&
9
- options.before.process_group_id === options.rootPid &&
10
- options.before.session_id === options.rootPid &&
11
- options.after.pid === options.rootPid &&
12
- options.after.parent_pid === options.before.parent_pid &&
13
- options.after.process_group_id === options.rootPid &&
14
- options.after.session_id === options.rootPid &&
15
- options.after.startTime === options.before.startTime &&
16
- options.observedRunId === options.expectedRunId;
8
+ export const isInitializedPtyRoot = (options) => {
9
+ const sessionIdentityMatches = (options.before.session_id === options.rootPid &&
10
+ options.after.session_id === options.rootPid) ||
11
+ (options.before.session_id === null && options.after.session_id === null);
12
+ return (options.before.pid === options.rootPid &&
13
+ options.before.process_group_id === options.rootPid &&
14
+ sessionIdentityMatches &&
15
+ options.after.pid === options.rootPid &&
16
+ options.after.parent_pid === options.before.parent_pid &&
17
+ options.after.process_group_id === options.rootPid &&
18
+ options.after.startTime === options.before.startTime &&
19
+ options.observedRunId === options.expectedRunId);
20
+ };
17
21
  const isExpectedProcReadFailure = (cause) => cause instanceof Error &&
18
22
  "code" in cause &&
19
23
  (cause.code === "ENOENT" ||
@@ -215,7 +219,7 @@ const readPsRows = async (signal) => {
215
219
  pid: Number(match[1]),
216
220
  parent_pid: Number(match[2]),
217
221
  process_group_id: Number(match[3]),
218
- session_id: Number(match[4]),
222
+ session_id: Number(match[4]) || null,
219
223
  command: match[5] ?? "",
220
224
  startTime: undefined,
221
225
  }))
@@ -232,7 +236,7 @@ const inspectInitializedPtyRoot = async (rootPid, runId, signal) => {
232
236
  const before = await readRootIdentity(rootPid, signal);
233
237
  if (before === undefined ||
234
238
  before.process_group_id !== rootPid ||
235
- before.session_id !== rootPid)
239
+ (before.session_id !== rootPid && before.session_id !== null))
236
240
  return undefined;
237
241
  let observedRunId;
238
242
  try {
@@ -21,6 +21,7 @@ const grantSchema = z.object({
21
21
  "artifact_extract",
22
22
  "native_mount",
23
23
  "reference_read",
24
+ "javascript_replay",
24
25
  ]),
25
26
  roots: z.array(z.string()),
26
27
  executables: z.array(z.string()),
@@ -0,0 +1,219 @@
1
+ import { analysisProfileSchema, } from "../domain/analysisProfile.js";
2
+ import { AnalysisCancelledError, AnalysisCapabilityUnavailableError, ProviderAdapterError, ProviderSelectionError, } from "../domain/errors.js";
3
+ import { jsonObjectSchema } from "../domain/jsonValue.js";
4
+ import { err, ok } from "../domain/result.js";
5
+ import { AnalysisProviderRegistry, } from "./AnalysisProviderRegistry.js";
6
+ import { ABORTED, waitForAbortable } from "./AbortablePromise.js";
7
+ import { CompositeProvider, compositeProviderIdentity, } from "./CompositeProvider.js";
8
+ /** Resolve either the compatibility single-provider seam or a selectable set. */
9
+ export class SessionProviderRouter {
10
+ runtime;
11
+ constructor(runtime) {
12
+ this.runtime = runtime;
13
+ }
14
+ /** Preserve the existing provider/factory seam used by focused embedders. */
15
+ static legacy(provider, options = {}) {
16
+ const identity = typeof provider === "function"
17
+ ? { id: "unidentified", name: "Unidentified provider", version: null }
18
+ : provider.identity();
19
+ const capabilities = typeof provider === "function"
20
+ ? undefined
21
+ : capabilityMap(provider.capabilities());
22
+ const resolveProfile = options.resolveAnalysisProfile ??
23
+ (typeof provider === "function" ||
24
+ provider.resolveAnalysisProfile === undefined
25
+ ? () => Promise.resolve(ok({ profile: null, compatibility: {} }))
26
+ : (target, resolutionOptions) => provider.resolveAnalysisProfile?.(target, resolutionOptions) ??
27
+ Promise.resolve(ok({ profile: null, compatibility: {} })));
28
+ return new SessionProviderRouter({
29
+ kind: "legacy",
30
+ provider,
31
+ identity,
32
+ capabilities,
33
+ resolveProfile,
34
+ });
35
+ }
36
+ /** Create selection-aware routing while keeping auxiliary families disjoint. */
37
+ static selectable(registry, auxiliaryProviders) {
38
+ const identities = [
39
+ ...registry.identities(),
40
+ ...auxiliaryProviders.map((provider) => provider.identity()),
41
+ ];
42
+ assertUniqueProviderIds(identities);
43
+ const auxiliaryOperations = assertDisjoint(auxiliaryProviders);
44
+ for (const operation of registry.declaredOperations())
45
+ if (auxiliaryOperations.has(operation))
46
+ throw new TypeError(`Deep and auxiliary providers both declare operation ${operation}`);
47
+ const initialRoute = selectableRoute(auxiliaryProviders, undefined);
48
+ return new SessionProviderRouter({
49
+ kind: "selectable",
50
+ registry,
51
+ auxiliaryProviders: [...auxiliaryProviders],
52
+ identity: identities.length === 0
53
+ ? emptyProviderIdentity()
54
+ : compositeProviderIdentity(identities),
55
+ initialRoute,
56
+ });
57
+ }
58
+ /** Compatibility identity covering every configured provider. */
59
+ configuredIdentity() {
60
+ return structuredClone(this.runtime.identity);
61
+ }
62
+ /** Provider identities exposed through the flat 1.x compatibility field. */
63
+ providerIdentities(route) {
64
+ if (this.runtime.kind === "legacy") {
65
+ if (route.capabilities === undefined)
66
+ return [route.identity];
67
+ return uniqueProviderIdentities([...route.capabilities.values()].map(({ provider }) => provider));
68
+ }
69
+ const selected = route.binding?.identity;
70
+ return uniqueProviderIdentities([
71
+ ...this.runtime.auxiliaryProviders.map((provider) => provider.identity()),
72
+ ...this.runtime.registry
73
+ .identities()
74
+ .map((identity) => identity.id === selected?.id ? selected : identity),
75
+ ]);
76
+ }
77
+ /** Target-free routes and discovery metadata. */
78
+ initialRoute() {
79
+ if (this.runtime.kind === "selectable")
80
+ return this.runtime.initialRoute;
81
+ const runtime = this.runtime;
82
+ return {
83
+ identity: structuredClone(runtime.identity),
84
+ capabilities: runtime.capabilities,
85
+ profile: null,
86
+ compatibility: {},
87
+ binding: null,
88
+ selection: undefined,
89
+ createClient: (target) => createLegacyClient(runtime, target, undefined),
90
+ };
91
+ }
92
+ /** Resolve target routes before any provider client is created. */
93
+ async resolve(target, providerId, signal) {
94
+ const resolutionOptions = signal === undefined ? undefined : { signal };
95
+ if (this.runtime.kind === "selectable") {
96
+ const selected = await this.runtime.registry.select(target, providerId, resolutionOptions);
97
+ return selected.ok
98
+ ? ok(selectableRoute(this.runtime.auxiliaryProviders, selected.value))
99
+ : selected;
100
+ }
101
+ const runtime = this.runtime;
102
+ if (providerId !== undefined &&
103
+ providerId !== "auto" &&
104
+ providerId !== runtime.identity.id)
105
+ return err(new ProviderSelectionError({
106
+ reason: "unknown_provider",
107
+ requestedProviderId: providerId,
108
+ candidateIds: [runtime.identity.id],
109
+ }));
110
+ const resolved = await waitForAbortable(runtime.resolveProfile(target, resolutionOptions), signal);
111
+ if (resolved === ABORTED)
112
+ return err(new AnalysisCancelledError("open_binary"));
113
+ if (!resolved.ok)
114
+ return resolved;
115
+ const normalized = normalizeProfileResolution(resolved.value, runtime.identity.id);
116
+ if (!normalized.ok)
117
+ return normalized;
118
+ return ok({
119
+ identity: structuredClone(runtime.identity),
120
+ capabilities: runtime.capabilities,
121
+ profile: normalized.value.profile,
122
+ compatibility: normalized.value.compatibility,
123
+ binding: null,
124
+ selection: undefined,
125
+ createClient: (openedTarget) => createLegacyClient(runtime, openedTarget, normalized.value.profile ?? undefined),
126
+ });
127
+ }
128
+ /** Candidate status authoritative for the active or target-free route. */
129
+ candidateStatuses(route) {
130
+ if (this.runtime.kind === "legacy")
131
+ return [];
132
+ return route.selection?.candidates ?? this.runtime.registry.candidates();
133
+ }
134
+ /** Produce exact candidate rejections for an intentionally unbound route. */
135
+ unboundOperationError(operation, route) {
136
+ if (this.runtime.kind !== "selectable" ||
137
+ route.binding !== null ||
138
+ route.selection === undefined)
139
+ return undefined;
140
+ return this.runtime.registry.unboundOperationError(operation, route.selection);
141
+ }
142
+ }
143
+ const selectableRoute = (auxiliaryProviders, selection) => {
144
+ const binding = selection?.binding ?? null;
145
+ const providers = [
146
+ ...auxiliaryProviders,
147
+ ...(binding === null ? [] : [binding.provider]),
148
+ ];
149
+ const provider = providers.length === 0 ? undefined : new CompositeProvider(providers);
150
+ const identity = provider?.identity() ?? emptyProviderIdentity();
151
+ const capabilities = capabilityMap(provider?.capabilities() ?? []);
152
+ return {
153
+ identity,
154
+ capabilities,
155
+ profile: binding?.profile ?? null,
156
+ compatibility: structuredClone(binding?.compatibility ?? {}),
157
+ binding,
158
+ selection,
159
+ createClient: (target) => provider?.createClient(target, binding?.profile) ?? emptyClient(identity),
160
+ };
161
+ };
162
+ const createLegacyClient = (runtime, target, profile) => typeof runtime.provider === "function"
163
+ ? runtime.provider(target, profile)
164
+ : runtime.provider.createClient(target, profile);
165
+ const emptyClient = (identity) => ({
166
+ execute: (operation) => operation === "health"
167
+ ? Promise.resolve(ok({
168
+ result: null,
169
+ rawResult: null,
170
+ provider: identity,
171
+ limitations: [],
172
+ locations: [],
173
+ subject: null,
174
+ }))
175
+ : Promise.resolve(err(new AnalysisCapabilityUnavailableError(identity.id, operation, "operation is not declared by this provider set"))),
176
+ close: () => Promise.resolve(),
177
+ });
178
+ const emptyProviderIdentity = () => ({
179
+ id: "composite:none",
180
+ name: "REA composite analysis provider",
181
+ version: null,
182
+ });
183
+ const capabilityMap = (capabilities) => new Map(capabilities.map((descriptor) => [descriptor.operation, descriptor]));
184
+ const uniqueProviderIdentities = (identities) => [...new Map(identities.map((identity) => [identity.id, identity])).values()]
185
+ .sort((left, right) => left.id.localeCompare(right.id))
186
+ .map((identity) => structuredClone(identity));
187
+ const assertDisjoint = (providers) => {
188
+ const routes = new Set();
189
+ for (const provider of providers)
190
+ for (const { operation } of provider.capabilities()) {
191
+ if (routes.has(operation))
192
+ throw new TypeError(`Multiple auxiliary providers declare operation ${operation}`);
193
+ routes.add(operation);
194
+ }
195
+ return routes;
196
+ };
197
+ const assertUniqueProviderIds = (identities) => {
198
+ const ids = new Set();
199
+ for (const identity of identities) {
200
+ if (ids.has(identity.id))
201
+ throw new TypeError(`Duplicate configured provider ID: ${identity.id}`);
202
+ ids.add(identity.id);
203
+ }
204
+ };
205
+ const normalizeProfileResolution = (resolution, providerId) => {
206
+ try {
207
+ return ok({
208
+ profile: resolution.profile === null
209
+ ? null
210
+ : analysisProfileSchema.parse(resolution.profile),
211
+ compatibility: jsonObjectSchema.parse(resolution.compatibility),
212
+ });
213
+ }
214
+ catch (cause) {
215
+ return err(new ProviderAdapterError(providerId, "resolve_analysis_profile", {
216
+ cause,
217
+ }));
218
+ }
219
+ };