rea-agents 2.5.0 → 3.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 (253) hide show
  1. package/README.md +20 -12
  2. package/bridge/ghidra/ReaGhidraBridge.java +477 -4
  3. package/bridge/hopper_bridge.py +54 -4
  4. package/dist/application/AnalysisContextQueries.js +142 -0
  5. package/dist/application/AnalysisSnapshotCache.js +4 -2
  6. package/dist/application/ApplicationWorkflowEvidenceResolver.js +19 -11
  7. package/dist/application/ArtifactInventory/policy.js +17 -0
  8. package/dist/application/ArtifactInventory/reader.js +1 -4
  9. package/dist/application/ArtifactInventory/scanCanonical.js +0 -3
  10. package/dist/application/ArtifactInventory/scanReader.js +7 -7
  11. package/dist/application/ArtifactInventory/types.js +1 -5
  12. package/dist/application/BinarySession.js +19 -20
  13. package/dist/application/BinarySessionComposition.js +21 -0
  14. package/dist/application/BinarySessionRecords.js +106 -10
  15. package/dist/application/BinarySessionStatus.js +11 -5
  16. package/dist/application/BrowserEvidence.js +3 -5
  17. package/dist/application/CapabilityClientRequirements.js +26 -0
  18. package/dist/application/CapabilityInventory.js +140 -55
  19. package/dist/application/ClientRegistrationStatus.js +4 -1
  20. package/dist/application/CrossVersionInventory.js +7 -6
  21. package/dist/application/DirectAnalysis.js +6 -2
  22. package/dist/application/ElectronActiveEvidence.js +55 -0
  23. package/dist/application/ElectronActiveObservationPort.js +1 -0
  24. package/dist/application/ElectronActiveObservationService.js +81 -0
  25. package/dist/application/EnhancedTools.js +49 -17
  26. package/dist/application/EvidenceBundleCommands.js +5 -1
  27. package/dist/application/EvidenceLedger.js +53 -17
  28. package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
  29. package/dist/application/JavaScriptReplayPermission.js +1 -1
  30. package/dist/application/JavaScriptReplayService.js +23 -15
  31. package/dist/application/LazyAnalysisProvider.js +77 -0
  32. package/dist/application/LoopbackReplay.js +1 -1
  33. package/dist/application/ManagedRuntimeCorrelationService.js +9 -5
  34. package/dist/application/NativeApiInspection.js +80 -0
  35. package/dist/application/NodeRuntimeCharacterizationService.js +8 -9
  36. package/dist/application/ProcessCaptureLifecycle.js +5 -0
  37. package/dist/application/ProcessCli.js +2 -1
  38. package/dist/application/ProcessHarness.js +8 -3
  39. package/dist/application/ProcessNormalization.js +2 -1
  40. package/dist/application/ProjectPermissionStore.js +1 -0
  41. package/dist/application/ReferenceSourceImport.js +2 -2
  42. package/dist/application/SessionProviderRouter.js +6 -6
  43. package/dist/application/SetupClientConfiguration.js +10 -3
  44. package/dist/application/WindowsCapabilities.js +5 -4
  45. package/dist/application/runtime.js +26 -9
  46. package/dist/artifacts/ArtifactProvider.js +8 -10
  47. package/dist/artifacts/SafeOutputTree.js +7 -8
  48. package/dist/browser/CdpCaptureStorageFingerprints.js +10 -7
  49. package/dist/browser/CdpElectronInspection.js +3 -1
  50. package/dist/browser/JavaScriptRuntimeScope.js +5 -0
  51. package/dist/browser/PlaywrightBrowserScenarioProvider.js +8 -2
  52. package/dist/browser/PlaywrightElectronActiveActions.js +324 -0
  53. package/dist/browser/PlaywrightElectronActiveProvider.js +294 -0
  54. package/dist/browser/PlaywrightScenarioBrowser.js +4 -4
  55. package/dist/browser/PlaywrightScenarioSession.js +4 -4
  56. package/dist/browser/SensitiveTextCapture.js +1 -1
  57. package/dist/browser/V8InspectorCaptureProjection.js +1 -0
  58. package/dist/browser/V8InspectorProvider.js +3 -3
  59. package/dist/catalogIdentity.js +15 -9
  60. package/dist/cli/artifactCommands.js +5 -3
  61. package/dist/cli/coreAnalysisCommands.js +41 -0
  62. package/dist/cli/managedCommands.js +1 -1
  63. package/dist/cliApplicationCommands.js +2 -2
  64. package/dist/cliBrowserAdvancedCommands.js +11 -5
  65. package/dist/cliBrowserCommands.js +14 -7
  66. package/dist/cliCommandNames.js +2 -0
  67. package/dist/cliElectronCommands.js +46 -4
  68. package/dist/cliJavaScriptRuntimeCommands.js +14 -6
  69. package/dist/cliObservationOptions.js +4 -0
  70. package/dist/cliPolicyCommands.js +1 -0
  71. package/dist/config/browserScenario.js +77 -0
  72. package/dist/config/electronAutomation.js +35 -0
  73. package/dist/config/environment.js +6 -0
  74. package/dist/config/javascriptReplay.js +41 -0
  75. package/dist/config/managedRuntime.js +25 -0
  76. package/dist/config/parseConfig.js +56 -200
  77. package/dist/config/parsers.js +10 -1
  78. package/dist/config/passiveObservation.js +157 -0
  79. package/dist/config/processCapture.js +47 -0
  80. package/dist/contracts/applicationToolContracts.js +2 -5
  81. package/dist/contracts/applicationWorkflowInputContracts.js +86 -96
  82. package/dist/contracts/artifactToolContracts.js +35 -37
  83. package/dist/contracts/browserToolContracts.js +2 -2
  84. package/dist/contracts/electronToolContracts.js +30 -1
  85. package/dist/contracts/enhancedInputs.js +21 -27
  86. package/dist/contracts/functionWorkflowToolContracts.js +29 -0
  87. package/dist/contracts/managedToolContracts.js +4 -9
  88. package/dist/contracts/managedWorkflowExamples.js +12 -9
  89. package/dist/contracts/managedWorkflowToolContracts.js +30 -27
  90. package/dist/contracts/nativeToolContracts.js +2 -3
  91. package/dist/contracts/promptContracts.js +14 -15
  92. package/dist/contracts/sessionToolSchemas.js +61 -0
  93. package/dist/contracts/toolContractExamples.js +4 -0
  94. package/dist/contracts/toolContractHelpers.js +23 -0
  95. package/dist/contracts/toolContracts.js +12 -67
  96. package/dist/contracts/toolEffects.js +19 -0
  97. package/dist/contracts/toolOutputSchemaGroups.js +66 -11
  98. package/dist/contracts/toolOutputSchemaPrimitives.js +76 -26
  99. package/dist/contracts/toolSchemaMetadata.js +128 -0
  100. package/dist/doctorRuntime.js +1 -1
  101. package/dist/domain/analysisErrorPresentation.js +8 -2
  102. package/dist/domain/analysisErrorProjection.js +1 -0
  103. package/dist/domain/androidApplication.js +2 -0
  104. package/dist/domain/appleApplication.js +2 -0
  105. package/dist/domain/binaryTarget.js +7 -5
  106. package/dist/domain/binaryTargetTypes.js +1 -0
  107. package/dist/domain/browserCaptureComparison.js +21 -69
  108. package/dist/domain/browserObservation.js +22 -9
  109. package/dist/domain/bytecodeProvider.js +177 -0
  110. package/dist/domain/callPath.js +3 -2
  111. package/dist/domain/conformancePackage.js +169 -0
  112. package/dist/domain/conformanceReplay.js +104 -0
  113. package/dist/domain/conformanceTrustGate.js +328 -0
  114. package/dist/domain/customProtocolCapture.js +137 -0
  115. package/dist/domain/electronActiveObservation.js +277 -0
  116. package/dist/domain/electronObservation.js +15 -11
  117. package/dist/domain/electronStaticAnalysisValues.js +4 -1
  118. package/dist/domain/eventProcessTree.js +217 -0
  119. package/dist/domain/evidenceBundle.js +47 -0
  120. package/dist/domain/functionComparisonNormalization.js +15 -8
  121. package/dist/domain/functionDossierEvidence.js +9 -4
  122. package/dist/domain/hopperStartupFailure.js +1 -1
  123. package/dist/domain/hopperValues.js +68 -68
  124. package/dist/domain/inputIssueProjection.js +11 -2
  125. package/dist/domain/investigationWorkspace.js +16 -15
  126. package/dist/domain/javascriptExportShapeComparisonSchemas.js +2 -2
  127. package/dist/domain/javascriptReplay.js +79 -63
  128. package/dist/domain/javascriptRuntimeObservation.js +1 -0
  129. package/dist/domain/javascriptRuntimeReconciliationActive.js +89 -0
  130. package/dist/domain/javascriptRuntimeReconciliationGraph.js +11 -10
  131. package/dist/domain/javascriptRuntimeReconciliationMatching.js +57 -49
  132. package/dist/domain/javascriptRuntimeReconciliationParsing.js +5 -1
  133. package/dist/domain/javascriptRuntimeReconciliationResult.js +21 -14
  134. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
  135. package/dist/domain/javascriptSemanticAnalysis.js +8 -12
  136. package/dist/domain/javascriptSourceParser.js +15 -0
  137. package/dist/domain/javascriptStaticAnalysis.js +8 -12
  138. package/dist/domain/knownPageCoverage.js +15 -7
  139. package/dist/domain/mobileApplicationInvestigation.js +159 -0
  140. package/dist/domain/nativeApiBoundary.js +138 -0
  141. package/dist/domain/nodeRuntimeCharacterization.js +14 -13
  142. package/dist/domain/objcSwiftMetadata.js +150 -0
  143. package/dist/domain/packageAnalysis.js +123 -0
  144. package/dist/domain/peInspection.js +196 -0
  145. package/dist/domain/processCaptureReactiveValidation.js +8 -3
  146. package/dist/domain/processCaptureValidation.js +7 -3
  147. package/dist/domain/processComparison.js +12 -7
  148. package/dist/domain/processObservation.js +5 -6
  149. package/dist/domain/processReactiveMatching.js +14 -7
  150. package/dist/domain/processReactiveTransition.js +9 -3
  151. package/dist/domain/processScenario.js +6 -3
  152. package/dist/domain/processTraceComparison.js +3 -2
  153. package/dist/domain/protocolCapture.js +245 -0
  154. package/dist/domain/reconstructionReadinessSchemas.js +30 -2
  155. package/dist/domain/referenceSourceImportParsing.js +2 -2
  156. package/dist/domain/replayMachineRuntime.js +5 -3
  157. package/dist/domain/sourceToBundleComparison.js +2 -2
  158. package/dist/domain/sourceToBundleComparisonSchemas.js +8 -8
  159. package/dist/domain/sourceToBundleSignals.js +7 -1
  160. package/dist/domain/staticRuntimeCorrelation.js +7 -5
  161. package/dist/domain/webBundleAnalysis.js +14 -14
  162. package/dist/domain/webCaptureDiff.js +15 -12
  163. package/dist/dotnet/ManagedNativeBoundaryInspector.js +2 -3
  164. package/dist/dotnet/ManagedStaticProvider.js +34 -5
  165. package/dist/generatedMcpToolCatalog.js +37 -0
  166. package/dist/generatedPackageMetadata.js +4 -4
  167. package/dist/ghidra/GhidraClient.js +1 -1
  168. package/dist/ghidra/GhidraClientStartup.js +1 -1
  169. package/dist/ghidra/GhidraDefaults.js +1 -1
  170. package/dist/ghidra/GhidraFunctionValues.js +44 -16
  171. package/dist/ghidra/GhidraInventoryValues.js +57 -47
  172. package/dist/ghidra/GhidraProvider.js +18 -10
  173. package/dist/ghidra/GhidraProviderCapabilities.js +45 -39
  174. package/dist/ghidra/GhidraSocketConnection.js +1 -1
  175. package/dist/ghidra/protocol.js +19 -42
  176. package/dist/hopper/BridgeLauncher.js +3 -1
  177. package/dist/hopper/HopperAnalysisProfile.js +2 -4
  178. package/dist/hopper/HopperCleanup.js +5 -6
  179. package/dist/hopper/HopperClient.js +27 -3
  180. package/dist/hopper/HopperProvider.js +42 -44
  181. package/dist/hopper/HopperRequestQueue.js +32 -4
  182. package/dist/hopper/HopperResponseStream.js +2 -2
  183. package/dist/hopper/LinuxPrivateDisplayProbe.js +16 -10
  184. package/dist/hopper/protocol.js +63 -21
  185. package/dist/main/reload.js +1 -6
  186. package/dist/main/state.js +0 -14
  187. package/dist/main/transport.js +31 -41
  188. package/dist/main.js +17 -13
  189. package/dist/mcpDoctor.js +4 -26
  190. package/dist/mcpStartupPolicy.js +14 -0
  191. package/dist/process/PrivateRuntimeRoot.js +17 -0
  192. package/dist/process/ProcessOwnership.js +64 -128
  193. package/dist/process/ProcessOwnershipIdentity.js +13 -0
  194. package/dist/process/ProcessOwnershipObservation.js +88 -0
  195. package/dist/process/ProcessOwnershipProcessTree.js +22 -0
  196. package/dist/process/ProviderDeadline.js +8 -12
  197. package/dist/process/WindowsAuthority.js +32 -0
  198. package/dist/reference/ReferenceSourceReader.js +3 -3
  199. package/dist/reference/ReferenceSourceReaderEntries.js +2 -2
  200. package/dist/replay/JavaScriptReplayWorker.js +95 -11
  201. package/dist/replay/JavaScriptReplayWorkerTypes.js +1 -0
  202. package/dist/replay/LinuxJavaScriptReplayRunner.js +10 -15
  203. package/dist/replay/ReplayOutcome.js +26 -15
  204. package/dist/replay/ReplayWorkerProtocol.js +34 -29
  205. package/dist/server/createServer.js +101 -144
  206. package/dist/server/mcpClientMetadata.js +32 -0
  207. package/dist/server/registerApplicationTools/characterization.js +6 -13
  208. package/dist/server/registerApplicationTools/compareExportShapes.js +2 -7
  209. package/dist/server/registerApplicationTools/compareSourceToBundle.js +2 -7
  210. package/dist/server/registerApplicationTools/compareVersions.js +3 -8
  211. package/dist/server/registerApplicationTools/controlledReplay.js +6 -11
  212. package/dist/server/registerApplicationTools/coverage.js +13 -19
  213. package/dist/server/registerApplicationTools/obligationLedger.js +1 -6
  214. package/dist/server/registerApplicationTools/readiness.js +1 -6
  215. package/dist/server/registerApplicationTools/traceFeature.js +3 -8
  216. package/dist/server/registerApplicationTools/traceSemantics.js +1 -6
  217. package/dist/server/registerArtifactComparisonTool.js +12 -16
  218. package/dist/server/registerBrowserScenarioTool.js +1 -6
  219. package/dist/server/registerBrowserTools.js +37 -79
  220. package/dist/server/registerBundleComparisonTool.js +10 -14
  221. package/dist/server/registerCloseLifecycleTool.js +6 -14
  222. package/dist/server/registerElectronTools.js +30 -47
  223. package/dist/server/registerEnhancedTools.js +124 -122
  224. package/dist/server/registerEvidenceResources.js +50 -101
  225. package/dist/server/registerEvidenceTools.js +5 -9
  226. package/dist/server/registerFunctionComparisonTool.js +11 -15
  227. package/dist/server/registerInvestigationTools.js +42 -59
  228. package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
  229. package/dist/server/registerJavaScriptRuntimeObservationTools.js +13 -27
  230. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -9
  231. package/dist/server/registerManagedWorkflowTools/contract.js +2 -3
  232. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -8
  233. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +3 -8
  234. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +8 -13
  235. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +4 -9
  236. package/dist/server/registerOfficialTools.js +8 -9
  237. package/dist/server/registerProcessComparisonTool.js +19 -24
  238. package/dist/server/registerReconstructionObligationLedgerResource.js +0 -7
  239. package/dist/server/registerReconstructionReadinessResource.js +0 -7
  240. package/dist/server/registerReplayMachineTool.js +4 -10
  241. package/dist/server/registerSessionRecordTools.js +146 -47
  242. package/dist/server/registerSessionStatusTool.js +14 -29
  243. package/dist/server/registerSessionTools.js +45 -41
  244. package/dist/server/sessionAvailabilityPolicy.js +2 -1
  245. package/dist/server/sessionToolPolicies.js +1 -5
  246. package/dist/server/toolRegistrationOptions.js +4 -177
  247. package/dist/server/toolResult.js +14 -18
  248. package/package.json +35 -16
  249. package/scripts/electron-active-hook-boundaries.cjs +394 -0
  250. package/scripts/electron-active-hook.cjs +501 -0
  251. package/skills/reverse-engineer-anything/SKILL.md +10 -3
  252. package/dist/server/DynamicToolAvailability.js +0 -70
  253. package/dist/server/toolInputValidation.js +0 -77
