rea-agents 2.4.0 → 2.5.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 (186) hide show
  1. package/README.md +80 -18
  2. package/bridge/ghidra/ReaGhidraBridge.java +48 -1
  3. package/bridge/hopper_bridge.py +259 -24
  4. package/dist/application/AnalysisClientCleanup.js +14 -0
  5. package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
  6. package/dist/application/BinarySession.js +15 -4
  7. package/dist/application/BinarySessionStatus.js +31 -1
  8. package/dist/application/BrowserEvidence.js +14 -0
  9. package/dist/application/BrowserScenarioCapturePort.js +1 -0
  10. package/dist/application/BrowserScenarioCaptureService.js +53 -0
  11. package/dist/application/BrowserScenarioEvidence.js +40 -0
  12. package/dist/application/CallPathTracing.js +160 -0
  13. package/dist/application/CapabilityInventory.js +68 -12
  14. package/dist/application/CompositeProvider.js +10 -1
  15. package/dist/application/DirectAnalysis.js +7 -2
  16. package/dist/application/EnhancedLiteralTracing.js +118 -0
  17. package/dist/application/EnhancedTools.js +35 -121
  18. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
  19. package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
  20. package/dist/application/JavaScriptRuntimeObservationEvidence.js +34 -0
  21. package/dist/application/JavaScriptRuntimeObservationPort.js +1 -0
  22. package/dist/application/JavaScriptRuntimeObservationService.js +46 -0
  23. package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +147 -0
  24. package/dist/application/JavaScriptSemanticGraphBuilder.js +34 -6
  25. package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +156 -0
  26. package/dist/application/JavaScriptSemanticGraphConstruction.js +2 -2
  27. package/dist/application/JavaScriptSemanticGraphDataProjection.js +203 -0
  28. package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +25 -0
  29. package/dist/application/JavaScriptSemanticGraphFlowProjection.js +129 -8
  30. package/dist/application/JavaScriptSemanticGraphObjectProjection.js +81 -0
  31. package/dist/application/JavaScriptSemanticGraphProjection.js +14 -7
  32. package/dist/application/JavaScriptSemanticGraphResourceProjection.js +59 -0
  33. package/dist/application/JavaScriptSemanticGraphValueProjection.js +77 -0
  34. package/dist/application/ProcessReactiveEffects.js +6 -0
  35. package/dist/application/ProcessReactiveHarness.js +16 -1
  36. package/dist/application/ProjectPermissionStore.js +1 -0
  37. package/dist/application/ReconstructionObligationAuthority.js +72 -0
  38. package/dist/application/ReconstructionObligationCandidates.js +265 -0
  39. package/dist/application/ReconstructionObligationLedgerDiagnostics.js +47 -0
  40. package/dist/application/ReconstructionObligationLedgerEvaluation.js +263 -0
  41. package/dist/application/ReconstructionObligationLedgerProjection.js +86 -0
  42. package/dist/application/ReconstructionObligationLedgerService.js +72 -0
  43. package/dist/application/ReconstructionObligationOriginalCases.js +33 -0
  44. package/dist/application/ReconstructionObligationPolicies.js +132 -0
  45. package/dist/application/ReconstructionReadinessService.js +48 -0
  46. package/dist/artifacts/ArtifactProvider.js +87 -22
  47. package/dist/browser/BrowserScenarioSecrets.js +53 -0
  48. package/dist/browser/BrowserScenarioSessionPort.js +1 -0
  49. package/dist/browser/CdpBrowserProvider.js +2 -2
  50. package/dist/browser/CdpCaptureDocuments.js +57 -0
  51. package/dist/browser/CdpCaptureStorage.js +71 -29
  52. package/dist/browser/CdpCaptureStorageFingerprints.js +328 -0
  53. package/dist/browser/CdpEndpoint.js +8 -6
  54. package/dist/browser/CdpPageCapture.js +2 -0
  55. package/dist/browser/JavaScriptRuntimeScope.js +38 -0
  56. package/dist/browser/PlaywrightBrowserScenarioProvider.js +253 -0
  57. package/dist/browser/PlaywrightExecutionBoundary.js +42 -0
  58. package/dist/browser/PlaywrightScenarioActions.js +62 -0
  59. package/dist/browser/PlaywrightScenarioArtifacts.js +238 -0
  60. package/dist/browser/PlaywrightScenarioBrowser.js +144 -0
  61. package/dist/browser/PlaywrightScenarioEvents.js +301 -0
  62. package/dist/browser/PlaywrightScenarioSession.js +300 -0
  63. package/dist/browser/V8InspectorCaptureProjection.js +110 -0
  64. package/dist/browser/V8InspectorEndpoint.js +72 -0
  65. package/dist/browser/V8InspectorProvider.js +267 -0
  66. package/dist/catalogIdentity.js +8 -0
  67. package/dist/cli/artifactCommands.js +39 -0
  68. package/dist/cli/coreAnalysisCommands.js +37 -0
  69. package/dist/cli.js +4 -0
  70. package/dist/cliApplicationCommands.js +30 -2
  71. package/dist/cliBrowserAdvancedCommands.js +17 -5
  72. package/dist/cliBrowserCommands.js +1 -0
  73. package/dist/cliBrowserScenarioCommands.js +43 -0
  74. package/dist/cliCommandNames.js +8 -0
  75. package/dist/cliJavaScriptRuntimeCommands.js +164 -0
  76. package/dist/cliObservationOptions.js +4 -0
  77. package/dist/cliPolicyCommands.js +1 -0
  78. package/dist/config/environment.js +12 -0
  79. package/dist/config/parseConfig.js +88 -17
  80. package/dist/contracts/analysisSearchContract.js +14 -0
  81. package/dist/contracts/applicationToolContracts.js +86 -2
  82. package/dist/contracts/applicationWorkflowInputContracts.js +18 -0
  83. package/dist/contracts/artifactToolContracts.js +22 -0
  84. package/dist/contracts/browserProviderToolContracts.js +7 -0
  85. package/dist/contracts/browserScenarioToolContracts.js +81 -0
  86. package/dist/contracts/browserToolContracts.js +88 -98
  87. package/dist/contracts/enhancedInputs.js +25 -6
  88. package/dist/contracts/functionInstructionContract.js +8 -0
  89. package/dist/contracts/hopperMemoryContracts.js +22 -0
  90. package/dist/contracts/javascriptApplicationWorkflowExamples.js +42 -0
  91. package/dist/contracts/javascriptRuntimeObservationToolContracts.js +58 -0
  92. package/dist/contracts/reconstructionReadinessExample.js +436 -0
  93. package/dist/contracts/toolContractExamples.js +5 -0
  94. package/dist/contracts/toolContractTypes.js +1 -0
  95. package/dist/contracts/toolContracts.js +13 -21
  96. package/dist/contracts/toolEffects.js +21 -0
  97. package/dist/contracts/toolOutputSchemaGroups.js +70 -20
  98. package/dist/contracts/toolOutputSchemaPrimitives.js +37 -0
  99. package/dist/domain/analysisErrorProjection.js +8 -0
  100. package/dist/domain/artifactInspection.js +347 -0
  101. package/dist/domain/browserCaptureComparison.js +82 -0
  102. package/dist/domain/browserObservation.js +8 -1
  103. package/dist/domain/browserObservationErrors.js +1 -0
  104. package/dist/domain/browserObservationSchemas.js +26 -0
  105. package/dist/domain/browserScenario.js +165 -0
  106. package/dist/domain/browserScenarioCapture.js +57 -0
  107. package/dist/domain/browserScenarioCaptureValues.js +204 -0
  108. package/dist/domain/browserScenarioDiff.js +324 -0
  109. package/dist/domain/browserScenarioDiffValues.js +157 -0
  110. package/dist/domain/browserScenarioNormalization.js +45 -0
  111. package/dist/domain/browserScenarioValues.js +372 -0
  112. package/dist/domain/hopperValues.js +10 -0
  113. package/dist/domain/javascriptRuntimeObservation.js +170 -0
  114. package/dist/domain/javascriptRuntimeReconciliationParsing.js +120 -2
  115. package/dist/domain/javascriptRuntimeReconciliationResult.js +3 -3
  116. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +2 -2
  117. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
  118. package/dist/domain/javascriptSemanticAnalysis.js +5 -4
  119. package/dist/domain/javascriptSemanticAsyncEffects.js +253 -0
  120. package/dist/domain/javascriptSemanticChildProcesses.js +237 -0
  121. package/dist/domain/javascriptSemanticDataEffectHelpers.js +125 -0
  122. package/dist/domain/javascriptSemanticDataEffects.js +284 -0
  123. package/dist/domain/javascriptSemanticDerivedAnalysis.js +41 -0
  124. package/dist/domain/javascriptSemanticFingerprints.js +174 -0
  125. package/dist/domain/javascriptSemanticIr.js +21 -1
  126. package/dist/domain/javascriptSemanticObjects.js +115 -0
  127. package/dist/domain/javascriptSemanticPromises.js +290 -0
  128. package/dist/domain/javascriptSemanticResources.js +136 -0
  129. package/dist/domain/javascriptStaticAnalysis.js +4 -3
  130. package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
  131. package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
  132. package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
  133. package/dist/domain/processCapture.js +8 -2
  134. package/dist/domain/processReactiveScenario.js +1 -0
  135. package/dist/domain/processReactiveTransition.js +9 -4
  136. package/dist/domain/providerCleanupError.js +11 -0
  137. package/dist/domain/reconstructionObligationLedgerSchemas.js +278 -0
  138. package/dist/domain/reconstructionReadiness.js +121 -0
  139. package/dist/domain/reconstructionReadinessFindingHelpers.js +17 -0
  140. package/dist/domain/reconstructionReadinessIntegrityFindings.js +118 -0
  141. package/dist/domain/reconstructionReadinessJourneyFindings.js +193 -0
  142. package/dist/domain/reconstructionReadinessSchemas.js +240 -0
  143. package/dist/domain/sourceToBundleComparison.js +335 -0
  144. package/dist/domain/sourceToBundleComparisonSchemas.js +133 -0
  145. package/dist/domain/sourceToBundleSignals.js +202 -0
  146. package/dist/domain/webCaptureDiff.js +141 -27
  147. package/dist/domain/webScreenshot.js +1 -1
  148. package/dist/generatedPackageMetadata.js +1 -1
  149. package/dist/ghidra/GhidraDefaults.js +1 -1
  150. package/dist/ghidra/GhidraFunctionValues.js +13 -1
  151. package/dist/ghidra/GhidraProviderCapabilities.js +7 -0
  152. package/dist/hopper/HopperCleanup.js +158 -0
  153. package/dist/hopper/HopperClient.js +69 -99
  154. package/dist/hopper/HopperProvider.js +20 -1
  155. package/dist/hopper/HopperRequestQueue.js +187 -0
  156. package/dist/hopper/HopperResponseStream.js +46 -0
  157. package/dist/hopper/protocol.js +1 -0
  158. package/dist/main/transport.js +24 -24
  159. package/dist/main.js +6 -0
  160. package/dist/mcpDoctor.js +25 -2
  161. package/dist/process/ProcessCommandIdentity.js +19 -0
  162. package/dist/process/ProcessOwnership.js +11 -8
  163. package/dist/server/DynamicToolAvailability.js +70 -0
  164. package/dist/server/createServer.js +46 -1
  165. package/dist/server/lifecycleProgress.js +10 -0
  166. package/dist/server/permissionFailure.js +12 -0
  167. package/dist/server/registerApplicationTools/compareSourceToBundle.js +35 -0
  168. package/dist/server/registerApplicationTools/helpers.js +11 -7
  169. package/dist/server/registerApplicationTools/obligationLedger.js +27 -0
  170. package/dist/server/registerApplicationTools/readiness.js +55 -0
  171. package/dist/server/registerApplicationTools.js +6 -0
  172. package/dist/server/registerArtifactTools.js +9 -1
  173. package/dist/server/registerBrowserScenarioTool.js +25 -0
  174. package/dist/server/registerBrowserTools.js +2 -2
  175. package/dist/server/registerCloseLifecycleTool.js +57 -0
  176. package/dist/server/registerEnhancedTools.js +16 -5
  177. package/dist/server/registerEvidenceResources.js +4 -0
  178. package/dist/server/registerEvidenceTools.js +9 -2
  179. package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
  180. package/dist/server/registerReconstructionObligationLedgerResource.js +39 -0
  181. package/dist/server/registerReconstructionReadinessResource.js +39 -0
  182. package/dist/server/registerSessionStatusTool.js +11 -8
  183. package/dist/server/registerSessionTools.js +11 -57
  184. package/dist/server/sessionAvailabilityPolicy.js +10 -8
  185. package/package.json +12 -6
  186. package/skills/reverse-engineer-anything/SKILL.md +2 -2
