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

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 (407) hide show
  1. package/README.md +69 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentSessions/BridgeHostInstance.d.ts +8 -3
  4. package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -1
  5. package/dist/agentSessions/BridgeHostInstance.js +14 -4
  6. package/dist/agentSessions/BridgeHostInstance.js.map +1 -1
  7. package/dist/agentSessions/HandoffOfferExpiry.d.ts +10 -0
  8. package/dist/agentSessions/HandoffOfferExpiry.d.ts.map +1 -0
  9. package/dist/agentSessions/HandoffOfferExpiry.js +18 -0
  10. package/dist/agentSessions/HandoffOfferExpiry.js.map +1 -0
  11. package/dist/agentSessions/ReturningVisitorRecap.js +1 -0
  12. package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
  13. package/dist/agentSessions/SessionJanitor.d.ts +31 -8
  14. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  15. package/dist/agentSessions/SessionJanitor.js +85 -41
  16. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  17. package/dist/agentSessions/SessionManager.d.ts +14 -4
  18. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  19. package/dist/agentSessions/SessionManager.js +28 -4
  20. package/dist/agentSessions/SessionManager.js.map +1 -1
  21. package/dist/agentSessions/conversationBrowsers.d.ts +61 -0
  22. package/dist/agentSessions/conversationBrowsers.d.ts.map +1 -0
  23. package/dist/agentSessions/conversationBrowsers.js +118 -0
  24. package/dist/agentSessions/conversationBrowsers.js.map +1 -0
  25. package/dist/agentSessions/sessionDeadline.d.ts +43 -0
  26. package/dist/agentSessions/sessionDeadline.d.ts.map +1 -0
  27. package/dist/agentSessions/sessionDeadline.js +68 -0
  28. package/dist/agentSessions/sessionDeadline.js.map +1 -0
  29. package/dist/auth/APIKeyScopeAuth.d.ts.map +1 -1
  30. package/dist/auth/APIKeyScopeAuth.js +5 -4
  31. package/dist/auth/APIKeyScopeAuth.js.map +1 -1
  32. package/dist/auth/loginEmailResolution.d.ts +41 -0
  33. package/dist/auth/loginEmailResolution.d.ts.map +1 -0
  34. package/dist/auth/loginEmailResolution.js +47 -0
  35. package/dist/auth/loginEmailResolution.js.map +1 -0
  36. package/dist/auth/magicLink/MagicLinkKeys.d.ts +50 -2
  37. package/dist/auth/magicLink/MagicLinkKeys.d.ts.map +1 -1
  38. package/dist/auth/magicLink/MagicLinkKeys.js +129 -12
  39. package/dist/auth/magicLink/MagicLinkKeys.js.map +1 -1
  40. package/dist/auth/magicLink/MagicLinkRouter.d.ts +3 -0
  41. package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
  42. package/dist/auth/magicLink/MagicLinkRouter.js +23 -5
  43. package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
  44. package/dist/auth/magicLink/MagicLinkService.d.ts +39 -5
  45. package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
  46. package/dist/auth/magicLink/MagicLinkService.js +221 -9
  47. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  48. package/dist/auth/magicLink/index.d.ts +1 -1
  49. package/dist/auth/magicLink/index.d.ts.map +1 -1
  50. package/dist/auth/magicLink/index.js +1 -1
  51. package/dist/auth/magicLink/index.js.map +1 -1
  52. package/dist/auth/magicLink/redeemLanding.d.ts +2 -2
  53. package/dist/auth/magicLink/redeemLanding.d.ts.map +1 -1
  54. package/dist/auth/magicLink/redeemLanding.js +7 -4
  55. package/dist/auth/magicLink/redeemLanding.js.map +1 -1
  56. package/dist/auth/magicLink/types.d.ts +27 -3
  57. package/dist/auth/magicLink/types.d.ts.map +1 -1
  58. package/dist/auth/magicLink/types.js +0 -4
  59. package/dist/auth/magicLink/types.js.map +1 -1
  60. package/dist/auth/newUsers.d.ts.map +1 -1
  61. package/dist/auth/newUsers.js +1 -0
  62. package/dist/auth/newUsers.js.map +1 -1
  63. package/dist/backgroundSweepConfigUnits.d.ts +231 -0
  64. package/dist/backgroundSweepConfigUnits.d.ts.map +1 -0
  65. package/dist/backgroundSweepConfigUnits.js +180 -0
  66. package/dist/backgroundSweepConfigUnits.js.map +1 -0
  67. package/dist/config.d.ts +906 -8
  68. package/dist/config.d.ts.map +1 -1
  69. package/dist/config.js +59 -0
  70. package/dist/config.js.map +1 -1
  71. package/dist/context.d.ts +2 -0
  72. package/dist/context.d.ts.map +1 -1
  73. package/dist/context.js +35 -4
  74. package/dist/context.js.map +1 -1
  75. package/dist/coreRoutes.d.ts +3 -1
  76. package/dist/coreRoutes.d.ts.map +1 -1
  77. package/dist/coreRoutes.js +6 -4
  78. package/dist/coreRoutes.js.map +1 -1
  79. package/dist/generated/graphql-schemas/__mj.d.ts +228 -0
  80. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  81. package/dist/generated/graphql-schemas/__mj.js +1163 -6
  82. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  83. package/dist/generic/OrphanedConversationDetailReconciler.d.ts +11 -0
  84. package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -1
  85. package/dist/generic/OrphanedConversationDetailReconciler.js +27 -1
  86. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
  87. package/dist/generic/ResolverBase.d.ts +50 -5
  88. package/dist/generic/ResolverBase.d.ts.map +1 -1
  89. package/dist/generic/ResolverBase.js +321 -132
  90. package/dist/generic/ResolverBase.js.map +1 -1
  91. package/dist/generic/RunViewResolver.d.ts +4 -0
  92. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  93. package/dist/generic/RunViewResolver.js +47 -7
  94. package/dist/generic/RunViewResolver.js.map +1 -1
  95. package/dist/index.d.ts +1 -0
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +157 -35
  98. package/dist/index.js.map +1 -1
  99. package/dist/integration/ConnectionPause.d.ts +121 -0
  100. package/dist/integration/ConnectionPause.d.ts.map +1 -0
  101. package/dist/integration/ConnectionPause.js +183 -0
  102. package/dist/integration/ConnectionPause.js.map +1 -0
  103. package/dist/integration/CustomColumnPromoter.d.ts +72 -6
  104. package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
  105. package/dist/integration/CustomColumnPromoter.js +87 -46
  106. package/dist/integration/CustomColumnPromoter.js.map +1 -1
  107. package/dist/integration/EntityMapLifecycle.d.ts +78 -4
  108. package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
  109. package/dist/integration/EntityMapLifecycle.js +199 -5
  110. package/dist/integration/EntityMapLifecycle.js.map +1 -1
  111. package/dist/integration/InactiveRowWarnings.d.ts +31 -0
  112. package/dist/integration/InactiveRowWarnings.d.ts.map +1 -1
  113. package/dist/integration/InactiveRowWarnings.js +29 -0
  114. package/dist/integration/InactiveRowWarnings.js.map +1 -1
  115. package/dist/integration/ObjectNamesByID.d.ts +28 -0
  116. package/dist/integration/ObjectNamesByID.d.ts.map +1 -0
  117. package/dist/integration/ObjectNamesByID.js +87 -0
  118. package/dist/integration/ObjectNamesByID.js.map +1 -0
  119. package/dist/integration/PostRestartIntrospect.d.ts +26 -0
  120. package/dist/integration/PostRestartIntrospect.d.ts.map +1 -0
  121. package/dist/integration/PostRestartIntrospect.js +27 -0
  122. package/dist/integration/PostRestartIntrospect.js.map +1 -0
  123. package/dist/integration/RSUPostRestartProgress.d.ts +176 -0
  124. package/dist/integration/RSUPostRestartProgress.d.ts.map +1 -0
  125. package/dist/integration/RSUPostRestartProgress.js +323 -0
  126. package/dist/integration/RSUPostRestartProgress.js.map +1 -0
  127. package/dist/integration/RSUProgressBridge.d.ts +41 -2
  128. package/dist/integration/RSUProgressBridge.d.ts.map +1 -1
  129. package/dist/integration/RSUProgressBridge.js +84 -1
  130. package/dist/integration/RSUProgressBridge.js.map +1 -1
  131. package/dist/integration/RunArtifactAuthorization.d.ts +39 -0
  132. package/dist/integration/RunArtifactAuthorization.d.ts.map +1 -0
  133. package/dist/integration/RunArtifactAuthorization.js +45 -0
  134. package/dist/integration/RunArtifactAuthorization.js.map +1 -0
  135. package/dist/integration/SchemaRefreshLaunch.d.ts +9 -0
  136. package/dist/integration/SchemaRefreshLaunch.d.ts.map +1 -1
  137. package/dist/integration/SchemaRefreshLaunch.js +3 -2
  138. package/dist/integration/SchemaRefreshLaunch.js.map +1 -1
  139. package/dist/integration/ScopedFieldsForBuild.d.ts +46 -0
  140. package/dist/integration/ScopedFieldsForBuild.d.ts.map +1 -0
  141. package/dist/integration/ScopedFieldsForBuild.js +91 -0
  142. package/dist/integration/ScopedFieldsForBuild.js.map +1 -0
  143. package/dist/integration/TargetConfigGuard.d.ts +40 -0
  144. package/dist/integration/TargetConfigGuard.d.ts.map +1 -0
  145. package/dist/integration/TargetConfigGuard.js +40 -0
  146. package/dist/integration/TargetConfigGuard.js.map +1 -0
  147. package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -1
  148. package/dist/realtimeSessions/ownedRealtimeSession.js +2 -3
  149. package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -1
  150. package/dist/realtimeSessions/sessionAccess.d.ts +15 -0
  151. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
  152. package/dist/realtimeSessions/sessionAccess.js +22 -0
  153. package/dist/realtimeSessions/sessionAccess.js.map +1 -1
  154. package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -1
  155. package/dist/realtimeWidget/WidgetSessionService.js +2 -0
  156. package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
  157. package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
  158. package/dist/realtimeWidget/visitorIdentity.js +1 -0
  159. package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
  160. package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
  161. package/dist/realtimeWidget/widgetCore.js +4 -7
  162. package/dist/realtimeWidget/widgetCore.js.map +1 -1
  163. package/dist/realtimeWidget/widgetGuestElevation.js +1 -0
  164. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  165. package/dist/requestOrigin.d.ts +22 -0
  166. package/dist/requestOrigin.d.ts.map +1 -0
  167. package/dist/requestOrigin.js +60 -0
  168. package/dist/requestOrigin.js.map +1 -0
  169. package/dist/resolvers/AgentSessionResolver.d.ts.map +1 -1
  170. package/dist/resolvers/AgentSessionResolver.js +6 -2
  171. package/dist/resolvers/AgentSessionResolver.js.map +1 -1
  172. package/dist/resolvers/AutotagPipelineResolver.d.ts.map +1 -1
  173. package/dist/resolvers/AutotagPipelineResolver.js +2 -1
  174. package/dist/resolvers/AutotagPipelineResolver.js.map +1 -1
  175. package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
  176. package/dist/resolvers/ConversationRunEventsResolver.js +2 -0
  177. package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
  178. package/dist/resolvers/ExecuteRemoteOperationResolver.d.ts +6 -0
  179. package/dist/resolvers/ExecuteRemoteOperationResolver.d.ts.map +1 -1
  180. package/dist/resolvers/ExecuteRemoteOperationResolver.js +30 -7
  181. package/dist/resolvers/ExecuteRemoteOperationResolver.js.map +1 -1
  182. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  183. package/dist/resolvers/GetDataResolver.js +34 -13
  184. package/dist/resolvers/GetDataResolver.js.map +1 -1
  185. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +401 -11
  186. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  187. package/dist/resolvers/IntegrationDiscoveryResolver.js +2690 -1305
  188. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  189. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  190. package/dist/resolvers/MCPResolver.js +13 -2
  191. package/dist/resolvers/MCPResolver.js.map +1 -1
  192. package/dist/resolvers/QuerySystemUserResolver.d.ts +36 -0
  193. package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
  194. package/dist/resolvers/QuerySystemUserResolver.js +174 -87
  195. package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
  196. package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
  197. package/dist/resolvers/RealtimeBridgeResolver.js +1 -0
  198. package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
  199. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +6 -0
  200. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  201. package/dist/resolvers/RealtimeClientSessionResolver.js +36 -5
  202. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  203. package/dist/resolvers/RemoteBrowserActionResolver.d.ts +62 -10
  204. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  205. package/dist/resolvers/RemoteBrowserActionResolver.js +217 -34
  206. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  207. package/dist/resolvers/RunAIAgentResolver.d.ts +24 -8
  208. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  209. package/dist/resolvers/RunAIAgentResolver.js +185 -67
  210. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  211. package/dist/resolvers/RunAIPromptResolver.d.ts +5 -3
  212. package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
  213. package/dist/resolvers/RunAIPromptResolver.js +19 -18
  214. package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
  215. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  216. package/dist/resolvers/RunTemplateResolver.js +3 -1
  217. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  218. package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
  219. package/dist/resolvers/meetingRecordingRegistration.js +2 -0
  220. package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
  221. package/dist/rest/MediaAccessKeys.d.ts.map +1 -1
  222. package/dist/rest/MediaAccessKeys.js +6 -2
  223. package/dist/rest/MediaAccessKeys.js.map +1 -1
  224. package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
  225. package/dist/rest/OAuthCallbackHandler.js +11 -5
  226. package/dist/rest/OAuthCallbackHandler.js.map +1 -1
  227. package/dist/rest/RealtimeRecordingHandler.d.ts +3 -3
  228. package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -1
  229. package/dist/rest/RealtimeRecordingHandler.js +2 -4
  230. package/dist/rest/RealtimeRecordingHandler.js.map +1 -1
  231. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  232. package/dist/rest/ViewOperationsHandler.js +2 -1
  233. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  234. package/dist/rest/setupRESTEndpoints.d.ts +3 -1
  235. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  236. package/dist/rest/setupRESTEndpoints.js +11 -2
  237. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  238. package/dist/services/DurableEntityActionTaskSubmitter.d.ts.map +1 -1
  239. package/dist/services/DurableEntityActionTaskSubmitter.js +6 -1
  240. package/dist/services/DurableEntityActionTaskSubmitter.js.map +1 -1
  241. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  242. package/dist/services/TaskGraphActionRunner.js +2 -26
  243. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  244. package/dist/services/TaskGraphAgentRunner.d.ts +6 -0
  245. package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
  246. package/dist/services/TaskGraphAgentRunner.js +38 -0
  247. package/dist/services/TaskGraphAgentRunner.js.map +1 -1
  248. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  249. package/dist/services/TaskGraphContinuationDeliverer.js +1 -0
  250. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  251. package/dist/services/WorkQueueHostService.d.ts +2 -1
  252. package/dist/services/WorkQueueHostService.d.ts.map +1 -1
  253. package/dist/services/WorkQueueHostService.js +19 -4
  254. package/dist/services/WorkQueueHostService.js.map +1 -1
  255. package/dist/services/workQueueConfig.d.ts +2 -2
  256. package/dist/services/workQueueConfig.js +5 -5
  257. package/dist/services/workQueueConfig.js.map +1 -1
  258. package/dist/sharedCache.js +1 -1
  259. package/dist/sharedCache.js.map +1 -1
  260. package/dist/types.d.ts +17 -0
  261. package/dist/types.d.ts.map +1 -1
  262. package/dist/types.js.map +1 -1
  263. package/package.json +98 -98
  264. package/src/__tests__/APIKeyScopeAuth.test.ts +4 -8
  265. package/src/__tests__/ActiveOperations.test.ts +68 -0
  266. package/src/__tests__/AgentSessionResolver.ownership.test.ts +13 -0
  267. package/src/__tests__/AssertTargetConfigs.test.ts +75 -0
  268. package/src/__tests__/BatchApplyParity.test.ts +109 -0
  269. package/src/__tests__/BridgeHostInstance.test.ts +42 -0
  270. package/src/__tests__/CollectInactiveRowWarnings.test.ts +115 -0
  271. package/src/__tests__/ConnectionPause.test.ts +192 -0
  272. package/src/__tests__/ConnectionPauseResolver.test.ts +166 -0
  273. package/src/__tests__/ConnectionPauseSave.test.ts +143 -0
  274. package/src/__tests__/CustomColumnPromoterCompletion.test.ts +142 -0
  275. package/src/__tests__/DeleteConnectionRemovesPerConnectionCatalog.test.ts +51 -0
  276. package/src/__tests__/DetachedDiscoveryStart.test.ts +65 -0
  277. package/src/__tests__/DurableEntityActionTaskSubmitter.test.ts +73 -0
  278. package/src/__tests__/EntityMapLifecycle.rekey.test.ts +252 -0
  279. package/src/__tests__/ExecuteRemoteOperationResolver.test.ts +213 -0
  280. package/src/__tests__/HandoffOfferExpiry.test.ts +40 -0
  281. package/src/__tests__/IntegrationRunArtifactAuthorization.test.ts +126 -0
  282. package/src/__tests__/MagicLinkKeys.test.ts +102 -0
  283. package/src/__tests__/MediaAccessKeys.test.ts +57 -10
  284. package/src/__tests__/NewArrivalsDefaultDisabled.test.ts +50 -0
  285. package/src/__tests__/ObjectNamesByID.test.ts +176 -0
  286. package/src/__tests__/PostRestartMapsInCatalogScope.test.ts +146 -0
  287. package/src/__tests__/QuerySystemUserResolver.childRows.test.ts +80 -0
  288. package/src/__tests__/QuerySystemUserResolver.collision.test.ts +200 -0
  289. package/src/__tests__/QuerySystemUserResolver.permissions.test.ts +132 -0
  290. package/src/__tests__/RSUPostRestartProgress.test.ts +343 -0
  291. package/src/__tests__/RSUProgressBridge.test.ts +188 -5
  292. package/src/__tests__/RSUStartupSweepWiring.test.ts +30 -0
  293. package/src/__tests__/ReactivateRefreshMessage.test.ts +10 -3
  294. package/src/__tests__/RealtimeClientSessionResolver.test.ts +22 -0
  295. package/src/__tests__/{RefreshAdoptsNewColumns.test.ts → RefreshReportsNewColumns.test.ts} +25 -16
  296. package/src/__tests__/RemoteBrowserActionRecovery.test.ts +287 -0
  297. package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +3 -0
  298. package/src/__tests__/RemoteBrowserActionResolver.ownership.test.ts +6 -4
  299. package/src/__tests__/RemoteBrowserAudioStream.test.ts +3 -0
  300. package/src/__tests__/RemoteBrowserSnapshot.test.ts +3 -0
  301. package/src/__tests__/ResolverBase.clientOldValues.test.ts +323 -26
  302. package/src/__tests__/ResolverBase.encryptedApiZeroReencrypt.test.ts +307 -0
  303. package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +53 -2
  304. package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +60 -0
  305. package/src/__tests__/RunAIAgentResolver.branch.test.ts +4 -0
  306. package/src/__tests__/RunAIAgentResolver.consultPredecessor.test.ts +289 -0
  307. package/src/__tests__/RunAIAgentResolver.handoff.test.ts +649 -0
  308. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +2 -0
  309. package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +2 -0
  310. package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +87 -12
  311. package/src/__tests__/SchemaEvolutionCustomColumns.test.ts +119 -0
  312. package/src/__tests__/SchemaRefreshLaunch.test.ts +24 -2
  313. package/src/__tests__/ScopedFieldsForBuild.test.ts +192 -0
  314. package/src/__tests__/SessionJanitor.test.ts +195 -4
  315. package/src/__tests__/SessionManager.test.ts +69 -0
  316. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +2 -2
  317. package/src/__tests__/TaskGraphAgentRunner.test.ts +272 -16
  318. package/src/__tests__/ViewOperationsHandler.test.ts +2 -5
  319. package/src/__tests__/WorkQueueHostService.test.ts +25 -7
  320. package/src/__tests__/backgroundSweepConfigUnits.test.ts +153 -0
  321. package/src/__tests__/contextRequestOrigin.test.ts +105 -0
  322. package/src/__tests__/conversationBrowsers.test.ts +62 -0
  323. package/src/__tests__/magicLinkExtensionCapabilities.test.ts +413 -0
  324. package/src/__tests__/orphanedConversationDetailReconciler.start.test.ts +82 -0
  325. package/src/__tests__/ownedRealtimeSession.test.ts +14 -0
  326. package/src/__tests__/realtimeRecordingHandler.test.ts +7 -2
  327. package/src/__tests__/realtimeSessions/sessionAccess.test.ts +79 -1
  328. package/src/__tests__/requestOrigin.test.ts +104 -0
  329. package/src/__tests__/securityHardeningPr6034.test.ts +120 -0
  330. package/src/__tests__/sessionDeadline.test.ts +51 -0
  331. package/src/__tests__/sharedCache.test.ts +11 -0
  332. package/src/__tests__/unifiedAuth.test.ts +73 -1
  333. package/src/agentSessions/BridgeHostInstance.ts +20 -5
  334. package/src/agentSessions/HandoffOfferExpiry.ts +18 -0
  335. package/src/agentSessions/ReturningVisitorRecap.ts +1 -0
  336. package/src/agentSessions/SessionJanitor.ts +92 -42
  337. package/src/agentSessions/SessionManager.ts +38 -8
  338. package/src/agentSessions/conversationBrowsers.ts +143 -0
  339. package/src/agentSessions/sessionDeadline.ts +81 -0
  340. package/src/auth/APIKeyScopeAuth.ts +5 -4
  341. package/src/auth/__tests__/loginEmailResolution.test.ts +67 -0
  342. package/src/auth/loginEmailResolution.ts +67 -0
  343. package/src/auth/magicLink/MagicLinkKeys.ts +146 -14
  344. package/src/auth/magicLink/MagicLinkRouter.ts +33 -6
  345. package/src/auth/magicLink/MagicLinkService.ts +250 -10
  346. package/src/auth/magicLink/index.ts +1 -1
  347. package/src/auth/magicLink/redeemLanding.ts +7 -4
  348. package/src/auth/magicLink/types.ts +28 -3
  349. package/src/auth/newUsers.ts +1 -0
  350. package/src/backgroundSweepConfigUnits.ts +213 -0
  351. package/src/config.ts +69 -0
  352. package/src/context.ts +39 -6
  353. package/src/coreRoutes.ts +14 -7
  354. package/src/generated/graphql-schemas/__mj.ts +822 -7
  355. package/src/generic/OrphanedConversationDetailReconciler.ts +32 -1
  356. package/src/generic/ResolverBase.ts +414 -143
  357. package/src/generic/RunViewResolver.ts +96 -49
  358. package/src/index.ts +201 -35
  359. package/src/integration/ConnectionPause.ts +222 -0
  360. package/src/integration/CustomColumnPromoter.ts +123 -53
  361. package/src/integration/EntityMapLifecycle.ts +229 -6
  362. package/src/integration/InactiveRowWarnings.ts +50 -0
  363. package/src/integration/ObjectNamesByID.ts +97 -0
  364. package/src/integration/PostRestartIntrospect.ts +49 -0
  365. package/src/integration/RSUPostRestartProgress.ts +359 -0
  366. package/src/integration/RSUProgressBridge.ts +85 -2
  367. package/src/integration/RunArtifactAuthorization.ts +65 -0
  368. package/src/integration/SchemaRefreshLaunch.ts +12 -2
  369. package/src/integration/ScopedFieldsForBuild.ts +113 -0
  370. package/src/integration/TargetConfigGuard.ts +71 -0
  371. package/src/realtimeSessions/ownedRealtimeSession.ts +2 -6
  372. package/src/realtimeSessions/sessionAccess.ts +30 -0
  373. package/src/realtimeWidget/WidgetSessionService.ts +2 -0
  374. package/src/realtimeWidget/visitorIdentity.ts +1 -0
  375. package/src/realtimeWidget/widgetCore.ts +4 -8
  376. package/src/realtimeWidget/widgetGuestElevation.ts +1 -0
  377. package/src/requestOrigin.ts +64 -0
  378. package/src/resolvers/AgentSessionResolver.ts +6 -2
  379. package/src/resolvers/AutotagPipelineResolver.ts +2 -1
  380. package/src/resolvers/ConversationRunEventsResolver.ts +2 -0
  381. package/src/resolvers/ExecuteRemoteOperationResolver.ts +41 -9
  382. package/src/resolvers/GetDataResolver.ts +35 -13
  383. package/src/resolvers/IntegrationDiscoveryResolver.ts +1522 -203
  384. package/src/resolvers/MCPResolver.ts +15 -2
  385. package/src/resolvers/QuerySystemUserResolver.ts +197 -98
  386. package/src/resolvers/RealtimeBridgeResolver.ts +1 -0
  387. package/src/resolvers/RealtimeClientSessionResolver.ts +40 -7
  388. package/src/resolvers/RemoteBrowserActionResolver.ts +242 -32
  389. package/src/resolvers/RunAIAgentResolver.ts +265 -86
  390. package/src/resolvers/RunAIPromptResolver.ts +18 -18
  391. package/src/resolvers/RunTemplateResolver.ts +3 -1
  392. package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +52 -0
  393. package/src/resolvers/meetingRecordingRegistration.ts +2 -0
  394. package/src/rest/MediaAccessKeys.ts +6 -2
  395. package/src/rest/OAuthCallbackHandler.ts +13 -5
  396. package/src/rest/RealtimeRecordingHandler.ts +5 -9
  397. package/src/rest/ViewOperationsHandler.ts +2 -1
  398. package/src/rest/setupRESTEndpoints.ts +11 -2
  399. package/src/services/DurableEntityActionTaskSubmitter.ts +10 -2
  400. package/src/services/TaskGraphActionRunner.ts +2 -23
  401. package/src/services/TaskGraphAgentRunner.ts +43 -0
  402. package/src/services/TaskGraphContinuationDeliverer.ts +1 -0
  403. package/src/services/WorkQueueHostService.ts +26 -4
  404. package/src/services/workQueueConfig.ts +5 -5
  405. package/src/sharedCache.ts +1 -1
  406. package/src/types.ts +18 -0
  407. package/src/services/TaskOrchestration-Integration.md +0 -188
