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

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 (560) hide show
  1. package/README.md +47 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentSessions/SessionJanitor.d.ts +91 -30
  4. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  5. package/dist/agentSessions/SessionJanitor.js +311 -81
  6. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  7. package/dist/agentSessions/SessionManager.d.ts +17 -3
  8. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  9. package/dist/agentSessions/SessionManager.js +44 -10
  10. package/dist/agentSessions/SessionManager.js.map +1 -1
  11. package/dist/apiRoot.d.ts +32 -0
  12. package/dist/apiRoot.d.ts.map +1 -0
  13. package/dist/apiRoot.js +67 -0
  14. package/dist/apiRoot.js.map +1 -0
  15. package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
  16. package/dist/auth/AuthProviderCatalogRouter.js +27 -0
  17. package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
  18. package/dist/auth/LoginScreenEngine.d.ts +22 -0
  19. package/dist/auth/LoginScreenEngine.d.ts.map +1 -0
  20. package/dist/auth/LoginScreenEngine.js +57 -0
  21. package/dist/auth/LoginScreenEngine.js.map +1 -0
  22. package/dist/auth/index.d.ts +1 -0
  23. package/dist/auth/index.d.ts.map +1 -1
  24. package/dist/auth/index.js +52 -10
  25. package/dist/auth/index.js.map +1 -1
  26. package/dist/auth/initializeProviders.d.ts +10 -0
  27. package/dist/auth/initializeProviders.d.ts.map +1 -1
  28. package/dist/auth/initializeProviders.js +37 -1
  29. package/dist/auth/initializeProviders.js.map +1 -1
  30. package/dist/auth/localDevAuth.d.ts +79 -0
  31. package/dist/auth/localDevAuth.d.ts.map +1 -0
  32. package/dist/auth/localDevAuth.js +439 -0
  33. package/dist/auth/localDevAuth.js.map +1 -0
  34. package/dist/auth/magicLink/MagicLinkKeys.d.ts +2 -2
  35. package/dist/auth/magicLink/MagicLinkKeys.d.ts.map +1 -1
  36. package/dist/auth/magicLink/MagicLinkKeys.js +1 -1
  37. package/dist/auth/magicLink/MagicLinkKeys.js.map +1 -1
  38. package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
  39. package/dist/auth/magicLink/MagicLinkRouter.js +3 -2
  40. package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
  41. package/dist/auth/magicLink/types.d.ts +12 -0
  42. package/dist/auth/magicLink/types.d.ts.map +1 -1
  43. package/dist/auth/sessionUserClone.d.ts +1 -1
  44. package/dist/auth/sessionUserClone.d.ts.map +1 -1
  45. package/dist/auth/sessionUserClone.js +3 -2
  46. package/dist/auth/sessionUserClone.js.map +1 -1
  47. package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts +292 -0
  48. package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts.map +1 -0
  49. package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js +442 -0
  50. package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js.map +1 -0
  51. package/dist/broadcast/index.d.ts +6 -0
  52. package/dist/broadcast/index.d.ts.map +1 -0
  53. package/dist/broadcast/index.js +6 -0
  54. package/dist/broadcast/index.js.map +1 -0
  55. package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.d.ts +43 -0
  56. package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.d.ts.map +1 -0
  57. package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.js +144 -0
  58. package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.js.map +1 -0
  59. package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.d.ts +46 -0
  60. package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.d.ts.map +1 -0
  61. package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.js +149 -0
  62. package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.js.map +1 -0
  63. package/dist/broadcast/providers/GCPPubSubBroadcastProvider.d.ts +49 -0
  64. package/dist/broadcast/providers/GCPPubSubBroadcastProvider.d.ts.map +1 -0
  65. package/dist/broadcast/providers/GCPPubSubBroadcastProvider.js +131 -0
  66. package/dist/broadcast/providers/GCPPubSubBroadcastProvider.js.map +1 -0
  67. package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.d.ts +24 -0
  68. package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.d.ts.map +1 -0
  69. package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.js +51 -0
  70. package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.js.map +1 -0
  71. package/dist/cache.d.ts +3 -2
  72. package/dist/cache.d.ts.map +1 -1
  73. package/dist/cache.js.map +1 -1
  74. package/dist/config.d.ts +632 -22
  75. package/dist/config.d.ts.map +1 -1
  76. package/dist/config.js +104 -4
  77. package/dist/config.js.map +1 -1
  78. package/dist/context.d.ts +3 -1
  79. package/dist/context.d.ts.map +1 -1
  80. package/dist/context.js +29 -8
  81. package/dist/context.js.map +1 -1
  82. package/dist/coreRoutes.d.ts +29 -0
  83. package/dist/coreRoutes.d.ts.map +1 -0
  84. package/dist/coreRoutes.js +156 -0
  85. package/dist/coreRoutes.js.map +1 -0
  86. package/dist/generated/graphql-schemas/__mj.d.ts +1016 -29
  87. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  88. package/dist/generated/graphql-schemas/__mj.js +5125 -434
  89. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  90. package/dist/generic/CacheInvalidationResolver.d.ts +85 -30
  91. package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
  92. package/dist/generic/CacheInvalidationResolver.js +175 -60
  93. package/dist/generic/CacheInvalidationResolver.js.map +1 -1
  94. package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -1
  95. package/dist/generic/OrphanedConversationDetailReconciler.js +2 -0
  96. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
  97. package/dist/generic/PubSubManager.d.ts +10 -0
  98. package/dist/generic/PubSubManager.d.ts.map +1 -1
  99. package/dist/generic/PubSubManager.js +44 -1
  100. package/dist/generic/PubSubManager.js.map +1 -1
  101. package/dist/generic/PushStatusResolver.d.ts +39 -6
  102. package/dist/generic/PushStatusResolver.d.ts.map +1 -1
  103. package/dist/generic/PushStatusResolver.js +94 -12
  104. package/dist/generic/PushStatusResolver.js.map +1 -1
  105. package/dist/generic/ResolverBase.d.ts +168 -69
  106. package/dist/generic/ResolverBase.d.ts.map +1 -1
  107. package/dist/generic/ResolverBase.js +464 -405
  108. package/dist/generic/ResolverBase.js.map +1 -1
  109. package/dist/generic/RunViewResolver.d.ts +11 -3
  110. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  111. package/dist/generic/RunViewResolver.js +91 -13
  112. package/dist/generic/RunViewResolver.js.map +1 -1
  113. package/dist/generic/actionOutputFieldSecurity.d.ts +26 -0
  114. package/dist/generic/actionOutputFieldSecurity.d.ts.map +1 -0
  115. package/dist/generic/actionOutputFieldSecurity.js +47 -0
  116. package/dist/generic/actionOutputFieldSecurity.js.map +1 -0
  117. package/dist/generic/fieldSecurityTransport.d.ts +30 -0
  118. package/dist/generic/fieldSecurityTransport.d.ts.map +1 -0
  119. package/dist/generic/fieldSecurityTransport.js +30 -0
  120. package/dist/generic/fieldSecurityTransport.js.map +1 -0
  121. package/dist/globalCors.d.ts +33 -0
  122. package/dist/globalCors.d.ts.map +1 -0
  123. package/dist/globalCors.js +58 -0
  124. package/dist/globalCors.js.map +1 -0
  125. package/dist/index.d.ts +14 -0
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +230 -222
  128. package/dist/index.js.map +1 -1
  129. package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
  130. package/dist/integration/CustomColumnPromoter.js +6 -1
  131. package/dist/integration/CustomColumnPromoter.js.map +1 -1
  132. package/dist/logging/variablesLoggingMiddleware.d.ts +12 -0
  133. package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
  134. package/dist/logging/variablesLoggingMiddleware.js +50 -1
  135. package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
  136. package/dist/multiTenancy/index.d.ts.map +1 -1
  137. package/dist/multiTenancy/index.js +22 -2
  138. package/dist/multiTenancy/index.js.map +1 -1
  139. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -1
  140. package/dist/realtimeSessions/RealtimeSessionVerificationService.js +2 -1
  141. package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -1
  142. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -1
  143. package/dist/realtimeSessions/RealtimeVerifyRouter.js +2 -1
  144. package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -1
  145. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts +100 -0
  146. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts.map +1 -0
  147. package/dist/realtimeSessions/RecordingAssemblyScheduler.js +173 -0
  148. package/dist/realtimeSessions/RecordingAssemblyScheduler.js.map +1 -0
  149. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -1
  150. package/dist/realtimeSessions/SessionVerificationPortsBase.js +1 -0
  151. package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -1
  152. package/dist/realtimeSessions/index.d.ts +2 -0
  153. package/dist/realtimeSessions/index.d.ts.map +1 -1
  154. package/dist/realtimeSessions/index.js +2 -0
  155. package/dist/realtimeSessions/index.js.map +1 -1
  156. package/dist/realtimeSessions/ownedRealtimeSession.d.ts +32 -0
  157. package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -0
  158. package/dist/realtimeSessions/ownedRealtimeSession.js +56 -0
  159. package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -0
  160. package/dist/realtimeSessions/sessionAccess.d.ts +91 -8
  161. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
  162. package/dist/realtimeSessions/sessionAccess.js +127 -20
  163. package/dist/realtimeSessions/sessionAccess.js.map +1 -1
  164. package/dist/realtimeSessions/sessionConfigStamps.js +1 -1
  165. package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -1
  166. package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -1
  167. package/dist/realtimeSessions/subscriptionAuthorization.js +5 -2
  168. package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -1
  169. package/dist/realtimeSessions/verificationWorkflow.d.ts +2 -0
  170. package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -1
  171. package/dist/realtimeSessions/verificationWorkflow.js +1 -1
  172. package/dist/realtimeSessions/verificationWorkflow.js.map +1 -1
  173. package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
  174. package/dist/realtimeWidget/WidgetRouter.js +19 -3
  175. package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
  176. package/dist/realtimeWidget/WidgetSessionService.d.ts +67 -7
  177. package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -1
  178. package/dist/realtimeWidget/WidgetSessionService.js +201 -19
  179. package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
  180. package/dist/realtimeWidget/host-identity.d.ts +1 -1
  181. package/dist/realtimeWidget/host-identity.js +1 -1
  182. package/dist/realtimeWidget/widgetCore.d.ts +20 -1
  183. package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
  184. package/dist/realtimeWidget/widgetCore.js +17 -1
  185. package/dist/realtimeWidget/widgetCore.js.map +1 -1
  186. package/dist/realtimeWidget/widgetGuestElevation.d.ts +1 -1
  187. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  188. package/dist/realtimeWidget/widgetGuestElevation.js +2 -1
  189. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  190. package/dist/resolvers/ActionResolver.d.ts +19 -1
  191. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  192. package/dist/resolvers/ActionResolver.js +63 -12
  193. package/dist/resolvers/ActionResolver.js.map +1 -1
  194. package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
  195. package/dist/resolvers/AdhocQueryResolver.js +1 -0
  196. package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
  197. package/dist/resolvers/AgentRunStatusPublisher.d.ts +18 -4
  198. package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -1
  199. package/dist/resolvers/AgentRunStatusPublisher.js +32 -8
  200. package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -1
  201. package/dist/resolvers/AgentSessionResolver.d.ts +10 -4
  202. package/dist/resolvers/AgentSessionResolver.d.ts.map +1 -1
  203. package/dist/resolvers/AgentSessionResolver.js +40 -17
  204. package/dist/resolvers/AgentSessionResolver.js.map +1 -1
  205. package/dist/resolvers/ArtifactFileResolver.d.ts +5 -1
  206. package/dist/resolvers/ArtifactFileResolver.d.ts.map +1 -1
  207. package/dist/resolvers/ArtifactFileResolver.js +9 -7
  208. package/dist/resolvers/ArtifactFileResolver.js.map +1 -1
  209. package/dist/resolvers/ConversationRunEventsResolver.d.ts +8 -4
  210. package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
  211. package/dist/resolvers/ConversationRunEventsResolver.js +6 -6
  212. package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
  213. package/dist/resolvers/DatasetResolver.d.ts +24 -3
  214. package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
  215. package/dist/resolvers/DatasetResolver.js +57 -8
  216. package/dist/resolvers/DatasetResolver.js.map +1 -1
  217. package/dist/resolvers/EntityCommunicationsResolver.d.ts +13 -1
  218. package/dist/resolvers/EntityCommunicationsResolver.d.ts.map +1 -1
  219. package/dist/resolvers/EntityCommunicationsResolver.js +50 -14
  220. package/dist/resolvers/EntityCommunicationsResolver.js.map +1 -1
  221. package/dist/resolvers/EntityRecordNameResolver.d.ts +2 -1
  222. package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
  223. package/dist/resolvers/EntityRecordNameResolver.js +3 -2
  224. package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
  225. package/dist/resolvers/FetchEntityVectorsResolver.d.ts +46 -3
  226. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  227. package/dist/resolvers/FetchEntityVectorsResolver.js +211 -50
  228. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  229. package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
  230. package/dist/resolvers/FileCategoryResolver.js +1 -0
  231. package/dist/resolvers/FileCategoryResolver.js.map +1 -1
  232. package/dist/resolvers/FileResolver.d.ts +87 -11
  233. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  234. package/dist/resolvers/FileResolver.js +292 -105
  235. package/dist/resolvers/FileResolver.js.map +1 -1
  236. package/dist/resolvers/GetDataContextDataResolver.d.ts +33 -7
  237. package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
  238. package/dist/resolvers/GetDataContextDataResolver.js +117 -38
  239. package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
  240. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  241. package/dist/resolvers/GetDataResolver.js +6 -3
  242. package/dist/resolvers/GetDataResolver.js.map +1 -1
  243. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  244. package/dist/resolvers/IntegrationDiscoveryResolver.js +49 -9
  245. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  246. package/dist/resolvers/MergeRecordsResolver.d.ts +8 -1
  247. package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
  248. package/dist/resolvers/MergeRecordsResolver.js +31 -3
  249. package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
  250. package/dist/resolvers/PipelineProgressResolver.d.ts +6 -0
  251. package/dist/resolvers/PipelineProgressResolver.d.ts.map +1 -1
  252. package/dist/resolvers/PipelineProgressResolver.js +5 -3
  253. package/dist/resolvers/PipelineProgressResolver.js.map +1 -1
  254. package/dist/resolvers/QueryResolver.d.ts +2 -0
  255. package/dist/resolvers/QueryResolver.d.ts.map +1 -1
  256. package/dist/resolvers/QueryResolver.js +33 -6
  257. package/dist/resolvers/QueryResolver.js.map +1 -1
  258. package/dist/resolvers/QuerySystemUserResolver.d.ts +2 -0
  259. package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
  260. package/dist/resolvers/QuerySystemUserResolver.js +15 -6
  261. package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
  262. package/dist/resolvers/RSUResolver.d.ts.map +1 -1
  263. package/dist/resolvers/RSUResolver.js +12 -0
  264. package/dist/resolvers/RSUResolver.js.map +1 -1
  265. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +18 -10
  266. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  267. package/dist/resolvers/RealtimeClientSessionResolver.js +92 -54
  268. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  269. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  270. package/dist/resolvers/RemoteBrowserActionResolver.js +11 -9
  271. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  272. package/dist/resolvers/RunAIAgentResolver.d.ts +56 -8
  273. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  274. package/dist/resolvers/RunAIAgentResolver.js +241 -67
  275. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  276. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  277. package/dist/resolvers/RunTemplateResolver.js +4 -4
  278. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  279. package/dist/resolvers/RunTestResolver.d.ts.map +1 -1
  280. package/dist/resolvers/RunTestResolver.js +3 -1
  281. package/dist/resolvers/RunTestResolver.js.map +1 -1
  282. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts +12 -1
  283. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts.map +1 -1
  284. package/dist/resolvers/SearchKnowledgeStreamResolver.js +15 -2
  285. package/dist/resolvers/SearchKnowledgeStreamResolver.js.map +1 -1
  286. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  287. package/dist/resolvers/SqlLoggingConfigResolver.js +2 -3
  288. package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
  289. package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
  290. package/dist/resolvers/SyncDataResolver.js +4 -0
  291. package/dist/resolvers/SyncDataResolver.js.map +1 -1
  292. package/dist/resolvers/TaskGraphFrameResolver.d.ts +2 -1
  293. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
  294. package/dist/resolvers/TaskGraphFrameResolver.js +28 -1
  295. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
  296. package/dist/resolvers/TestQuerySQLResolver.d.ts +24 -0
  297. package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
  298. package/dist/resolvers/TestQuerySQLResolver.js +66 -13
  299. package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
  300. package/dist/resolvers/TransactionGroupResolver.d.ts +34 -2
  301. package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
  302. package/dist/resolvers/TransactionGroupResolver.js +150 -27
  303. package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
  304. package/dist/resolvers/UserViewResolver.d.ts +1 -1
  305. package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
  306. package/dist/resolvers/UserViewResolver.js +2 -1
  307. package/dist/resolvers/UserViewResolver.js.map +1 -1
  308. package/dist/resolvers/agent-run-data-guard.d.ts +31 -0
  309. package/dist/resolvers/agent-run-data-guard.d.ts.map +1 -0
  310. package/dist/resolvers/agent-run-data-guard.js +72 -0
  311. package/dist/resolvers/agent-run-data-guard.js.map +1 -0
  312. package/dist/rest/EntityCRUDHandler.d.ts +6 -0
  313. package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
  314. package/dist/rest/EntityCRUDHandler.js +19 -5
  315. package/dist/rest/EntityCRUDHandler.js.map +1 -1
  316. package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
  317. package/dist/rest/RESTEndpointHandler.js +8 -5
  318. package/dist/rest/RESTEndpointHandler.js.map +1 -1
  319. package/dist/rest/RealtimeRecordingHandler.d.ts +49 -0
  320. package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -0
  321. package/dist/rest/RealtimeRecordingHandler.js +383 -0
  322. package/dist/rest/RealtimeRecordingHandler.js.map +1 -0
  323. package/dist/rest/ViewOperationsHandler.d.ts +9 -1
  324. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  325. package/dist/rest/ViewOperationsHandler.js +43 -17
  326. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  327. package/dist/rest/setupRESTEndpoints.d.ts +6 -0
  328. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  329. package/dist/rest/setupRESTEndpoints.js +6 -0
  330. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  331. package/dist/serverExtensionReservedRoots.d.ts +12 -10
  332. package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
  333. package/dist/serverExtensionReservedRoots.js +14 -17
  334. package/dist/serverExtensionReservedRoots.js.map +1 -1
  335. package/dist/serverRoleConfigUnits.d.ts +29 -0
  336. package/dist/serverRoleConfigUnits.d.ts.map +1 -0
  337. package/dist/serverRoleConfigUnits.js +33 -0
  338. package/dist/serverRoleConfigUnits.js.map +1 -0
  339. package/dist/services/MJStorageBlobStore.d.ts +8 -1
  340. package/dist/services/MJStorageBlobStore.d.ts.map +1 -1
  341. package/dist/services/MJStorageBlobStore.js +25 -19
  342. package/dist/services/MJStorageBlobStore.js.map +1 -1
  343. package/dist/services/StartTaskGraphDispatcher.js +2 -2
  344. package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
  345. package/dist/services/TaskGraphActionRunner.d.ts +5 -3
  346. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  347. package/dist/services/TaskGraphActionRunner.js +27 -5
  348. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  349. package/dist/services/TaskGraphAgentRunner.d.ts +14 -2
  350. package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
  351. package/dist/services/TaskGraphAgentRunner.js +157 -9
  352. package/dist/services/TaskGraphAgentRunner.js.map +1 -1
  353. package/dist/services/TaskGraphContinuationDeliverer.d.ts +59 -2
  354. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  355. package/dist/services/TaskGraphContinuationDeliverer.js +626 -16
  356. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  357. package/dist/sharedCache.d.ts.map +1 -1
  358. package/dist/sharedCache.js +3 -0
  359. package/dist/sharedCache.js.map +1 -1
  360. package/dist/types.d.ts +23 -1
  361. package/dist/types.d.ts.map +1 -1
  362. package/dist/types.js.map +1 -1
  363. package/package.json +99 -98
  364. package/src/__tests__/ActionResolver.fieldSecurity.test.ts +237 -0
  365. package/src/__tests__/AdhocQueryResolver.dialect.test.ts +137 -0
  366. package/src/__tests__/AgentRunStatusPublisher.test.ts +49 -0
  367. package/src/__tests__/AgentSessionResolver.ownership.test.ts +137 -0
  368. package/src/__tests__/CustomColumnPromoterOnePass.test.ts +15 -1
  369. package/src/__tests__/DatasetResolver.itemFilters.test.ts +201 -0
  370. package/src/__tests__/EntityCommunicationsResolver.actingUser.test.ts +151 -0
  371. package/src/__tests__/EntityRecordNameResolver.rowSecurity.test.ts +152 -0
  372. package/src/__tests__/EvolutionActsOnWhatItDetects.test.ts +113 -0
  373. package/src/__tests__/FetchEntityVectorsResolver.test.ts +369 -18
  374. package/src/__tests__/FileResolver.fieldSecurity.test.ts +82 -0
  375. package/src/__tests__/FileResolver.storageAccess.test.ts +562 -0
  376. package/src/__tests__/GetDataContextDataResolver.sqlItems.test.ts +416 -0
  377. package/src/__tests__/ListOperationsResolver.adhocScreen.test.ts +137 -0
  378. package/src/__tests__/LoginScreenEngine.test.ts +86 -0
  379. package/src/__tests__/MJStorageBlobStore.storageGate.test.ts +63 -0
  380. package/src/__tests__/PipelineProgressResolver.filter.test.ts +58 -0
  381. package/src/__tests__/QuerySystemUserResolver.fieldSecurity.test.ts +49 -0
  382. package/src/__tests__/RESTEndpointHandler.test.ts +25 -0
  383. package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +23 -3
  384. package/src/__tests__/RealtimeClientSessionResolver.test.ts +324 -46
  385. package/src/__tests__/RecordingAssemblyScheduler.test.ts +178 -0
  386. package/src/__tests__/RemoteBrowserActionResolver.ownership.test.ts +98 -0
  387. package/src/__tests__/ResolverBase.adhocReadScope.test.ts +133 -2
  388. package/src/__tests__/ResolverBase.balancedClause.test.ts +155 -0
  389. package/src/__tests__/ResolverBase.clauseUnscopedRead.test.ts +127 -0
  390. package/src/__tests__/ResolverBase.clientOldValues.test.ts +243 -7
  391. package/src/__tests__/ResolverBase.deleteReturnProjection.test.ts +52 -0
  392. package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +176 -0
  393. package/src/__tests__/ResolverBase.filterEscaping.test.ts +5 -2
  394. package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +23 -1
  395. package/src/__tests__/ResolverBase.publishStatusUpdate.test.ts +68 -0
  396. package/src/__tests__/ResolverBase.userViewCacheAndDedup.test.ts +130 -0
  397. package/src/__tests__/RunAIAgentResolver.branch.test.ts +69 -13
  398. package/src/__tests__/RunAIAgentResolver.conversationWriter.test.ts +210 -0
  399. package/src/__tests__/RunAIAgentResolver.fireAndForgetCompletion.test.ts +209 -0
  400. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +20 -28
  401. package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +264 -0
  402. package/src/__tests__/RunAIAgentResolver.serverReply.test.ts +358 -0
  403. package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +4 -1
  404. package/src/__tests__/RunTemplateResolver.test.ts +35 -2
  405. package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +11 -0
  406. package/src/__tests__/RunViewResolver.cacheCheckScreen.test.ts +165 -0
  407. package/src/__tests__/SearchKnowledgeStreamResolver.test.ts +161 -0
  408. package/src/__tests__/SessionJanitor.test.ts +365 -10
  409. package/src/__tests__/SessionManager.test.ts +122 -0
  410. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +25 -0
  411. package/src/__tests__/TaskGraphAgentRunner.test.ts +266 -0
  412. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +468 -23
  413. package/src/__tests__/TaskGraphFrameResolver.test.ts +22 -0
  414. package/src/__tests__/TestQuerySQLResolver.test.ts +274 -0
  415. package/src/__tests__/TransactionGroupResolver.fieldSecurity.test.ts +199 -0
  416. package/src/__tests__/TransactionGroupResolver.refusals.test.ts +98 -1
  417. package/src/__tests__/UpdateMJDataContextItem.oldValues.test.ts +220 -0
  418. package/src/__tests__/UserViewResolver.updateWhereClause.test.ts +15 -0
  419. package/src/__tests__/ViewOperationsHandler.clauseScreen.test.ts +157 -0
  420. package/src/__tests__/ViewOperationsHandler.test.ts +7 -2
  421. package/src/__tests__/WidgetSessionService.test.ts +583 -4
  422. package/src/__tests__/agent-run-data-guard.test.ts +130 -0
  423. package/src/__tests__/apiRootBoot.test.ts +202 -0
  424. package/src/__tests__/buildMagicLinkSessionUser.test.ts +96 -0
  425. package/src/__tests__/cacheBroadcastProviders.test.ts +403 -0
  426. package/src/__tests__/cacheInvalidationRecordData.test.ts +109 -0
  427. package/src/__tests__/conversationRunEvents.test.ts +56 -14
  428. package/src/__tests__/fieldSecurityFixtures.ts +91 -0
  429. package/src/__tests__/globalCors.test.ts +217 -0
  430. package/src/__tests__/localDevAuth.test.ts +196 -0
  431. package/src/__tests__/multiTenancy.postgresRewrite.test.ts +181 -0
  432. package/src/__tests__/multiTenancy.security.test.ts +51 -0
  433. package/src/__tests__/multiTenancy.test.ts +1 -1
  434. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +10 -0
  435. package/src/__tests__/ownedRealtimeSession.test.ts +39 -0
  436. package/src/__tests__/pushStatusResolver.filter.test.ts +64 -1
  437. package/src/__tests__/realtimeRecordingHandler.test.ts +669 -0
  438. package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +29 -1
  439. package/src/__tests__/realtimeSessions/ownedRealtimeSession.anonymous.test.ts +31 -0
  440. package/src/__tests__/realtimeSessions/ownedRealtimeSession.namedScoped.test.ts +37 -0
  441. package/src/__tests__/realtimeSessions/sessionAccess.test.ts +146 -7
  442. package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +1 -1
  443. package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +25 -4
  444. package/src/__tests__/resolverBase.cloudEventChangedFields.test.ts +157 -0
  445. package/src/__tests__/resolverBase.fieldSecurityTransport.test.ts +222 -0
  446. package/src/__tests__/resolverBase.fls.test.ts +146 -97
  447. package/src/__tests__/restTransport.fieldSecurity.test.ts +148 -0
  448. package/src/__tests__/runParamsTimeZone.test.ts +179 -0
  449. package/src/__tests__/runStreams.fieldSecurity.test.ts +100 -0
  450. package/src/__tests__/runViewProperties.test.ts +114 -0
  451. package/src/__tests__/scalabilityBenchmarks.test.ts +765 -0
  452. package/src/__tests__/scalabilityDatabaseIntegration.test.ts +207 -0
  453. package/src/__tests__/serverExtensionHostOverlay.test.ts +66 -0
  454. package/src/__tests__/serverExtensionReservedRoots.test.ts +11 -98
  455. package/src/__tests__/sessionUserClone.test.ts +5 -1
  456. package/src/__tests__/sharedCache.test.ts +5 -3
  457. package/src/__tests__/startupSweepOrder.test.ts +40 -0
  458. package/src/__tests__/unifiedAuth.test.ts +28 -0
  459. package/src/__tests__/widgetGuestElevation.test.ts +2 -0
  460. package/src/agentSessions/SessionJanitor.ts +369 -93
  461. package/src/agentSessions/SessionManager.ts +45 -10
  462. package/src/apiRoot.ts +78 -0
  463. package/src/auth/AuthProviderCatalogRouter.ts +29 -0
  464. package/src/auth/LoginScreenEngine.ts +50 -0
  465. package/src/auth/index.ts +57 -12
  466. package/src/auth/initializeProviders.ts +43 -1
  467. package/src/auth/localDevAuth.ts +528 -0
  468. package/src/auth/magicLink/MagicLinkKeys.ts +2 -2
  469. package/src/auth/magicLink/MagicLinkRouter.ts +3 -2
  470. package/src/auth/magicLink/types.ts +10 -0
  471. package/src/auth/sessionUserClone.ts +3 -2
  472. package/src/broadcast/BaseCacheInvalidationBroadcastProvider.ts +674 -0
  473. package/src/broadcast/index.ts +5 -0
  474. package/src/broadcast/providers/AWSIoTCoreBroadcastProvider.ts +180 -0
  475. package/src/broadcast/providers/AzureWebPubSubBroadcastProvider.ts +182 -0
  476. package/src/broadcast/providers/GCPPubSubBroadcastProvider.ts +169 -0
  477. package/src/broadcast/providers/SequencedRoleBucketBroadcastProvider.ts +57 -0
  478. package/src/cache.ts +2 -1
  479. package/src/config.ts +115 -5
  480. package/src/context.ts +32 -8
  481. package/src/coreRoutes.ts +181 -0
  482. package/src/generated/graphql-schemas/__mj.ts +3684 -284
  483. package/src/generic/CacheInvalidationResolver.ts +172 -60
  484. package/src/generic/OrphanedConversationDetailReconciler.ts +4 -2
  485. package/src/generic/PubSubManager.ts +54 -1
  486. package/src/generic/PushStatusResolver.ts +109 -12
  487. package/src/generic/ResolverBase.ts +540 -431
  488. package/src/generic/RunViewResolver.ts +97 -15
  489. package/src/generic/actionOutputFieldSecurity.ts +75 -0
  490. package/src/generic/fieldSecurityTransport.ts +62 -0
  491. package/src/globalCors.ts +71 -0
  492. package/src/index.ts +239 -238
  493. package/src/integration/CustomColumnPromoter.ts +6 -1
  494. package/src/logging/variablesLoggingMiddleware.ts +59 -3
  495. package/src/multiTenancy/index.ts +24 -2
  496. package/src/realtimeSessions/README.md +7 -3
  497. package/src/realtimeSessions/RealtimeSessionVerificationService.ts +2 -1
  498. package/src/realtimeSessions/RealtimeVerifyRouter.ts +2 -1
  499. package/src/realtimeSessions/RecordingAssemblyScheduler.ts +234 -0
  500. package/src/realtimeSessions/SessionVerificationPortsBase.ts +1 -0
  501. package/src/realtimeSessions/index.ts +2 -0
  502. package/src/realtimeSessions/ownedRealtimeSession.ts +69 -0
  503. package/src/realtimeSessions/sessionAccess.ts +183 -23
  504. package/src/realtimeSessions/sessionConfigStamps.ts +1 -1
  505. package/src/realtimeSessions/subscriptionAuthorization.ts +4 -2
  506. package/src/realtimeSessions/verificationWorkflow.ts +3 -1
  507. package/src/realtimeWidget/WidgetRouter.ts +22 -4
  508. package/src/realtimeWidget/WidgetSessionService.ts +252 -17
  509. package/src/realtimeWidget/host-identity.ts +1 -1
  510. package/src/realtimeWidget/widgetCore.ts +30 -1
  511. package/src/realtimeWidget/widgetGuestElevation.ts +2 -1
  512. package/src/resolvers/ActionResolver.ts +78 -15
  513. package/src/resolvers/AdhocQueryResolver.ts +1 -0
  514. package/src/resolvers/AgentRunStatusPublisher.ts +36 -8
  515. package/src/resolvers/AgentSessionResolver.ts +46 -18
  516. package/src/resolvers/ArtifactFileResolver.ts +9 -8
  517. package/src/resolvers/ConversationRunEventsResolver.ts +15 -11
  518. package/src/resolvers/DatasetResolver.ts +70 -10
  519. package/src/resolvers/EntityCommunicationsResolver.ts +56 -15
  520. package/src/resolvers/EntityRecordNameResolver.ts +3 -2
  521. package/src/resolvers/FetchEntityVectorsResolver.ts +248 -55
  522. package/src/resolvers/FileCategoryResolver.ts +1 -0
  523. package/src/resolvers/FileResolver.ts +334 -109
  524. package/src/resolvers/GetDataContextDataResolver.ts +139 -41
  525. package/src/resolvers/GetDataResolver.ts +6 -3
  526. package/src/resolvers/IntegrationDiscoveryResolver.ts +53 -9
  527. package/src/resolvers/MergeRecordsResolver.ts +23 -2
  528. package/src/resolvers/PipelineProgressResolver.ts +12 -3
  529. package/src/resolvers/QueryResolver.ts +31 -6
  530. package/src/resolvers/QuerySystemUserResolver.ts +15 -6
  531. package/src/resolvers/RSUResolver.ts +12 -0
  532. package/src/resolvers/RealtimeClientSessionResolver.ts +114 -66
  533. package/src/resolvers/RemoteBrowserActionResolver.ts +15 -10
  534. package/src/resolvers/RunAIAgentResolver.ts +296 -85
  535. package/src/resolvers/RunTemplateResolver.ts +6 -4
  536. package/src/resolvers/RunTestResolver.ts +3 -1
  537. package/src/resolvers/SearchKnowledgeStreamResolver.ts +19 -3
  538. package/src/resolvers/SqlLoggingConfigResolver.ts +2 -4
  539. package/src/resolvers/SyncDataResolver.ts +4 -0
  540. package/src/resolvers/TaskGraphFrameResolver.ts +33 -1
  541. package/src/resolvers/TestQuerySQLResolver.ts +69 -13
  542. package/src/resolvers/TransactionGroupResolver.ts +185 -30
  543. package/src/resolvers/UserViewResolver.ts +2 -1
  544. package/src/resolvers/__tests__/GetDataResolver.validation.test.ts +95 -0
  545. package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +43 -0
  546. package/src/resolvers/agent-run-data-guard.ts +89 -0
  547. package/src/rest/EntityCRUDHandler.ts +22 -5
  548. package/src/rest/RESTEndpointHandler.ts +8 -5
  549. package/src/rest/RealtimeRecordingHandler.ts +467 -0
  550. package/src/rest/ViewOperationsHandler.ts +52 -18
  551. package/src/rest/setupRESTEndpoints.ts +6 -0
  552. package/src/serverExtensionReservedRoots.ts +14 -17
  553. package/src/serverRoleConfigUnits.ts +48 -0
  554. package/src/services/MJStorageBlobStore.ts +31 -30
  555. package/src/services/StartTaskGraphDispatcher.ts +2 -2
  556. package/src/services/TaskGraphActionRunner.ts +25 -5
  557. package/src/services/TaskGraphAgentRunner.ts +188 -11
  558. package/src/services/TaskGraphContinuationDeliverer.ts +738 -16
  559. package/src/sharedCache.ts +3 -0
  560. package/src/types.ts +23 -1