@@ -0,0 +1,41 @@
1
+ import { ConfigurationError } from "../domain/errors.js";
2
+ import { err, ok } from "../domain/result.js";
3
+ import { parseAbsoluteRoots } from "./parsers.js";
4
+ import { permissionScope } from "./permissions.js";
5
+ /** Parse controlled replay configuration into disabled or fully enabled state. */
6
+ export const parseJavaScriptReplayPolicy = (env) => {
7
+ const roots = parseAbsoluteRoots(env.REA_JAVASCRIPT_REPLAY_ROOTS_JSON, "REA_JAVASCRIPT_REPLAY_ROOTS_JSON");
8
+ if (!roots.ok)
9
+ return roots;
10
+ if (env.REA_JAVASCRIPT_REPLAY_ENABLED !== "true")
11
+ return ok({ status: "disabled" });
12
+ const [firstRoot, ...remainingRoots] = roots.value;
13
+ if (firstRoot === undefined)
14
+ return err(new ConfigurationError("REA_JAVASCRIPT_REPLAY_ROOTS_JSON must encode at least one absolute root when JavaScript replay is enabled"));
15
+ return ok({
16
+ status: "enabled",
17
+ roots: [firstRoot, ...remainingRoots],
18
+ nodePath: env.REA_JAVASCRIPT_REPLAY_NODE_PATH,
19
+ bubblewrapPath: env.REA_JAVASCRIPT_REPLAY_BWRAP_PATH,
20
+ systemdRunPath: env.REA_JAVASCRIPT_REPLAY_SYSTEMD_RUN_PATH,
21
+ systemctlPath: env.REA_JAVASCRIPT_REPLAY_SYSTEMCTL_PATH,
22
+ shellPath: env.REA_JAVASCRIPT_REPLAY_SHELL_PATH,
23
+ });
24
+ };
25
+ /** Add the exact controlled replay ceiling when replay is enabled. */
26
+ export const appendJavaScriptReplayCeiling = (ceilings, policy) => {
27
+ if (policy.status === "disabled")
28
+ return;
29
+ ceilings.push(permissionScope("javascript_replay", policy.roots, {
30
+ executables: replayExecutables(policy),
31
+ network: "none",
32
+ mount: true,
33
+ }));
34
+ };
35
+ const replayExecutables = (policy) => [
36
+ policy.nodePath,
37
+ policy.bubblewrapPath,
38
+ policy.systemdRunPath,
39
+ policy.systemctlPath,
40
+ policy.shellPath,
41
+ ];
@@ -0,0 +1,25 @@
1
+ import { ConfigurationError } from "../domain/errors.js";
2
+ import { err, ok } from "../domain/result.js";
3
+ import { permissionScope } from "./permissions.js";
4
+ /** Parse managed runtime correlation into a closed disabled or enabled policy. */
5
+ export const parseManagedRuntimePolicy = (env, roots) => {
6
+ if (env.REA_MANAGED_RUNTIME_ENABLED !== "true")
7
+ return ok({ status: "disabled" });
8
+ const [firstRoot, ...remainingRoots] = roots;
9
+ if (firstRoot === undefined)
10
+ return err(new ConfigurationError("REA_MANAGED_RUNTIME_ROOTS_JSON must encode at least one absolute root when managed runtime correlation is enabled"));
11
+ return ok({
12
+ status: "enabled",
13
+ roots: [firstRoot, ...remainingRoots],
14
+ executablePath: env.REA_MANAGED_RUNTIME_EXECUTABLE_PATH,
15
+ });
16
+ };
17
+ /** Add the separately permissioned, no-network managed runtime ceiling. */
18
+ export const appendManagedRuntimeCeiling = (ceilings, policy) => {
19
+ if (policy.status === "disabled")
20
+ return;
21
+ ceilings.push(permissionScope("managed_runtime", policy.roots, {
22
+ executables: [policy.executablePath],
23
+ network: "none",
24
+ }));
25
+ };
@@ -1,10 +1,14 @@
1
- import { isAbsolute } from "node:path";
2
1
  import { ConfigurationError } from "../domain/errors.js";