@@ -23,6 +23,8 @@ vi.mock('../../auth/index.js', () => ({ GetSystemUser: vi.fn(),
23
23
  vi.mock('mssql', () => ({ default: { Request: vi.fn() } }));
24
24
 
25
25
  import {
26
+ GetDataResolver,
27
+ GetDataInputType,
26
28
  RegisterAccessToken,
27
29
  DeleteAccessToken,
28
30
  TokenExists,
@@ -31,6 +33,7 @@ import {
31
33
  PruneExpiredTokens,
32
34
  GetAccessTokenCount,
33
35
  } from '../GetDataResolver.js';
36
+ import type { AppContext } from '../../types.js';
34
37
 
35
38
  // ---------------------------------------------------------------------------
36
39
  // Regression coverage for a memory leak (Memory Leak Audit Round 7, Critical):
@@ -137,4 +140,53 @@ describe('GetDataResolver access-token lifecycle', () => {
137
140
  expect(GetAccessTokenCount()).toBeLessThan(before + 51);
138
141
  expect(TokenExists(survivorToken)).toBe(true);
139
142
  });
143
+
144
+ it('never leaks raw secret token values in thrown or returned error messages', async () => {
145
+ const duplicateSecret = `secret-dup-${uniqueToken()}`;
146
+ RegisterAccessToken(duplicateSecret, 60_000);
147
+
148
+ try {
149
+ RegisterAccessToken(duplicateSecret, 60_000);
150
+ expect.unreachable('Expected duplicate registration to throw');
151
+ } catch (err) {
152
+ expect((err as Error).message).not.toContain(duplicateSecret);
153
+ }
154
+
155
+ const missingSecret = `secret-missing-${uniqueToken()}`;
156
+ try {
157
+ DeleteAccessToken(missingSecret);
158
+ expect.unreachable('Expected deleting unknown token to throw');
159
+ } catch (err) {
160
+ expect((err as Error).message).not.toContain(missingSecret);
161
+ }
162
+
163
+ try {
164
+ RecordTokenUse(missingSecret, {});
165
+ expect.unreachable('Expected recording unknown token use to throw');
166
+ } catch (err) {
167
+ expect((err as Error).message).not.toContain(missingSecret);
168
+ }
169
+
170
+ const resolver = new GetDataResolver();
171
+ const input = new GetDataInputType();
172
+ input.Token = missingSecret;
173
+ input.Queries = ['SELECT 1'];
174
+ const output = await resolver.GetData(input, { dataSources: [] } as Partial<AppContext> as AppContext);
175
+ expect(output.Success).toBe(false);
176
+ expect(JSON.stringify(output.ErrorMessages)).not.toContain(missingSecret);
177
+ });
178
+
179
+ it('rejects empty tokens and near-miss prefix tokens across multiple active slots', () => {
180
+ const first = `slot-a-${uniqueToken()}`;
181
+ const second = `slot-b-${uniqueToken()}`;
182
+ RegisterAccessToken(first, 60_000);
183
+ RegisterAccessToken(second, 60_000);
184
+
185
+ expect(IsTokenValid('')).toBe(false);
186
+ expect(TokenExists('')).toBe(false);
187
+ expect(IsTokenValid(first.slice(0, -1))).toBe(false);
188
+ expect(IsTokenValid(`${second}-extra`)).toBe(false);
189
+ expect(IsTokenValid(first)).toBe(true);
190
+ expect(IsTokenValid(second)).toBe(true);
191
+ });
140
192
  });
@@ -268,6 +268,7 @@ async function findConversationByEgressID(egressID: string, contextUser: UserInf
268
268
  Fields: ['ID'],
269
269
  OrderBy: '__mj_CreatedAt DESC',
270
270
  MaxRows: 1,
271
+ SkipTotalRowCount: true,
271
272
  ResultType: 'simple',
272
273
  },
273
274
  contextUser,
@@ -288,6 +289,7 @@ async function findConversationByRoomName(roomName: string, contextUser: UserInf
288
289
  Fields: ['ID'],
289
290
  OrderBy: '__mj_CreatedAt DESC',
290
291
  MaxRows: 1,
292
+ SkipTotalRowCount: true,
291
293
  ResultType: 'simple',
292
294
  },
293
295
  contextUser,
@@ -18,7 +18,7 @@
18
18
 
19
19
  import { BaseSingleton } from '@memberjunction/global';
20
20
  import { LogStatus } from '@memberjunction/core';
21
- import { randomBytes } from 'node:crypto';
21
+ import { createHmac, randomBytes } from 'node:crypto';
22
22
  import jwt from 'jsonwebtoken';
23
23
 
24
24
  /** The token's `typ` claim — the route rejects any token whose `typ` differs. */
@@ -78,7 +78,11 @@ export class MediaAccessKeyManager extends BaseSingleton<MediaAccessKeyManager>
78
78
  }
79
79
  const configured = process.env.MJ_BASE_ENCRYPTION_KEY?.trim();
80
80
  if (configured) {
81
- this.secret = configured;
81
+ // Key separation: never sign tokens with the field-encryption master key itself. Derive a
82
+ // dedicated HS256 signing key (HKDF-style HMAC expand) so a token-signing compromise and the
83
+ // data-at-rest key stay decoupled. Tokens are short-lived, so changing the derivation only
84
+ // invalidates in-flight URLs, exactly like a restart on the ephemeral path below.
85
+ this.secret = createHmac('sha256', configured).update('mj-media-access-token-signing-v1').digest('base64');
82
86
  } else {
83
87
  this.secret = randomBytes(32).toString('base64');
84
88
  LogStatus(
@@ -28,6 +28,15 @@ const ENTITY_MCP_SERVERS = 'MJ: MCP Servers';
28
28
  /** Entity name for OAuth Authorization States */
29
29
  const ENTITY_OAUTH_AUTHORIZATION_STATES = 'MJ: O Auth Authorization States';
30
30
 
31
+ const UUID_SHAPE = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
32
+
33
+ function sqlUuid(value: string, argName: string): string {
34
+ if (typeof value !== 'string' || !UUID_SHAPE.test(value)) {
35
+ throw new Error(`${argName} must be a UUID`);
36
+ }
37
+ return value;
38
+ }
39
+
31
40
  /**
32
41
  * Configuration for OAuth callback handler
33
42
  */
@@ -693,12 +702,11 @@ export class OAuthCallbackHandler {
693
702
  const rv = new RunView();
694
703
 
695
704
  // Get connection to get server ID.
696
- // connectionId is caller-supplied (POST /oauth/initiate body). MJ ExtraFilter is a raw
697
- // SQL fragment, so single quotes MUST be doubled to prevent injection — matching the
698
- // escaping used for stateParameter in loadAuthorizationState().
705
+ // connectionId is caller-supplied (POST /oauth/initiate body); enforce strict UUID shape
706
+ // (matching MCPResolver.getServerOAuthConfig) before interpolating into ExtraFilter.
699
707
  const connResult = await rv.RunView<{ MCPServerID: string }>({
700
708
  EntityName: ENTITY_MCP_SERVER_CONNECTIONS,
701
- ExtraFilter: `ID='${connectionId.replace(/'/g, "''")}'`,
709
+ ExtraFilter: `ID='${sqlUuid(connectionId, 'connectionId')}'`,
702
710
  Fields: ['MCPServerID'],
703
711
  ResultType: 'simple'
704
712
  }, contextUser);
@@ -719,7 +727,7 @@ export class OAuthCallbackHandler {
719
727
  OAuthRequirePKCE: boolean | null;
720
728
  }>({
721
729
  EntityName: ENTITY_MCP_SERVERS,
722
- ExtraFilter: `ID='${serverId}'`,
730
+ ExtraFilter: `ID='${sqlUuid(serverId, 'serverId')}'`,
723
731
  Fields: [
724
732
  'OAuthIssuerURL', 'OAuthScopes', 'OAuthMetadataCacheTTLMinutes',
725
733
  'OAuthClientID', 'OAuthClientSecretEncrypted', 'OAuthRequirePKCE'
@@ -34,7 +34,7 @@ import {
34
34
  LoadOwnedRealtimeSession, RealtimeSessionNotFoundError, RealtimeSessionOwnershipError,
35
35
  } from '../realtimeSessions/ownedRealtimeSession.js';
36
36
  import type { IRecordingAssemblyScheduler } from '../realtimeSessions/RecordingAssemblyScheduler.js';
37
- import { AuthorizeSessionAccess, LoadSessionConversationScope } from '../realtimeSessions/sessionAccess.js';
37
+ import { AuthorizeLoadedSession } from '../realtimeSessions/sessionAccess.js';
38
38
 
39
39
  /** Where {@link CreateRealtimeRecordingRouter} is mounted (under the reserved `/realtime` root). */
40
40
  export const REALTIME_RECORDING_MOUNT_PATH = '/realtime/recording';
@@ -76,8 +76,8 @@ export interface RealtimeRecordingRouterDeps {
76
76
  /** The authenticated caller, or null (answered 401). */
77
77
  ResolveCaller(req: Request): RealtimeRecordingCaller | null;
78
78
  LoadOwnedSession: typeof LoadOwnedRealtimeSession;
79
- /** The session conversation's scope id and whether the caller could read it: the scope half of the access decision. */
80
- LoadConversationScope: typeof LoadSessionConversationScope;
79
+ /** The per-session scope rule of the access decision, applied to the session {@link LoadOwnedSession} returned. */
80
+ AuthorizeSession: typeof AuthorizeLoadedSession;
81
81
  /** The ledger for one request; `contextUser` is the caller (used for logging by the procs). */
82
82
  CreateLedger(provider: DatabaseProviderBase, contextUser: UserInfo): IRealtimeRecordingLedger;
83
83
  Scheduler: IRecordingAssemblyScheduler;
@@ -258,7 +258,7 @@ async function handleTerminal(deps: RealtimeRecordingRouterDeps, req: Request, r
258
258
 
259
259
  /**
260
260
  * Loads the session through the shared ownership gate, then applies the per-session scope rule of
261
- * {@link AuthorizeSessionAccess}. The production gate (`LoadOwnedRealtimeSession`) already applies the same
261
+ * {@link AuthorizeLoadedSession}. The production gate (`LoadOwnedRealtimeSession`) already applies the same
262
262
  * rule, so this is a deliberate second check at the HTTP boundary: `LoadOwnedSession` is an injected dependency,
263
263
  * and without the scope rule one anonymous guest could write shards to another guest's recording (every guest
264
264
  * shares the one Anonymous user), and a different-bytes shard would mark it Failed. It costs one extra
@@ -266,11 +266,7 @@ async function handleTerminal(deps: RealtimeRecordingRouterDeps, req: Request, r
266
266
  */
267
267
  async function loadAuthorizedSession(deps: RealtimeRecordingRouterDeps, sessionID: string, caller: RealtimeRecordingCaller): Promise<MJAIAgentSessionEntity> {
268
268
  const session = await deps.LoadOwnedSession(sessionID, caller.ContextUser, caller.Provider);
269
- const conversation = await deps.LoadConversationScope(session, caller.ContextUser, caller.Provider);
270
- const decision = AuthorizeSessionAccess(
271
- { SessionUserID: session.UserID, ConversationExternalID: conversation.ExternalID, ConversationReadable: conversation.Readable },
272
- caller.ContextUser,
273
- );
269
+ const decision = await deps.AuthorizeSession(session, caller.ContextUser, caller.Provider);
274
270
  if (decision.Allowed === false) {
275
271
  LogError(`RealtimeRecordingHandler: refused user ${caller.ContextUser.ID} on session ${sessionID}: ${decision.Reason}`);
276
272
  throw new RecordingRequestError(403, 'Not authorized for this realtime session');
@@ -2,6 +2,7 @@ import {
2
2
  BaseEntity, EntityInfo, LogError, Metadata, RunView, RunViewParams,
3
3
  RunViewResult, UserInfo, type IRunViewProvider
4
4
  } from '@memberjunction/core';
5
+ import { EscapeSQLString } from '@memberjunction/global';
5
6
  import { ClientClauseScreen } from '@memberjunction/generic-database-provider';
6
7
  import { ProjectRowsForCaller } from '../generic/fieldSecurityTransport.js';
7
8
 
@@ -163,7 +164,7 @@ export class ViewOperationsHandler {
163
164
  // Run a view to get the available views
164
165
  const params: RunViewParams = {
165
166
  EntityName: 'MJ: User Views',
166
- ExtraFilter: `Entity = '${entityName}'`
167
+ ExtraFilter: `Entity = '${EscapeSQLString(entity.Name)}'`
167
168
  };
168
169
 
169
170
  const runView = new RunView();
@@ -53,10 +53,12 @@ export interface RESTApiOptions {
53
53
  }
54
54
 
55
55
  /**
56
- * Default REST API configuration
56
+ * Default REST API configuration. Disabled by default (matching the documented default and
57
+ * MJServer's own config default): mounting a full-entity REST API must be an explicit decision,
58
+ * never a side effect of calling SetupRESTEndpoints with no options.
57
59
  */
58
60
  export const DEFAULT_REST_API_OPTIONS: RESTApiOptions = {
59
- enabled: true,
61
+ enabled: false,
60
62
  };
61
63
 
62
64
  /**
@@ -95,6 +97,13 @@ export function SetupRESTEndpoints(
95
97
  if (authMiddleware) {
96
98
  app.use(basePath, BodyParser.json({ limit: '50mb' }), authMiddleware, restHandler.getRouter());
97
99
  } else {
100
+ // MJServer itself is safe here (its unified auth middleware runs globally before this
101
+ // mount), but a third-party caller passing no authMiddleware may be mounting a fully
102
+ // UNauthenticated entity CRUD API — say so loudly.
103
+ LogStatusEx({
104
+ message: `REST API mounted at ${basePath} WITHOUT a route-level auth middleware. ` +
105
+ `Ensure an authentication middleware runs globally before this mount, or pass one to SetupRESTEndpoints.`,
106
+ });
98
107
  app.use(basePath, BodyParser.json({ limit: '50mb' }), restHandler.getRouter());
99
108
  }
100
109
 
@@ -15,7 +15,7 @@ import type {
15
15
  DurableEntityActionSubmission,
16
16
  DurableEntityActionSubmitter,
17
17
  } from '@memberjunction/actions-base';
18
- import { LogError } from '@memberjunction/core';
18
+ import { type IEntityDataProvider, type IMetadataProvider, LogError } from '@memberjunction/core';
19
19
  import { TaskNode, type TaskGraphSpec } from '@memberjunction/ai-core-plus';
20
20
  import { MJEnvironmentEntityExtended } from '@memberjunction/core-entities';
21
21
  import { TaskGraphService, type ProviderFactory } from '@memberjunction/task-graph';
@@ -59,7 +59,9 @@ export class DurableEntityActionTaskSubmitter implements DurableEntityActionSubm
59
59
  durable: true,
60
60
  };
61
61
 
62
- const provider = await this.providerFactory.CreateProvider();
62
+ const provider: IMetadataProvider = isMetadataProvider(request.Provider)
63
+ ? request.Provider
64
+ : await this.providerFactory.CreateProvider();
63
65
  const result = await new TaskGraphService().Submit(spec, {
64
66
  EnvironmentID: this.environmentID,
65
67
  ContextUser: request.ContextUser,
@@ -76,3 +78,9 @@ export class DurableEntityActionTaskSubmitter implements DurableEntityActionSubm
76
78
  }
77
79
  }
78
80
  }
81
+
82
+ function isMetadataProvider(
83
+ provider: IMetadataProvider | IEntityDataProvider | undefined,
84
+ ): provider is IMetadataProvider {
85
+ return !!provider && 'GetEntityObject' in provider && typeof provider.GetEntityObject === 'function';
86
+ }
@@ -11,6 +11,7 @@
11
11
  */
12
12
  import { ActionEngineServer } from '@memberjunction/actions';
13
13
  import { ActionParam } from '@memberjunction/actions-base';
14
+ import { BuildActionOutputObject } from '@memberjunction/ai-core-plus';
14
15
  import { LogError } from '@memberjunction/core';
15
16
  import { UUIDsEqual } from '@memberjunction/global';
16
17
  import type { TaskActionRunner, TaskActionRunParams, TaskActionRunResult } from '@memberjunction/task-graph';
@@ -97,29 +98,7 @@ export class TaskGraphActionRunner implements TaskActionRunner {
97
98
  * produced.
98
99
  */
99
100
  private buildOutput(actionParams: ActionParam[], resultMessage?: string | null): Record<string, unknown> {
100
- const output: Record<string, unknown> = {};
101
- if (typeof resultMessage === 'string') {
102
- const trimmed = resultMessage.trim();
103
- if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
104
- try {
105
- const parsed: unknown = JSON.parse(trimmed);
106
- if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
107
- Object.assign(output, parsed as Record<string, unknown>);
108
- }
109
- } catch {
110
- // Non-JSON prose message; ignore.
111
- }
112
- }
113
- }
114
- for (const p of actionParams ?? []) {
115
- if (p.Type === 'Output' || p.Type === 'Both') output[p.Name] = p.Value;
116
- }
117
- if (typeof output.handle === 'string' && output.Handle === undefined) {
118
- output.Handle = output.handle;
119
- } else if (typeof output.Handle === 'string' && output.handle === undefined) {
120
- output.handle = output.Handle;
121
- }
122
- return output;
101
+ return BuildActionOutputObject(actionParams, resultMessage);
123
102
  }
124
103
 
125
104
  /**
@@ -43,6 +43,25 @@ export class TaskGraphAgentRunner implements TaskAgentRunner {
43
43
  };
44
44
  }
45
45
  }
46
+
47
+ let configurationId: string | undefined;
48
+ const requestedPreset = params.ConfigurationPresetName?.trim();
49
+ if (requestedPreset) {
50
+ const matched = AIEngine.Instance.FindActiveAgentConfigurationPreset(agent.ID, requestedPreset);
51
+ if (!matched) {
52
+ const presets = AIEngine.Instance.GetAgentConfigurationPresets(agent.ID, true);
53
+ const available = presets.map((p) => p.Name).join(', ') || 'none';
54
+ return {
55
+ Success: false,
56
+ ErrorMessage: `Agent '${agent.Name || params.AgentID}' has no active preset '${requestedPreset}'. Available: ${available}.`,
57
+ };
58
+ }
59
+ configurationId = matched.AIConfigurationID ?? undefined;
60
+ } else {
61
+ configurationId = parentRun?.ConfigurationID ?? undefined;
62
+ }
63
+
64
+ const parentAgentHierarchy = this.buildParentAgentHierarchy(parentRun, params);
46
65
  const taskContext = await this.resolveTaskContext(params);
47
66
  const conversationDetailId =
48
67
  parentRun?.ConversationDetailID ?? taskContext.conversationDetailId ?? undefined;
@@ -66,6 +85,8 @@ export class TaskGraphAgentRunner implements TaskAgentRunner {
66
85
  // rather than starting the chain over. Without it MAX_REINVOKE_DEPTH never fires.
67
86
  continuationDepth: params.ContinuationDepth ?? 0,
68
87
  parentRun,
88
+ parentAgentHierarchy,
89
+ configurationId,
69
90
  // The bridge from the agent's own progress stream up to graph-level observers: the
70
91
  // dispatcher turns these into rate-limited `NodeProgress` frames, which is how a
71
92
  // running Agent step shows "what it is doing right now" on the workflow canvas.
@@ -221,6 +242,28 @@ export class TaskGraphAgentRunner implements TaskAgentRunner {
221
242
  }
222
243
  }
223
244
 
245
+ /**
246
+ * Reads the root-first ancestor agent name hierarchy carried on the task from when its graph was
247
+ * submitted (`params.ParentAgentHierarchy`), falling back to the submitting run's own agent name
248
+ * when no hierarchy was persisted on the parent task.
249
+ */
250
+ private buildParentAgentHierarchy(
251
+ parentRun: MJAIAgentRunEntityExtended | undefined,
252
+ params: TaskAgentRunParams,
253
+ ): string[] | undefined {
254
+ if (Array.isArray(params.ParentAgentHierarchy)) {
255
+ const carried = params.ParentAgentHierarchy
256
+ .filter((name): name is string => typeof name === 'string')
257
+ .map((name) => name.trim())
258
+ .filter((name) => name.length > 0);
259
+ if (carried.length > 0) {
260
+ return carried;
261
+ }
262
+ }
263
+ const submittingAgentName = parentRun?.Agent?.trim();
264
+ return submittingAgentName ? [submittingAgentName] : undefined;
265
+ }
266
+
224
267
  /**
225
268
  * Builds the agent's instruction from the task's name/description, its structured input payload,
226
269
  * and its dependencies' outputs.
@@ -491,6 +491,7 @@ export class TaskGraphContinuationDeliverer implements TaskContinuationDeliverer
491
491
  Fields: ['ID'],
492
492
  OrderBy: '__mj_CreatedAt DESC',
493
493
  MaxRows: 1,
494
+ SkipTotalRowCount: true,
494
495
  ResultType: 'simple',
495
496
  BypassCache: true,
496
497
  },
@@ -28,13 +28,25 @@ export interface StartableWorkQueueHost {
28
28
  export interface WorkQueueHostStartDependencies {
29
29
  Env: EnvironmentVariables;
30
30
  FindUserByEmail(email: string): UserInfo | undefined;
31
+ FindSystemUser?(): UserInfo | undefined;
31
32
  ConfigureEngine(user: UserInfo, provider: DatabaseProviderBase): Promise<WorkQueueEngine>;
32
33
  CreateHost(config: WorkQueueHostConfig, engine: WorkQueueEngine, user: UserInfo, provider: DatabaseProviderBase, providerSource: WorkQueueProviderSource): StartableWorkQueueHost;
33
34
  }
34
35
 
36
+ const DEFAULT_SYSTEM_USER_EMAILS = new Set(['system@memberjunction.org', 'not.set@nowhere.com']);
37
+
38
+ type IndependentProviderCapable = IMetadataProvider & {
39
+ CreateIndependentInstance(): Promise<IMetadataProvider>;
40
+ };
41
+
42
+ function hasCreateIndependentInstance(provider: IMetadataProvider): provider is IndependentProviderCapable {
43
+ return 'CreateIndependentInstance' in provider && typeof provider.CreateIndependentInstance === 'function';
44
+ }
45
+
35
46
  export const DEFAULT_WORK_QUEUE_HOST_START_DEPENDENCIES: WorkQueueHostStartDependencies = {
36
47
  Env: process.env,
37
48
  FindUserByEmail: email => UserCache.Users.find(user => user.Email?.trim().toLowerCase() === email.trim().toLowerCase()),
49
+ FindSystemUser: () => UserCache.Instance.GetSystemUser(),
38
50
  ConfigureEngine: async (user, provider) => {
39
51
  await WorkQueueEngine.Instance.Config(false, user, provider);
40
52
  await ReportTopologyIssues(WorkQueueEngine.Instance);
@@ -89,7 +101,7 @@ export function BuildWorkQueueHostConfig(config: WorkQueueConfig, instanceID: st
89
101
  };
90
102
  }
91
103
 
92
- /** A fresh SQL Server provider per delivery over the shared pool; the server provider otherwise. */
104
+ /** A fresh SQL Server or PostgreSQL provider per delivery over the shared pool; the server provider otherwise. */
93
105
  export class MJServerWorkQueueProviderSource implements WorkQueueProviderSource {
94
106
  private readonly factory: TaskGraphProviderFactory | null;
95
107
 
@@ -97,8 +109,14 @@ export class MJServerWorkQueueProviderSource implements WorkQueueProviderSource
97
109
  this.factory = pool ? new TaskGraphProviderFactory(pool) : null;
98
110
  }
99
111
 
100
- public CreateProvider(): Promise<IMetadataProvider> {
101
- return this.factory ? this.factory.CreateProvider() : Promise.resolve(this.fallback);
112
+ public async CreateProvider(): Promise<IMetadataProvider> {
113
+ if (this.factory) {
114
+ return this.factory.CreateProvider();
115
+ }
116
+ if (hasCreateIndependentInstance(this.fallback)) {
117
+ return this.fallback.CreateIndependentInstance();
118
+ }
119
+ return this.fallback;
102
120
  }
103
121
  }
104
122
 
@@ -116,7 +134,11 @@ export async function StartWorkQueueHost(
116
134
  LogStatus(`[WorkQueue] Host disabled by ${WORK_QUEUE_DISABLE_ENV}=1 — this process publishes but runs no subscriptions.`);
117
135
  return null;
118
136
  }
119
- const user = dependencies.FindUserByEmail(config.systemUserEmail);
137
+ const configuredEmail = config.systemUserEmail?.trim() ?? '';
138
+ let user = configuredEmail ? dependencies.FindUserByEmail(configuredEmail) : undefined;
139
+ if (!user && (!configuredEmail || DEFAULT_SYSTEM_USER_EMAILS.has(configuredEmail.toLowerCase()))) {
140
+ user = dependencies.FindSystemUser?.();
141
+ }
120
142
  if (!user) {
121
143
  throw new Error(`[WorkQueue] System user not found with email: ${config.systemUserEmail} — set workQueue.systemUserEmail in mj.config.cjs`);
122
144
  }
@@ -18,7 +18,7 @@ export const WorkQueueSubscriptionEntrySchema = z.object({
18
18
  */
19
19
  export const WorkQueueSchema = z
20
20
  .object({
21
- enabled: z.boolean().optional().default(false),
21
+ enabled: z.boolean().optional().default(true),
22
22
  systemUserEmail: z.string().optional().default('system@memberjunction.org'),
23
23
  subscriptions: z.array(WorkQueueSubscriptionEntrySchema).optional().default([{ name: '*', concurrency: 4 }]),
24
24
  idlePollMinMs: z.number().int().positive().optional().default(250),
@@ -36,12 +36,12 @@ export const WorkQueueSchema = z
36
36
  export type WorkQueueConfig = z.infer<typeof WorkQueueSchema>;
37
37
 
38
38
  /**
39
- * The merge base for mj.config.cjs. Like scheduledJobs and integrationSyncWorker, the EFFECTIVE default system user
40
- * is the placeholder: set workQueue.systemUserEmail explicitly, or StartWorkQueueHost fails fast and says so.
39
+ * The merge base for mj.config.cjs. Enabled by default with the Database transport out of the box; StartWorkQueueHost
40
+ * resolves `systemUserEmail` first and falls back to `UserCache.Instance.GetSystemUser()` when the default is unchanged.
41
41
  */
42
42
  export const DEFAULT_WORK_QUEUE_CONFIG: WorkQueueConfig = {
43
- enabled: false,
44
- systemUserEmail: 'not.set@nowhere.com',
43
+ enabled: true,
44
+ systemUserEmail: 'system@memberjunction.org',
45
45
  subscriptions: [{ name: '*', concurrency: 4 }],
46
46
  idlePollMinMs: 250,
47
47
  idlePollMaxMs: 5000,
@@ -238,7 +238,7 @@ function relayRunViewChangeToBrowsers(event: CacheChangedEvent): void {
238
238
  PubSubManager.Instance.Publish(CACHE_INVALIDATION_TOPIC, {
239
239
  entityName,
240
240
  primaryKeyValues: null, // entity-level invalidation
241
- action: event.Action,
241
+ action: event.Action === 'row_delta' ? 'set' : event.Action,
242
242
  sourceServerId: event.SourceServerId || 'unknown',
243
243
  timestamp: new Date(),
244
244
  });
package/src/types.ts CHANGED
@@ -73,6 +73,19 @@ export type AppContext = {
73
73
  * Used only to key abuse limits (e.g. realtime verification sends) — never as an identity.
74
74
  */
75
75
  ClientIp?: string;
76
+
77
+ /**
78
+ * The request's `Origin` header as a normalized origin — scheme, host and port, lowercased, no
79
+ * trailing slash (e.g. `https://app.example.com:8443`). Normalized by `NormalizeOrigin`, the same
80
+ * helper the realtime widget allowlist uses, so it compares to allowlist entries normalized the
81
+ * same way with plain string equality. Ports are kept as sent; browsers omit default ports.
82
+ *
83
+ * Undefined when the request sent no `Origin` (server-to-server calls, many same-origin GETs),
84
+ * sent the opaque `null` origin, or sent a value that is not an http(s) origin. Always absent on
85
+ * WebSocket (subscription) contexts. Treat undefined as "origin unknown": an allowlist check
86
+ * must fail closed on it.
87
+ */
88
+ RequestOrigin?: string;
76
89
  };
77
90
 
78
91
  export class ProviderInfo {
@@ -145,6 +158,11 @@ export type RunViewGenericParams = {
145
158
  * Propagated to `RunViewParams.IncludeBinaryFields`.
146
159
  */
147
160
  includeBinaryFields?: boolean;
161
+ /**
162
+ * When true, no count runs to populate `TotalRowCount`, which comes back undefined.
163
+ * Propagated to `RunViewParams.SkipTotalRowCount`.
164
+ */
165
+ skipTotalRowCount?: boolean;
148
166
  /**
149
167
  * Optional registered Alternate Base View logical Name (from `EntityAlternateBaseView.Name`)
150
168
  * for this entity. Propagated to `RunViewParams.AlternateBaseView`.