@memberjunction/server 6.2.0-edge.2 → 6.2.0-edge.4

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 (435) hide show
  1. package/README.md +30 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentSessions/BridgeHostInstance.d.ts +25 -0
  4. package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -0
  5. package/dist/agentSessions/BridgeHostInstance.js +30 -0
  6. package/dist/agentSessions/BridgeHostInstance.js.map +1 -0
  7. package/dist/agentSessions/HostInstance.d.ts +75 -11
  8. package/dist/agentSessions/HostInstance.d.ts.map +1 -1
  9. package/dist/agentSessions/HostInstance.js +99 -28
  10. package/dist/agentSessions/HostInstance.js.map +1 -1
  11. package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
  12. package/dist/agentSessions/ReturningVisitorRecap.js +7 -3
  13. package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
  14. package/dist/agentSessions/SessionJanitor.d.ts +173 -25
  15. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  16. package/dist/agentSessions/SessionJanitor.js +452 -54
  17. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  18. package/dist/agentSessions/SessionManager.d.ts +43 -2
  19. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  20. package/dist/agentSessions/SessionManager.js +99 -8
  21. package/dist/agentSessions/SessionManager.js.map +1 -1
  22. package/dist/agentSessions/SessionRunIDVerifier.d.ts +63 -0
  23. package/dist/agentSessions/SessionRunIDVerifier.d.ts.map +1 -0
  24. package/dist/agentSessions/SessionRunIDVerifier.js +129 -0
  25. package/dist/agentSessions/SessionRunIDVerifier.js.map +1 -0
  26. package/dist/agentSessions/index.d.ts +2 -0
  27. package/dist/agentSessions/index.d.ts.map +1 -1
  28. package/dist/agentSessions/index.js +10 -3
  29. package/dist/agentSessions/index.js.map +1 -1
  30. package/dist/auth/actionAuthorization.d.ts +40 -0
  31. package/dist/auth/actionAuthorization.d.ts.map +1 -0
  32. package/dist/auth/actionAuthorization.js +94 -0
  33. package/dist/auth/actionAuthorization.js.map +1 -0
  34. package/dist/auth/index.d.ts.map +1 -1
  35. package/dist/auth/index.js +3 -10
  36. package/dist/auth/index.js.map +1 -1
  37. package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
  38. package/dist/auth/magicLink/MagicLinkService.js +6 -3
  39. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  40. package/dist/auth/newUsers.d.ts +10 -0
  41. package/dist/auth/newUsers.d.ts.map +1 -1
  42. package/dist/auth/newUsers.js +80 -11
  43. package/dist/auth/newUsers.js.map +1 -1
  44. package/dist/config.d.ts +4567 -71
  45. package/dist/config.d.ts.map +1 -1
  46. package/dist/config.js +246 -3
  47. package/dist/config.js.map +1 -1
  48. package/dist/context.d.ts +8 -0
  49. package/dist/context.d.ts.map +1 -1
  50. package/dist/context.js +25 -34
  51. package/dist/context.js.map +1 -1
  52. package/dist/generated/graphql-schemas/__mj.d.ts +1073 -10
  53. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  54. package/dist/generated/graphql-schemas/__mj.js +9188 -3649
  55. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  56. package/dist/generic/OrphanedConversationDetailReconciler.js +3 -3
  57. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
  58. package/dist/generic/ResolverBase.d.ts +62 -6
  59. package/dist/generic/ResolverBase.d.ts.map +1 -1
  60. package/dist/generic/ResolverBase.js +179 -35
  61. package/dist/generic/ResolverBase.js.map +1 -1
  62. package/dist/generic/RunViewResolver.d.ts +4 -0
  63. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  64. package/dist/generic/RunViewResolver.js +37 -1
  65. package/dist/generic/RunViewResolver.js.map +1 -1
  66. package/dist/index.d.ts +7 -0
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +214 -159
  69. package/dist/index.js.map +1 -1
  70. package/dist/isolatedProvider.d.ts +20 -0
  71. package/dist/isolatedProvider.d.ts.map +1 -0
  72. package/dist/isolatedProvider.js +22 -0
  73. package/dist/isolatedProvider.js.map +1 -0
  74. package/dist/postgresqlCompat.d.ts +8 -0
  75. package/dist/postgresqlCompat.d.ts.map +1 -0
  76. package/dist/postgresqlCompat.js +19 -0
  77. package/dist/postgresqlCompat.js.map +1 -0
  78. package/dist/postgresqlPoolSettings.d.ts +108 -0
  79. package/dist/postgresqlPoolSettings.d.ts.map +1 -0
  80. package/dist/postgresqlPoolSettings.js +134 -0
  81. package/dist/postgresqlPoolSettings.js.map +1 -0
  82. package/dist/realtimeProxy/RealtimeProxyServer.d.ts +44 -4
  83. package/dist/realtimeProxy/RealtimeProxyServer.d.ts.map +1 -1
  84. package/dist/realtimeProxy/RealtimeProxyServer.js +121 -16
  85. package/dist/realtimeProxy/RealtimeProxyServer.js.map +1 -1
  86. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts +171 -0
  87. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts.map +1 -0
  88. package/dist/realtimeProxy/RealtimeRelayTunnel.js +532 -0
  89. package/dist/realtimeProxy/RealtimeRelayTunnel.js.map +1 -0
  90. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts +148 -0
  91. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts.map +1 -0
  92. package/dist/realtimeSessions/RealtimeSessionEventService.js +191 -0
  93. package/dist/realtimeSessions/RealtimeSessionEventService.js.map +1 -0
  94. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts +66 -0
  95. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -0
  96. package/dist/realtimeSessions/RealtimeSessionVerificationService.js +138 -0
  97. package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -0
  98. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts +38 -0
  99. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -0
  100. package/dist/realtimeSessions/RealtimeVerifyRouter.js +98 -0
  101. package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -0
  102. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts +61 -0
  103. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -0
  104. package/dist/realtimeSessions/SessionVerificationPortsBase.js +149 -0
  105. package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -0
  106. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts +57 -0
  107. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts.map +1 -0
  108. package/dist/realtimeSessions/SlidingWindowRateLimiter.js +69 -0
  109. package/dist/realtimeSessions/SlidingWindowRateLimiter.js.map +1 -0
  110. package/dist/realtimeSessions/index.d.ts +17 -0
  111. package/dist/realtimeSessions/index.d.ts.map +1 -0
  112. package/dist/realtimeSessions/index.js +17 -0
  113. package/dist/realtimeSessions/index.js.map +1 -0
  114. package/dist/realtimeSessions/sessionAccess.d.ts +86 -0
  115. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -0
  116. package/dist/realtimeSessions/sessionAccess.js +90 -0
  117. package/dist/realtimeSessions/sessionAccess.js.map +1 -0
  118. package/dist/realtimeSessions/sessionConfigStamps.d.ts +70 -0
  119. package/dist/realtimeSessions/sessionConfigStamps.d.ts.map +1 -0
  120. package/dist/realtimeSessions/sessionConfigStamps.js +93 -0
  121. package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -0
  122. package/dist/realtimeSessions/subscriptionAuthorization.d.ts +65 -0
  123. package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -0
  124. package/dist/realtimeSessions/subscriptionAuthorization.js +71 -0
  125. package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -0
  126. package/dist/realtimeSessions/verificationCore.d.ts +243 -0
  127. package/dist/realtimeSessions/verificationCore.d.ts.map +1 -0
  128. package/dist/realtimeSessions/verificationCore.js +356 -0
  129. package/dist/realtimeSessions/verificationCore.js.map +1 -0
  130. package/dist/realtimeSessions/verificationPages.d.ts +66 -0
  131. package/dist/realtimeSessions/verificationPages.d.ts.map +1 -0
  132. package/dist/realtimeSessions/verificationPages.js +110 -0
  133. package/dist/realtimeSessions/verificationPages.js.map +1 -0
  134. package/dist/realtimeSessions/verificationPolicy.d.ts +147 -0
  135. package/dist/realtimeSessions/verificationPolicy.d.ts.map +1 -0
  136. package/dist/realtimeSessions/verificationPolicy.js +249 -0
  137. package/dist/realtimeSessions/verificationPolicy.js.map +1 -0
  138. package/dist/realtimeSessions/verificationWorkflow.d.ts +263 -0
  139. package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -0
  140. package/dist/realtimeSessions/verificationWorkflow.js +435 -0
  141. package/dist/realtimeSessions/verificationWorkflow.js.map +1 -0
  142. package/dist/realtimeWidget/widgetGuestElevation.d.ts +20 -2
  143. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  144. package/dist/realtimeWidget/widgetGuestElevation.js +31 -2
  145. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  146. package/dist/resolvers/ActionResolver.d.ts +31 -5
  147. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  148. package/dist/resolvers/ActionResolver.js +75 -14
  149. package/dist/resolvers/ActionResolver.js.map +1 -1
  150. package/dist/resolvers/AdhocQueryResolver.d.ts +35 -17
  151. package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
  152. package/dist/resolvers/AdhocQueryResolver.js +92 -166
  153. package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
  154. package/dist/resolvers/CacheStatsResolver.d.ts +27 -0
  155. package/dist/resolvers/CacheStatsResolver.d.ts.map +1 -1
  156. package/dist/resolvers/CacheStatsResolver.js +113 -2
  157. package/dist/resolvers/CacheStatsResolver.js.map +1 -1
  158. package/dist/resolvers/ClientToolRequestResolver.d.ts +4 -2
  159. package/dist/resolvers/ClientToolRequestResolver.d.ts.map +1 -1
  160. package/dist/resolvers/ClientToolRequestResolver.js +28 -10
  161. package/dist/resolvers/ClientToolRequestResolver.js.map +1 -1
  162. package/dist/resolvers/EntityRecordNameResolver.d.ts +7 -23
  163. package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
  164. package/dist/resolvers/EntityRecordNameResolver.js +9 -47
  165. package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
  166. package/dist/resolvers/FetchEntityVectorsResolver.d.ts +12 -1
  167. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  168. package/dist/resolvers/FetchEntityVectorsResolver.js +83 -2
  169. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  170. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  171. package/dist/resolvers/GetDataResolver.js +9 -0
  172. package/dist/resolvers/GetDataResolver.js.map +1 -1
  173. package/dist/resolvers/HumanHandoffResolver.d.ts +107 -0
  174. package/dist/resolvers/HumanHandoffResolver.d.ts.map +1 -0
  175. package/dist/resolvers/HumanHandoffResolver.js +330 -0
  176. package/dist/resolvers/HumanHandoffResolver.js.map +1 -0
  177. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  178. package/dist/resolvers/MCPResolver.js +9 -4
  179. package/dist/resolvers/MCPResolver.js.map +1 -1
  180. package/dist/resolvers/MeetingResolver.d.ts +69 -0
  181. package/dist/resolvers/MeetingResolver.d.ts.map +1 -0
  182. package/dist/resolvers/MeetingResolver.js +381 -0
  183. package/dist/resolvers/MeetingResolver.js.map +1 -0
  184. package/dist/resolvers/RealtimeBridgeResolver.d.ts +88 -3
  185. package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
  186. package/dist/resolvers/RealtimeBridgeResolver.js +352 -12
  187. package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
  188. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +156 -108
  189. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  190. package/dist/resolvers/RealtimeClientSessionResolver.js +395 -293
  191. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  192. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts +61 -0
  193. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts.map +1 -0
  194. package/dist/resolvers/RealtimeSessionEventsResolver.js +130 -0
  195. package/dist/resolvers/RealtimeSessionEventsResolver.js.map +1 -0
  196. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts +85 -0
  197. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts.map +1 -0
  198. package/dist/resolvers/RealtimeSessionVerificationResolver.js +188 -0
  199. package/dist/resolvers/RealtimeSessionVerificationResolver.js.map +1 -0
  200. package/dist/resolvers/RemoteBrowserActionResolver.d.ts +2 -0
  201. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  202. package/dist/resolvers/RemoteBrowserActionResolver.js +5 -1
  203. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  204. package/dist/resolvers/RunAIAgentResolver.d.ts +10 -0
  205. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  206. package/dist/resolvers/RunAIAgentResolver.js +68 -11
  207. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  208. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  209. package/dist/resolvers/RunTemplateResolver.js +12 -11
  210. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  211. package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
  212. package/dist/resolvers/SyncDataResolver.js +6 -2
  213. package/dist/resolvers/SyncDataResolver.js.map +1 -1
  214. package/dist/resolvers/SyncRolesUsersResolver.d.ts +2 -0
  215. package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
  216. package/dist/resolvers/SyncRolesUsersResolver.js +23 -6
  217. package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
  218. package/dist/resolvers/UserAvatarResolver.d.ts +16 -0
  219. package/dist/resolvers/UserAvatarResolver.d.ts.map +1 -0
  220. package/dist/resolvers/UserAvatarResolver.js +124 -0
  221. package/dist/resolvers/UserAvatarResolver.js.map +1 -0
  222. package/dist/resolvers/UserResolver.d.ts.map +1 -1
  223. package/dist/resolvers/UserResolver.js +2 -17
  224. package/dist/resolvers/UserResolver.js.map +1 -1
  225. package/dist/resolvers/adhocTimeout.d.ts +7 -0
  226. package/dist/resolvers/adhocTimeout.d.ts.map +1 -0
  227. package/dist/resolvers/adhocTimeout.js +12 -0
  228. package/dist/resolvers/adhocTimeout.js.map +1 -0
  229. package/dist/resolvers/agentVisionConsentAudit.d.ts +37 -0
  230. package/dist/resolvers/agentVisionConsentAudit.d.ts.map +1 -0
  231. package/dist/resolvers/agentVisionConsentAudit.js +63 -0
  232. package/dist/resolvers/agentVisionConsentAudit.js.map +1 -0
  233. package/dist/resolvers/avatarInputValidation.d.ts +40 -0
  234. package/dist/resolvers/avatarInputValidation.d.ts.map +1 -0
  235. package/dist/resolvers/avatarInputValidation.js +97 -0
  236. package/dist/resolvers/avatarInputValidation.js.map +1 -0
  237. package/dist/resolvers/currentUserRoles.d.ts +29 -0
  238. package/dist/resolvers/currentUserRoles.d.ts.map +1 -1
  239. package/dist/resolvers/currentUserRoles.js +30 -0
  240. package/dist/resolvers/currentUserRoles.js.map +1 -1
  241. package/dist/resolvers/meetings/index.d.ts +5 -0
  242. package/dist/resolvers/meetings/index.d.ts.map +1 -0
  243. package/dist/resolvers/meetings/index.js +5 -0
  244. package/dist/resolvers/meetings/index.js.map +1 -0
  245. package/dist/resolvers/meetings/meetingHelpers.d.ts +17 -0
  246. package/dist/resolvers/meetings/meetingHelpers.d.ts.map +1 -0
  247. package/dist/resolvers/meetings/meetingHelpers.js +212 -0
  248. package/dist/resolvers/meetings/meetingHelpers.js.map +1 -0
  249. package/dist/resolvers/meetings/meetingMutations.d.ts +18 -0
  250. package/dist/resolvers/meetings/meetingMutations.d.ts.map +1 -0
  251. package/dist/resolvers/meetings/meetingMutations.js +439 -0
  252. package/dist/resolvers/meetings/meetingMutations.js.map +1 -0
  253. package/dist/resolvers/meetings/meetingQueries.d.ts +7 -0
  254. package/dist/resolvers/meetings/meetingQueries.d.ts.map +1 -0
  255. package/dist/resolvers/meetings/meetingQueries.js +113 -0
  256. package/dist/resolvers/meetings/meetingQueries.js.map +1 -0
  257. package/dist/resolvers/meetings/meetingTypes.d.ts +89 -0
  258. package/dist/resolvers/meetings/meetingTypes.d.ts.map +1 -0
  259. package/dist/resolvers/meetings/meetingTypes.js +345 -0
  260. package/dist/resolvers/meetings/meetingTypes.js.map +1 -0
  261. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  262. package/dist/rest/ViewOperationsHandler.js +8 -5
  263. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  264. package/dist/services/TaskGraphActionRunner.d.ts +8 -0
  265. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  266. package/dist/services/TaskGraphActionRunner.js +27 -1
  267. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  268. package/dist/services/TaskGraphContinuationDeliverer.d.ts +4 -3
  269. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  270. package/dist/services/TaskGraphContinuationDeliverer.js +13 -7
  271. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  272. package/dist/services/WorkQueueHostService.d.ts +36 -0
  273. package/dist/services/WorkQueueHostService.d.ts.map +1 -0
  274. package/dist/services/WorkQueueHostService.js +97 -0
  275. package/dist/services/WorkQueueHostService.js.map +1 -0
  276. package/dist/services/workQueueConfig.d.ts +103 -0
  277. package/dist/services/workQueueConfig.d.ts.map +1 -0
  278. package/dist/services/workQueueConfig.js +48 -0
  279. package/dist/services/workQueueConfig.js.map +1 -0
  280. package/dist/sharedCache.d.ts +105 -0
  281. package/dist/sharedCache.d.ts.map +1 -0
  282. package/dist/sharedCache.js +276 -0
  283. package/dist/sharedCache.js.map +1 -0
  284. package/dist/types.d.ts +11 -0
  285. package/dist/types.d.ts.map +1 -1
  286. package/dist/types.js.map +1 -1
  287. package/package.json +97 -94
  288. package/src/__tests__/ActionResolver.authorization.test.ts +353 -0
  289. package/src/__tests__/AdhocQueryResolver.bugs.test.ts +14 -35
  290. package/src/__tests__/AdhocQueryResolver.pagination.test.ts +6 -2
  291. package/src/__tests__/AdhocQueryResolver.scopeGuard.test.ts +3 -3
  292. package/src/__tests__/AdhocQueryResolver.sqlAuthorizer.test.ts +104 -0
  293. package/src/__tests__/BridgeHostInstance.test.ts +232 -0
  294. package/src/__tests__/ClientToolRequestResolver.test.ts +116 -0
  295. package/src/__tests__/EntityRecordNameResolver.fieldSecurity.test.ts +27 -72
  296. package/src/__tests__/FetchEntityVectorsResolver.test.ts +285 -0
  297. package/src/__tests__/HostInstance.test.ts +84 -0
  298. package/src/__tests__/HumanHandoffResolver.test.ts +250 -0
  299. package/src/__tests__/MeetingResolver.test.ts +448 -0
  300. package/src/__tests__/RealtimeBridgeResolver.test.ts +651 -4
  301. package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +383 -0
  302. package/src/__tests__/RealtimeClientSessionResolver.test.ts +682 -58
  303. package/src/__tests__/RealtimeProxyServer.test.ts +16 -1
  304. package/src/__tests__/RealtimeRelay.test.ts +876 -0
  305. package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +129 -0
  306. package/src/__tests__/ResolverBase.adhocReadScope.test.ts +96 -0
  307. package/src/__tests__/ResolverBase.aggregateScreen.test.ts +174 -0
  308. package/src/__tests__/ResolverBase.clientOldValues.test.ts +6 -3
  309. package/src/__tests__/ResolverBase.filterEscaping.test.ts +21 -2
  310. package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +291 -0
  311. package/src/__tests__/ReturningVisitorRecap.test.ts +115 -0
  312. package/src/__tests__/RunAIAgentResolver.branch.test.ts +169 -0
  313. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +4 -4
  314. package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +166 -0
  315. package/src/__tests__/RunTemplateResolver.test.ts +132 -0
  316. package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +63 -0
  317. package/src/__tests__/SessionJanitor.test.ts +845 -18
  318. package/src/__tests__/SessionManager.test.ts +213 -17
  319. package/src/__tests__/SessionRunIDVerifier.test.ts +251 -0
  320. package/src/__tests__/SyncRolesUsersResolver.userRoles.test.ts +97 -0
  321. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +41 -0
  322. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +50 -3
  323. package/src/__tests__/UserAvatarResolver.test.ts +255 -0
  324. package/src/__tests__/UserResolver.currentUser.test.ts +16 -1
  325. package/src/__tests__/WorkQueueHostService.test.ts +133 -0
  326. package/src/__tests__/actionAuthorization.test.ts +130 -0
  327. package/src/__tests__/adhocTimeoutClamp.test.ts +26 -0
  328. package/src/__tests__/agentVisionConsentAudit.test.ts +118 -0
  329. package/src/__tests__/avatarInputValidation.test.ts +160 -0
  330. package/src/__tests__/isolatedProviderTransactions.test.ts +169 -0
  331. package/src/__tests__/magicLinkService.consume.test.ts +6 -0
  332. package/src/__tests__/magicLinkService.provisionLog.test.ts +5 -0
  333. package/src/__tests__/newUsers.template.test.ts +151 -0
  334. package/src/__tests__/newUsers.test.ts +74 -5
  335. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +17 -2
  336. package/src/__tests__/postgresqlPoolSettings.test.ts +131 -0
  337. package/src/__tests__/realtimeSessions/RealtimeSessionEventService.test.ts +201 -0
  338. package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +215 -0
  339. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationResolver.test.ts +102 -0
  340. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationService.test.ts +349 -0
  341. package/src/__tests__/realtimeSessions/RealtimeVerifyRouter.test.ts +131 -0
  342. package/src/__tests__/realtimeSessions/SlidingWindowRateLimiter.test.ts +56 -0
  343. package/src/__tests__/realtimeSessions/helpers.ts +4 -0
  344. package/src/__tests__/realtimeSessions/sessionAccess.test.ts +129 -0
  345. package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +124 -0
  346. package/src/__tests__/realtimeSessions/verificationCore.test.ts +355 -0
  347. package/src/__tests__/realtimeSessions/verificationPages.test.ts +84 -0
  348. package/src/__tests__/realtimeSessions/verificationPolicy.test.ts +226 -0
  349. package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +633 -0
  350. package/src/__tests__/resolverBase.fls.test.ts +87 -4
  351. package/src/__tests__/serverExtensionReservedRoots.test.ts +2 -0
  352. package/src/__tests__/sharedCache.test.ts +310 -0
  353. package/src/__tests__/translateBracketsToPG.test.ts +20 -0
  354. package/src/__tests__/widgetGuestElevation.test.ts +44 -0
  355. package/src/agentSessions/BridgeHostInstance.ts +32 -0
  356. package/src/agentSessions/HostInstance.ts +124 -28
  357. package/src/agentSessions/ReturningVisitorRecap.ts +7 -3
  358. package/src/agentSessions/SessionJanitor.ts +543 -57
  359. package/src/agentSessions/SessionManager.ts +125 -25
  360. package/src/agentSessions/SessionRunIDVerifier.ts +171 -0
  361. package/src/agentSessions/index.ts +10 -3
  362. package/src/auth/actionAuthorization.ts +116 -0
  363. package/src/auth/index.ts +3 -8
  364. package/src/auth/magicLink/MagicLinkService.ts +6 -3
  365. package/src/auth/newUsers.ts +99 -11
  366. package/src/config.ts +255 -3
  367. package/src/context.ts +26 -34
  368. package/src/generated/graphql-schemas/__mj.ts +22701 -18838
  369. package/src/generic/OrphanedConversationDetailReconciler.ts +3 -3
  370. package/src/generic/ResolverBase.ts +210 -36
  371. package/src/generic/RunViewResolver.ts +37 -2
  372. package/src/index.ts +236 -170
  373. package/src/isolatedProvider.ts +22 -0
  374. package/src/postgresqlCompat.ts +21 -0
  375. package/src/postgresqlPoolSettings.ts +213 -0
  376. package/src/realtimeProxy/RealtimeProxyServer.ts +148 -16
  377. package/src/realtimeProxy/RealtimeRelayTunnel.ts +645 -0
  378. package/src/realtimeSessions/README.md +179 -0
  379. package/src/realtimeSessions/RealtimeSessionEventService.ts +274 -0
  380. package/src/realtimeSessions/RealtimeSessionVerificationService.ts +167 -0
  381. package/src/realtimeSessions/RealtimeVerifyRouter.ts +108 -0
  382. package/src/realtimeSessions/SessionVerificationPortsBase.ts +189 -0
  383. package/src/realtimeSessions/SlidingWindowRateLimiter.ts +92 -0
  384. package/src/realtimeSessions/index.ts +16 -0
  385. package/src/realtimeSessions/sessionAccess.ts +141 -0
  386. package/src/realtimeSessions/sessionConfigStamps.ts +123 -0
  387. package/src/realtimeSessions/subscriptionAuthorization.ts +116 -0
  388. package/src/realtimeSessions/verificationCore.ts +502 -0
  389. package/src/realtimeSessions/verificationPages.ts +149 -0
  390. package/src/realtimeSessions/verificationPolicy.ts +321 -0
  391. package/src/realtimeSessions/verificationWorkflow.ts +702 -0
  392. package/src/realtimeWidget/widgetGuestElevation.ts +34 -2
  393. package/src/resolvers/ActionResolver.ts +84 -21
  394. package/src/resolvers/AdhocQueryResolver.ts +105 -187
  395. package/src/resolvers/CacheStatsResolver.ts +89 -2
  396. package/src/resolvers/ClientToolRequestResolver.ts +25 -7
  397. package/src/resolvers/EntityRecordNameResolver.ts +9 -51
  398. package/src/resolvers/FetchEntityVectorsResolver.ts +97 -2
  399. package/src/resolvers/GetDataResolver.ts +10 -0
  400. package/src/resolvers/HumanHandoffResolver.ts +312 -0
  401. package/src/resolvers/MCPResolver.ts +8 -5
  402. package/src/resolvers/MeetingResolver.ts +438 -0
  403. package/src/resolvers/RealtimeBridgeResolver.ts +385 -19
  404. package/src/resolvers/RealtimeClientSessionResolver.ts +503 -344
  405. package/src/resolvers/RealtimeSessionEventsResolver.ts +133 -0
  406. package/src/resolvers/RealtimeSessionVerificationResolver.ts +174 -0
  407. package/src/resolvers/RemoteBrowserActionResolver.ts +11 -1
  408. package/src/resolvers/RunAIAgentResolver.ts +78 -11
  409. package/src/resolvers/RunTemplateResolver.ts +13 -12
  410. package/src/resolvers/SyncDataResolver.ts +6 -2
  411. package/src/resolvers/SyncRolesUsersResolver.ts +24 -6
  412. package/src/resolvers/UserAvatarResolver.ts +111 -0
  413. package/src/resolvers/UserResolver.ts +2 -16
  414. package/src/resolvers/adhocTimeout.ts +12 -0
  415. package/src/resolvers/agentVisionConsentAudit.ts +82 -0
  416. package/src/resolvers/avatarInputValidation.ts +123 -0
  417. package/src/resolvers/currentUserRoles.ts +32 -1
  418. package/src/resolvers/meetings/index.ts +4 -0
  419. package/src/resolvers/meetings/meetingHelpers.ts +307 -0
  420. package/src/resolvers/meetings/meetingMutations.ts +556 -0
  421. package/src/resolvers/meetings/meetingQueries.ts +172 -0
  422. package/src/resolvers/meetings/meetingTypes.ts +238 -0
  423. package/src/rest/ViewOperationsHandler.ts +8 -5
  424. package/src/services/TaskGraphActionRunner.ts +29 -1
  425. package/src/services/TaskGraphContinuationDeliverer.ts +13 -7
  426. package/src/services/WorkQueueHostService.ts +129 -0
  427. package/src/services/workQueueConfig.ts +52 -0
  428. package/src/sharedCache.ts +302 -0
  429. package/src/types.ts +12 -0
  430. package/dist/resolvers/adhoc-query-helpers.d.ts +0 -33
  431. package/dist/resolvers/adhoc-query-helpers.d.ts.map +0 -1
  432. package/dist/resolvers/adhoc-query-helpers.js +0 -50
  433. package/dist/resolvers/adhoc-query-helpers.js.map +0 -1
  434. package/src/__tests__/adhoc-query-helpers.test.ts +0 -50
  435. package/src/resolvers/adhoc-query-helpers.ts +0 -67