3
- import { err, ok } from "../domain/result.js";
2
+ import { ok } from "../domain/result.js";
4
3
  import { parseEnvironment } from "./environment.js";
5
- import { parseStringArray, parseBrowserArray, parseElectronFileRoots, parseLoaderArgs, } from "./parsers.js";
6
- import { filePolicy, permissionScope, administratorGrants, browserNetworkScope, } from "./permissions.js";
7
- import { browserEndpointSchema, browserOriginSchema, } from "../domain/browserObservation.js";
4
+ import { parseStringArray, parseAbsoluteRoots, parseLoaderArgs, } from "./parsers.js";
5
+ import { filePolicy, permissionScope, administratorGrants, } from "./permissions.js";
6
+ import { appendElectronAutomationCeiling, parseElectronAutomationPolicy, } from "./electronAutomation.js";
7
+ import { appendBrowserScenarioCeiling, parseBrowserScenarioPolicy, } from "./browserScenario.js";
8
+ import { appendManagedRuntimeCeiling, parseManagedRuntimePolicy, } from "./managedRuntime.js";
9
+ import { appendJavaScriptReplayCeiling, parseJavaScriptReplayPolicy, } from "./javascriptReplay.js";
10
+ import { appendProcessCaptureCeiling, parseProcessExecutionPolicy, } from "./processCapture.js";
11
+ import { appendPassiveObservationCeilings, parsePassiveObservationPolicies, } from "./passiveObservation.js";
8
12
  const DEFAULT_HOPPER_LAUNCHER_PATH = "/Applications/Hopper Disassembler.app/Contents/MacOS/hopper";
