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,328 @@
1
+ import { z } from "zod";
2
+ /** Result of comparing a single dimension. */
3
+ export const dimensionResultSchema = z.strictObject({
4
+ name: z.string().min(1),
5
+ status: z.enum(["match", "mismatch", "unknown", "truncated"]),
6
+ message: z.string().default(""),
7
+ evidence_ids: z.array(z.string()).default([]),
8
+ });
9
+ /** Result of evaluating a trust gate for one scenario. */
10
+ export const trustGateResultSchema = z.strictObject({
11
+ scenario_id: z.string().min(1),
12
+ verdict: z.enum(["pass", "fail", "unknown"]),
13
+ dimension_results: z.array(dimensionResultSchema),
14
+ first_divergence: z
15
+ .strictObject({
16
+ dimension: z.string().min(1),
17
+ evidence_id: z.string().min(1),
18
+ message: z.string(),
19
+ })
20
+ .nullable(),
21
+ });
22
+ /** Dimension that is volatile due to timing or normalization. */
23
+ const VOLATILE_DIMENSIONS = new Set([
24
+ "timing",
25
+ "timestamp",
26
+ "pid",
27
+ "ppid",
28
+ "duration_ms",
29
+ "created_at",
30
+ "updated_at",
31
+ ]);
32
+ /** Dimension that carries semantic content. */
33
+ const SEMANTIC_DIMENSIONS = new Set([
34
+ "exit_code",
35
+ "stdout",
36
+ "stderr",
37
+ "filesystem",
38
+ "process",
39
+ "process_tree",
40
+ "shim_events",
41
+ "protocol_events",
42
+ "event_journal",
43
+ ]);
44
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
45
+ const uniqueStrings = (values) => [
46
+ ...new Set(values.filter((value) => value.length > 0)),
47
+ ];
48
+ const stringValues = (value) => {
49
+ if (typeof value === "string")
50
+ return value.length > 0 ? [value] : [];
51
+ if (!Array.isArray(value))
52
+ return [];
53
+ return value.filter((item) => typeof item === "string" && item.length > 0);
54
+ };
55
+ const evidenceIds = (record) => uniqueStrings([
56
+ ...stringValues(record["evidence_id"]),
57
+ ...stringValues(record["evidence_ids"]),
58
+ ...stringValues(record["evidence_links"]),
59
+ ]);
60
+ const incompleteStatus = (value) => {
61
+ if (!isRecord(value))
62
+ return null;
63
+ const record = value;
64
+ if (record["truncated"] === true)
65
+ return "truncated";
66
+ const status = record["status"];
67
+ if (status === "truncated")
68
+ return "truncated";
69
+ if (status === "unknown" ||
70
+ status === "unavailable" ||
71
+ status === "partial" ||
72
+ status === "incomplete" ||
73
+ status === "unverifiable" ||
74
+ status === "failed" ||
75
+ status === "not_approved")
76
+ return "unknown";
77
+ for (const key of ["coverage", "completeness"]) {
78
+ const nested = record[key];
79
+ if (!isRecord(nested))
80
+ continue;
81
+ const nestedStatus = incompleteStatus(nested);
82
+ if (nestedStatus !== null)
83
+ return nestedStatus;
84
+ }
85
+ return null;
86
+ };
87
+ const hasResidualUnknowns = (value) => isRecord(value) &&
88
+ Array.isArray(value["residual_unknowns"]) &&
89
+ value["residual_unknowns"].length > 0;
90
+ const unknownScopes = (record) => {
91
+ const residualUnknowns = record["residual_unknowns"];
92
+ if (!Array.isArray(residualUnknowns))
93
+ return [];
94
+ return residualUnknowns.flatMap((item) => {
95
+ if (!isRecord(item) || typeof item["scope"] !== "string")
96
+ return [];
97
+ return [item["scope"]];
98
+ });
99
+ };
100
+ const evidenceView = (input) => {
101
+ if (!isRecord(input))
102
+ return {
103
+ values: {},
104
+ evidence_ids: [],
105
+ status: null,
106
+ unknown_scopes: [],
107
+ };
108
+ const normalized = input["normalized_result"];
109
+ const values = isRecord(normalized) ? normalized : input;
110
+ const normalizedStatus = isRecord(normalized)
111
+ ? incompleteStatus(normalized)
112
+ : null;
113
+ return {
114
+ values,
115
+ evidence_ids: evidenceIds(input),
116
+ status: incompleteStatus(input) ?? normalizedStatus,
117
+ unknown_scopes: uniqueStrings([
118
+ ...unknownScopes(input),
119
+ ...(isRecord(normalized) ? unknownScopes(normalized) : []),
120
+ ]),
121
+ };
122
+ };
123
+ const dimensionScope = (dimensionName) => {
124
+ if (dimensionName === "exit_code" || dimensionName === "exit")
125
+ return "exit";
126
+ if (dimensionName === "process" ||
127
+ dimensionName === "process_tree" ||
128
+ dimensionName === "event_journal")
129
+ return "process";
130
+ if (dimensionName === "stdout" || dimensionName === "stderr")
131
+ return "terminal";
132
+ if (dimensionName === "filesystem")
133
+ return "filesystem";
134
+ if (dimensionName === "shim_events")
135
+ return "shim";
136
+ if (dimensionName === "protocol_events")
137
+ return "protocol";
138
+ return null;
139
+ };
140
+ const statusForDimension = (view, dimensionName) => {
141
+ const valueStatus = incompleteStatus(view.values[dimensionName]);
142
+ if (valueStatus !== null)
143
+ return valueStatus;
144
+ if (hasResidualUnknowns(view.values[dimensionName]))
145
+ return "unknown";
146
+ const scope = dimensionScope(dimensionName);
147
+ return scope !== null && view.unknown_scopes.includes(scope)
148
+ ? "unknown"
149
+ : view.status;
150
+ };
151
+ const comparisonIncompleteStatus = (expected, actual, options) => {
152
+ const expectedStatus = options.expected_status ?? incompleteStatus(expected);
153
+ const actualStatus = options.actual_status ?? incompleteStatus(actual);
154
+ if (options.truncated)
155
+ return "truncated";
156
+ if (expectedStatus === "truncated" || actualStatus === "truncated")
157
+ return "truncated";
158
+ if (expectedStatus === "unknown" || actualStatus === "unknown")
159
+ return "unknown";
160
+ return null;
161
+ };
162
+ /** Check if a dimension name is volatile (timing/normalization noise). */
163
+ export function isVolatileDimension(name) {
164
+ return VOLATILE_DIMENSIONS.has(name);
165
+ }
166
+ /** Check if a dimension name carries semantic content. */
167
+ export function isSemanticDimension(name) {
168
+ return SEMANTIC_DIMENSIONS.has(name);
169
+ }
170
+ /**
171
+ * Compare two values for a dimension, classifying semantic diffs
172
+ * from timing/normalization noise.
173
+ *
174
+ * Volatile dimensions (timing, timestamps, PIDs) are always treated
175
+ * as matches because their values are expected to differ across
176
+ * runs and do not carry semantic meaning.
177
+ */
178
+ export function compareDimension(dimensionName, expected, actual, options = {}) {
179
+ // Volatile dimensions: always match regardless of values
180
+ if (isVolatileDimension(dimensionName)) {
181
+ return {
182
+ name: dimensionName,
183
+ status: "match",
184
+ message: "volatile dimension ignored",
185
+ evidence_ids: uniqueStrings(options.evidence_ids ?? []),
186
+ };
187
+ }
188
+ const status = comparisonIncompleteStatus(expected, actual, options);
189
+ const resultEvidenceIds = uniqueStrings(options.evidence_ids ?? []);
190
+ if (status !== null) {
191
+ return {
192
+ name: dimensionName,
193
+ status,
194
+ message: status === "truncated"
195
+ ? "evidence was truncated"
196
+ : "evidence completeness is unknown",
197
+ evidence_ids: resultEvidenceIds,
198
+ };
199
+ }
200
+ if (expected === undefined && actual === undefined) {
201
+ return {
202
+ name: dimensionName,
203
+ status: "unknown",
204
+ message: "both expected and actual are undefined",
205
+ evidence_ids: resultEvidenceIds,
206
+ };
207
+ }
208
+ if (expected === undefined || actual === undefined) {
209
+ return {
210
+ name: dimensionName,
211
+ status: "unknown",
212
+ message: "one side has no observed value",
213
+ evidence_ids: resultEvidenceIds,
214
+ };
215
+ }
216
+ // Semantic comparison for structured objects
217
+ if (typeof expected === "object" && typeof actual === "object") {
218
+ const expectedJson = JSON.stringify(sortKeys(expected));
219
+ const actualJson = JSON.stringify(sortKeys(actual));
220
+ if (expectedJson === actualJson) {
221
+ return {
222
+ name: dimensionName,
223
+ status: "match",
224
+ message: "",
225
+ evidence_ids: resultEvidenceIds,
226
+ };
227
+ }
228
+ return {
229
+ name: dimensionName,
230
+ status: "mismatch",
231
+ message: "semantic content differs",
232
+ evidence_ids: resultEvidenceIds,
233
+ };
234
+ }
235
+ // Primitive comparison
236
+ if (expected === actual) {
237
+ return {
238
+ name: dimensionName,
239
+ status: "match",
240
+ message: "",
241
+ evidence_ids: resultEvidenceIds,
242
+ };
243
+ }
244
+ return {
245
+ name: dimensionName,
246
+ status: "mismatch",
247
+ message: `expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`,
248
+ evidence_ids: resultEvidenceIds,
249
+ };
250
+ }
251
+ /** Recursively sort object keys for deterministic comparison. */
252
+ function sortKeys(value) {
253
+ if (value === null || typeof value !== "object")
254
+ return value;
255
+ if (Array.isArray(value))
256
+ return value.map(sortKeys);
257
+ if (!isRecord(value))
258
+ return value;
259
+ const sorted = {};
260
+ for (const key of Object.keys(value).sort()) {
261
+ sorted[key] = sortKeys(value[key]);
262
+ }
263
+ return sorted;
264
+ }
265
+ /**
266
+ * Evaluate a trust gate for one scenario by comparing expected
267
+ * evidence against the actual captured run.
268
+ */
269
+ export function evaluateTrustGate(contract, expectedEvidence, actualEvidence, options = {}) {
270
+ const dimensionResults = [];
271
+ let firstDivergence = null;
272
+ const expectedView = evidenceView(expectedEvidence);
273
+ const actualView = evidenceView(actualEvidence);
274
+ for (const dim of contract.dimensions) {
275
+ if (!dim.required)
276
+ continue;
277
+ const expectedValue = expectedView.values[dim.name];
278
+ const actualValue = actualView.values[dim.name];
279
+ const result = compareDimension(dim.name, expectedValue, actualValue, {
280
+ ...options,
281
+ expected_status: statusForDimension(expectedView, dim.name),
282
+ actual_status: statusForDimension(actualView, dim.name),
283
+ evidence_ids: uniqueStrings([
284
+ ...actualView.evidence_ids,
285
+ ...expectedView.evidence_ids,
286
+ ]),
287
+ });
288
+ dimensionResults.push(result);
289
+ if (result.status === "mismatch" && firstDivergence === null) {
290
+ firstDivergence = {
291
+ dimension: dim.name,
292
+ evidence_id: result.evidence_ids[0] ?? "unknown",
293
+ message: result.message,
294
+ };
295
+ }
296
+ }
297
+ const hasFail = dimensionResults.some((r) => r.status === "mismatch" || r.status === "truncated");
298
+ const hasUnknown = dimensionResults.some((r) => r.status === "unknown");
299
+ const verdict = hasFail
300
+ ? "fail"
301
+ : hasUnknown
302
+ ? "unknown"
303
+ : "pass";
304
+ return {
305
+ scenario_id: contract.scenario_id,
306
+ verdict,
307
+ dimension_results: dimensionResults,
308
+ first_divergence: firstDivergence,
309
+ };
310
+ }
311
+ /**
312
+ * Evaluate trust gates for all scenarios in a conformance package.
313
+ * Rejects runs that differ in required dimensions. Unknown/truncated
314
+ * evidence is never treated as equivalence.
315
+ */
316
+ export function evaluatePackageTrustGates(pkg, actualEvidence, options = {}) {
317
+ const results = [];
318
+ for (const contract of pkg.verifier_contracts) {
319
+ const expected = pkg.expected_evidence.find((e) => e.scenario_id === contract.scenario_id);
320
+ if (!expected)
321
+ continue;
322
+ const expectedEvidence = expected.envelopes[0] ?? {};
323
+ const actual = actualEvidence[contract.scenario_id] ?? {};
324
+ const result = evaluateTrustGate(contract, expectedEvidence, actual, options);
325
+ results.push(result);
326
+ }
327
+ return results;
328
+ }
@@ -0,0 +1,137 @@
1
+ import { z } from "zod";
2
+ import { jsonValueSchema } from "./jsonValue.js";
3
+ /** Supported transport types for custom protocol capture. */
4
+ export const transportTypeSchema = z.enum([
5
+ "tcp",
6
+ "udp",
7
+ "ipc",
8
+ "unix-socket",
9
+ "named-pipe",
10
+ "xpc",
11
+ ]);
12
+ /** Direction of a protocol frame. */
13
+ export const frameDirectionSchema = z.enum(["sent", "received", "intercepted"]);
14
+ /** A captured protocol frame. */
15
+ export const protocolFrameSchema = z.strictObject({
16
+ /** Monotonic sequence number. */
17
+ sequence: z.number().int().nonnegative(),
18
+ /** Timestamp in milliseconds. */
19
+ at_ms: z.number().int().nonnegative(),
20
+ /** Transport type. */
21
+ transport: transportTypeSchema,
22
+ /** Direction of the frame. */
23
+ direction: frameDirectionSchema,
24
+ /** Source process identity. */
25
+ source_pid: z.number().int().nullable(),
26
+ /** Destination process identity. */
27
+ dest_pid: z.number().int().nullable(),
28
+ /** Endpoint address (IP:port, socket path, pipe name). */
29
+ source_endpoint: z.string().nullable(),
30
+ /** Destination endpoint. */
31
+ dest_endpoint: z.string().nullable(),
32
+ /** Raw frame data as base64. */
33
+ raw_data: z.string().nullable(),
34
+ /** Decoded/parsed frame content if known. */
35
+ decoded_content: jsonValueSchema.nullable(),
36
+ /** Frame size in bytes. */
37
+ size: z.number().int().nonnegative(),
38
+ /** Whether the frame was truncated. */
39
+ truncated: z.boolean().default(false),
40
+ });
41
+ /** Authentication flow stage. */
42
+ export const authStageSchema = z.enum([
43
+ "init",
44
+ "challenge",
45
+ "response",
46
+ "token_exchange",
47
+ "renewal",
48
+ "revocation",
49
+ "failure",
50
+ "success",
51
+ ]);
52
+ /** Token lifecycle event. */
53
+ export const tokenLifecycleEventSchema = z.enum([
54
+ "issued",
55
+ "refreshed",
56
+ "expired",
57
+ "revoked",
58
+ "renewed",
59
+ ]);
60
+ /** A captured authentication flow event. */
61
+ export const authFlowEventSchema = z.strictObject({
62
+ /** Monotonic sequence number. */
63
+ sequence: z.number().int().nonnegative(),
64
+ /** Timestamp in milliseconds. */
65
+ at_ms: z.number().int().nonnegative(),
66
+ /** Authentication stage. */
67
+ stage: authStageSchema,
68
+ /** Protocol used. */
69
+ protocol: z.string().min(1),
70
+ /** Token type if applicable. */
71
+ token_type: z.string().nullable(),
72
+ /** Token lifecycle event. */
73
+ token_lifecycle: tokenLifecycleEventSchema.nullable(),
74
+ /** Correlation ID linking challenge-response pairs. */
75
+ correlation_id: z.string().nullable(),
76
+ /** Whether credentials were detected and redacted. */
77
+ credentials_redacted: z.boolean().default(false),
78
+ /** Whether the authentication succeeded. */
79
+ succeeded: z.boolean().default(false),
80
+ /** Error message if authentication failed. */
81
+ error: z.string().nullable(),
82
+ });
83
+ /** A captured protocol session. */
84
+ export const customProtocolCaptureSchema = z.strictObject({
85
+ /** Transport type for this session. */
86
+ transport: transportTypeSchema,
87
+ /** Captured frames in order. */
88
+ frames: z.array(protocolFrameSchema).min(0).max(100_000),
89
+ /** Authentication flow events. */
90
+ auth_events: z.array(authFlowEventSchema).default([]),
91
+ /** Whether any frame was truncated. */
92
+ has_truncated: z.boolean().default(false),
93
+ /** Whether credentials were detected. */
94
+ credentials_detected: z.boolean().default(false),
95
+ });
96
+ /** Correlate a frame with process identity. */
97
+ export function correlateProcessIdentity(frame, pid) {
98
+ return frame.source_pid === pid || frame.dest_pid === pid;
99
+ }
100
+ /** Check if a frame contains credential-like content. */
101
+ export function looksLikeCredentialFrame(frame) {
102
+ const patterns = [
103
+ "password",
104
+ "token",
105
+ "secret",
106
+ "api_key",
107
+ "apikey",
108
+ "authorization",
109
+ "credential",
110
+ ];
111
+ const content = JSON.stringify(frame.decoded_content ?? "").toLowerCase();
112
+ return patterns.some((p) => content.includes(p));
113
+ }
114
+ /** Filter frames by transport type. */
115
+ export function framesByTransport(frames, transport) {
116
+ return frames.filter((f) => f.transport === transport);
117
+ }
118
+ /** Get all authentication flow events for a specific protocol. */
119
+ export function authEventsByProtocol(events, protocol) {
120
+ return events.filter((e) => e.protocol === protocol);
121
+ }
122
+ /** Get successful authentication events. */
123
+ export function successfulAuthEvents(events) {
124
+ return events.filter((e) => e.succeeded);
125
+ }
126
+ /** Get failed authentication events. */
127
+ export function failedAuthEvents(events) {
128
+ return events.filter((e) => !e.succeeded);
129
+ }
130
+ /** Compute the duration of an authentication flow in milliseconds. */
131
+ export function authFlowDuration(events) {
132
+ const first = events.at(0);
133
+ const last = events.at(-1);
134
+ if (first === undefined || last === undefined)
135
+ return null;
136
+ return last.at_ms - first.at_ms;
137
+ }