@@ -1,5 +1,6 @@
1
- import { Field, Float, Int, ObjectType, Query, Resolver } from 'type-graphql';
2
- import { LocalCacheManager, CacheStats, CacheEntryType } from '@memberjunction/core';
1
+ import { Arg, Field, Float, Int, ObjectType, Query, Resolver } from 'type-graphql';
2
+ import { BaseEngine, BaseEngineRegistry, LocalCacheManager, CacheStats, CacheEntryType } from '@memberjunction/core';
3
+ import type { EngineStateCensus } from '@memberjunction/core';
3
4
  import { RequireSystemUser } from '../directives/index.js';
4
5
 
5
6
  // ============================================================================
@@ -66,10 +67,83 @@ class CacheStatsDetailGQL extends CacheStatsGQL {
66
67
  EntityBreakdown: CacheEntityBreakdownGQL[];
67
68
  }
68
69
 
70
+ @ObjectType()
71
+ class EnginePropertyCensusGQL {
72
+ @Field(() => String)
73
+ PropertyName: string;
74
+
75
+ @Field(() => String, { nullable: true })
76
+ EntityName?: string;
77
+
78
+ @Field(() => String, { nullable: true })
79
+ DatasetName?: string;
80
+
81
+ @Field(() => Int)
82
+ RowCount: number;
83
+
84
+ @Field(() => String, { nullable: true })
85
+ MaxUpdatedAt: string | null;
86
+
87
+ @Field(() => String, { nullable: true })
88
+ IdentityHash: string | null;
89
+
90
+ @Field(() => Boolean)
91
+ LoadedSuccessfully: boolean;
92
+
93
+ @Field(() => Boolean)
94
+ PermissionDenied: boolean;
95
+ }
96
+
97
+ @ObjectType()
98
+ class EngineDerivedCountGQL {
99
+ @Field(() => String)
100
+ Name: string;
101
+
102
+ @Field(() => Int)
103
+ Value: number;
104
+ }
105
+
106
+ @ObjectType()
107
+ class EngineStateCensusGQL {
108
+ @Field(() => String)
109
+ EngineClass: string;
110
+
111
+ @Field(() => Boolean)
112
+ Loaded: boolean;
113
+
114
+ @Field(() => Boolean)
115
+ PermissionConstrained: boolean;
116
+
117
+ @Field(() => [EnginePropertyCensusGQL])
118
+ Properties: EnginePropertyCensusGQL[];
119
+
120
+ @Field(() => [EngineDerivedCountGQL])
121
+ Derived: EngineDerivedCountGQL[];
122
+ }
123
+
69
124
  // ============================================================================