9
13
  const defaultHopperLauncherPath = () => process.platform === "linux"
10
14
  ? "/opt/hopper/bin/Hopper"
@@ -13,15 +17,6 @@ const parseAllArrays = (env) => {
13
17
  const loaderArgs = parseLoaderArgs(env.HOPPER_LOADER_ARGS_JSON);
14
18
  if (!loaderArgs.ok)
15
19
  return loaderArgs;
16
- const executableRoots = parseStringArray(env.REA_PROCESS_EXECUTABLE_ROOTS_JSON, "REA_PROCESS_EXECUTABLE_ROOTS_JSON");
17
- if (!executableRoots.ok)
18
- return executableRoots;
19
- const workingRoots = parseStringArray(env.REA_PROCESS_WORKING_ROOTS_JSON, "REA_PROCESS_WORKING_ROOTS_JSON");
20
- if (!workingRoots.ok)
21
- return workingRoots;
22
- const allowedEnvironment = parseStringArray(env.REA_PROCESS_ALLOWED_ENV_JSON, "REA_PROCESS_ALLOWED_ENV_JSON");
23
- if (!allowedEnvironment.ok)
24
- return allowedEnvironment;
25
20
  const evidenceRoots = parseStringArray(env.REA_EVIDENCE_ROOTS_JSON, "REA_EVIDENCE_ROOTS_JSON");
26
21
  if (!evidenceRoots.ok)
27
22
  return evidenceRoots;
@@ -37,160 +32,24 @@ const parseAllArrays = (env) => {
37
32
  const secretPatterns = parseStringArray(env.REA_REFERENCE_SECRET_PATTERNS_JSON, "REA_REFERENCE_SECRET_PATTERNS_JSON");
38
33
  if (!secretPatterns.ok)
39
34
  return secretPatterns;
40
- const observations = parseObservationArrays(env);
41
- if (!observations.ok)
42
- return observations;
43
- const javascriptReplayRoots = parseAbsoluteRoots(env.REA_JAVASCRIPT_REPLAY_ROOTS_JSON, "REA_JAVASCRIPT_REPLAY_ROOTS_JSON");
44
- if (!javascriptReplayRoots.ok)
45
- return javascriptReplayRoots;
46
35
  const managedRuntimeRoots = parseAbsoluteRoots(env.REA_MANAGED_RUNTIME_ROOTS_JSON, "REA_MANAGED_RUNTIME_ROOTS_JSON");
47
36
  if (!managedRuntimeRoots.ok)
48
37
  return managedRuntimeRoots;
49
38
  return ok({
50
39
  loaderArgs: loaderArgs.value,
51
- executableRoots: executableRoots.value,
52
- workingRoots: workingRoots.value,
53
- allowedEnvironment: allowedEnvironment.value,
54
40
  evidenceRoots: evidenceRoots.value,
55
41
  investigationInputRoots: investigationInputRoots.value,
56
42
  analysisSnapshotRoots: analysisSnapshotRoots.value,
57
43
  referenceRoots: referenceRoots.value,
58
44
  secretPatterns: secretPatterns.value,
59
- ...observations.value,
60
- javascriptReplayRoots: javascriptReplayRoots.value,
61
45
  managedRuntimeRoots: managedRuntimeRoots.value,
62
46
  });
63
47
  };
64
- const parseObservationArrays = (env) => {
65
- const browserEndpoints = parseBrowserArray(env.REA_BROWSER_CDP_ENDPOINTS_JSON, "REA_BROWSER_CDP_ENDPOINTS_JSON", browserEndpointSchema, 16);
66
- if (!browserEndpoints.ok)
67
- return browserEndpoints;
68
- const browserOrigins = parseBrowserArray(env.REA_BROWSER_ALLOWED_ORIGINS_JSON, "REA_BROWSER_ALLOWED_ORIGINS_JSON", browserOriginSchema, 32);
69
- if (!browserOrigins.ok)
70
- return browserOrigins;
71
- const browserScenarioExecutableRoots = parseAbsoluteRoots(env.REA_BROWSER_SCENARIO_EXECUTABLE_ROOTS_JSON, "REA_BROWSER_SCENARIO_EXECUTABLE_ROOTS_JSON");
72
- if (!browserScenarioExecutableRoots.ok)
73
- return browserScenarioExecutableRoots;
74
- const browserScenarioEndpoints = parseBrowserArray(env.REA_BROWSER_SCENARIO_CDP_ENDPOINTS_JSON, "REA_BROWSER_SCENARIO_CDP_ENDPOINTS_JSON", browserEndpointSchema, 16);
75
- if (!browserScenarioEndpoints.ok)
76
- return browserScenarioEndpoints;
77
- const browserScenarioOrigins = parseBrowserArray(env.REA_BROWSER_SCENARIO_ALLOWED_ORIGINS_JSON, "REA_BROWSER_SCENARIO_ALLOWED_ORIGINS_JSON", browserOriginSchema, 32);
78
- if (!browserScenarioOrigins.ok)
79
- return browserScenarioOrigins;
80
- const browserScenarioEnvironment = parseStringArray(env.REA_BROWSER_SCENARIO_ALLOWED_ENV_JSON, "REA_BROWSER_SCENARIO_ALLOWED_ENV_JSON");
81
- if (!browserScenarioEnvironment.ok)
82
- return browserScenarioEnvironment;
83
- const electronEndpoints = parseBrowserArray(env.REA_ELECTRON_CDP_ENDPOINTS_JSON, "REA_ELECTRON_CDP_ENDPOINTS_JSON", browserEndpointSchema, 16);
84
- if (!electronEndpoints.ok)
85
- return electronEndpoints;
86
- const electronFileRoots = parseElectronFileRoots(env.REA_ELECTRON_FILE_ROOTS_JSON);
87
- if (!electronFileRoots.ok)
88
- return electronFileRoots;
89
- const v8InspectorEndpoints = parseBrowserArray(env.REA_V8_INSPECTOR_ENDPOINTS_JSON, "REA_V8_INSPECTOR_ENDPOINTS_JSON", browserEndpointSchema, 16);
90
- if (!v8InspectorEndpoints.ok)
91
- return v8InspectorEndpoints;
92
- const v8InspectorFileRoots = parseAbsoluteRoots(env.REA_V8_INSPECTOR_FILE_ROOTS_JSON, "REA_V8_INSPECTOR_FILE_ROOTS_JSON");
93
- if (!v8InspectorFileRoots.ok)
94
- return v8InspectorFileRoots;
95
- const v8InspectorOrigins = parseBrowserArray(env.REA_V8_INSPECTOR_ALLOWED_ORIGINS_JSON, "REA_V8_INSPECTOR_ALLOWED_ORIGINS_JSON", browserOriginSchema, 32);
96
- if (!v8InspectorOrigins.ok)
97
- return v8InspectorOrigins;
98
- return ok({
99
- browserEndpoints: browserEndpoints.value,
100
- browserOrigins: browserOrigins.value,
101
- browserScenarioExecutableRoots: browserScenarioExecutableRoots.value,
102
- browserScenarioEndpoints: browserScenarioEndpoints.value,
103
- browserScenarioOrigins: browserScenarioOrigins.value,
104
- browserScenarioEnvironment: browserScenarioEnvironment.value,
105
- electronEndpoints: electronEndpoints.value,
106
- electronFileRoots: electronFileRoots.value,
107
- v8InspectorEndpoints: v8InspectorEndpoints.value,
108
- v8InspectorFileRoots: v8InspectorFileRoots.value,
109
- v8InspectorOrigins: v8InspectorOrigins.value,
110
- });
111
- };
112
- const parseAbsoluteRoots = (value, name) => {
113
- const parsed = parseStringArray(value, name);
114
- if (!parsed.ok)
115
- return parsed;
116
- return parsed.value.some((root) => !isAbsolute(root))
117
- ? err(new ConfigurationError(`${name} must encode absolute roots`))
118
- : parsed;
119
- };
120
- const appendProcessCaptureCeiling = (ceilings, env, arrays) => {
121
- if (env.REA_PROCESS_CAPTURE_ENABLED !== "true")
122
- return;
123
- ceilings.push(permissionScope("process_capture", arrays.workingRoots, {
124
- executables: arrays.executableRoots,
125
- environment_names: arrays.allowedEnvironment,
126
- network: env.REA_PROCESS_ALLOW_EXTERNAL_NETWORK === "true" ? "external" : "none",
127
- }));
128
- };
129
- const appendBrowserObservationCeiling = (ceilings, env, arrays) => {
130
- if (env.REA_BROWSER_OBSERVE_ENABLED !== "true")
131
- return;
132
- ceilings.push(permissionScope("browser_observe", [], {
133
- origins: [...arrays.browserEndpoints, ...arrays.browserOrigins],
134
- network: browserNetworkScope(arrays.browserOrigins),
135
- }));
136
- };
137
- const appendBrowserScenarioCeiling = (ceilings, env, arrays) => {
138
- if (env.REA_BROWSER_SCENARIO_ENABLED !== "true")
139
- return;
140
- ceilings.push(permissionScope("browser_automate", [], {
141
- executables: arrays.browserScenarioExecutableRoots,
142
- environment_names: arrays.browserScenarioEnvironment,
143
- origins: [
144
- ...arrays.browserScenarioEndpoints,
145
- ...arrays.browserScenarioOrigins,
146
- ],
147
- network: browserNetworkScope(arrays.browserScenarioOrigins),
148
- }));
149
- };
150
- const appendElectronObservationCeiling = (ceilings, env, arrays) => {
151
- if (env.REA_ELECTRON_OBSERVE_ENABLED !== "true")
152
- return;
153
- ceilings.push(permissionScope("electron_observe", arrays.electronFileRoots, {
154
- origins: arrays.electronEndpoints,
155
- network: "loopback",
156
- }));
157
- };
158
- const appendV8InspectorObservationCeiling = (ceilings, env, arrays) => {
159
- if (env.REA_V8_INSPECTOR_OBSERVE_ENABLED !== "true")
160
- return;
161
- ceilings.push(permissionScope("v8_inspector_observe", arrays.v8InspectorFileRoots, {
162
- origins: [...arrays.v8InspectorEndpoints, ...arrays.v8InspectorOrigins],
163
- network: "loopback",
164
- }));
165
- };
166
48
  const appendNativeMountCeiling = (ceilings, env) => {
167
49
  if (env.REA_ARTIFACT_NATIVE_MOUNT_ENABLED === "true")
168
50
  ceilings.push(permissionScope("native_mount", [], { mount: true }));
169
51
  };
170
- const appendJavaScriptReplayCeiling = (ceilings, env, arrays) => {
171
- if (env.REA_JAVASCRIPT_REPLAY_ENABLED !== "true")
172
- return;
173
- ceilings.push(permissionScope("javascript_replay", arrays.javascriptReplayRoots, {
174
- executables: [
175
- env.REA_JAVASCRIPT_REPLAY_NODE_PATH,
176
- env.REA_JAVASCRIPT_REPLAY_BWRAP_PATH,
177
- env.REA_JAVASCRIPT_REPLAY_SYSTEMD_RUN_PATH,
178
- env.REA_JAVASCRIPT_REPLAY_SYSTEMCTL_PATH,
179
- env.REA_JAVASCRIPT_REPLAY_SHELL_PATH,
180
- ],
181
- network: "none",
182
- mount: true,
183
- }));
184
- };
185
- const appendManagedRuntimeCeiling = (ceilings, env, arrays) => {
186
- if (env.REA_MANAGED_RUNTIME_ENABLED !== "true")
187
- return;
188
- ceilings.push(permissionScope("managed_runtime", arrays.managedRuntimeRoots, {
189
- executables: [env.REA_MANAGED_RUNTIME_EXECUTABLE_PATH],
190
- network: "none",
191
- }));
192
- };
193
- const buildPermissionCeilings = (env, arrays) => {
52
+ const buildPermissionCeilings = (env, arrays, policies) => {
194
53
  const ceilings = [
195
54
  permissionScope("evidence_read", arrays.evidenceRoots),
196
55
  permissionScope("evidence_write", arrays.evidenceRoots),
@@ -202,17 +61,16 @@ const buildPermissionCeilings = (env, arrays) => {
202
61
  permissionScope("artifact_extract", ["/"]),
203
62
  permissionScope("reference_read", arrays.referenceRoots),
204
63
  ];
205
- appendProcessCaptureCeiling(ceilings, env, arrays);
206
- appendBrowserObservationCeiling(ceilings, env, arrays);
207
- appendBrowserScenarioCeiling(ceilings, env, arrays);
208
- appendElectronObservationCeiling(ceilings, env, arrays);
209
- appendV8InspectorObservationCeiling(ceilings, env, arrays);
64
+ appendProcessCaptureCeiling(ceilings, policies.processCapture);
65
+ appendPassiveObservationCeilings(ceilings, policies.passiveObservation);
66
+ appendBrowserScenarioCeiling(ceilings, policies.browserScenario);
67
+ appendElectronAutomationCeiling(ceilings, policies.electronAutomation);
210
68
  appendNativeMountCeiling(ceilings, env);
211
- appendJavaScriptReplayCeiling(ceilings, env, arrays);
212
- appendManagedRuntimeCeiling(ceilings, env, arrays);
69
+ appendJavaScriptReplayCeiling(ceilings, policies.javascriptReplay);
70
+ appendManagedRuntimeCeiling(ceilings, policies.managedRuntime);
213
71
  return ceilings;
214
72
  };
215
- const buildAppConfig = (env, arrays, permissionCeilings) => ({
73
+ const buildAppConfig = (env, arrays, permissionCeilings, policies) => ({
216
74
  analysisProvider: env.REA_ANALYSIS_PROVIDER,
217
75
  ghidraInstallDir: env.GHIDRA_INSTALL_DIR,
218
76
  ghidraJavaHome: env.JAVA_HOME,
@@ -222,13 +80,7 @@ const buildAppConfig = (env, arrays, permissionCeilings) => ({
222
80
  hopperTargetKind: env.HOPPER_TARGET_KIND,
223
81
  hopperLoaderArgs: arrays.loaderArgs,
224
82
  logLevel: env.REA_LOG_LEVEL,
225
- processExecutionPolicy: {
226
- enabled: env.REA_PROCESS_CAPTURE_ENABLED === "true",
227
- executableRoots: arrays.executableRoots,
228
- workingRoots: arrays.workingRoots,
229
- allowedEnvironment: arrays.allowedEnvironment,
230
- allowExternalNetwork: env.REA_PROCESS_ALLOW_EXTERNAL_NETWORK === "true",
231
- },
83
+ processExecutionPolicy: policies.processCapture,
232
84
  artifactNativeMountEnabled: env.REA_ARTIFACT_NATIVE_MOUNT_ENABLED === "true",
233
85
  artifactIntegrityContinueEnabled: env.REA_ARTIFACT_INTEGRITY_CONTINUE_ENABLED === "true",
234
86
  evidenceFilePolicy: filePolicy(arrays.evidenceRoots),
@@ -242,42 +94,20 @@ const buildAppConfig = (env, arrays, permissionCeilings) => ({
242
94
  maxDepth: 32,
243
95
  maxPathBytes: 4_096,
244
96
  },
245
- browserObservationEnabled: env.REA_BROWSER_OBSERVE_ENABLED === "true",
246
- browserCdpEndpoints: arrays.browserEndpoints,
247
- browserAllowedOrigins: arrays.browserOrigins,
248
- browserScenarioPolicy: {
249
- enabled: env.REA_BROWSER_SCENARIO_ENABLED === "true",
250
- executableRoots: arrays.browserScenarioExecutableRoots,
251
- cdpEndpoints: arrays.browserScenarioEndpoints,
252
- allowedOrigins: arrays.browserScenarioOrigins,
253
- allowedEnvironment: arrays.browserScenarioEnvironment,
254
- },
255
- electronObservationEnabled: env.REA_ELECTRON_OBSERVE_ENABLED === "true",
256
- electronCdpEndpoints: arrays.electronEndpoints,
257
- electronFileRoots: arrays.electronFileRoots,
258
- v8InspectorObservationEnabled: env.REA_V8_INSPECTOR_OBSERVE_ENABLED === "true",
259
- v8InspectorEndpoints: arrays.v8InspectorEndpoints,
260
- v8InspectorFileRoots: arrays.v8InspectorFileRoots,
261
- v8InspectorAllowedOrigins: arrays.v8InspectorOrigins,
262
- javascriptReplayPolicy: {
263
- enabled: env.REA_JAVASCRIPT_REPLAY_ENABLED === "true",
264
- roots: arrays.javascriptReplayRoots,
265
- nodePath: env.REA_JAVASCRIPT_REPLAY_NODE_PATH,
266
- bubblewrapPath: env.REA_JAVASCRIPT_REPLAY_BWRAP_PATH,
267
- systemdRunPath: env.REA_JAVASCRIPT_REPLAY_SYSTEMD_RUN_PATH,
268
- systemctlPath: env.REA_JAVASCRIPT_REPLAY_SYSTEMCTL_PATH,
269
- shellPath: env.REA_JAVASCRIPT_REPLAY_SHELL_PATH,
270
- },
271
- managedRuntimePolicy: {
272
- enabled: env.REA_MANAGED_RUNTIME_ENABLED === "true",
273
- roots: arrays.managedRuntimeRoots,
274
- executablePath: env.REA_MANAGED_RUNTIME_EXECUTABLE_PATH,
275
- },
97
+ browserObservationPolicy: policies.passiveObservation.browser,
98
+ browserScenarioPolicy: policies.browserScenario,
99
+ electronObservationPolicy: policies.passiveObservation.electron,
100
+ electronAutomationPolicy: policies.electronAutomation,
101
+ v8InspectorObservationPolicy: policies.passiveObservation.v8Inspector,
102
+ javascriptReplayPolicy: policies.javascriptReplay,
103
+ managedRuntimePolicy: policies.managedRuntime,
276
104
  permissionCeilings,
277
105
  administratorPermissionGrants: administratorGrants(permissionCeilings.filter(({ capability }) => (capability !== "process_capture" ||
278
106
  env.REA_PROCESS_CAPTURE_AUTO_GRANT === "true") &&
279
107
  (capability !== "browser_automate" ||
280
- env.REA_BROWSER_SCENARIO_AUTO_GRANT === "true"))),
108
+ env.REA_BROWSER_SCENARIO_AUTO_GRANT === "true") &&
109
+ (capability !== "electron_automate" ||
110
+ env.REA_ELECTRON_AUTOMATE_AUTO_GRANT === "true"))),
281
111
  permissionProjectRoot: env.REA_PERMISSION_PROJECT_ROOT,
282
112
  permissionProjectStore: env.REA_PERMISSION_PROJECT_STORE,
283
113
  });
@@ -294,6 +124,32 @@ export const parseConfig = (environment) => {
294
124
  const arraysResult = parseAllArrays(envResult.value);
295
125
  if (!arraysResult.ok)
296
126
  return arraysResult;
297
- const permissionCeilings = buildPermissionCeilings(envResult.value, arraysResult.value);
298
- return ok(buildAppConfig(envResult.value, arraysResult.value, permissionCeilings));
127
+ const passiveObservationPolicies = parsePassiveObservationPolicies(envResult.value);
128
+ if (!passiveObservationPolicies.ok)
129
+ return passiveObservationPolicies;
130
+ const processCapturePolicy = parseProcessExecutionPolicy(envResult.value);
131
+ if (!processCapturePolicy.ok)
132
+ return processCapturePolicy;
133
+ const browserScenarioPolicy = parseBrowserScenarioPolicy(envResult.value);
134
+ if (!browserScenarioPolicy.ok)
135
+ return browserScenarioPolicy;
136
+ const electronAutomationPolicy = parseElectronAutomationPolicy(envResult.value);
137
+ if (!electronAutomationPolicy.ok)
138
+ return electronAutomationPolicy;
139
+ const javascriptReplayPolicy = parseJavaScriptReplayPolicy(envResult.value);
140
+ if (!javascriptReplayPolicy.ok)
141
+ return javascriptReplayPolicy;
142
+ const managedRuntimePolicy = parseManagedRuntimePolicy(envResult.value, arraysResult.value.managedRuntimeRoots);
143
+ if (!managedRuntimePolicy.ok)
144
+ return managedRuntimePolicy;
145
+ const policies = {
146
+ passiveObservation: passiveObservationPolicies.value,
147
+ processCapture: processCapturePolicy.value,
148
+ browserScenario: browserScenarioPolicy.value,
149
+ electronAutomation: electronAutomationPolicy.value,
150
+ javascriptReplay: javascriptReplayPolicy.value,
151
+ managedRuntime: managedRuntimePolicy.value,
152
+ };
153
+ const permissionCeilings = buildPermissionCeilings(envResult.value, arraysResult.value, policies);
154
+ return ok(buildAppConfig(envResult.value, arraysResult.value, permissionCeilings, policies));
299
155
  };
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
+ import { isAbsolute } from "node:path";
2
3
  import { ConfigurationError } from "../domain/errors.js";
3
4
  import { err, ok } from "../domain/result.js";
4
- import {} from "../domain/browserObservation.js";
5
5
  import { electronFileRootsSchema } from "../domain/electronObservation.js";
6
6
  export const parseStringArray = (encoded, name) => {
7
7
  try {
@@ -19,6 +19,15 @@ export const parseStringArray = (encoded, name) => {
19
19
  return err(new ConfigurationError(`${name} must be valid JSON`, { cause }));
20
20
  }
21
21
  };
22
+ /** Parse a JSON string array whose members must all be absolute paths. */
23
+ export const parseAbsoluteRoots = (encoded, name) => {
24
+ const parsed = parseStringArray(encoded, name);
25
+ if (!parsed.ok)
26
+ return parsed;
27
+ return parsed.value.some((root) => !isAbsolute(root))
28
+ ? err(new ConfigurationError(`${name} must encode absolute roots`))
29
+ : parsed;
30
+ };
22
31
  export const parseBrowserArray = (encoded, name, itemSchema, maximum) => {
23
32
  try {
24
33
  const parsed = z
@@ -0,0 +1,157 @@
1
+ import { ConfigurationError } from "../domain/errors.js";
2
+ import { err, ok } from "../domain/result.js";
3
+ import { browserEndpointSchema, browserOriginSchema, } from "../domain/browserObservation.js";
4
+ import { parseAbsoluteRoots, parseBrowserArray, parseElectronFileRoots, } from "./parsers.js";
5
+ import { browserNetworkScope, permissionScope } from "./permissions.js";
6
+ /** Parse every passive observation capability into closed policy variants. */
7
+ export const parsePassiveObservationPolicies = (env) => {
8
+ const browser = parseBrowserObservationPolicy(env);
9
+ if (!browser.ok)
10
+ return browser;
11
+ const electron = parseElectronObservationPolicy(env);
12
+ if (!electron.ok)
13
+ return electron;
14
+ const v8Inspector = parseV8InspectorObservationPolicy(env);
15
+ if (!v8Inspector.ok)
16
+ return v8Inspector;
17
+ return ok({
18
+ browser: browser.value,
19
+ electron: electron.value,
20
+ v8Inspector: v8Inspector.value,
21
+ });
22
+ };
23
+ /** Add permission ceilings for each enabled passive observation policy. */
24
+ export const appendPassiveObservationCeilings = (ceilings, policies) => {
25
+ appendBrowserCeiling(ceilings, policies.browser);
26
+ appendElectronCeiling(ceilings, policies.electron);
27
+ appendV8InspectorCeiling(ceilings, policies.v8Inspector);
28
+ };
29
+ /** Project the legal file and origin scopes from an enabled V8 policy. */
30
+ export const v8InspectorLocationScopes = (locations) => {
31
+ switch (locations.scope) {
32
+ case "files":
33
+ return { fileRoots: locations.fileRoots, allowedOrigins: [] };
34
+ case "origins":
35
+ return { fileRoots: [], allowedOrigins: locations.allowedOrigins };
36
+ case "files-and-origins":
37
+ return locations;
38
+ }
39
+ };
40
+ const parseBrowserObservationPolicy = (env) => {
41
+ const endpoints = parseBrowserArray(env.REA_BROWSER_CDP_ENDPOINTS_JSON, "REA_BROWSER_CDP_ENDPOINTS_JSON", browserEndpointSchema, 16);
42
+ if (!endpoints.ok)
43
+ return endpoints;
44
+ const origins = parseBrowserArray(env.REA_BROWSER_ALLOWED_ORIGINS_JSON, "REA_BROWSER_ALLOWED_ORIGINS_JSON", browserOriginSchema, 32);
45
+ if (!origins.ok)
46
+ return origins;
47
+ if (env.REA_BROWSER_OBSERVE_ENABLED !== "true")
48
+ return ok({ status: "disabled" });
49
+ const parsedEndpoints = requireFirst(endpoints.value, "REA_BROWSER_CDP_ENDPOINTS_JSON must encode at least one loopback endpoint when browser observation is enabled");
50
+ if (!parsedEndpoints.ok)
51
+ return parsedEndpoints;
52
+ const parsedOrigins = requireFirst(origins.value, "REA_BROWSER_ALLOWED_ORIGINS_JSON must encode at least one exact origin when browser observation is enabled");
53
+ if (!parsedOrigins.ok)
54
+ return parsedOrigins;
55
+ return ok({
56
+ status: "enabled",
57
+ cdpEndpoints: parsedEndpoints.value,
58
+ allowedOrigins: parsedOrigins.value,
59
+ });
60
+ };
61
+ const parseElectronObservationPolicy = (env) => {
62
+ const endpoints = parseBrowserArray(env.REA_ELECTRON_CDP_ENDPOINTS_JSON, "REA_ELECTRON_CDP_ENDPOINTS_JSON", browserEndpointSchema, 16);
63
+ if (!endpoints.ok)
64
+ return endpoints;
65
+ const roots = parseElectronFileRoots(env.REA_ELECTRON_FILE_ROOTS_JSON);
66
+ if (!roots.ok)
67
+ return roots;
68
+ if (env.REA_ELECTRON_OBSERVE_ENABLED !== "true")
69
+ return ok({ status: "disabled" });
70
+ const parsedEndpoints = requireFirst(endpoints.value, "REA_ELECTRON_CDP_ENDPOINTS_JSON must encode at least one loopback endpoint when Electron observation is enabled");
71
+ if (!parsedEndpoints.ok)
72
+ return parsedEndpoints;
73
+ const parsedRoots = requireFirst(roots.value, "REA_ELECTRON_FILE_ROOTS_JSON must encode at least one absolute root when Electron observation is enabled");
74
+ if (!parsedRoots.ok)
75
+ return parsedRoots;
76
+ return ok({
77
+ status: "enabled",
78
+ cdpEndpoints: parsedEndpoints.value,
79
+ fileRoots: parsedRoots.value,
80
+ });
81
+ };
82
+ const parseV8InspectorObservationPolicy = (env) => {
83
+ const endpoints = parseBrowserArray(env.REA_V8_INSPECTOR_ENDPOINTS_JSON, "REA_V8_INSPECTOR_ENDPOINTS_JSON", browserEndpointSchema, 16);
84
+ if (!endpoints.ok)
85
+ return endpoints;
86
+ const roots = parseAbsoluteRoots(env.REA_V8_INSPECTOR_FILE_ROOTS_JSON, "REA_V8_INSPECTOR_FILE_ROOTS_JSON");
87
+ if (!roots.ok)
88
+ return roots;
89
+ const origins = parseBrowserArray(env.REA_V8_INSPECTOR_ALLOWED_ORIGINS_JSON, "REA_V8_INSPECTOR_ALLOWED_ORIGINS_JSON", browserOriginSchema, 32);
90
+ if (!origins.ok)
91
+ return origins;
92
+ if (env.REA_V8_INSPECTOR_OBSERVE_ENABLED !== "true")
93
+ return ok({ status: "disabled" });
94
+ const parsedEndpoints = requireFirst(endpoints.value, "REA_V8_INSPECTOR_ENDPOINTS_JSON must encode at least one loopback endpoint when V8 Inspector observation is enabled");
95
+ if (!parsedEndpoints.ok)
96
+ return parsedEndpoints;
97
+ const locations = parseV8Locations(roots.value, origins.value);
98
+ if (!locations.ok)
99
+ return locations;
100
+ return ok({
101
+ status: "enabled",
102
+ endpoints: parsedEndpoints.value,
103
+ locations: locations.value,
104
+ });
105
+ };
106
+ const parseV8Locations = (roots, origins) => {
107
+ const [firstRoot, ...remainingRoots] = roots;
108
+ const [firstOrigin, ...remainingOrigins] = origins;
109
+ if (firstRoot !== undefined && firstOrigin !== undefined)
110
+ return ok({
111
+ scope: "files-and-origins",
112
+ fileRoots: [firstRoot, ...remainingRoots],
113
+ allowedOrigins: [firstOrigin, ...remainingOrigins],
114
+ });
115
+ if (firstRoot !== undefined)
116
+ return ok({
117
+ scope: "files",
118
+ fileRoots: [firstRoot, ...remainingRoots],
119
+ });
120
+ if (firstOrigin !== undefined)
121
+ return ok({
122
+ scope: "origins",
123
+ allowedOrigins: [firstOrigin, ...remainingOrigins],
124
+ });
125
+ return err(new ConfigurationError("V8 Inspector observation requires at least one file root or exact origin when enabled"));
126
+ };
127
+ const requireFirst = (values, message) => {
128
+ const [first, ...remaining] = values;
129
+ return first === undefined
130
+ ? err(new ConfigurationError(message))
131
+ : ok([first, ...remaining]);
132
+ };
133
+ const appendBrowserCeiling = (ceilings, policy) => {
134
+ if (policy.status === "disabled")
135
+ return;
136
+ ceilings.push(permissionScope("browser_observe", [], {
137
+ origins: [...policy.cdpEndpoints, ...policy.allowedOrigins],
138
+ network: browserNetworkScope(policy.allowedOrigins),
139
+ }));
140
+ };
141
+ const appendElectronCeiling = (ceilings, policy) => {
142
+ if (policy.status === "disabled")
143
+ return;
144
+ ceilings.push(permissionScope("electron_observe", policy.fileRoots, {
145
+ origins: policy.cdpEndpoints,
146
+ network: "loopback",
147
+ }));
148
+ };
149
+ const appendV8InspectorCeiling = (ceilings, policy) => {
150
+ if (policy.status === "disabled")
151
+ return;
152
+ const scopes = v8InspectorLocationScopes(policy.locations);
153
+ ceilings.push(permissionScope("v8_inspector_observe", scopes.fileRoots, {
154
+ origins: [...policy.endpoints, ...scopes.allowedOrigins],
155
+ network: "loopback",
156
+ }));
157
+ };
@@ -0,0 +1,47 @@
1
+ import { ConfigurationError } from "../domain/errors.js";
2
+ import { err, ok } from "../domain/result.js";
3
+ import { parseAbsoluteRoots, parseStringArray } from "./parsers.js";
4
+ import { permissionScope } from "./permissions.js";
5
+ /** Parse process capture into disabled or fully authorized state. */
6
+ export const parseProcessExecutionPolicy = (env) => {
7
+ const executableRoots = parseAbsoluteRoots(env.REA_PROCESS_EXECUTABLE_ROOTS_JSON, "REA_PROCESS_EXECUTABLE_ROOTS_JSON");
8
+ if (!executableRoots.ok)
9
+ return executableRoots;
10
+ const workingRoots = parseAbsoluteRoots(env.REA_PROCESS_WORKING_ROOTS_JSON, "REA_PROCESS_WORKING_ROOTS_JSON");
11
+ if (!workingRoots.ok)
12
+ return workingRoots;
13
+ const allowedEnvironment = parseStringArray(env.REA_PROCESS_ALLOWED_ENV_JSON, "REA_PROCESS_ALLOWED_ENV_JSON");
14
+ if (!allowedEnvironment.ok)
15
+ return allowedEnvironment;
16
+ if (env.REA_PROCESS_CAPTURE_ENABLED !== "true")
17
+ return ok({ status: "disabled" });
18
+ const parsedExecutables = requireRoots(executableRoots.value, "REA_PROCESS_EXECUTABLE_ROOTS_JSON must encode at least one absolute root when process capture is enabled");
19
+ if (!parsedExecutables.ok)
20
+ return parsedExecutables;
21
+ const parsedWorking = requireRoots(workingRoots.value, "REA_PROCESS_WORKING_ROOTS_JSON must encode at least one absolute root when process capture is enabled");
22
+ if (!parsedWorking.ok)
23
+ return parsedWorking;
24
+ return ok({
25
+ status: "enabled",
26
+ executableRoots: parsedExecutables.value,
27
+ workingRoots: parsedWorking.value,
28
+ allowedEnvironment: allowedEnvironment.value,
29
+ networkAccess: env.REA_PROCESS_ALLOW_EXTERNAL_NETWORK === "true" ? "external" : "none",
30
+ });
31
+ };
32
+ /** Add the exact process-capture ceiling when capture is enabled. */
33
+ export const appendProcessCaptureCeiling = (ceilings, policy) => {
34
+ if (policy.status === "disabled")
35
+ return;
36
+ ceilings.push(permissionScope("process_capture", policy.workingRoots, {
37
+ executables: policy.executableRoots,
38
+ environment_names: policy.allowedEnvironment,
39
+ network: policy.networkAccess,
40
+ }));
41
+ };
42
+ const requireRoots = (roots, message) => {
43
+ const [first, ...remaining] = roots;
44
+ return first === undefined
45
+ ? err(new ConfigurationError(message))
46
+ : ok([first, ...remaining]);
47
+ };
@@ -69,7 +69,6 @@ const NODE_PREPARATION_EXAMPLE = jsonObjectSchema.parse({
69
69
  entry_export: "selected",
70
70
  },
71
71
  cases: [{ case_id: "empty", arguments: [""] }],
72
- approved: false,
73
72
  },
74
73
  });
75
74
  const COVERAGE_WORKSPACE_EXAMPLE = jsonObjectSchema.parse({
@@ -226,7 +225,6 @@ export const APPLICATION_TOOL_CONTRACTS = [
226
225
  result_depth: 16,
227
226
  result_nodes: 10000,
228
227
  },
229
- approved: false,
230
228
  },
231
229
  },
232
230
  ],
@@ -347,10 +345,9 @@ export const APPLICATION_TOOL_CONTRACTS = [
347
345
  ],
348
346
  },
349
347
  ];
350
- /** Resolve one named application contract without relying on array position. */
351
- export const applicationToolContract = (name) => {
348
+ export function applicationToolContract(name) {
352
349
  const contract = APPLICATION_TOOL_CONTRACTS.find(({ name: candidate }) => candidate === name);
353
350
  if (contract === undefined)
354
351
  throw new Error(`Missing application tool contract: ${name}`);
355
352
  return contract;
356
- };
353
+ }