@@ -0,0 +1,372 @@
1
+ import { z } from "zod";
2
+ import { browserAllowedOriginsSchema, browserEndpointSchema, browserOriginSchema, } from "./browserObservation.js";
3
+ export const BROWSER_SCENARIO_LIMITS = {
4
+ actions: 128,
5
+ secrets: 64,
6
+ storageEntries: 512,
7
+ replayRoutes: 256,
8
+ durationMs: 300_000,
9
+ actionTimeoutMs: 60_000,
10
+ };
11
+ export const scenarioIdentifierSchema = z
12
+ .string()
13
+ .regex(/^[A-Za-z][A-Za-z0-9._-]{0,63}$/u);
14
+ const absoluteExecutablePathSchema = z
15
+ .string()
16
+ .min(1)
17
+ .max(4_096)
18
+ .refine((value) => value.startsWith("/") ||
19
+ /^[A-Za-z]:[\\/]/u.test(value) ||
20
+ value.startsWith("\\\\"), "Expected an absolute browser executable path");
21
+ const browserScenarioBaseUrlSchema = z
22
+ .string()
23
+ .min(1)
24
+ .max(65_536)
25
+ .transform((value, context) => {
26
+ let url;
27
+ try {
28
+ url = new URL(value);
29
+ }
30
+ catch {
31
+ context.addIssue({ code: "custom", message: "Invalid browser URL" });
32
+ return z.NEVER;
33
+ }
34
+ if ((url.protocol !== "http:" && url.protocol !== "https:") ||
35
+ url.username !== "" ||
36
+ url.password !== "" ||
37
+ url.search !== "" ||
38
+ url.hash !== "") {
39
+ context.addIssue({
40
+ code: "custom",
41
+ message: "Browser URLs must be HTTP(S), omit credentials, and declare query values separately",
42
+ });
43
+ return z.NEVER;
44
+ }
45
+ return url.toString();
46
+ });
47
+ export const browserScenarioValueSchema = z.discriminatedUnion("source", [
48
+ z.strictObject({
49
+ source: z.literal("literal"),
50
+ value: z.string().max(65_536),
51
+ classification: z.literal("public"),
52
+ }),
53
+ z.strictObject({
54
+ source: z.literal("secret"),
55
+ secret_id: scenarioIdentifierSchema,
56
+ }),
57
+ ]);
58
+ const queryEntrySchema = z.strictObject({
59
+ name: z.string().min(1).max(256),
60
+ value: browserScenarioValueSchema,
61
+ });
62
+ /** URL whose values remain explicit public literals or declared secret references. */
63
+ export const browserScenarioUrlSchema = z.strictObject({
64
+ url: browserScenarioBaseUrlSchema,
65
+ query: z.array(queryEntrySchema).max(64).default([]),
66
+ });
67
+ export const browserScenarioBrowserSchema = z.discriminatedUnion("mode", [
68
+ z.strictObject({
69
+ mode: z.literal("launch"),
70
+ executable_path: absoluteExecutablePathSchema,
71
+ headless: z.literal(true),
72
+ user_data: z.literal("temporary-owned"),
73
+ cleanup: z.literal("close-and-delete-profile"),
74
+ }),
75
+ z.strictObject({
76
+ mode: z.literal("connect"),
77
+ cdp_endpoint: browserEndpointSchema,
78
+ target_id: z.string().trim().min(1).max(256),
79
+ ownership: z.literal("external"),
80
+ cleanup: z.literal("disconnect-only"),
81
+ }),
82
+ ]);
83
+ export const browserScenarioEnvironmentSchema = z.strictObject({
84
+ viewport: z.strictObject({
85
+ width: z.number().int().min(320).max(7_680),
86
+ height: z.number().int().min(240).max(4_320),
87
+ device_scale_factor: z.number().min(0.5).max(4).default(1),
88
+ }),
89
+ locale: z
90
+ .string()
91
+ .min(2)
92
+ .max(64)
93
+ .regex(/^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$/u),
94
+ timezone: z
95
+ .string()
96
+ .min(1)
97
+ .max(128)
98
+ .regex(/^[A-Za-z0-9_+-]+(?:\/[A-Za-z0-9_+-]+)*$/u),
99
+ color_scheme: z.enum(["light", "dark", "no-preference"]),
100
+ reduced_motion: z.enum(["reduce", "no-preference"]),
101
+ service_workers: z.literal("block"),
102
+ });
103
+ const locatorSchema = z.discriminatedUnion("kind", [
104
+ z.strictObject({
105
+ kind: z.literal("test_id"),
106
+ value: z.string().min(1).max(512),
107
+ }),
108
+ z.strictObject({
109
+ kind: z.literal("role"),
110
+ role: z.enum([
111
+ "button",
112
+ "checkbox",
113
+ "combobox",
114
+ "dialog",
115
+ "link",
116
+ "listbox",
117
+ "menuitem",
118
+ "option",
119
+ "radio",
120
+ "slider",
121
+ "spinbutton",
122
+ "switch",
123
+ "tab",
124
+ "textbox",
125
+ ]),
126
+ name: z.string().min(1).max(1_024),
127
+ exact: z.literal(true),
128
+ }),
129
+ z.strictObject({
130
+ kind: z.literal("css"),
131
+ selector: z.string().min(1).max(4_096),
132
+ approved: z.literal(true),
133
+ }),
134
+ ]);
135
+ const stepBase = {
136
+ step_id: scenarioIdentifierSchema,
137
+ timeout_ms: z
138
+ .number()
139
+ .int()
140
+ .min(1)
141
+ .max(BROWSER_SCENARIO_LIMITS.actionTimeoutMs)
142
+ .optional(),
143
+ };
144
+ export const browserScenarioActionSchema = z.discriminatedUnion("action", [
145
+ z.strictObject({
146
+ ...stepBase,
147
+ action: z.literal("goto"),
148
+ destination: browserScenarioUrlSchema,
149
+ wait_until: z.enum(["commit", "domcontentloaded", "load"]),
150
+ }),
151
+ z.strictObject({
152
+ ...stepBase,
153
+ action: z.literal("click"),
154
+ locator: locatorSchema,
155
+ button: z.enum(["left", "middle", "right"]).default("left"),
156
+ click_count: z.number().int().min(1).max(3).default(1),
157
+ }),
158
+ z.strictObject({
159
+ ...stepBase,
160
+ action: z.literal("fill"),
161
+ locator: locatorSchema,
162
+ value: browserScenarioValueSchema,
163
+ }),
164
+ z.strictObject({
165
+ ...stepBase,
166
+ action: z.literal("press"),
167
+ locator: locatorSchema,
168
+ key: z.string().min(1).max(64),
169
+ }),
170
+ z.strictObject({
171
+ ...stepBase,
172
+ action: z.literal("select_option"),
173
+ locator: locatorSchema,
174
+ value: browserScenarioValueSchema,
175
+ }),
176
+ z.strictObject({
177
+ ...stepBase,
178
+ action: z.enum(["check", "uncheck"]),
179
+ locator: locatorSchema,
180
+ }),
181
+ z.strictObject({
182
+ ...stepBase,
183
+ action: z.literal("wait_for"),
184
+ locator: locatorSchema,
185
+ state: z.enum(["attached", "detached", "visible", "hidden"]),
186
+ }),
187
+ z.strictObject({
188
+ step_id: scenarioIdentifierSchema,
189
+ action: z.literal("wait_for_timeout"),
190
+ duration_ms: z
191
+ .number()
192
+ .int()
193
+ .min(1)
194
+ .max(BROWSER_SCENARIO_LIMITS.actionTimeoutMs),
195
+ }),
196
+ ]);
197
+ const storageEntrySchema = z.strictObject({
198
+ name: z.string().min(1).max(1_024),
199
+ value: browserScenarioValueSchema,
200
+ });
201
+ export const browserScenarioStorageSchema = z.strictObject({
202
+ cookies: z
203
+ .array(z.strictObject({
204
+ name: z.string().min(1).max(1_024),
205
+ value: browserScenarioValueSchema,
206
+ destination: browserScenarioUrlSchema,
207
+ http_only: z.boolean(),
208
+ secure: z.boolean(),
209
+ same_site: z.enum(["Strict", "Lax", "None"]),
210
+ }))
211
+ .max(128)
212
+ .default([]),
213
+ local_storage: z
214
+ .array(z.strictObject({
215
+ origin: browserOriginSchema,
216
+ entries: z.array(storageEntrySchema).max(128),
217
+ }))
218
+ .max(32)
219
+ .default([]),
220
+ session_storage: z
221
+ .array(z.strictObject({
222
+ origin: browserOriginSchema,
223
+ entries: z.array(storageEntrySchema).max(128),
224
+ }))
225
+ .max(32)
226
+ .default([]),
227
+ });
228
+ const headerNameSchema = z
229
+ .string()
230
+ .min(1)
231
+ .max(256)
232
+ .regex(/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u)
233
+ .transform((value) => value.toLowerCase());
234
+ const replayHeaderSchema = z.strictObject({
235
+ name: headerNameSchema,
236
+ value: browserScenarioValueSchema,
237
+ });
238
+ const replayResponseSchema = z.discriminatedUnion("kind", [
239
+ z.strictObject({
240
+ kind: z.literal("response"),
241
+ status: z.number().int().min(100).max(599),
242
+ headers: z.array(replayHeaderSchema).max(64).default([]),
243
+ body: browserScenarioValueSchema.optional(),
244
+ }),
245
+ z.strictObject({
246
+ kind: z.literal("redirect"),
247
+ status: z.union([
248
+ z.literal(301),
249
+ z.literal(302),
250
+ z.literal(303),
251
+ z.literal(307),
252
+ z.literal(308),
253
+ ]),
254
+ destination: browserScenarioUrlSchema,
255
+ }),
256
+ ]);
257
+ const replayRouteSchema = z.strictObject({
258
+ route_id: scenarioIdentifierSchema,
259
+ method: z.enum(["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]),
260
+ request: browserScenarioUrlSchema,
261
+ response: replayResponseSchema,
262
+ });
263
+ export const browserScenarioRequestReplaySchema = z.discriminatedUnion("mode", [
264
+ z.strictObject({ mode: z.literal("disabled") }),
265
+ z.strictObject({
266
+ mode: z.literal("exact"),
267
+ unmatched: z.enum(["abort", "passthrough-approved-origins"]),
268
+ routes: z
269
+ .array(replayRouteSchema)
270
+ .min(1)
271
+ .max(BROWSER_SCENARIO_LIMITS.replayRoutes),
272
+ }),
273
+ ]);
274
+ export const browserScenarioSecretSchema = z.strictObject({
275
+ secret_id: scenarioIdentifierSchema,
276
+ environment_variable: z.string().regex(/^[A-Z_][A-Z0-9_]{0,127}$/u),
277
+ purpose: z.enum(["input", "storage", "request-replay"]),
278
+ redaction: z.literal("replace-with-secret-reference"),
279
+ });
280
+ const REQUIRED_REDACTED_HEADERS = [
281
+ "authorization",
282
+ "cookie",
283
+ "proxy-authorization",
284
+ "set-cookie",
285
+ ];
286
+ const normalizedNames = (maximum) => z
287
+ .array(z
288
+ .string()
289
+ .trim()
290
+ .min(1)
291
+ .max(256)
292
+ .transform((value) => value.toLowerCase()))
293
+ .max(maximum)
294
+ .transform((values) => [...new Set(values)].sort());
295
+ export const browserScenarioRedactionSchema = z
296
+ .strictObject({
297
+ secret_values: z.literal("replace-with-secret-reference"),
298
+ query_parameter_names: normalizedNames(128).default([]),
299
+ header_names: normalizedNames(128).default([...REQUIRED_REDACTED_HEADERS]),
300
+ })
301
+ .superRefine(({ header_names: names }, context) => {
302
+ for (const required of REQUIRED_REDACTED_HEADERS)
303
+ if (!names.includes(required))
304
+ context.addIssue({
305
+ code: "custom",
306
+ path: ["header_names"],
307
+ message: `Required credential header ${required} must be redacted`,
308
+ });
309
+ });
310
+ const snapshotKindSchema = z.enum([
311
+ "screenshot",
312
+ "dom",
313
+ "accessibility",
314
+ "url",
315
+ "history",
316
+ "storage",
317
+ ]);
318
+ export const browserScenarioCaptureSchema = z.strictObject({
319
+ after_each_step: z.array(snapshotKindSchema).max(6),
320
+ at_end: z.array(snapshotKindSchema).max(6),
321
+ events: z.array(z.enum([
322
+ "console",
323
+ "page-errors",
324
+ "network",
325
+ "websockets",
326
+ "frames",
327
+ "workers",
328
+ "popups",
329
+ "downloads",
330
+ ])),
331
+ });
332
+ export const browserScenarioCaptureLimitsSchema = z.strictObject({
333
+ max_duration_ms: z
334
+ .number()
335
+ .int()
336
+ .min(100)
337
+ .max(BROWSER_SCENARIO_LIMITS.durationMs),
338
+ action_timeout_ms: z
339
+ .number()
340
+ .int()
341
+ .min(1)
342
+ .max(BROWSER_SCENARIO_LIMITS.actionTimeoutMs),
343
+ navigation_timeout_ms: z
344
+ .number()
345
+ .int()
346
+ .min(1)
347
+ .max(BROWSER_SCENARIO_LIMITS.actionTimeoutMs),
348
+ max_events: z.number().int().min(1).max(100_000),
349
+ max_frames: z.number().int().min(1).max(1_000),
350
+ max_workers: z.number().int().min(0).max(1_000),
351
+ max_popups: z.number().int().min(0).max(100),
352
+ max_websockets: z.number().int().min(0).max(10_000),
353
+ max_dom_nodes: z.number().int().min(1).max(100_000),
354
+ max_accessibility_nodes: z.number().int().min(1).max(100_000),
355
+ max_screenshots: z.number().int().min(0).max(256),
356
+ max_screenshot_bytes: z
357
+ .number()
358
+ .int()
359
+ .min(1)
360
+ .max(8 * 1_024 * 1_024),
361
+ max_storage_entries: z
362
+ .number()
363
+ .int()
364
+ .min(0)
365
+ .max(BROWSER_SCENARIO_LIMITS.storageEntries),
366
+ max_total_metadata_bytes: z
367
+ .number()
368
+ .int()
369
+ .min(1_024)
370
+ .max(64 * 1_024 * 1_024),
371
+ });
372
+ export const browserScenarioAllowedOriginsSchema = browserAllowedOriginsSchema;
@@ -114,6 +114,16 @@ const boundedSchema = (item) => z
114
114
  });