70
125
  // Helpers (pure core)
71
126
  // ============================================================================
72
127
 
128
+ function censusToGQL(census: EngineStateCensus): EngineStateCensusGQL {
129
+ const gql = new EngineStateCensusGQL();
130
+ gql.EngineClass = census.EngineClass;
131
+ gql.Loaded = census.Loaded;
132
+ gql.PermissionConstrained = census.PermissionConstrained;
133
+ gql.Properties = census.Properties.map(p => Object.assign(new EnginePropertyCensusGQL(), p));
134
+ gql.Derived = Object.entries(census.Derived).map(([Name, Value]) => Object.assign(new EngineDerivedCountGQL(), { Name, Value }));
135
+ return gql;
136
+ }
137
+
138
+ /** Census of every registered engine in this process, optionally narrowed to one class name. */
139
+ function buildEngineCensus(engineClass?: string): EngineStateCensusGQL[] {
140
+ return BaseEngineRegistry.Instance.GetAllEngines()
141
+ .filter((engine): engine is BaseEngine<unknown> => engine instanceof BaseEngine)
142
+ .filter(engine => !engineClass || engine.constructor.name === engineClass)
143
+ .map(engine => censusToGQL(engine.GetStateCensus()))
144
+ .sort((a, b) => a.EngineClass.localeCompare(b.EngineClass));
145
+ }
146
+
73
147
  function toGQL(stats: CacheStats): CacheStatsGQL {
74
148
  const gql = new CacheStatsGQL();
75
149
  gql.TotalEntries = stats.totalEntries;
@@ -139,4 +213,17 @@ export class CacheStatsResolver {
139
213
  result.EntityBreakdown = buildEntityBreakdown();
140
214
  return result;
141
215
  }
216
+
217
+ /**
218
+ * What each engine in this server process holds — row counts, newest timestamps, a row-version
219
+ * hash, and engine-specific derived-state counts. Comparing the hashes across servers shows
220
+ * whether they converged; a derived count of zero next to a full array shows lost derived state.
221
+ */
222
+ @RequireSystemUser()
223
+ @Query(() => [EngineStateCensusGQL])
224
+ EngineStateCensus(
225
+ @Arg('EngineClass', () => String, { nullable: true }) engineClass?: string
226
+ ): EngineStateCensusGQL[] {
227
+ return buildEngineCensus(engineClass);
228
+ }
142
229
  }