@@ -158,7 +158,7 @@ describe('IncludeBinaryFields forwarding — batch resolver path', () => {
158
158
  it('RunViewsGeneric → RunViewsGenericInternal forwards the per-view flag to provider.RunViews', async () => {
159
159
  const { provider, runViewsCalls } = recordingProvider();
160
160
  const inputs = [
161
- { EntityName: ENTITY_NAME, ExtraFilter: '', OrderBy: '', IncludeBinaryFields: true },
161
+ { EntityName: ENTITY_NAME, ExtraFilter: '', OrderBy: '', IncludeBinaryFields: true, AlternateBaseView: 'Active Vectors' },
162
162
  { EntityName: ENTITY_NAME, ExtraFilter: '', OrderBy: '' },
163
163
  ] as (RunViewByNameInput & RunViewByIDInput & RunDynamicViewInput)[];
164
164
 
@@ -167,7 +167,29 @@ describe('IncludeBinaryFields forwarding — batch resolver path', () => {
167
167
  expect(runViewsCalls).toHaveLength(1);
168
168
  expect(runViewsCalls[0]).toHaveLength(2);
169
169
  expect(runViewsCalls[0][0].IncludeBinaryFields).toBe(true);
170
+ expect(runViewsCalls[0][0].AlternateBaseView).toBe('Active Vectors');
170
171
  expect(runViewsCalls[0][1].IncludeBinaryFields).toBeUndefined();
172
+ expect(runViewsCalls[0][1].AlternateBaseView).toBeUndefined();
173
+ });
174
+
175
+ it('RunDynamicViewGeneric, RunViewByNameGeneric, and RunViewByIDGeneric forward AlternateBaseView to provider.RunView', async () => {
176
+ const { provider, runViewCalls } = recordingProvider();
177
+ const probe = new Probe();
178
+
179
+ await probe.RunDynamicViewGeneric(
180
+ { EntityName: ENTITY_NAME, ExtraFilter: '', OrderBy: '', AlternateBaseView: 'Active Vectors' } as RunDynamicViewInput,
181
+ provider, fakePayload(), undefined as never,
182
+ );
183
+ await probe.RunViewByNameGeneric(
184
+ { ViewName: 'Saved View', ExtraFilter: '', OrderBy: '', AlternateBaseView: '' } as RunViewByNameInput,
185
+ provider, fakePayload(), undefined as never,
186
+ );
187
+ await probe.RunViewByIDGeneric(
188
+ { ViewID: 'view-1', ExtraFilter: '', OrderBy: '', AlternateBaseView: 'Draft Vectors' } as RunViewByIDInput,
189
+ provider, fakePayload(), undefined as never,
190
+ );
191
+
192
+ expect(runViewCalls.map(c => c.AlternateBaseView)).toEqual(['Active Vectors', '', 'Draft Vectors']);
171
193
  });
172
194
  });
173
195
 
@@ -0,0 +1,68 @@
1
+ // ResolverBase transitively pulls in type-graphql decorators, which need the
2
+ // Reflect.metadata polyfill at import time.
3
+ import 'reflect-metadata';
4
+ import { describe, it, expect, vi } from 'vitest';
5
+ import type { PubSubEngine } from 'type-graphql';
6
+ import { UserInfo } from '@memberjunction/core';
7
+ import { ResolverBase } from '../generic/ResolverBase.js';
8
+ import { PUSH_STATUS_UPDATES_TOPIC, StatusUpdateOwnerID } from '../generic/PushStatusResolver.js';
9
+ import type { UserPayload } from '../types.js';
10
+
11
+ /**
12
+ * `ResolverBase.PublishStatusUpdate` stamps the owner the caller's socket is authenticated as. For a widget guest
13
+ * whose run is elevated to the system user, that is the guest's owner key: a push stamped with the elevated user's ID
14
+ * never passes the subscription filter on the guest's socket.
15
+ */
16
+
17
+ const ANONYMOUS_USER_ID = 'AAAAAAAA-0000-4000-8000-0000000000A0';
18
+ const SYSTEM_USER_ID = 'BBBBBBBB-0000-4000-8000-0000000000B0';
19
+
20
+ /** Reaches the protected publish wrapper. */
21
+ class Probe extends ResolverBase {
22
+ public Publish(pubSub: PubSubEngine, userPayload: UserPayload): void {
23
+ this.PublishStatusUpdate(pubSub, 'session-1', 'progress', userPayload);
24
+ }
25
+ }
26
+
27
+ function elevatedGuestPayload(): UserPayload {
28
+ const guest = new UserInfo(null, { ID: ANONYMOUS_USER_ID, Email: 'anonymous@magic-link.local' });
29
+ guest.IsMagicLinkAnonymous = true;
30
+ guest.AnonymousVisitorID = 'sid-guest-1';
31
+ return {
32
+ sessionId: 'session-1',
33
+ email: 'system@example.com',
34
+ userRecord: new UserInfo(null, { ID: SYSTEM_USER_ID, Email: 'system@example.com' }),
35
+ ElevatedFrom: guest,
36
+ };
37
+ }
38
+
39
+ describe('ResolverBase.PublishStatusUpdate — the owner it stamps', () => {
40
+ it("stamps an elevated widget guest's own owner key, not the system user it was elevated to", () => {
41
+ const publish = vi.fn().mockResolvedValue(undefined);
42
+ const pubSub: PubSubEngine = { publish, subscribe: vi.fn(), unsubscribe: vi.fn(), asyncIterator: vi.fn() };
43
+ const userPayload = elevatedGuestPayload();
44
+
45
+ new Probe().Publish(pubSub, userPayload);
46
+
47
+ expect(publish).toHaveBeenCalledOnce();
48
+ expect(publish.mock.calls[0][0]).toBe(PUSH_STATUS_UPDATES_TOPIC);
49
+ const payload = publish.mock.calls[0][1] as { sessionId: string; ownerUserId: string; message: string };
50
+ expect(payload).toMatchObject({ sessionId: 'session-1', message: 'progress' });
51
+ expect(payload.ownerUserId).toBe(StatusUpdateOwnerID(userPayload));
52
+ expect(payload.ownerUserId).toBe(`${ANONYMOUS_USER_ID.toLowerCase()}|sid-guest-1`);
53
+ });
54
+
55
+ it('stamps a signed-in user with their user ID', () => {
56
+ const publish = vi.fn().mockResolvedValue(undefined);
57
+ const pubSub: PubSubEngine = { publish, subscribe: vi.fn(), unsubscribe: vi.fn(), asyncIterator: vi.fn() };
58
+ const userPayload: UserPayload = {
59
+ sessionId: 'session-1',
60
+ email: 'user@example.com',
61
+ userRecord: new UserInfo(null, { ID: 'CCCCCCCC-0000-4000-8000-0000000000C0', Email: 'user@example.com' }),
62
+ };
63
+
64
+ new Probe().Publish(pubSub, userPayload);
65
+
66
+ expect((publish.mock.calls[0][1] as { ownerUserId: string }).ownerUserId).toBe('CCCCCCCC-0000-4000-8000-0000000000C0');
67
+ });
68
+ });
@@ -0,0 +1,130 @@
1
+ import 'reflect-metadata';
2
+ import { describe, it, expect, vi, afterEach } from 'vitest';
3
+ import { UserViewEngine } from '@memberjunction/core-entities';
4
+ import type { MJUserViewEntityExtended } from '@memberjunction/core-entities';
5
+ import { RunView } from '@memberjunction/core';
6
+ import type { IMetadataProvider, IRunViewProvider, RunViewParams, UserInfo } from '@memberjunction/core';
7
+ import { ResolverBase } from '../generic/ResolverBase.js';
8
+ import { RunViewResolver, RunViewByNameInput, RunViewByIDInput } from '../generic/RunViewResolver.js';
9
+
10
+ class UserViewProbe extends ResolverBase {
11
+ public async TestRunViewByID(
12
+ viewInput: RunViewByIDInput,
13
+ provider: IMetadataProvider,
14
+ userPayload: { userRecord: UserInfo; email: string }
15
+ ) {
16
+ return this.RunViewByIDGeneric(viewInput, provider, userPayload as never);
17
+ }
18
+
19
+ public async TestRunViewByName(
20
+ viewInput: RunViewByNameInput,
21
+ provider: IMetadataProvider,
22
+ userPayload: { userRecord: UserInfo; email: string }
23
+ ) {
24
+ return this.RunViewByNameGeneric(viewInput, provider, userPayload as never);
25
+ }
26
+ }
27
+
28
+ describe('ResolverBase & RunViewResolver UserViewEngine cache and ViewEntity forwarding (MJ-CORE-9)', () => {
29
+ afterEach(() => {
30
+ vi.restoreAllMocks();
31
+ });
32
+
33
+ it('resolves MJ: User Views from UserViewEngine cache first, forwards ViewEntity into RunViewParams, and reuses _resolvedViewEntity in RunViewResolver', async () => {
34
+ const mockViewEntity = {
35
+ ID: 'view-123',
36
+ Name: 'Active Widgets',
37
+ EntityID: 'entity-widgets',
38
+ Entity: 'Widgets',
39
+ WhereClause: 'Status = 1',
40
+ GridState: null,
41
+ SortState: null,
42
+ } as unknown as MJUserViewEntityExtended;
43
+
44
+ vi.spyOn(UserViewEngine.Instance, 'Loaded', 'get').mockReturnValue(true);
45
+ const getViewByIdSpy = vi.spyOn(UserViewEngine.Instance, 'GetViewById').mockReturnValue(mockViewEntity);
46
+ const getViewByNameSpy = vi.spyOn(UserViewEngine.Instance, 'GetViewByName').mockReturnValue(mockViewEntity);
47
+
48
+ const capturedRunViewParams: RunViewParams[] = [];
49
+ const providerRunViewSpy = vi.fn().mockImplementation(async (params: RunViewParams) => {
50
+ capturedRunViewParams.push(params);
51
+ return {
52
+ Success: true,
53
+ Results: [{ ID: 'w-1', Name: 'Widget A' }],
54
+ RowCount: 1,
55
+ TotalRowCount: 1,
56
+ ExecutionTime: 2,
57
+ ErrorMessage: '',
58
+ UserViewRunID: '',
59
+ };
60
+ });
61
+ const fakeProvider = {
62
+ Entities: [
63
+ {
64
+ ID: 'entity-widgets',
65
+ Name: 'Widgets',
66
+ PrimaryKeys: [{ Name: 'ID', CodeName: 'ID' }],
67
+ Fields: [
68
+ { Name: 'ID', CodeName: 'ID', AllowInView: true, DefaultInView: true, IsBinaryFieldType: false },
69
+ { Name: 'Name', CodeName: 'Name', AllowInView: true, DefaultInView: true, IsBinaryFieldType: false },
70
+ ],
71
+ EncryptedFields: [],
72
+ },
73
+ ],
74
+ EntityByName: () => ({
75
+ ID: 'entity-widgets',
76
+ Name: 'Widgets',
77
+ PrimaryKeys: [{ Name: 'ID', CodeName: 'ID' }],
78
+ Fields: [
79
+ { Name: 'ID', CodeName: 'ID', AllowInView: true, DefaultInView: true, IsBinaryFieldType: false },
80
+ { Name: 'Name', CodeName: 'Name', AllowInView: true, DefaultInView: true, IsBinaryFieldType: false },
81
+ ],
82
+ EncryptedFields: [],
83
+ }),
84
+ EntityByID: () => ({
85
+ ID: 'entity-widgets',
86
+ Name: 'Widgets',
87
+ PrimaryKeys: [{ Name: 'ID', CodeName: 'ID' }],
88
+ Fields: [
89
+ { Name: 'ID', CodeName: 'ID', AllowInView: true, DefaultInView: true, IsBinaryFieldType: false },
90
+ { Name: 'Name', CodeName: 'Name', AllowInView: true, DefaultInView: true, IsBinaryFieldType: false },
91
+ ],
92
+ EncryptedFields: [],
93
+ }),
94
+ RunView: providerRunViewSpy,
95
+ } as unknown as IMetadataProvider & IRunViewProvider;
96
+
97
+ const userPayload = {
98
+ email: 'tester@example.com',
99
+ userRecord: { ID: 'u-1', Email: 'tester@example.com' } as unknown as UserInfo,
100
+ };
101
+
102
+ const resolver = new RunViewResolver();
103
+ const findBySpy = vi.spyOn(
104
+ resolver as unknown as { findBy: (...args: unknown[]) => Promise<unknown> },
105
+ 'findBy'
106
+ );
107
+
108
+ const byIdResult = await resolver.RunViewByID(
109
+ { ViewID: 'view-123' } as RunViewByIDInput,
110
+ { providers: [{ provider: fakeProvider, type: 'Read-Only' }], userPayload } as never
111
+ );
112
+
113
+ expect(getViewByIdSpy).toHaveBeenCalledWith('view-123');
114
+ expect(findBySpy).not.toHaveBeenCalled();
115
+ expect(capturedRunViewParams).toHaveLength(1);
116
+ expect(capturedRunViewParams[0].ViewEntity).toBe(mockViewEntity);
117
+ expect(byIdResult?.Results).toHaveLength(1);
118
+
119
+ const byNameResult = await resolver.RunViewByName(
120
+ { ViewName: 'Active Widgets' } as RunViewByNameInput,
121
+ { providers: [{ provider: fakeProvider, type: 'Read-Only' }], userPayload } as never
122
+ );
123
+
124
+ expect(getViewByNameSpy).toHaveBeenCalledWith('Active Widgets');
125
+ expect(findBySpy).not.toHaveBeenCalled();
126
+ expect(capturedRunViewParams).toHaveLength(2);
127
+ expect(capturedRunViewParams[1].ViewEntity).toBe(mockViewEntity);
128
+ expect(byNameResult?.Results).toHaveLength(1);
129
+ });
130
+ });
@@ -1,10 +1,12 @@
1
1
  /**
2
2
  * @fileoverview The conversation branch on `RunAIAgentFromConversationDetail`.
3
3
  *
4
- * The branch comes from the placeholder row the mutation is given, never from a request argument.
5
- * These tests pin that the mutation loads history along that branch's path, hands the branch to the
6
- * agent run on both the synchronous and fire-and-forget paths, and reads the trunk when the row has
7
- * no branch; and that `executeAIAgent` puts the branch on the run's params only when there is one.
4
+ * The branch defaults to the person's message the mutation is given, or — when `replyBranchId` is supplied
5
+ * (such as Regenerate forking from an earlier message) — is validated to be a branch of the conversation
6
+ * whose path holds the person's message. These tests pin that the mutation loads history along that branch's
7
+ * path, creates the reply on that branch, hands the branch to the agent run on both the synchronous and
8
+ * fire-and-forget paths, and reads the trunk when the message has no branch; and that `executeAIAgent` puts
9
+ * the branch on the run's params only when there is one.
8
10
  */
9
11
  import 'reflect-metadata'; // must precede any type-graphql decorator evaluation
10
12
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
@@ -26,6 +28,7 @@ vi.mock('type-graphql', () => {
26
28
 
27
29
  const hoisted = vi.hoisted(() => ({
28
30
  runAgentInConversation: vi.fn(),
31
+ createAgentReplyDetail: vi.fn(),
29
32
  }));
30
33
 
31
34
  vi.mock('@memberjunction/ai-agents', () => ({
@@ -33,6 +36,9 @@ vi.mock('@memberjunction/ai-agents', () => ({
33
36
  RunAgentInConversation(...args: unknown[]) {
34
37
  return hoisted.runAgentInConversation(...args);
35
38
  }
39
+ CreateAgentReplyDetail(...args: unknown[]) {
40
+ return hoisted.createAgentReplyDetail(...args);
41
+ }
36
42
  },
37
43
  ArtifactToolManager: class {},
38
44
  }));
@@ -70,11 +76,12 @@ function makeResolver(): { resolver: RunAIAgentResolver; seams: ResolverSeams }
70
76
  return { resolver, seams };
71
77
  }
72
78
 
73
- function makeContext(branchId: string | null): AppContext {
79
+ function makeContext(branchId: string | null, sequence = 3): AppContext {
74
80
  const provider = {
75
81
  GetEntityObject: vi.fn().mockResolvedValue({
76
82
  ConversationID: 'conv-1',
77
83
  BranchID: branchId,
84
+ Sequence: sequence,
78
85
  Load: vi.fn().mockResolvedValue(true),
79
86
  }),
80
87
  };
@@ -87,11 +94,18 @@ function makeContext(branchId: string | null): AppContext {
87
94
 
88
95
  const pubSub = { publish: vi.fn() } as unknown as PubSubEngine;
89
96
 
90
- async function runMutation(resolver: RunAIAgentResolver, branchId: string | null, fireAndForget?: boolean) {
97
+ async function runMutation(
98
+ resolver: RunAIAgentResolver,
99
+ branchId: string | null,
100
+ fireAndForget?: boolean,
101
+ replyBranchId?: string,
102
+ sequence = 3
103
+ ) {
91
104
  return resolver.RunAIAgentFromConversationDetail(
92
- 'detail-1', 'agent-1', makeContext(branchId), 'session-1', pubSub,
105
+ 'detail-1', 'agent-1', makeContext(branchId, sequence), 'session-1', pubSub,
93
106
  undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
94
- undefined, undefined, fireAndForget, undefined, undefined, undefined
107
+ undefined, undefined, fireAndForget, undefined, undefined, undefined,
108
+ undefined, undefined, replyBranchId
95
109
  );
96
110
  }
97
111
 
@@ -108,23 +122,64 @@ describe('RunAIAgentFromConversationDetail — branch', () => {
108
122
  seams.loadConversationHistoryWithAttachments = vi.fn().mockResolvedValue([]);
109
123
  seams.executeAIAgent = vi.fn().mockResolvedValue({ success: true, result: '{}' });
110
124
  seams.executeAgentInBackground = vi.fn();
125
+ hoisted.createAgentReplyDetail.mockReset().mockResolvedValue({ ID: 'reply-1', __mj_CreatedAt: new Date() });
111
126
  });
112
127
 
113
- it('loads history on the placeholder row\'s branch and hands the branch to the run', async () => {
128
+ // executeAIAgent / executeAgentInBackground end with (..., branchId, replyDetail).
129
+ it('loads history on the message\'s branch, creates the reply there, and hands the branch to the run', async () => {
114
130
  await runMutation(resolver, 'branch-b');
115
131
  expect(seams.loadConversationHistoryWithAttachments.mock.calls[0][6]).toBe('branch-b');
116
- expect(seams.executeAIAgent.mock.calls[0].at(-1)).toBe('branch-b');
132
+ expect(hoisted.createAgentReplyDetail).toHaveBeenCalledWith(expect.objectContaining({ branchId: 'branch-b' }));
133
+ expect(seams.executeAIAgent.mock.calls[0].at(-2)).toBe('branch-b');
117
134
  });
118
135
 
119
136
  it('passes the branch to the background path too', async () => {
120
137
  await runMutation(resolver, 'branch-b', true);
121
- expect(seams.executeAgentInBackground.mock.calls[0].at(-1)).toBe('branch-b');
138
+ expect(seams.executeAgentInBackground.mock.calls[0].at(-2)).toBe('branch-b');
122
139
  });
123
140
 
124
- it('reads the trunk when the placeholder has no branch (control)', async () => {
141
+ it('reads the trunk when the message has no branch (control)', async () => {
125
142
  await runMutation(resolver, null);
126
143
  expect(seams.loadConversationHistoryWithAttachments.mock.calls[0][6]).toBeNull();
127
- expect(seams.executeAIAgent.mock.calls[0].at(-1)).toBeNull();
144
+ expect(hoisted.createAgentReplyDetail).toHaveBeenCalledWith(expect.objectContaining({ branchId: null }));
145
+ expect(seams.executeAIAgent.mock.calls[0].at(-2)).toBeNull();
146
+ });
147
+
148
+ it('places the reply and history on replyBranchId when a regeneration forks from a message on its ancestor path', async () => {
149
+ vi.spyOn(ConversationEngine, 'LoadBranchesFresh').mockResolvedValue([
150
+ {
151
+ ID: 'branch-regen',
152
+ ConversationID: 'conv-1',
153
+ ParentBranchID: null,
154
+ ForkFromSequence: 5,
155
+ } as never,
156
+ ]);
157
+
158
+ const result = await runMutation(resolver, null, false, 'branch-regen', 3);
159
+
160
+ expect(result.success).toBe(true);
161
+ expect(seams.loadConversationHistoryWithAttachments.mock.calls[0][6]).toBe('branch-regen');
162
+ expect(hoisted.createAgentReplyDetail).toHaveBeenCalledWith(expect.objectContaining({ branchId: 'branch-regen' }));
163
+ expect(seams.executeAIAgent.mock.calls[0].at(-2)).toBe('branch-regen');
164
+ });
165
+
166
+ it('refuses a replyBranchId whose path does not include the user message, and creates nothing', async () => {
167
+ vi.spyOn(console, 'error').mockImplementation(() => undefined);
168
+ vi.spyOn(ConversationEngine, 'LoadBranchesFresh').mockResolvedValue([
169
+ {
170
+ ID: 'branch-regen',
171
+ ConversationID: 'conv-1',
172
+ ParentBranchID: null,
173
+ ForkFromSequence: 5,
174
+ } as never,
175
+ ]);
176
+
177
+ const result = await runMutation(resolver, null, false, 'branch-regen', 8);
178
+
179
+ expect(result.success).toBe(false);
180
+ expect(result.errorMessage).toContain('branch-regen');
181
+ expect(hoisted.createAgentReplyDetail).not.toHaveBeenCalled();
182
+ expect(seams.executeAIAgent).not.toHaveBeenCalled();
128
183
  });
129
184
  });
130
185
 
@@ -159,6 +214,7 @@ describe('executeAIAgent — ConversationBranchID', () => {
159
214
  {}, {}, 'agent-1', userPayload, '[{"role":"user","content":"hi"}]', 'session-1', pubSub,
160
215
  undefined, undefined, undefined, undefined, undefined, undefined, 'detail-1', false, false,
161
216
  undefined, undefined, 'conv-1', undefined, undefined, undefined, undefined, undefined,
217
+ false, // trustReservedRunData
162
218
  ];
163
219
  await execute(...base, 'branch-b');
164
220
  await execute(...base, null);
@@ -0,0 +1,210 @@
1
+ /**
2
+ * @fileoverview A widget guest's agent run executes as the system user, but the conversation belongs to the guest,
3
+ * and only the owner (or a grantee) may write a conversation's messages (MJConversationDetailEntityExtended, MJ#4791).
4
+ * So the resolver names the guest as `ConversationWriter`: AgentRunner then writes the reply as the guest and the
5
+ * run's own records as the system user. Before this, every reply save of a widget guest was refused and the widget
6
+ * never showed the agent's answer.
7
+ */
8
+ import 'reflect-metadata'; // must precede any type-graphql decorator evaluation
9
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
10
+ import type { PubSubEngine } from 'type-graphql';
11
+
12
+ // type-graphql's real decorators need emitDecoratorMetadata, which vitest's esbuild transform
13
+ // does not emit; the schema is irrelevant here, so every decorator is a no-op.
14
+ vi.mock('type-graphql', () => {
15
+ const decoratorFactory = (..._args: unknown[]) => (..._decorated: unknown[]) => undefined;
16
+ const exportNames = [
17
+ 'Resolver', 'Query', 'Mutation', 'Subscription', 'Arg', 'Args', 'ArgsType', 'Ctx', 'Root',
18
+ 'Info', 'Field', 'FieldResolver', 'ObjectType', 'InputType', 'InterfaceType', 'Authorized',
19
+ 'UseMiddleware', 'Extensions', 'Directive', 'ID', 'Int', 'Float', 'GraphQLISODateTime',
20
+ 'GraphQLTimestamp', 'registerEnumType', 'createMethodDecorator', 'createParamDecorator',
21
+ 'buildSchema', 'buildSchemaSync', 'PubSub',
22
+ ];
23
+ return Object.fromEntries(exportNames.map((name) => [name, decoratorFactory]));
24
+ });
25
+
26
+ const hoisted = vi.hoisted(() => ({
27
+ runAgentInConversation: vi.fn(),
28
+ createAgentReplyDetail: vi.fn(),
29
+ resolveWidgetGuestRunContext: vi.fn(),
30
+ authorize: vi.fn(),
31
+ }));
32
+
33
+ // Only the key engine is stubbed: Authorize allows `agent:trusted` for the key whose hash is 'hash-trusted'.
34
+ vi.mock('@memberjunction/api-keys', async (importOriginal) => ({
35
+ ...(await importOriginal<typeof import('@memberjunction/api-keys')>()),
36
+ GetAPIKeyEngine: () => ({ Authorize: hoisted.authorize }),
37
+ }));
38
+
39
+ vi.mock('@memberjunction/ai-agents', () => ({
40
+ AgentRunner: class {
41
+ RunAgentInConversation(...args: unknown[]) {
42
+ return hoisted.runAgentInConversation(...args);
43
+ }
44
+ CreateAgentReplyDetail(...args: unknown[]) {
45
+ return hoisted.createAgentReplyDetail(...args);
46
+ }
47
+ },
48
+ ArtifactToolManager: class {},
49
+ }));
50
+
51
+ // Only the widget lookup is stubbed; ElevateUserPayload is the real one, so the widget-guest test runs
52
+ // against the elevated system-user payload the resolver really builds.
53
+ vi.mock('../realtimeWidget/widgetGuestElevation.js', async (importOriginal) => ({
54
+ ...(await importOriginal<typeof import('../realtimeWidget/widgetGuestElevation.js')>()),
55
+ ResolveWidgetGuestRunContext: hoisted.resolveWidgetGuestRunContext,
56
+ }));
57
+
58
+ import { UserCache } from '@memberjunction/generic-database-provider';
59
+ import type { UserInfo } from '@memberjunction/core';
60
+ import { RunAIAgentResolver } from '../resolvers/RunAIAgentResolver.js';
61
+ import type { AppContext, UserPayload } from '../types.js';
62
+
63
+ const SCOPE_RECORD_ID = 'B1A2C3D4-0000-4000-8000-00000000A115';
64
+ const ORDINARY = { conversationId: 'conv-1', latestMessageId: 'detail-1', invocationReason: 'user-message' };
65
+ const CLIENT_DATA = JSON.stringify({
66
+ ...ORDINARY,
67
+ PrimaryScopeRecordID: SCOPE_RECORD_ID,
68
+ PrimaryScopeEntityName: 'MJ: Companies',
69
+ SecondaryScopes: { TeamID: 'team-other' },
70
+ __agentTypePromptParams: { enableTaskGraphs: true },
71
+ });
72
+
73
+ const USER = { ID: 'user-1', Email: 'browser.user@example.com' };
74
+ const SYSTEM_USER = { ID: 'system-user', Email: 'system@example.com' };
75
+ // A widget guest always carries its per-visitor scope id (mj_sid) as its MagicLinkScope.ResourceID, and its
76
+ // conversation is stamped with the same value as ExternalID: that stamp is what tells one guest from another
77
+ // under the shared Anonymous user (MJ#6032), so the fake conversation below carries it.
78
+ const GUEST = { ID: 'guest-1', Email: 'anonymous@magic-link.local', IsMagicLinkAnonymous: true, AnonymousVisitorID: 'sid-1', MagicLinkScope: { ResourceID: 'sid-1' } };
79
+
80
+ type Fn = ReturnType<typeof vi.fn>;
81
+
82
+ /** The private members this test reaches, through an explicit shape (no `any`). */
83
+ interface ResolverSeams {
84
+ CheckAPIKeyScopeAuthorization: Fn;
85
+ GetUserFromPayload: Fn;
86
+ loadConversationHistoryWithAttachments: Fn;
87
+ validateAgent: Fn;
88
+ persistInFlightAgentFailure: Fn;
89
+ }
90
+
91
+ const pubSub = { publish: vi.fn().mockResolvedValue(undefined) } as unknown as PubSubEngine;
92
+
93
+ function makeResolver(): { resolver: RunAIAgentResolver; seams: ResolverSeams } {
94
+ const resolver = new RunAIAgentResolver();
95
+ const seams = resolver as unknown as ResolverSeams;
96
+ seams.CheckAPIKeyScopeAuthorization = vi.fn().mockResolvedValue(undefined);
97
+ seams.GetUserFromPayload = vi.fn((payload: UserPayload) => payload.userRecord);
98
+ seams.loadConversationHistoryWithAttachments = vi.fn().mockResolvedValue([{ role: 'user', content: 'hi' }]);
99
+ seams.validateAgent = vi.fn().mockResolvedValue({ ID: 'agent-1', Name: 'Test Agent' });
100
+ seams.persistInFlightAgentFailure = vi.fn().mockResolvedValue(undefined);
101
+ return { resolver, seams };
102
+ }
103
+
104
+ function makeContext(userPayload: Partial<UserPayload>): AppContext {
105
+ const provider = {
106
+ GetEntityObject: vi.fn().mockResolvedValue({ ConversationID: 'conv-1', UserID: GUEST.ID, ExternalID: 'sid-1', Load: vi.fn().mockResolvedValue(true) }),
107
+ };
108
+ return {
109
+ userPayload: { sessionId: 'session-1', email: USER.Email, userRecord: USER, ...userPayload } as UserPayload,
110
+ providers: [{ type: 'Read-Write', provider }],
111
+ dataSource: {},
112
+ } as unknown as AppContext;
113
+ }
114
+
115
+ /** The params the n-th run was handed by the real executeAIAgent (what AgentRunner.RunAgentInConversation received). */
116
+ interface HandedParams {
117
+ data: Record<string, unknown>;
118
+ TrustReservedRunData?: boolean;
119
+ contextUser: { ID: string };
120
+ }
121
+
122
+ /** Waits for the n-th run to start (the fire-and-forget path starts it after the resolver has returned). */
123
+ async function handedParams(n = 0): Promise<HandedParams> {
124
+ await vi.waitFor(() => expect(hoisted.runAgentInConversation.mock.calls.length).toBeGreaterThan(n));
125
+ return hoisted.runAgentInConversation.mock.calls[n][0] as HandedParams;
126
+ }
127
+
128
+ function runAIAgent(resolver: RunAIAgentResolver, ctx: AppContext, fireAndForget?: boolean) {
129
+ return resolver.RunAIAgent(
130
+ 'agent-1', ctx, '[{"role":"user","content":"hi"}]', 'session-1', pubSub, CLIENT_DATA,
131
+ undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
132
+ fireAndForget
133
+ );
134
+ }
135
+
136
+ function runFromDetail(resolver: RunAIAgentResolver, ctx: AppContext, fireAndForget?: boolean) {
137
+ return resolver.RunAIAgentFromConversationDetail(
138
+ 'detail-1', 'agent-1', ctx, 'session-1', pubSub, undefined, CLIENT_DATA,
139
+ undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, fireAndForget
140
+ );
141
+ }
142
+
143
+ beforeEach(() => {
144
+ hoisted.resolveWidgetGuestRunContext.mockReset().mockResolvedValue(null);
145
+ // Stop right after the run's params are captured — the rest of the run is out of scope.
146
+ hoisted.runAgentInConversation.mockReset().mockRejectedValue(new Error('stop here'));
147
+ hoisted.createAgentReplyDetail.mockReset().mockResolvedValue({ ID: 'reply-1', __mj_CreatedAt: new Date() });
148
+ hoisted.authorize.mockReset().mockImplementation(async (apiKeyHash: string, _app: string, scopePath: string) =>
149
+ apiKeyHash === 'hash-trusted' && scopePath === 'agent:trusted'
150
+ ? { Allowed: true, MatchedKeyRule: { ScopePath: scopePath }, EvaluatedRules: [] }
151
+ : { Allowed: false, Reason: 'No matching key scope rules', EvaluatedRules: [] });
152
+ vi.spyOn(UserCache.Instance, 'GetSystemUser').mockReturnValue(SYSTEM_USER as UserInfo);
153
+ vi.spyOn(console, 'log').mockImplementation(() => undefined);
154
+ vi.spyOn(console, 'error').mockImplementation(() => undefined);
155
+ });
156
+
157
+ afterEach(() => {
158
+ vi.restoreAllMocks();
159
+ });
160
+
161
+ /** The options the n-th run was handed (the second argument of AgentRunner.RunAgentInConversation). */
162
+ async function handedOptions(n = 0): Promise<{ ConversationWriter?: { ID: string } }> {
163
+ await vi.waitFor(() => expect(hoisted.runAgentInConversation.mock.calls.length).toBeGreaterThan(n));
164
+ return hoisted.runAgentInConversation.mock.calls[n][1] as { ConversationWriter?: { ID: string } };
165
+ }
166
+
167
+ describe('RunAIAgentFromConversationDetail — who writes the conversation', () => {
168
+ it('runs a widget guest as the system user but writes its conversation as the guest, on both paths', async () => {
169
+ const { resolver } = makeResolver();
170
+ hoisted.resolveWidgetGuestRunContext.mockResolvedValue({ ElevatedUser: SYSTEM_USER, Widget: {}, PinnedAgentId: 'pinned-agent' });
171
+ const ctx = makeContext({ email: GUEST.Email, userRecord: GUEST });
172
+
173
+ await runFromDetail(resolver, ctx);
174
+ await runFromDetail(resolver, ctx, true);
175
+
176
+ expect((await handedParams(0)).contextUser.ID).toBe(SYSTEM_USER.ID);
177
+ expect((await handedOptions(0)).ConversationWriter?.ID).toBe(GUEST.ID);
178
+ expect((await handedParams(1)).contextUser.ID).toBe(SYSTEM_USER.ID);
179
+ expect((await handedOptions(1)).ConversationWriter?.ID).toBe(GUEST.ID);
180
+ // The server-created reply row (A19) is written as the guest too, never as the elevated system user.
181
+ for (const [args] of hoisted.createAgentReplyDetail.mock.calls) {
182
+ expect((args as { contextUser: { ID: string } }).contextUser.ID).toBe(GUEST.ID);
183
+ }
184
+ expect(hoisted.createAgentReplyDetail).toHaveBeenCalledTimes(2);
185
+ });
186
+
187
+ it('refuses a widget guest on another visitor\'s conversation before any row is written (MJ#6032)', async () => {
188
+ const { resolver } = makeResolver();
189
+ hoisted.resolveWidgetGuestRunContext.mockResolvedValue({ ElevatedUser: SYSTEM_USER, Widget: {}, PinnedAgentId: 'pinned-agent' });
190
+ // The conversation is stamped sid-1; this guest's scope is sid-2, so the shared Anonymous user must not be
191
+ // enough. Without the AuthorizeConversationTurn gate the run would proceed and the reply row below be created.
192
+ const ctx = makeContext({ email: GUEST.Email, userRecord: { ...GUEST, AnonymousVisitorID: 'sid-2', MagicLinkScope: { ResourceID: 'sid-2' } } as UserPayload['userRecord'] });
193
+
194
+ const result = await runFromDetail(resolver, ctx);
195
+
196
+ expect(result.success).toBe(false);
197
+ expect(result.errorMessage).toContain('Not authorized: you do not own this conversation');
198
+ expect(hoisted.createAgentReplyDetail).not.toHaveBeenCalled();
199
+ expect(hoisted.runAgentInConversation).not.toHaveBeenCalled();
200
+ });
201
+
202
+ it('names no separate writer for an ordinary user (it runs and writes as itself)', async () => {
203
+ const { resolver } = makeResolver();
204
+
205
+ await runFromDetail(resolver, makeContext({}));
206
+
207
+ expect((await handedOptions()).ConversationWriter).toBeUndefined();
208
+ expect((await handedParams()).contextUser.ID).toBe(USER.ID);
209
+ });
210
+ });