115
115
  }
116
116
  });
117
+ /** Provider-neutral bounded raw-instruction window for one analyzed function. */
118
+ export const functionInstructionWindowSchema = z
119
+ .object({
120
+ procedure: procedureIdentitySchema,
121
+ instructions: boundedSchema(z.string()),
122
+ instructions_scanned: z.number().int().min(0),
123
+ instruction_scan_truncated: z.boolean(),
124
+ limitations: z.array(z.string()),
125
+ })
126
+ .strict();
117
127
  const availableReferenceKindSchema = z
118
128
  .object({
119
129
  available: z.literal(true),
@@ -0,0 +1,170 @@
1
+ import { isAbsolute, resolve } from "node:path";
2
+ import { z } from "zod";
3
+ import { browserEndpointSchema, browserOriginSchema, } from "./browserObservation.js";
4
+ const boundedTextSchema = z.string().min(1).max(4_096);
5
+ const runtimeFileRootsSchema = z
6
+ .array(z
7
+ .string()
8
+ .min(1)
9
+ .max(16_384)
10
+ .refine(isAbsolute, "Runtime file roots must be absolute paths")
11
+ .overwrite(resolve))
12
+ .max(32)
13
+ .overwrite((roots) => [...new Set(roots)].sort())
14
+ .default([]);
15
+ const runtimeOriginsSchema = z
16
+ .array(browserOriginSchema)
17
+ .max(32)
18
+ .overwrite((origins) => [...new Set(origins)].sort())
19
+ .default([]);
20
+ const approvedRuntimeScope = {
21
+ inspector_endpoint: browserEndpointSchema,
22
+ allowed_file_roots: runtimeFileRootsSchema,
23
+ allowed_origins: runtimeOriginsSchema,
24
+ approved: z.literal(true),
25
+ };
26
+ const requireRuntimeScope = (input, context) => {
27
+ if (input.allowed_file_roots.length === 0 &&
28
+ input.allowed_origins.length === 0)
29
+ context.addIssue({
30
+ code: "custom",
31
+ path: ["allowed_file_roots"],
32
+ message: "At least one exact file root or HTTP(S) origin is required",
33
+ });
34
+ };
35
+ /** Input for listing approved Node/Electron V8 Inspector targets. */
36
+ export const listJavaScriptRuntimeTargetsInputSchema = z
37
+ .strictObject({
38
+ ...approvedRuntimeScope,
39
+ offset: z.number().int().min(0).default(0),
40
+ limit: z.number().int().min(1).max(200).default(100),
41
+ })
42
+ .superRefine(requireRuntimeScope);
43
+ export const javascriptRuntimeKindSchema = z.enum([
44
+ "node",
45
+ "electron-main",
46
+ "electron-preload",
47
+ "electron-renderer",
48
+ ]);
49
+ export const javascriptRuntimeObservationLimitsSchema = z.strictObject({
50
+ max_events: z.number().int().min(1).max(50_000).default(10_000),
51
+ max_scripts: z.number().int().min(1).max(10_000).default(2_000),
52
+ max_execution_contexts: z.number().int().min(1).max(5_000).default(1_000),
53
+ max_location_bytes: z.number().int().min(64).max(65_536).default(16_384),
54
+ max_total_metadata_bytes: z
55
+ .number()
56
+ .int()
57
+ .min(1_024)
58
+ .max(32 * 1_024 * 1_024)
59
+ .default(4 * 1_024 * 1_024),
60
+ });
61
+ /** Input for one bounded, attach-only V8 Inspector observation. */
62
+ export const observeJavaScriptRuntimeInputSchema = z
63
+ .strictObject({
64
+ ...approvedRuntimeScope,
65
+ target_id: z.string().trim().min(1).max(256),
66
+ runtime_kind: javascriptRuntimeKindSchema,
67
+ observation_ms: z.number().int().min(0).max(10_000).default(100),
68
+ limits: javascriptRuntimeObservationLimitsSchema.default({
69
+ max_events: 10_000,
70
+ max_scripts: 2_000,
71
+ max_execution_contexts: 1_000,
72
+ max_location_bytes: 16_384,
73
+ max_total_metadata_bytes: 4 * 1_024 * 1_024,
74
+ }),
75
+ })
76
+ .superRefine(requireRuntimeScope);
77
+ export const javascriptRuntimeVersionSchema = z.strictObject({
78
+ product: z.string().min(1).max(1_024),
79
+ protocol_version: z.string().min(1).max(100),
80
+ v8_version: z.string().max(1_024).nullable(),
81
+ });
82
+ export const javascriptRuntimeLocationSchema = z.discriminatedUnion("kind", [
83
+ z.strictObject({
84
+ kind: z.literal("file"),
85
+ file_path: z.string().min(1).max(16_384),
86
+ }),
87
+ z.strictObject({
88
+ kind: z.literal("url"),
89
+ origin: z.string().min(1).max(2_048),
90
+ sanitized_url: z.string().min(1).max(65_536),
91
+ }),
92
+ z.strictObject({
93
+ kind: z.literal("builtin"),
94
+ specifier: z.string().min(1).max(4_096),
95
+ }),
96
+ ]);
97
+ const javascriptRuntimeTargetSchema = z.strictObject({
98
+ target_id: z.string().min(1).max(256),
99
+ protocol_type: z.string().min(1).max(100),
100
+ attached: z.boolean(),
101
+ location: javascriptRuntimeLocationSchema,
102
+ });
103
+ /** Root/origin-filtered V8 Inspector target inventory. */
104
+ export const javascriptRuntimeTargetListSchema = z.strictObject({
105
+ schema_version: z.literal(1),
106
+ runtime: javascriptRuntimeVersionSchema,
107
+ targets: z.strictObject({
108
+ items: z.array(javascriptRuntimeTargetSchema),
109
+ offset: z.number().int().min(0),
110
+ limit: z.number().int().min(1),
111
+ total: z.number().int().min(0),
112
+ next_offset: z.number().int().min(0).nullable(),
113
+ has_more: z.boolean(),
114
+ }),
115
+ excluded: z.strictObject({
116
+ outside_file_roots: z.number().int().min(0),
117
+ outside_origins: z.number().int().min(0),
118
+ unsupported_location: z.number().int().min(0),
119
+ unconnectable: z.number().int().min(0),
120
+ }),
121
+ limitations: z.array(boundedTextSchema).max(100),
122
+ });
123
+ const javascriptRuntimeScriptSchema = z.strictObject({
124
+ script_key: z.string().regex(/^v8_script_[a-f0-9]{64}$/u),
125
+ location: javascriptRuntimeLocationSchema,
126
+ execution_context_key: z.string().max(64).nullable(),
127
+ cdp_hash: z.string().max(512).nullable(),
128
+ length: z.number().int().min(0),
129
+ is_module: z.boolean(),
130
+ status: z.literal("observed-loaded"),
131
+ });
132
+ const javascriptRuntimeContextSchema = z.strictObject({
133
+ context_key: z.string().min(1).max(64),
134
+ state: z.enum(["created", "destroyed", "cleared"]),
135
+ name: z.string().max(1_024).nullable(),
136
+ origin: z.string().max(4_096).nullable(),
137
+ });
138
+ /** Deterministic passive script/context snapshot from one bounded window. */
139
+ export const javascriptRuntimeObservationSchema = z.strictObject({
140
+ schema_version: z.literal(1),
141
+ runtime: javascriptRuntimeVersionSchema,
142
+ target: javascriptRuntimeTargetSchema.extend({
143
+ runtime_kind: javascriptRuntimeKindSchema,
144
+ runtime_kind_authority: z.literal("caller-declared-unverified"),
145
+ }),
146
+ capture: z.strictObject({
147
+ observation_ms: z.number().int().min(0),
148
+ events_observed: z.number().int().min(0),
149
+ events_retained: z.number().int().min(0),
150
+ events_dropped: z.number().int().min(0),
151
+ metadata_bytes_retained: z.number().int().min(0),
152
+ truncated: z.boolean(),
153
+ truncation_reasons: z.array(boundedTextSchema).max(20),
154
+ }),
155
+ scripts: z.strictObject({
156
+ items: z.array(javascriptRuntimeScriptSchema),
157
+ observed_total: z.number().int().min(0),
158
+ excluded: z.strictObject({
159
+ outside_file_roots: z.number().int().min(0),
160
+ outside_origins: z.number().int().min(0),
161
+ unsupported_location: z.number().int().min(0),
162
+ invalid_protocol_value: z.number().int().min(0),
163
+ }),
164
+ }),
165
+ execution_contexts: z.array(javascriptRuntimeContextSchema),
166
+ directly_observed: z.array(boundedTextSchema).max(20),
167
+ unavailable_without_instrumentation: z.array(boundedTextSchema).max(20),
168
+ unknowns: z.array(boundedTextSchema).max(100),
169
+ limitations: z.array(boundedTextSchema).max(100),
170
+ });
@@ -1,8 +1,11 @@
1
1
  import { createHash } from "node:crypto";
2
+ import { isAbsolute, relative } from "node:path";
2
3
  import canonicalize from "canonicalize";
3
4
  import { z } from "zod";
4
- import { browserAllowedOriginsSchema, browserEndpointSchema, webPageInspectionSchema, } from "./browserObservation.js";
5
+ import { browserAllowedOriginsSchema, browserEndpointSchema, browserOriginSchema, webPageInspectionSchema, } from "./browserObservation.js";
6
+ import { classifyBrowserCompleteness, } from "./browserCompleteness.js";
5
7
  import { electronFileRootsSchema, electronPageInspectionSchema, } from "./electronObservation.js";
8
+ import { javascriptRuntimeObservationSchema, javascriptRuntimeKindSchema, } from "./javascriptRuntimeObservation.js";
6
9
  import { parseEvidence } from "./evidence.js";
7
10
  import { javascriptApplicationAnalysisResultSchema, } from "./javascriptApplicationAnalysis.js";
8
11
  import { compareCodePoints, } from "./javascriptApplicationGraph.js";
@@ -109,8 +112,123 @@ const parseRuntimeCapture = (input) => {
109
112
  scriptsCompleteWithinScope: scriptsComplete(inspection.completeness),
110
113
  };
111
114
  }
112
- throw new TypeError("Runtime reconciliation requires inspect_web_page or inspect_electron_page Evidence");
115
+ if (evidence.operation === "observe_javascript_runtime") {
116
+ assertEvidenceIdentity(evidence, {
117
+ operation: "observe_javascript_runtime",
118
+ predicate: "rea.javascript-runtime-observation/v1",
119
+ providerId: "rea-v8-inspector",
120
+ providerName: "REA passive Node/Electron V8 Inspector provider",
121
+ providerVersion: "1",
122
+ authority: "external-service",
123
+ confidence: "observed",
124
+ });
125
+ const result = javascriptRuntimeObservationSchema.parse(evidence.normalized_result);
126
+ assertV8RuntimeParameters(evidence, result);
127
+ const inspection = normalizeV8Inspection(result);
128
+ return {
129
+ kind: "v8-inspector",
130
+ evidence,
131
+ inspection,
132
+ captureSha256: digestCanonical(result),
133
+ scriptsCompleteWithinScope: false,
134
+ };
135
+ }
136
+ throw new TypeError("Runtime reconciliation requires inspect_web_page, inspect_electron_page, or observe_javascript_runtime Evidence");
137
+ };
138
+ const assertV8RuntimeParameters = (evidence, result) => {
139
+ const parameters = z
140
+ .object({
141
+ inspector_endpoint: browserEndpointSchema,
142
+ allowed_file_roots: z
143
+ .array(z.string().min(1).max(16_384).refine(isAbsolute))
144
+ .max(32),
145
+ allowed_origins: z.array(browserOriginSchema).max(32),
146
+ target_id: z.string().trim().min(1).max(256),
147
+ runtime_kind: javascriptRuntimeKindSchema,
148
+ })
149
+ .passthrough()
150
+ .parse(evidence.parameters);
151
+ if (parameters.target_id !== result.target.target_id ||
152
+ parameters.runtime_kind !== result.target.runtime_kind)
153
+ throw new TypeError("Runtime Evidence target or declared role disagrees with its result");
154
+ for (const location of [
155
+ result.target.location,
156
+ ...result.scripts.items.map(({ location }) => location),
157
+ ])
158
+ if ((location.kind === "file" &&
159
+ !parameters.allowed_file_roots.some((root) => isWithinRoot(root, location.file_path))) ||
160
+ (location.kind === "url" &&
161
+ !parameters.allowed_origins.includes(location.origin)) ||
162
+ (location.kind === "builtin" && !location.specifier.startsWith("node:")))
163
+ throw new TypeError("Runtime Evidence contains a location outside its recorded scope");
164
+ };
165
+ const isWithinRoot = (root, path) => {
166
+ const remainder = relative(root, path);
167
+ return (remainder === "" || (!remainder.startsWith("..") && !isAbsolute(remainder)));
168
+ };
169
+ const normalizeV8Inspection = (result) => ({
170
+ target: {
171
+ target_id: result.target.target_id,
172
+ type: result.target.protocol_type,
173
+ title: result.target.runtime_kind,
174
+ attached: result.target.attached,
175
+ ...runtimeLocation(result.target.location),
176
+ },
177
+ frames: [],
178
+ scripts: {
179
+ items: result.scripts.items.map((script) => ({
180
+ script_key: script.script_key,
181
+ frame_id: script.execution_context_key,
182
+ ...runtimeLocation(script.location),
183
+ cdp_hash: script.cdp_hash ?? "",
184
+ length: script.length,
185
+ is_module: script.is_module,
186
+ language: null,
187
+ source: {
188
+ included: false,
189
+ reason: "V8 Inspector source capture is outside passive authority.",
190
+ },
191
+ })),
192
+ },
193
+ workers: [],
194
+ completeness: classifyBrowserCompleteness({
195
+ policyFilteredSections: new Set(excludedV8Scripts(result) > 0 ? ["scripts"] : []),
196
+ attachLimitedSections: new Set([
197
+ "frames",
198
+ "scripts",
199
+ "script_sources",
200
+ "workers",
201
+ ]),
202
+ truncatedSections: new Set(result.capture.truncated ? ["scripts"] : []),
203
+ unavailableSections: new Set(["frames", "script_sources", "workers"]),
204
+ excluded: excludedV8Scripts(result) === 0
205
+ ? []
206
+ : [
207
+ {
208
+ section: "scripts",
209
+ reason: "out_of_target_scope",
210
+ count: excludedV8Scripts(result),
211
+ },
212
+ ],
213
+ droppedEvents: {
214
+ scripts: result.capture.events_dropped,
215
+ network_requests: 0,
216
+ console_events: 0,
217
+ websocket_connections: 0,
218
+ websocket_frames: 0,
219
+ webmcp_tools: 0,
220
+ timeline_events: 0,
221
+ },
222
+ }),
223
+ });
224
+ const runtimeLocation = (location) => {
225
+ if (location.kind === "file")
226
+ return { file_path: location.file_path };
227
+ if (location.kind === "url")
228
+ return { url: location.sanitized_url };
229
+ return { url: location.specifier };
113
230
  };
231
+ const excludedV8Scripts = (result) => Object.values(result.scripts.excluded).reduce((total, count) => total + count, 0);
114
232
  const assertRuntimeParameters = (evidence, expected) => {
115
233
  const common = {
116
234
  target_id: z.string().trim().min(1).max(256),