@@ -14,6 +14,7 @@ import { AppContext } from '../types.js';
14
14
  import { LogStatus, LogError } from '@memberjunction/core';
15
15
  import { ResolverBase } from '../generic/ResolverBase.js';
16
16
  import { ClientToolRequestManager, CLIENT_TOOL_REQUEST_TOPIC, ClientToolRequestNotificationPayload } from '@memberjunction/ai-agents';
17
+ import { ParseClientToolMedia } from '@memberjunction/ai-core-plus';
17
18
 
18
19
  @ObjectType()
19
20
  export class ClientToolRequestNotification {
@@ -71,7 +72,9 @@ export class ClientToolRequestResolver extends ResolverBase {
71
72
  /**
72
73
  * Client sends the result of executing a client tool back to the server.
73
74
  * This resolves the pending Promise in ClientToolRequestManager so the
74
- * agent loop can continue.
75
+ * agent loop can continue. `media` is an optional JSON array of images.
76
+ * When `media` fails validation or `result` is not valid JSON, the request
77
+ * resolves as a failed result.
75
78
  */
76
79
  @Mutation(() => Boolean)
77
80
  async RespondToClientToolRequest(
@@ -79,15 +82,25 @@ export class ClientToolRequestResolver extends ResolverBase {
79
82
  @Arg('success') success: boolean,
80
83
  @Arg('result', { nullable: true }) result: string | undefined,
81
84
  @Arg('errorMessage', { nullable: true }) errorMessage: string | undefined,
85
+ @Arg('media', { nullable: true }) media: string | undefined,
82
86
  @Ctx() _context: AppContext = {} as AppContext
83
87
  ): Promise<boolean> {
84
88
  try {
85
- const found = ClientToolRequestManager.Instance.ReceiveResponse({
86
- RequestID: requestID,
87
- Success: success,
88
- Result: result ? JSON.parse(result) : undefined,
89
- ErrorMessage: errorMessage
90
- });
89
+ const parsedMedia = ParseClientToolMedia(media);
90
+ // `=== true` narrows the union; this package compiles without strictNullChecks.
91
+ const found = ClientToolRequestManager.Instance.ReceiveResponse(parsedMedia.ok === true
92
+ ? {
93
+ RequestID: requestID,
94
+ Success: success,
95
+ Result: result ? JSON.parse(result) : undefined,
96
+ ErrorMessage: errorMessage,
97
+ Media: parsedMedia.media.length ? parsedMedia.media : undefined
98
+ }
99
+ : {
100
+ RequestID: requestID,
101
+ Success: false,
102
+ ErrorMessage: `Client tool media rejected: ${parsedMedia.error}`
103
+ });
91
104
 
92
105
  if (!found) {
93
106
  LogError(`RespondToClientToolRequest: no pending request for ${requestID} (may have timed out)`);
@@ -96,6 +109,11 @@ export class ClientToolRequestResolver extends ResolverBase {
96
109
  } catch (error) {
97
110
  const msg = error instanceof Error ? error.message : String(error);
98
111
  LogError(`RespondToClientToolRequest error: ${msg}`);
112
+ ClientToolRequestManager.Instance.ReceiveResponse({
113
+ RequestID: requestID,
114
+ Success: false,
115
+ ErrorMessage: `Client tool response rejected: ${msg}`
116
+ });
99
117
  return false;
100
118
  }
101
119
  }
@@ -1,4 +1,4 @@
1
- import { CompositeKey, DatabaseProviderBase, EntityInfo, LogDebug, UserInfo } from '@memberjunction/core';
1
+ import { CompositeKey, DatabaseProviderBase } from '@memberjunction/core';
2
2
  import { Arg, Ctx, Field, InputType, ObjectType, Query, Resolver } from 'type-graphql';
3
3
  import { AppContext, UserPayload } from '../types.js';
4
4
  import { CompositeKeyInputType, CompositeKeyOutputType } from '../generic/KeyInputOutputTypes.js';
@@ -36,20 +36,13 @@ export class EntityRecordNameResult {
36
36
  * Resolves a record's display NAME from its primary key — the lookup behind every foreign-key
37
37
  * link, breadcrumb and picker label in the UI.
38
38
  *
39
- * **This is a read of entity data and is gated like one.** It historically took no user context
40
- * at all, which made it an open side channel: a caller denied READ on an entity's name field
41
- * could still obtain that name here, because the name never travelled through the resolver that
42
- * strips denied fields. Field-level security turned that latent gap into a live bypass — the
43
- * form-field FK control falls through to this query precisely WHEN the joined display column is
44
- * denied, so the one case the fallback exists for was the case that leaked.
39
+ * Entity-level read permission is checked here ({@link ResolverBase.CheckUserReadPermissions}).
40
+ * Field- and row-level security are applied by the provider's lookup, for the acting user passed
41
+ * to it: when any field the name is built from is withheld, it answers with no name.
45
42
  *
46
- * Two gates now apply, matching what the generated single-record resolvers do:
47
- * 1. entity-level read permission ({@link ResolverBase.CheckUserReadPermissions});
48
- * 2. field-level read permission on the entity's own name field.
49
- *
50
- * A field-level denial answers `Success: false` with no name rather than throwing. Callers
51
- * already treat "no name" as "show the primary key", which is the intended degradation — and it
52
- * keeps this query from becoming a probe that distinguishes "restricted" from "missing".
43
+ * A withheld name answers `Success: false` with the same status as a record that does not exist.
44
+ * Callers already treat "no name" as "show the primary key", and the identical answer keeps this
45
+ * query from becoming a probe that distinguishes "restricted" from "missing".
53
46
  */
54
47
  @Resolver(EntityRecordNameResult)
55
48
  export class EntityRecordNameResolver extends ResolverBase {
@@ -91,53 +84,18 @@ export class EntityRecordNameResolver extends ResolverBase {
91
84
  const e = md.Entities.find((e) => e.Name === EntityName);
92
85
  if (e) {
93
86
  const contextUser = userPayload ? this.GetUserFromPayload(userPayload) : undefined;
94
- if (this.IsNameFieldDeniedToUser(e, contextUser)) {
95
- LogDebug(
96
- `[FieldSecurity] Suppressed GetEntityRecordName for '${EntityName}': ` +
97
- `the name field is not readable by this user`
98
- );
99
- return {
100
- Success: false,
101
- Status: `Name for record, or record ${pk.ToString()} itself not found, could be an access issue`,
102
- CompositeKey: pk,
103
- EntityName,
104
- };
105
- }
106
- // Pass the acting user through: the provider signature accepts it, and omitting it ran the
107
- // underlying lookup with no identity at all — so row-level security had nothing to filter on
108
- // either. The field-level gate above is the column half; this is the row half.
87
+ // The acting user is what field- and row-level security are applied for.
109
88
  const recordName = await md.GetEntityRecordName(e.Name, pk, contextUser);
110
89
  if (recordName) return { Success: true, Status: 'OK', CompositeKey: pk, RecordName: recordName, EntityName };
111
90
  else
112
91
  return {
113
92
  Success: false,
114
- Status: `Name for record, or record ${pk.ToString()} itself not found, could be an access issue if user doesn't have Row Level Access (RLS) if RLS is enabled for this entity`,
93
+ Status: `Name for record, or record ${pk.ToString()} itself not found, could be an access issue`,
115
94
  CompositeKey: pk,
116
95
  EntityName,
117
96
  };
118
97
  } else return { Success: false, Status: `Entity ${EntityName} not found`, CompositeKey: pk, EntityName };
119
98
  }
120
-
121
- /**
122
- * Whether field security withholds this entity's NAME field from the user.
123
- *
124
- * Resolves the name field the same way the provider's own lookup does — the designated
125
- * `IsNameField`, else a field literally called `Name` — so the check cannot drift from the
126
- * value it is guarding. Fails OPEN only where field security does not apply at all (flag off,
127
- * no user, no name field), matching every other FLS gate.
128
- */
129
- protected IsNameFieldDeniedToUser(entity: EntityInfo, contextUser?: UserInfo): boolean {
130
- if (!entity?.EnableFieldLevelSecurity || !contextUser) {
131
- return false;
132
- }
133
- const nameField =
134
- entity.Fields?.find(f => f.IsNameField) ??
135
- entity.Fields?.find(f => f.Name?.trim().toLowerCase() === 'name');
136
- if (!nameField) {
137
- return false;
138
- }
139
- return entity.GetDeniedReadFields(contextUser).has(nameField.Name.trim().toLowerCase());
140
- }
141
99
  }
142
100
 
143
101
  export default EntityRecordNameResolver;
@@ -1,8 +1,9 @@
1
1
  import { Resolver, Query, Arg, Ctx, ObjectType, Field, Float, Int } from 'type-graphql';
2
2
  import { AppContext } from '../types.js';
3
- import { LogError, LogStatus, Metadata, RunView, UserInfo } from '@memberjunction/core';
3
+ import { CompositeKey, EntityInfo, IMetadataProvider, LogError, LogStatus, Metadata, RunView, UserInfo } from '@memberjunction/core';
4
4
  import { MJEntityDocumentEntity, MJVectorIndexEntity, MJVectorDatabaseEntity } from '@memberjunction/core-entities';
5
5
  import { ResolverBase } from '../generic/ResolverBase.js';
6
+ import { GetReadOnlyProvider } from '../util.js';
6
7
  import { GetAIAPIKey } from '@memberjunction/ai';
7
8
  import { VectorDBBase } from '@memberjunction/ai-vectordb';
8
9
  import { AIEngine } from '@memberjunction/aiengine';
@@ -50,7 +51,7 @@ export class FetchEntityVectorsResolver extends ResolverBase {
50
51
  @Arg('entityDocumentID') entityDocumentID: string,
51
52
  @Arg('maxRecords', () => Int, { nullable: true }) maxRecords: number | undefined,
52
53
  @Arg('filter', { nullable: true }) filter: string | undefined,
53
- @Ctx() { userPayload }: AppContext = {} as AppContext
54
+ @Ctx() { userPayload, providers }: AppContext = {} as AppContext
54
55
  ): Promise<FetchEntityVectorsResult> {
55
56
  const startTime = Date.now();
56
57
  try {
@@ -85,6 +86,17 @@ export class FetchEntityVectorsResolver extends ResolverBase {
85
86
  );
86
87
  }
87
88
 
89
+ // Providers that keep their vectors in MJ, keyed by EntityDocumentID (the in-process
90
+ // SimpleVectorServiceProvider), can't be listed through QueryIndex: they key by the
91
+ // document ID rather than the index name, aren't handed the context user, and return
92
+ // matches without vector values. Read the stored Entity Record Document rows instead.
93
+ if (vectorDBInstance.QueryKeyIsEntityDocumentID) {
94
+ const md = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true }) ?? Metadata.Provider;
95
+ const results = await this.fetchStoredVectors(entityDoc, limit, filter, currentUser, md);
96
+ LogStatus(`FetchEntityVectors: Loaded ${results.length} stored vectors for entity "${entityDoc.Entity}" in ${Date.now() - startTime}ms`);
97
+ return { Success: true, Results: results, TotalCount: results.length, ElapsedMs: Date.now() - startTime };
98
+ }
99
+
88
100
  // Step 4: Query with zero vector + Entity metadata filter.
89
101
  // Pinecone's list API doesn't support metadata filtering, but query does.
90
102
  // A zero vector returns results in arbitrary order (similarity is meaningless),
@@ -227,6 +239,89 @@ export class FetchEntityVectorsResolver extends ResolverBase {
227
239
  return instance;
228
240
  }
229
241
 
242
+ /**
243
+ * Load the vectors an EntityDocument stored in MJ (`MJ: Entity Record Documents.VectorJSON`),
244
+ * restricted to the entity records that pass `filter`. Each item's metadata carries the entity
245
+ * name, the record ID and the record's name fields, which is what the cluster view labels from.
246
+ */
247
+ private async fetchStoredVectors(
248
+ entityDoc: MJEntityDocumentEntity,
249
+ limit: number,
250
+ filter: string | undefined,
251
+ contextUser: UserInfo,
252
+ md: IMetadataProvider
253
+ ): Promise<EntityVectorItem[]> {
254
+ const entityInfo = md.EntityByName(entityDoc.Entity);
255
+ if (!entityInfo) {
256
+ throw new Error(`Entity "${entityDoc.Entity}" not found in metadata`);
257
+ }
258
+ const labelsByRecordID = await this.loadRecordLabels(entityInfo, filter, contextUser);
259
+
260
+ const rv = new RunView();
261
+ const docResult = await rv.RunView<{ ID: string; RecordID: string; VectorJSON: string }>({
262
+ EntityName: 'MJ: Entity Record Documents',
263
+ ExtraFilter: `EntityDocumentID='${EscapeSQLString(entityDoc.ID)}' AND VectorJSON IS NOT NULL`,
264
+ Fields: ['ID', 'RecordID', 'VectorJSON'],
265
+ IgnoreMaxRows: true,
266
+ ResultType: 'simple',
267
+ }, contextUser);
268
+ if (!docResult.Success) {
269
+ throw new Error(`Failed to load stored vectors: ${docResult.ErrorMessage}`);
270
+ }
271
+
272
+ const results: EntityVectorItem[] = [];
273
+ for (const row of docResult.Results) {
274
+ const labels = labelsByRecordID.get(row.RecordID.toLowerCase());
275
+ if (!labels) continue; // filtered out, not readable by this user, or the record no longer exists
276
+ results.push({
277
+ ID: row.ID,
278
+ Values: JSON.parse(row.VectorJSON) as number[],
279
+ Metadata: JSON.stringify({ Entity: entityDoc.Entity, RecordID: row.RecordID, ...labels }),
280
+ });
281
+ if (results.length >= limit) break;
282
+ }
283
+ return results;
284
+ }
285
+
286
+ /**
287
+ * Map each record that passes `filter` to its name-field values, keyed by the same compact
288
+ * record-ID form the vector sync writes to `MJ: Entity Record Documents.RecordID` (lower-cased).
289
+ */
290
+ private async loadRecordLabels(
291
+ entityInfo: EntityInfo,
292
+ filter: string | undefined,
293
+ contextUser: UserInfo
294
+ ): Promise<Map<string, Record<string, string>>> {
295
+ const nameFields = entityInfo.Fields.filter(f => f.IsNameField).map(f => f.Name);
296
+ if (nameFields.length === 0 && entityInfo.NameField) {
297
+ nameFields.push(entityInfo.NameField.Name);
298
+ }
299
+ const keyFields = entityInfo.PrimaryKeys.map(pk => pk.Name);
300
+
301
+ const rv = new RunView();
302
+ const result = await rv.RunView<Record<string, unknown>>({
303
+ EntityName: entityInfo.Name,
304
+ ExtraFilter: filter || undefined,
305
+ Fields: [...new Set([...keyFields, ...nameFields])],
306
+ IgnoreMaxRows: true,
307
+ ResultType: 'simple',
308
+ }, contextUser);
309
+ if (!result.Success) {
310
+ throw new Error(`Failed to load "${entityInfo.Name}" records: ${result.ErrorMessage}`);
311
+ }
312
+
313
+ const map = new Map<string, Record<string, string>>();
314
+ for (const row of result.Results) {
315
+ const key = CompositeKey.FromEntityRecord(entityInfo, row).ToCompactURLSegment().toLowerCase();
316
+ const labels: Record<string, string> = {};
317
+ for (const name of nameFields) {
318
+ if (row[name] != null) labels[name] = String(row[name]);
319
+ }
320
+ map.set(key, labels);
321
+ }
322
+ return map;
323
+ }
324
+
230
325
  private errorResult(message: string, startTime: number): FetchEntityVectorsResult {
231
326
  return {
232
327
  Success: false,
@@ -1,4 +1,5 @@
1
1
  import { Arg, Ctx, Field, InputType, ObjectType, Query } from 'type-graphql';
2
+ import { SQLExpressionValidator } from '@memberjunction/global';
2
3
  import { AppContext } from '../types.js';
3
4
  import { LogError, LogStatus, LogStatusEx, Metadata } from '@memberjunction/core';
4
5
  import { QueryCompositionEngine } from '@memberjunction/generic-database-provider';
@@ -154,6 +155,15 @@ export class GetDataResolver {
154
155
  resolvedSQL = compositionResult.ResolvedSQL;
155
156
  }
156
157
 
158
+ // Defense-in-depth: even system-token holders get SELECT-only SQL here.
159
+ // The read-only pool is the primary control, but if it is ever
160
+ // misconfigured to a read-write login this validator still refuses DML/DDL
161
+ // (mirrors AdhocQueryResolver).
162
+ const validation = SQLExpressionValidator.Instance.validateFullQuery(resolvedSQL);
163
+ if (!validation.valid) {
164
+ return { result: null, error: validation.error || 'SQL validation failed' };
165
+ }
166
+
157
167
  const request = new sql.Request(readOnlyDataSource);
158
168
  const result = await request.query(resolvedSQL);
159
169
  return { result: result.recordset, error: null };