@memberjunction/server 6.2.0-edge.5 → 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 (401) hide show
  1. package/README.md +27 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentSessions/SessionJanitor.d.ts +3 -3
  4. package/dist/agentSessions/SessionJanitor.js +3 -3
  5. package/dist/agentSessions/SessionManager.d.ts +15 -5
  6. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  7. package/dist/agentSessions/SessionManager.js +34 -12
  8. package/dist/agentSessions/SessionManager.js.map +1 -1
  9. package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
  10. package/dist/auth/AuthProviderCatalogRouter.js +2 -0
  11. package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
  12. package/dist/auth/index.d.ts.map +1 -1
  13. package/dist/auth/index.js +51 -10
  14. package/dist/auth/index.js.map +1 -1
  15. package/dist/auth/initializeProviders.d.ts +10 -0
  16. package/dist/auth/initializeProviders.d.ts.map +1 -1
  17. package/dist/auth/initializeProviders.js +37 -1
  18. package/dist/auth/initializeProviders.js.map +1 -1
  19. package/dist/auth/localDevAuth.d.ts +79 -0
  20. package/dist/auth/localDevAuth.d.ts.map +1 -0
  21. package/dist/auth/localDevAuth.js +439 -0
  22. package/dist/auth/localDevAuth.js.map +1 -0
  23. package/dist/auth/magicLink/MagicLinkKeys.d.ts +2 -2
  24. package/dist/auth/magicLink/MagicLinkKeys.d.ts.map +1 -1
  25. package/dist/auth/magicLink/MagicLinkKeys.js +1 -1
  26. package/dist/auth/magicLink/MagicLinkKeys.js.map +1 -1
  27. package/dist/auth/magicLink/types.d.ts +12 -0
  28. package/dist/auth/magicLink/types.d.ts.map +1 -1
  29. package/dist/auth/sessionUserClone.d.ts +1 -1
  30. package/dist/auth/sessionUserClone.d.ts.map +1 -1
  31. package/dist/auth/sessionUserClone.js +3 -2
  32. package/dist/auth/sessionUserClone.js.map +1 -1
  33. package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts +292 -0
  34. package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts.map +1 -0
  35. package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js +442 -0
  36. package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js.map +1 -0
  37. package/dist/broadcast/index.d.ts +6 -0
  38. package/dist/broadcast/index.d.ts.map +1 -0
  39. package/dist/broadcast/index.js +6 -0
  40. package/dist/broadcast/index.js.map +1 -0
  41. package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.d.ts +43 -0
  42. package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.d.ts.map +1 -0
  43. package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.js +144 -0
  44. package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.js.map +1 -0
  45. package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.d.ts +46 -0
  46. package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.d.ts.map +1 -0
  47. package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.js +149 -0
  48. package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.js.map +1 -0
  49. package/dist/broadcast/providers/GCPPubSubBroadcastProvider.d.ts +49 -0
  50. package/dist/broadcast/providers/GCPPubSubBroadcastProvider.d.ts.map +1 -0
  51. package/dist/broadcast/providers/GCPPubSubBroadcastProvider.js +131 -0
  52. package/dist/broadcast/providers/GCPPubSubBroadcastProvider.js.map +1 -0
  53. package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.d.ts +24 -0
  54. package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.d.ts.map +1 -0
  55. package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.js +51 -0
  56. package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.js.map +1 -0
  57. package/dist/cache.d.ts +3 -2
  58. package/dist/cache.d.ts.map +1 -1
  59. package/dist/cache.js.map +1 -1
  60. package/dist/config.d.ts +496 -0
  61. package/dist/config.d.ts.map +1 -1
  62. package/dist/config.js +61 -0
  63. package/dist/config.js.map +1 -1
  64. package/dist/context.d.ts +3 -1
  65. package/dist/context.d.ts.map +1 -1
  66. package/dist/context.js +29 -8
  67. package/dist/context.js.map +1 -1
  68. package/dist/coreRoutes.d.ts.map +1 -1
  69. package/dist/coreRoutes.js +14 -0
  70. package/dist/coreRoutes.js.map +1 -1
  71. package/dist/generated/graphql-schemas/__mj.d.ts +635 -14
  72. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  73. package/dist/generated/graphql-schemas/__mj.js +3366 -418
  74. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  75. package/dist/generic/CacheInvalidationResolver.d.ts +50 -30
  76. package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
  77. package/dist/generic/CacheInvalidationResolver.js +154 -79
  78. package/dist/generic/CacheInvalidationResolver.js.map +1 -1
  79. package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -1
  80. package/dist/generic/OrphanedConversationDetailReconciler.js +2 -0
  81. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
  82. package/dist/generic/PubSubManager.d.ts +10 -0
  83. package/dist/generic/PubSubManager.d.ts.map +1 -1
  84. package/dist/generic/PubSubManager.js +44 -1
  85. package/dist/generic/PubSubManager.js.map +1 -1
  86. package/dist/generic/PushStatusResolver.d.ts +39 -6
  87. package/dist/generic/PushStatusResolver.d.ts.map +1 -1
  88. package/dist/generic/PushStatusResolver.js +93 -11
  89. package/dist/generic/PushStatusResolver.js.map +1 -1
  90. package/dist/generic/ResolverBase.d.ts +65 -25
  91. package/dist/generic/ResolverBase.d.ts.map +1 -1
  92. package/dist/generic/ResolverBase.js +201 -101
  93. package/dist/generic/ResolverBase.js.map +1 -1
  94. package/dist/generic/RunViewResolver.d.ts +11 -3
  95. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  96. package/dist/generic/RunViewResolver.js +79 -13
  97. package/dist/generic/RunViewResolver.js.map +1 -1
  98. package/dist/generic/actionOutputFieldSecurity.d.ts +26 -0
  99. package/dist/generic/actionOutputFieldSecurity.d.ts.map +1 -0
  100. package/dist/generic/actionOutputFieldSecurity.js +47 -0
  101. package/dist/generic/actionOutputFieldSecurity.js.map +1 -0
  102. package/dist/generic/fieldSecurityTransport.d.ts +30 -0
  103. package/dist/generic/fieldSecurityTransport.d.ts.map +1 -0
  104. package/dist/generic/fieldSecurityTransport.js +30 -0
  105. package/dist/generic/fieldSecurityTransport.js.map +1 -0
  106. package/dist/index.d.ts +3 -0
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +122 -66
  109. package/dist/index.js.map +1 -1
  110. package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
  111. package/dist/integration/CustomColumnPromoter.js +6 -1
  112. package/dist/integration/CustomColumnPromoter.js.map +1 -1
  113. package/dist/logging/variablesLoggingMiddleware.d.ts +12 -0
  114. package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
  115. package/dist/logging/variablesLoggingMiddleware.js +50 -1
  116. package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
  117. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -1
  118. package/dist/realtimeSessions/SessionVerificationPortsBase.js +1 -0
  119. package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -1
  120. package/dist/realtimeSessions/ownedRealtimeSession.d.ts +8 -6
  121. package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -1
  122. package/dist/realtimeSessions/ownedRealtimeSession.js +15 -6
  123. package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -1
  124. package/dist/realtimeSessions/sessionAccess.d.ts +88 -11
  125. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
  126. package/dist/realtimeSessions/sessionAccess.js +125 -22
  127. package/dist/realtimeSessions/sessionAccess.js.map +1 -1
  128. package/dist/realtimeSessions/sessionConfigStamps.js +1 -1
  129. package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -1
  130. package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -1
  131. package/dist/realtimeSessions/subscriptionAuthorization.js +5 -2
  132. package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -1
  133. package/dist/realtimeSessions/verificationWorkflow.d.ts +2 -0
  134. package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -1
  135. package/dist/realtimeSessions/verificationWorkflow.js +1 -1
  136. package/dist/realtimeSessions/verificationWorkflow.js.map +1 -1
  137. package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
  138. package/dist/realtimeWidget/WidgetRouter.js +19 -3
  139. package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
  140. package/dist/realtimeWidget/WidgetSessionService.d.ts +67 -7
  141. package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -1
  142. package/dist/realtimeWidget/WidgetSessionService.js +201 -19
  143. package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
  144. package/dist/realtimeWidget/host-identity.d.ts +1 -1
  145. package/dist/realtimeWidget/host-identity.js +1 -1
  146. package/dist/realtimeWidget/widgetCore.d.ts +20 -1
  147. package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
  148. package/dist/realtimeWidget/widgetCore.js +17 -1
  149. package/dist/realtimeWidget/widgetCore.js.map +1 -1
  150. package/dist/realtimeWidget/widgetGuestElevation.d.ts +1 -1
  151. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  152. package/dist/realtimeWidget/widgetGuestElevation.js +2 -1
  153. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  154. package/dist/resolvers/ActionResolver.d.ts +19 -1
  155. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  156. package/dist/resolvers/ActionResolver.js +63 -12
  157. package/dist/resolvers/ActionResolver.js.map +1 -1
  158. package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
  159. package/dist/resolvers/AdhocQueryResolver.js +1 -0
  160. package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
  161. package/dist/resolvers/AgentRunStatusPublisher.d.ts +18 -4
  162. package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -1
  163. package/dist/resolvers/AgentRunStatusPublisher.js +32 -8
  164. package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -1
  165. package/dist/resolvers/AgentSessionResolver.d.ts +10 -4
  166. package/dist/resolvers/AgentSessionResolver.d.ts.map +1 -1
  167. package/dist/resolvers/AgentSessionResolver.js +40 -17
  168. package/dist/resolvers/AgentSessionResolver.js.map +1 -1
  169. package/dist/resolvers/EntityCommunicationsResolver.d.ts +13 -1
  170. package/dist/resolvers/EntityCommunicationsResolver.d.ts.map +1 -1
  171. package/dist/resolvers/EntityCommunicationsResolver.js +50 -14
  172. package/dist/resolvers/EntityCommunicationsResolver.js.map +1 -1
  173. package/dist/resolvers/FetchEntityVectorsResolver.d.ts +28 -0
  174. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  175. package/dist/resolvers/FetchEntityVectorsResolver.js +117 -21
  176. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  177. package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
  178. package/dist/resolvers/FileCategoryResolver.js +1 -0
  179. package/dist/resolvers/FileCategoryResolver.js.map +1 -1
  180. package/dist/resolvers/FileResolver.d.ts +5 -0
  181. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  182. package/dist/resolvers/FileResolver.js +13 -4
  183. package/dist/resolvers/FileResolver.js.map +1 -1
  184. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  185. package/dist/resolvers/IntegrationDiscoveryResolver.js +45 -7
  186. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  187. package/dist/resolvers/MergeRecordsResolver.d.ts +8 -1
  188. package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
  189. package/dist/resolvers/MergeRecordsResolver.js +31 -3
  190. package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
  191. package/dist/resolvers/PipelineProgressResolver.d.ts +6 -0
  192. package/dist/resolvers/PipelineProgressResolver.d.ts.map +1 -1
  193. package/dist/resolvers/PipelineProgressResolver.js +5 -3
  194. package/dist/resolvers/PipelineProgressResolver.js.map +1 -1
  195. package/dist/resolvers/QueryResolver.d.ts.map +1 -1
  196. package/dist/resolvers/QueryResolver.js +20 -6
  197. package/dist/resolvers/QueryResolver.js.map +1 -1
  198. package/dist/resolvers/QuerySystemUserResolver.d.ts +2 -0
  199. package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
  200. package/dist/resolvers/QuerySystemUserResolver.js +15 -6
  201. package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
  202. package/dist/resolvers/RSUResolver.d.ts.map +1 -1
  203. package/dist/resolvers/RSUResolver.js +12 -0
  204. package/dist/resolvers/RSUResolver.js.map +1 -1
  205. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +16 -2
  206. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  207. package/dist/resolvers/RealtimeClientSessionResolver.js +82 -28
  208. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  209. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  210. package/dist/resolvers/RemoteBrowserActionResolver.js +11 -9
  211. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  212. package/dist/resolvers/RunAIAgentResolver.d.ts +56 -8
  213. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  214. package/dist/resolvers/RunAIAgentResolver.js +209 -64
  215. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  216. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  217. package/dist/resolvers/RunTemplateResolver.js +4 -4
  218. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  219. package/dist/resolvers/RunTestResolver.d.ts.map +1 -1
  220. package/dist/resolvers/RunTestResolver.js +3 -1
  221. package/dist/resolvers/RunTestResolver.js.map +1 -1
  222. package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
  223. package/dist/resolvers/SyncDataResolver.js +4 -0
  224. package/dist/resolvers/SyncDataResolver.js.map +1 -1
  225. package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
  226. package/dist/resolvers/TestQuerySQLResolver.js +1 -0
  227. package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
  228. package/dist/resolvers/TransactionGroupResolver.d.ts +17 -2
  229. package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
  230. package/dist/resolvers/TransactionGroupResolver.js +60 -15
  231. package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
  232. package/dist/resolvers/UserViewResolver.d.ts +1 -1
  233. package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
  234. package/dist/resolvers/UserViewResolver.js +2 -1
  235. package/dist/resolvers/UserViewResolver.js.map +1 -1
  236. package/dist/rest/EntityCRUDHandler.d.ts +6 -0
  237. package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
  238. package/dist/rest/EntityCRUDHandler.js +19 -5
  239. package/dist/rest/EntityCRUDHandler.js.map +1 -1
  240. package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
  241. package/dist/rest/RESTEndpointHandler.js +8 -5
  242. package/dist/rest/RESTEndpointHandler.js.map +1 -1
  243. package/dist/rest/RealtimeRecordingHandler.d.ts +3 -3
  244. package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -1
  245. package/dist/rest/RealtimeRecordingHandler.js +7 -7
  246. package/dist/rest/RealtimeRecordingHandler.js.map +1 -1
  247. package/dist/rest/ViewOperationsHandler.d.ts +6 -0
  248. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  249. package/dist/rest/ViewOperationsHandler.js +22 -5
  250. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  251. package/dist/serverRoleConfigUnits.d.ts +29 -0
  252. package/dist/serverRoleConfigUnits.d.ts.map +1 -0
  253. package/dist/serverRoleConfigUnits.js +33 -0
  254. package/dist/serverRoleConfigUnits.js.map +1 -0
  255. package/dist/services/TaskGraphContinuationDeliverer.d.ts +5 -0
  256. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  257. package/dist/services/TaskGraphContinuationDeliverer.js +42 -15
  258. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  259. package/dist/types.d.ts +23 -1
  260. package/dist/types.d.ts.map +1 -1
  261. package/dist/types.js.map +1 -1
  262. package/package.json +98 -98
  263. package/src/__tests__/ActionResolver.fieldSecurity.test.ts +237 -0
  264. package/src/__tests__/AdhocQueryResolver.dialect.test.ts +137 -0
  265. package/src/__tests__/AgentRunStatusPublisher.test.ts +49 -0
  266. package/src/__tests__/AgentSessionResolver.ownership.test.ts +137 -0
  267. package/src/__tests__/CustomColumnPromoterOnePass.test.ts +15 -1
  268. package/src/__tests__/EntityCommunicationsResolver.actingUser.test.ts +151 -0
  269. package/src/__tests__/EvolutionActsOnWhatItDetects.test.ts +113 -0
  270. package/src/__tests__/FetchEntityVectorsResolver.test.ts +206 -3
  271. package/src/__tests__/FileResolver.fieldSecurity.test.ts +82 -0
  272. package/src/__tests__/PipelineProgressResolver.filter.test.ts +58 -0
  273. package/src/__tests__/QuerySystemUserResolver.fieldSecurity.test.ts +49 -0
  274. package/src/__tests__/RESTEndpointHandler.test.ts +25 -0
  275. package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +23 -3
  276. package/src/__tests__/RealtimeClientSessionResolver.test.ts +324 -46
  277. package/src/__tests__/RemoteBrowserActionResolver.ownership.test.ts +98 -0
  278. package/src/__tests__/ResolverBase.clientOldValues.test.ts +37 -4
  279. package/src/__tests__/ResolverBase.deleteReturnProjection.test.ts +52 -0
  280. package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +176 -0
  281. package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +23 -1
  282. package/src/__tests__/ResolverBase.publishStatusUpdate.test.ts +68 -0
  283. package/src/__tests__/ResolverBase.userViewCacheAndDedup.test.ts +130 -0
  284. package/src/__tests__/RunAIAgentResolver.branch.test.ts +68 -13
  285. package/src/__tests__/RunAIAgentResolver.conversationWriter.test.ts +210 -0
  286. package/src/__tests__/RunAIAgentResolver.fireAndForgetCompletion.test.ts +209 -0
  287. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +17 -27
  288. package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +8 -2
  289. package/src/__tests__/RunAIAgentResolver.serverReply.test.ts +358 -0
  290. package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +4 -1
  291. package/src/__tests__/RunTemplateResolver.test.ts +35 -2
  292. package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +11 -0
  293. package/src/__tests__/SessionManager.test.ts +95 -0
  294. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +114 -3
  295. package/src/__tests__/TransactionGroupResolver.fieldSecurity.test.ts +199 -0
  296. package/src/__tests__/UserViewResolver.updateWhereClause.test.ts +15 -0
  297. package/src/__tests__/ViewOperationsHandler.test.ts +7 -2
  298. package/src/__tests__/WidgetSessionService.test.ts +583 -4
  299. package/src/__tests__/apiRootBoot.test.ts +1 -1
  300. package/src/__tests__/buildMagicLinkSessionUser.test.ts +96 -0
  301. package/src/__tests__/cacheBroadcastProviders.test.ts +403 -0
  302. package/src/__tests__/cacheInvalidationRecordData.test.ts +45 -0
  303. package/src/__tests__/fieldSecurityFixtures.ts +91 -0
  304. package/src/__tests__/globalCors.test.ts +3 -3
  305. package/src/__tests__/localDevAuth.test.ts +196 -0
  306. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +10 -0
  307. package/src/__tests__/pushStatusResolver.filter.test.ts +57 -1
  308. package/src/__tests__/realtimeRecordingHandler.test.ts +19 -2
  309. package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +29 -1
  310. package/src/__tests__/realtimeSessions/ownedRealtimeSession.anonymous.test.ts +31 -0
  311. package/src/__tests__/realtimeSessions/ownedRealtimeSession.namedScoped.test.ts +37 -0
  312. package/src/__tests__/realtimeSessions/sessionAccess.test.ts +146 -7
  313. package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +1 -1
  314. package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +25 -4
  315. package/src/__tests__/resolverBase.cloudEventChangedFields.test.ts +157 -0
  316. package/src/__tests__/resolverBase.fieldSecurityTransport.test.ts +222 -0
  317. package/src/__tests__/resolverBase.fls.test.ts +146 -97
  318. package/src/__tests__/restTransport.fieldSecurity.test.ts +148 -0
  319. package/src/__tests__/runParamsTimeZone.test.ts +179 -0
  320. package/src/__tests__/runStreams.fieldSecurity.test.ts +100 -0
  321. package/src/__tests__/runViewProperties.test.ts +114 -0
  322. package/src/__tests__/scalabilityBenchmarks.test.ts +765 -0
  323. package/src/__tests__/scalabilityDatabaseIntegration.test.ts +207 -0
  324. package/src/__tests__/sessionUserClone.test.ts +5 -1
  325. package/src/__tests__/startupSweepOrder.test.ts +40 -0
  326. package/src/__tests__/unifiedAuth.test.ts +28 -0
  327. package/src/__tests__/widgetGuestElevation.test.ts +2 -0
  328. package/src/agentSessions/SessionJanitor.ts +3 -3
  329. package/src/agentSessions/SessionManager.ts +35 -12
  330. package/src/auth/AuthProviderCatalogRouter.ts +3 -0
  331. package/src/auth/index.ts +56 -12
  332. package/src/auth/initializeProviders.ts +43 -1
  333. package/src/auth/localDevAuth.ts +528 -0
  334. package/src/auth/magicLink/MagicLinkKeys.ts +2 -2
  335. package/src/auth/magicLink/types.ts +10 -0
  336. package/src/auth/sessionUserClone.ts +3 -2
  337. package/src/broadcast/BaseCacheInvalidationBroadcastProvider.ts +674 -0
  338. package/src/broadcast/index.ts +5 -0
  339. package/src/broadcast/providers/AWSIoTCoreBroadcastProvider.ts +180 -0
  340. package/src/broadcast/providers/AzureWebPubSubBroadcastProvider.ts +182 -0
  341. package/src/broadcast/providers/GCPPubSubBroadcastProvider.ts +169 -0
  342. package/src/broadcast/providers/SequencedRoleBucketBroadcastProvider.ts +57 -0
  343. package/src/cache.ts +2 -1
  344. package/src/config.ts +69 -0
  345. package/src/context.ts +32 -8
  346. package/src/coreRoutes.ts +15 -0
  347. package/src/generated/graphql-schemas/__mj.ts +2239 -102
  348. package/src/generic/CacheInvalidationResolver.ts +135 -78
  349. package/src/generic/OrphanedConversationDetailReconciler.ts +4 -2
  350. package/src/generic/PubSubManager.ts +54 -1
  351. package/src/generic/PushStatusResolver.ts +108 -11
  352. package/src/generic/ResolverBase.ts +237 -107
  353. package/src/generic/RunViewResolver.ts +80 -15
  354. package/src/generic/actionOutputFieldSecurity.ts +75 -0
  355. package/src/generic/fieldSecurityTransport.ts +62 -0
  356. package/src/index.ts +127 -68
  357. package/src/integration/CustomColumnPromoter.ts +6 -1
  358. package/src/logging/variablesLoggingMiddleware.ts +59 -3
  359. package/src/realtimeSessions/README.md +7 -3
  360. package/src/realtimeSessions/SessionVerificationPortsBase.ts +1 -0
  361. package/src/realtimeSessions/ownedRealtimeSession.ts +20 -6
  362. package/src/realtimeSessions/sessionAccess.ts +181 -25
  363. package/src/realtimeSessions/sessionConfigStamps.ts +1 -1
  364. package/src/realtimeSessions/subscriptionAuthorization.ts +4 -2
  365. package/src/realtimeSessions/verificationWorkflow.ts +3 -1
  366. package/src/realtimeWidget/WidgetRouter.ts +22 -4
  367. package/src/realtimeWidget/WidgetSessionService.ts +252 -17
  368. package/src/realtimeWidget/host-identity.ts +1 -1
  369. package/src/realtimeWidget/widgetCore.ts +30 -1
  370. package/src/realtimeWidget/widgetGuestElevation.ts +2 -1
  371. package/src/resolvers/ActionResolver.ts +78 -15
  372. package/src/resolvers/AdhocQueryResolver.ts +1 -0
  373. package/src/resolvers/AgentRunStatusPublisher.ts +36 -8
  374. package/src/resolvers/AgentSessionResolver.ts +46 -18
  375. package/src/resolvers/EntityCommunicationsResolver.ts +56 -15
  376. package/src/resolvers/FetchEntityVectorsResolver.ts +132 -21
  377. package/src/resolvers/FileCategoryResolver.ts +1 -0
  378. package/src/resolvers/FileResolver.ts +14 -4
  379. package/src/resolvers/IntegrationDiscoveryResolver.ts +49 -7
  380. package/src/resolvers/MergeRecordsResolver.ts +23 -2
  381. package/src/resolvers/PipelineProgressResolver.ts +12 -3
  382. package/src/resolvers/QueryResolver.ts +20 -6
  383. package/src/resolvers/QuerySystemUserResolver.ts +15 -6
  384. package/src/resolvers/RSUResolver.ts +12 -0
  385. package/src/resolvers/RealtimeClientSessionResolver.ts +104 -33
  386. package/src/resolvers/RemoteBrowserActionResolver.ts +15 -10
  387. package/src/resolvers/RunAIAgentResolver.ts +258 -82
  388. package/src/resolvers/RunTemplateResolver.ts +6 -4
  389. package/src/resolvers/RunTestResolver.ts +3 -1
  390. package/src/resolvers/SyncDataResolver.ts +4 -0
  391. package/src/resolvers/TestQuerySQLResolver.ts +1 -0
  392. package/src/resolvers/TransactionGroupResolver.ts +66 -15
  393. package/src/resolvers/UserViewResolver.ts +2 -1
  394. package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +43 -0
  395. package/src/rest/EntityCRUDHandler.ts +22 -5
  396. package/src/rest/RESTEndpointHandler.ts +8 -5
  397. package/src/rest/RealtimeRecordingHandler.ts +13 -10
  398. package/src/rest/ViewOperationsHandler.ts +24 -6
  399. package/src/serverRoleConfigUnits.ts +48 -0
  400. package/src/services/TaskGraphContinuationDeliverer.ts +52 -20
  401. package/src/types.ts +23 -1
package/dist/index.js CHANGED
@@ -35,7 +35,7 @@ import { BuildPostgreSQLConnectionConfig, DescribeReadOnlyLoginOverreach, Postgr
35
35
  import { default as jwt } from 'jsonwebtoken';
36
36
  import { contextFunction, CreateReadOnlyProvider, CreateUnifiedAuthMiddleware, getUserPayload } from './context.js';
37
37
  import { requireSystemUserDirective, publicDirective } from './directives/index.js';
38
- import { variablesLoggingMiddleware } from './logging/variablesLoggingMiddleware.js';
38
+ import { ApplyRootVariablesLoggingMiddleware } from './logging/variablesLoggingMiddleware.js';
39
39
  import { auditResolversForUndecoratedArgs } from './logging/bootAudit.js';
40
40
  import { StartupLogger } from './logging/StartupLogger.js';
41
41
  import { AuthProviderFactory } from '@memberjunction/auth-providers';
@@ -43,7 +43,7 @@ import createMSSQLConfig from './orm.js';
43
43
  import { setupRESTEndpoints } from './rest/setupRESTEndpoints.js';
44
44
  import { CreateRealtimeRecordingRouter, REALTIME_RECORDING_MOUNT_PATH } from './rest/RealtimeRecordingHandler.js';
45
45
  import { LoadOwnedRealtimeSession } from './realtimeSessions/ownedRealtimeSession.js';
46
- import { LoadSessionConversationExternalID } from './realtimeSessions/sessionAccess.js';
46
+ import { AuthorizeAnonymousRoomSessions, LoadSessionConversationScope } from './realtimeSessions/sessionAccess.js';
47
47
  import { RecordingAssemblyScheduler } from './realtimeSessions/RecordingAssemblyScheduler.js';
48
48
  import { RealtimeSessionEventService, ParseReplicatedRealtimeSessionEvent, } from './realtimeSessions/index.js';
49
49
  import { resolve } from 'node:path';
@@ -59,8 +59,8 @@ import { CacheManagerConfigFromSettings, CreateSharedCacheFromEnvironment, Start
59
59
  import { PubSubManager } from './generic/PubSubManager.js';
60
60
  import { ReconcileOrphanedConversationDetails } from './generic/OrphanedConversationDetailReconciler.js';
61
61
  import { HANDOFF_OFFER_FANOUT_CHANNEL, HANDOFF_OFFER_TOPIC, SetHandoffOfferPublishHook, ParseReplicatedHandoffOfferUpdate, } from './resolvers/HumanHandoffResolver.js';
62
- import { RoomHandoffEngine } from '@memberjunction/livekit-room-server';
63
- import { IntegrationProgressEmitter } from '@memberjunction/integration-progress-artifacts';
62
+ import { RoomAuthorizationService, RoomHandoffEngine } from '@memberjunction/livekit-room-server';
63
+ import { IntegrationProgressEmitter, SweepInterruptedRuns } from '@memberjunction/integration-progress-artifacts';
64
64
  import { PublishIntegrationProgress } from './resolvers/IntegrationProgressResolver.js';
65
65
  import { RegisterRSUProgressBridge } from './integration/RSUProgressBridge.js';
66
66
  import { ClientToolRequestManager, AgentRunWatchdog, SqlRealtimeRecordingLedger } from '@memberjunction/ai-agents';
@@ -79,8 +79,13 @@ import { ApiRoute, ApiRootPath, ConfiguredPublicUrl } from './apiRoot.js';
79
79
  import { MountHealthcheckRoute, MountPublicCoreRoutes, MountExtensionHealthRoute, MountAuthCatalogRoute, MountAuthenticatedCoreRoutes } from './coreRoutes.js';
80
80
  import { MetadataCacheRefreshIntervalSeconds } from './providerConfigUnits.js';
81
81
  import { CreateMetadataRefreshSignalHandler, METADATA_REFRESH_SIGNAL } from './metadataRefreshSignal.js';
82
+ import { CacheInvalidationBroadcastManager } from './broadcast/index.js';
83
+ import { ResolveServerRole, ShouldRunBackgroundWorkers } from './serverRoleConfigUnits.js';
82
84
  const cacheRefreshInterval = configInfo.databaseSettings.metadataCacheRefreshInterval;
83
85
  export { MetadataCacheRefreshIntervalSeconds } from './providerConfigUnits.js';
86
+ export * from './serverRoleConfigUnits.js';
87
+ export * from './broadcast/index.js';
88
+ export { ApplyRootVariablesLoggingMiddleware } from './logging/variablesLoggingMiddleware.js';
84
89
  /**
85
90
  * Returns the configured database platform from the `DB_PLATFORM` environment
86
91
  * variable, falling back to `'sqlserver'` when the env var is unset. An
@@ -359,6 +364,9 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
359
364
  SetHostInstancePort(graphqlPort);
360
365
  // The realtime bridge engine stamps its bridge rows with the same identity and reconciles orphans by it (#5310).
361
366
  BindBridgeEngineHostInstance();
367
+ // An anonymous visitor may join only the LiveKit agent-session room it owns by scope; the room gate cannot import
368
+ // this package's session-access decision, so it is handed in here, before any resolver runs (MJ#6044).
369
+ RoomAuthorizationService.Instance.SetAnonymousSessionOwnerCheck(AuthorizeAnonymousRoomSessions);
362
370
  // Level-gated startup logger. Resolves verbosity from telemetry.level (single
363
371
  // operator knob). At `standard` (default), per-phase timings are collapsed into
364
372
  // the one-line summary; at `verbose`+ each phase prints inline as before.
@@ -411,6 +419,8 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
411
419
  // Every API pool carries the statement and idle-in-transaction timeouts from connection #1.
412
420
  const pgConnectionConfig = BuildPostgreSQLConnectionConfig(pgEndpoint, configInfo.databaseSettings, 'api');
413
421
  const pgPool = new pg.default.Pool(ToPGPoolConfig(pgConnectionConfig));
422
+ // An idle connection the server drops is emitted on the pool; without a listener Node exits.
423
+ pgPool.on('error', (err) => console.error('[PostgreSQL pool] Idle connection error (connection evicted):', err.message));
414
424
  // Verify connection
415
425
  const testClient = await pgPool.connect();
416
426
  await testClient.query('SELECT 1');
@@ -426,6 +436,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
426
436
  ...ToPGPoolConfig(BuildPostgreSQLConnectionConfig({ ...pgEndpoint, ...pgReadOnlyCredentials }, configInfo.databaseSettings, 'read-only')),
427
437
  types: MJPostgresTypes,
428
438
  });
439
+ readOnlyPgPool.on('error', (err) => console.error('[PostgreSQL read-only pool] Idle connection error (connection evicted):', err.message));
429
440
  const readOnlyTestClient = await readOnlyPgPool.connect();
430
441
  try {
431
442
  for (const warning of await DescribeReadOnlyLoginOverreach(readOnlyTestClient, mj_core_schema)) {
@@ -496,6 +507,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
496
507
  // long CodeGen timeout rather than the API one, as the SQL Server CodeGen pool does.
497
508
  const codegenPgConnectionConfig = BuildPostgreSQLConnectionConfig({ ...pgEndpoint, User: pgCodegenUser, Password: pgCodegenPass }, configInfo.databaseSettings, 'codegen');
498
509
  const codegenPgPool = new pg.default.Pool(ToPGPoolConfig(codegenPgConnectionConfig));
510
+ codegenPgPool.on('error', (err) => console.error('[PostgreSQL CodeGen pool] Idle connection error (connection evicted):', err.message));
499
511
  const codegenTestClient = await codegenPgPool.connect();
500
512
  await codegenTestClient.query('SELECT 1');
501
513
  codegenTestClient.release();
@@ -523,7 +535,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
523
535
  });
524
536
  startupLog.LogIf('verbose', 'RSU in-process CodeGen runner initialized (PostgreSQL).');
525
537
  // Inject CodeGen output paths for targeted git staging
526
- const { initializeConfig } = await import('@memberjunction/codegen-lib');
538
+ const { initializeConfig, ResolveAdditionalSchemaInfoPath } = await import('@memberjunction/codegen-lib');
527
539
  const cgConfig = initializeConfig(rsuWorkDir);
528
540
  const outputPaths = (cgConfig.output ?? []).map((o) => o.directory);
529
541
  RuntimeSchemaManager.Instance.SetCodeGenOutputPaths(outputPaths);
@@ -531,9 +543,12 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
531
543
  // Point RSU's soft PK/FK writer at the SAME file CodeGen reads (mj.config.cjs
532
544
  // `additionalSchemaInfo`), or RSU writes soft PKs to its own default path while
533
545
  // CodeGen reads a different one and skips integration tables with "No primary key found".
534
- if (cgConfig.additionalSchemaInfo) {
535
- RuntimeSchemaManager.Instance.SetAdditionalSchemaInfoPath(cgConfig.additionalSchemaInfo);
536
- startupLog.LogIf('verbose', `RSU additionalSchemaInfo path: ${cgConfig.additionalSchemaInfo}`);
546
+ // Inject the ABSOLUTE path CodeGen resolves (env override, else relative to the mj.config
547
+ // file's directory) so RSU, the resolvers and CodeGen agree whatever their cwd (#5858).
548
+ const resolvedSchemaInfoPath = ResolveAdditionalSchemaInfoPath();
549
+ if (resolvedSchemaInfoPath) {
550
+ RuntimeSchemaManager.Instance.SetAdditionalSchemaInfoPath(resolvedSchemaInfoPath);
551
+ startupLog.LogIf('verbose', `RSU additionalSchemaInfo path: ${resolvedSchemaInfoPath}`);
537
552
  }
538
553
  else if (RuntimeSchemaManager.Instance.IsEnabled) {
539
554
  // U5 — boot-time assert: RSU is enabled but CodeGen has NO additionalSchemaInfo path
@@ -541,7 +556,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
541
556
  // resolved soft PK would be silently lost ("No primary key found" per table). LOUD,
542
557
  // named, and actionable — grep for RSU_ADDITIONAL_SCHEMA_INFO_DIVERGENCE.
543
558
  console.error(`[RSU_ADDITIONAL_SCHEMA_INFO_DIVERGENCE] Runtime Schema Update is ENABLED but mj.config.cjs has no ` +
544
- `'additionalSchemaInfo' setting — RSU writes soft PK/FK definitions to '${process.env.RSU_ADDITIONAL_SCHEMA_INFO_PATH ?? 'additionalSchemaInfo.json'}' ` +
559
+ `'additionalSchemaInfo' setting (and RSU_ADDITIONAL_SCHEMA_INFO_PATH is unset) — RSU writes soft PK/FK definitions to '${RuntimeSchemaManager.Instance.AdditionalSchemaInfoPath}' ` +
545
560
  `while CodeGen reads none, so resolved soft primary keys will be silently LOST at codegen time. ` +
546
561
  `Set 'additionalSchemaInfo' in mj.config.cjs to the same file so the write path and read path agree.`);
547
562
  }
@@ -651,7 +666,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
651
666
  });
652
667
  startupLog.LogIf('verbose', 'RSU in-process CodeGen runner initialized.');
653
668
  // Inject CodeGen output paths for targeted git staging
654
- const { initializeConfig } = await import('@memberjunction/codegen-lib');
669
+ const { initializeConfig, ResolveAdditionalSchemaInfoPath } = await import('@memberjunction/codegen-lib');
655
670
  const codegenConfig = initializeConfig(rsuWorkDir);
656
671
  const outputPaths = (codegenConfig.output ?? []).map((o) => o.directory);
657
672
  RuntimeSchemaManager.Instance.SetCodeGenOutputPaths(outputPaths);
@@ -660,14 +675,17 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
660
675
  // `additionalSchemaInfo`). Without this, RSU writes soft PKs to its own default
661
676
  // path while CodeGen reads a different one and skips every integration table
662
677
  // with "No primary key found".
663
- if (codegenConfig.additionalSchemaInfo) {
664
- RuntimeSchemaManager.Instance.SetAdditionalSchemaInfoPath(codegenConfig.additionalSchemaInfo);
665
- startupLog.LogIf('verbose', `RSU additionalSchemaInfo path: ${codegenConfig.additionalSchemaInfo}`);
678
+ // Inject the ABSOLUTE path CodeGen resolves (env override, else relative to the mj.config
679
+ // file's directory) so RSU, the resolvers and CodeGen agree whatever their cwd (#5858).
680
+ const resolvedSchemaInfoPath = ResolveAdditionalSchemaInfoPath();
681
+ if (resolvedSchemaInfoPath) {
682
+ RuntimeSchemaManager.Instance.SetAdditionalSchemaInfoPath(resolvedSchemaInfoPath);
683
+ startupLog.LogIf('verbose', `RSU additionalSchemaInfo path: ${resolvedSchemaInfoPath}`);
666
684
  }
667
685
  else if (RuntimeSchemaManager.Instance.IsEnabled) {
668
686
  // U5 — boot-time assert: write path ≠ read path (see the PostgreSQL branch for detail).
669
687
  console.error(`[RSU_ADDITIONAL_SCHEMA_INFO_DIVERGENCE] Runtime Schema Update is ENABLED but mj.config.cjs has no ` +
670
- `'additionalSchemaInfo' setting — RSU writes soft PK/FK definitions to '${process.env.RSU_ADDITIONAL_SCHEMA_INFO_PATH ?? 'additionalSchemaInfo.json'}' ` +
688
+ `'additionalSchemaInfo' setting (and RSU_ADDITIONAL_SCHEMA_INFO_PATH is unset) — RSU writes soft PK/FK definitions to '${RuntimeSchemaManager.Instance.AdditionalSchemaInfoPath}' ` +
671
689
  `while CodeGen reads none, so resolved soft primary keys will be silently LOST at codegen time. ` +
672
690
  `Set 'additionalSchemaInfo' in mj.config.cjs to the same file so the write path and read path agree.`);
673
691
  }
@@ -868,6 +886,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
868
886
  // config.ts loads and validates at module scope, so importing it there would pull full config
869
887
  // validation into every import chain that touches the resolver, unit tests included.
870
888
  ConfigureRecordDataBroadcast(configInfo.cacheSettings?.recordDataBroadcastEntities);
889
+ CacheInvalidationBroadcastManager.Instance.Configure(configInfo.cacheSettings?.broadcast);
871
890
  // Global listener: broadcast CACHE_INVALIDATION to all browser clients whenever
872
891
  // ANY BaseEntity save/delete occurs on this server — regardless of whether it
873
892
  // originated from a GraphQL mutation or internal server-side code (agents, actions,
@@ -888,7 +907,8 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
888
907
  // Opt-in only: this event reaches every connected client unfiltered, and this listener
889
908
  // fires for server-internal saves too (agents, actions, orchestrator), which are exactly
890
909
  // the ones no browser session asked for.
891
- recordData: beEvent.type === 'save' && MayBroadcastRecordData(entityName)
910
+ recordData: beEvent.type === 'save' && MayBroadcastRecordData(entityName, beEvent.baseEntity.EntityInfo)
911
+ // fls-guard: MayBroadcastRecordData refuses FLS entities and Record Changes
892
912
  ? JSON.stringify(beEvent.baseEntity.GetAll())
893
913
  : undefined,
894
914
  });
@@ -936,7 +956,6 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
936
956
  scalarsMap: [{ type: Date, scalar: GraphQLTimestamp }],
937
957
  emitSchemaFile: websiteRunFromPackage !== 1,
938
958
  pubSub,
939
- globalMiddlewares: [variablesLoggingMiddleware],
940
959
  });
941
960
  const buildMs = performance.now() - tBuild;
942
961
  if (cpuProf && profSession) {
@@ -957,6 +976,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
957
976
  // and aren't @NoLog-marked. No-op in default config (logVariables=false).
958
977
  auditResolversForUndecoratedArgs();
959
978
  const tTransform = performance.now();
979
+ schema = ApplyRootVariablesLoggingMiddleware(schema);
960
980
  schema = requireSystemUserDirective.transformer(schema);
961
981
  schema = publicDirective.transformer(schema);
962
982
  // Apply middleware-contributed schema transformers (after built-in directive transformers)
@@ -1303,11 +1323,29 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
1303
1323
  // No per-route authMiddleware needed — unified auth middleware already ran
1304
1324
  setupRESTEndpoints(app, restApiConfig);
1305
1325
  // ─── GraphQL middleware (contextFunction reads req.userPayload, no re-auth) ─────
1306
- app.use(graphqlRootPath, cors(), BodyParser.json({ limit: '50mb' }),
1326
+ app.use(graphqlRootPath, cors({
1327
+ exposedHeaders: ['X-MJ-Cache-Seq', 'X-MJ-Server-ID'],
1328
+ }), BodyParser.json({ limit: '50mb' }),
1307
1329
  // Express 5 leaves req.body as undefined for non-JSON or empty bodies;
1308
1330
  // Apollo Server's expressMiddleware requires req.body to be defined.
1309
- (req, _res, next) => { if (req.body === undefined)
1310
- req.body = {}; next(); }, expressMiddleware(apolloServer, {
1331
+ // Also piggyback the latest monotonic cache invalidation sequence and server process ID
1332
+ // onto every GraphQL HTTP response so clients can detect and recover missed invalidations.
1333
+ (req, res, next) => {
1334
+ if (req.body === undefined)
1335
+ req.body = {};
1336
+ const broadcastProvider = CacheInvalidationBroadcastManager.Instance.Provider;
1337
+ res.setHeader('X-MJ-Cache-Seq', String(broadcastProvider.CurrentSequence));
1338
+ res.setHeader('X-MJ-Server-ID', broadcastProvider.ServerProcessID);
1339
+ const originalWriteHead = res.writeHead.bind(res);
1340
+ res.writeHead = ((...args) => {
1341
+ if (!res.headersSent) {
1342
+ res.setHeader('X-MJ-Cache-Seq', String(broadcastProvider.CurrentSequence));
1343
+ res.setHeader('X-MJ-Server-ID', broadcastProvider.ServerProcessID);
1344
+ }
1345
+ return originalWriteHead(...args);
1346
+ });
1347
+ next();
1348
+ }, expressMiddleware(apolloServer, {
1311
1349
  context: contextFunction({
1312
1350
  setupComplete$,
1313
1351
  dataSource: extendConnectionPoolWithQuery(dataSources[0].dataSource), // default read-write data source
@@ -1318,9 +1356,24 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
1318
1356
  for (const mw of mwPostRoute) {
1319
1357
  app.use(mw);
1320
1358
  }
1359
+ const serverRole = ResolveServerRole(configInfo.serverRole ?? process.env.MJ_SERVER_ROLE);
1360
+ const runBackgroundWorkers = ShouldRunBackgroundWorkers(serverRole);
1361
+ if (!runBackgroundWorkers) {
1362
+ LogStatus(`[ServerRole] Running in '${serverRole}' mode — background worker services are disabled on this replica.`);
1363
+ }
1364
+ // Close out run artifacts a dead process left open, BEFORE anything below can start a new run.
1365
+ //
1366
+ // A killed process (OOM killer, SIGKILL, host reboot) never writes its run's terminal result, so
1367
+ // the run reads as in-flight forever: the wizard spins, the active-operations panel shows a step
1368
+ // that will never advance, and no failure is reported anywhere. Sound only before the first new
1369
+ // run: artifacts are process-local, so anything still in flight as THIS process starts belongs
1370
+ // to a process that no longer exists. That is why it runs here, ahead of the scheduler, the
1371
+ // integration sync worker (its Start() polls immediately), the HTTP listener (a request can
1372
+ // start a discovery) and pending RSU work, and why it is awaited. It needs none of them.
1373
+ await SweepInterruptedRuns(undefined, msg => console.warn(msg));
1321
1374
  // Initialize and start scheduled jobs service if enabled
1322
1375
  let scheduledJobsService = null;
1323
- if (configInfo.scheduledJobs?.enabled) {
1376
+ if (runBackgroundWorkers && configInfo.scheduledJobs?.enabled) {
1324
1377
  try {
1325
1378
  scheduledJobsService = new ScheduledJobsService(configInfo.scheduledJobs);
1326
1379
  await scheduledJobsService.Initialize();
@@ -1334,7 +1387,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
1334
1387
  // Initialize and start the integration sync worker if enabled (PR 1 item 8).
1335
1388
  // Off by default — deployments that don't opt in keep running syncs inline.
1336
1389
  let integrationSyncWorker = null;
1337
- if (configInfo.integrationSyncWorker?.enabled) {
1390
+ if (runBackgroundWorkers && configInfo.integrationSyncWorker?.enabled) {
1338
1391
  try {
1339
1392
  integrationSyncWorker = new IntegrationSyncWorkerService(configInfo.integrationSyncWorker);
1340
1393
  await integrationSyncWorker.Initialize();
@@ -1368,47 +1421,49 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
1368
1421
  startupLog.SetScheduledJobCount(scheduledJobsService.GetStatus().activeJobs);
1369
1422
  }
1370
1423
  startupLog.PrintSummary();
1371
- // Process pending RSU work from pre-restart (entity maps, field maps, sync)
1372
- processRSUPendingWork().catch(err => console.warn(`RSU pending work processing failed: ${err}`));
1373
- // Resume any integration syncs that were orphaned by the previous process restart
1374
1424
  const resumeUser = UserCache.Instance.GetSystemUser();
1375
- if (resumeUser) {
1376
- IntegrationEngine.Instance.ResumeOrphanedSyncs(resumeUser)
1377
- .catch(err => console.warn(`[IntegrationEngine] Orphaned sync resume failed: ${err}`));
1378
- }
1379
- // Force-fail any agent runs left 'Running' by a process that died (restart/crash/OOM) or whose
1380
- // terminal-state write never landed. Staleness-based, so it never touches runs another healthy
1381
- // instance is still heart-beating. The watchdog also self-registers for graceful-shutdown
1382
- // cancellation (via ShutdownRegistry) once it begins tracking this process's first live run.
1383
- if (resumeUser && Metadata.Provider instanceof DatabaseProviderBase) { // global-provider-ok: server startup recovery — one-shot orphaned-run sweep at boot
1384
- const sweepUser = resumeUser;
1385
- const sweepProvider = Metadata.Provider; // global-provider-ok: server startup recovery — one-shot orphaned-run sweep at boot
1386
- AgentRunWatchdog.SweepOrphanedRuns(sweepProvider, sweepUser)
1387
- .catch(err => console.warn(`[AgentRunWatchdog] Startup sweep failed: ${err}`));
1388
- // The watchdog repairs the RUN; nothing repaired the conversation detail, which is the row the
1389
- // chat actually renders from (MJ #4222). A process that dies mid-run leaves a terminal run
1390
- // beside a message that still claims to be generating, and it spins forever for anyone who
1391
- // opens it. Runs at boot (closes restart orphans) and on a timer (closes mid-life orphans),
1392
- // mirroring the watchdog's own two-phase shape.
1393
- const reconcileOrphans = () => ReconcileOrphanedConversationDetails(sweepProvider, sweepUser)
1394
- .catch(err => console.warn(`[OrphanDetailReconciler] Pass failed: ${err}`));
1395
- void reconcileOrphans();
1396
- const orphanDetailTimer = setInterval(() => void reconcileOrphans(), ORPHAN_DETAIL_SWEEP_INTERVAL_MS);
1397
- ShutdownRegistry.Instance.Register({
1398
- ShutdownName: 'OrphanDetailReconciler',
1399
- Shutdown: () => { clearInterval(orphanDetailTimer); },
1400
- });
1401
- }
1402
- // Launch the AI Agent Session janitor: run own-host orphan recovery once at boot, then a periodic tick
1403
- // that closes stale and over-deadline sessions and rebuilds lost realtime recordings from their
1404
- // crash-recovery shards (storage reads and writes). Self-registers with ShutdownRegistry, so its timer
1405
- // is cleared by the gracefulShutdown drain below (no explicit Stop() wiring needed here).
1406
- if (resumeUser && Metadata.Provider instanceof DatabaseProviderBase) { // global-provider-ok: server startup recovery — boot-time session janitor uses the server's own provider
1407
- SessionJanitor.Instance.Start(Metadata.Provider, resumeUser) // global-provider-ok: server-owned background reconciler runs under the server's provider + system user
1408
- .catch(err => console.warn(`[SessionJanitor] Startup failed: ${err}`));
1409
- // The bridge engine's orphan reconcile likewise starts only now that this process holds its port, so it can't
1410
- // take the live bridges of another MJAPI still serving that port for its own orphans (#5310).
1411
- StartBridgeOrphanReconciliation(Metadata.Provider, resumeUser); // global-provider-ok: server-owned background reconciler runs under the server's provider + system user
1425
+ if (runBackgroundWorkers) {
1426
+ // Process pending RSU work from pre-restart (entity maps, field maps, sync)
1427
+ processRSUPendingWork().catch(err => console.warn(`RSU pending work processing failed: ${err}`));
1428
+ // Resume any integration syncs that were orphaned by the previous process restart
1429
+ if (resumeUser) {
1430
+ IntegrationEngine.Instance.ResumeOrphanedSyncs(resumeUser)
1431
+ .catch(err => console.warn(`[IntegrationEngine] Orphaned sync resume failed: ${err}`));
1432
+ }
1433
+ // Force-fail any agent runs left 'Running' by a process that died (restart/crash/OOM) or whose
1434
+ // terminal-state write never landed. Staleness-based, so it never touches runs another healthy
1435
+ // instance is still heart-beating. The watchdog also self-registers for graceful-shutdown
1436
+ // cancellation (via ShutdownRegistry) once it begins tracking this process's first live run.
1437
+ if (resumeUser && Metadata.Provider instanceof DatabaseProviderBase) { // global-provider-ok: server startup recovery — one-shot orphaned-run sweep at boot
1438
+ const sweepUser = resumeUser;
1439
+ const sweepProvider = Metadata.Provider; // global-provider-ok: server startup recovery — one-shot orphaned-run sweep at boot
1440
+ AgentRunWatchdog.SweepOrphanedRuns(sweepProvider, sweepUser)
1441
+ .catch(err => console.warn(`[AgentRunWatchdog] Startup sweep failed: ${err}`));
1442
+ // The watchdog repairs the RUN; nothing repaired the conversation detail, which is the row the
1443
+ // chat actually renders from (MJ #4222). A process that dies mid-run leaves a terminal run
1444
+ // beside a message that still claims to be generating, and it spins forever for anyone who
1445
+ // opens it. Runs at boot (closes restart orphans) and on a timer (closes mid-life orphans),
1446
+ // mirroring the watchdog's own two-phase shape.
1447
+ const reconcileOrphans = () => ReconcileOrphanedConversationDetails(sweepProvider, sweepUser)
1448
+ .catch(err => console.warn(`[OrphanDetailReconciler] Pass failed: ${err}`));
1449
+ void reconcileOrphans();
1450
+ const orphanDetailTimer = setInterval(() => void reconcileOrphans(), ORPHAN_DETAIL_SWEEP_INTERVAL_MS);
1451
+ ShutdownRegistry.Instance.Register({
1452
+ ShutdownName: 'OrphanDetailReconciler',
1453
+ Shutdown: () => { clearInterval(orphanDetailTimer); },
1454
+ });
1455
+ }
1456
+ // Launch the AI Agent Session janitor: run own-host orphan recovery once at boot, then a periodic tick
1457
+ // that closes stale and over-deadline sessions and rebuilds lost realtime recordings from their
1458
+ // crash-recovery shards (storage reads and writes). Self-registers with ShutdownRegistry, so its timer
1459
+ // is cleared by the gracefulShutdown drain below (no explicit Stop() wiring needed here).
1460
+ if (resumeUser && Metadata.Provider instanceof DatabaseProviderBase) { // global-provider-ok: server startup recovery — boot-time session janitor uses the server's own provider
1461
+ SessionJanitor.Instance.Start(Metadata.Provider, resumeUser) // global-provider-ok: server-owned background reconciler runs under the server's provider + system user
1462
+ .catch(err => console.warn(`[SessionJanitor] Startup failed: ${err}`));
1463
+ // The bridge engine's orphan reconcile likewise starts only now that this process holds its port, so it can't
1464
+ // take the live bridges of another MJAPI still serving that port for its own orphans (#5310).
1465
+ StartBridgeOrphanReconciliation(Metadata.Provider, resumeUser); // global-provider-ok: server-owned background reconciler runs under the server's provider + system user
1466
+ }
1412
1467
  }
1413
1468
  // Launch the durable task-graph dispatcher: claim Pending tasks, execute them with a fresh
1414
1469
  // provider each, and reconcile claims orphaned by a crash. Without this nothing ever picks up a
@@ -1437,7 +1492,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
1437
1492
  SuppressTaskGraphSubmission('MJ_DISABLE_TASK_GRAPH_DISPATCHER=1 is set on this host');
1438
1493
  LogStatus('[TaskGraphDispatcher] Disabled by MJ_DISABLE_TASK_GRAPH_DISPATCHER=1 — this process will neither accept nor execute task graphs.');
1439
1494
  }
1440
- else if (resumeUser && taskGraphPool instanceof sql.ConnectionPool) {
1495
+ else if (runBackgroundWorkers && resumeUser && taskGraphPool instanceof sql.ConnectionPool) {
1441
1496
  StartTaskGraphDispatcher(taskGraphPool, resumeUser)
1442
1497
  .catch(err => console.warn(`[TaskGraphDispatcher] Startup failed: ${err}`));
1443
1498
  }
@@ -1446,7 +1501,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
1446
1501
  // ShutdownAll() drains it (up to 2 × shutdownDrainMs) before the HTTP server closes.
1447
1502
  // Not awaited: a slow engine load must not delay readiness, and a failure never stops the API.
1448
1503
  const workQueueProvider = Metadata.Provider; // global-provider-ok: server startup — the work-queue host runs on the server's own provider
1449
- if (configInfo.workQueue?.enabled && workQueueProvider instanceof DatabaseProviderBase) {
1504
+ if (runBackgroundWorkers && configInfo.workQueue?.enabled && workQueueProvider instanceof DatabaseProviderBase) {
1450
1505
  const workQueuePool = dataSources[0]?.dataSource;
1451
1506
  const providerSource = new MJServerWorkQueueProviderSource(workQueuePool instanceof sql.ConnectionPool ? workQueuePool : null, workQueueProvider);
1452
1507
  StartWorkQueueHost(configInfo.workQueue, workQueueProvider, providerSource)
@@ -1911,10 +1966,11 @@ function mountRealtimeRecordingRoutes(app) {
1911
1966
  }
1912
1967
  const graceMs = () => configInfo.realtime.recordingAssemblyGraceSeconds * 1000;
1913
1968
  const systemUser = UserCache.Instance.GetSystemUser();
1914
- if (systemUser) {
1969
+ const runWorkers = ShouldRunBackgroundWorkers(ResolveServerRole(configInfo.serverRole ?? process.env.MJ_SERVER_ROLE));
1970
+ if (systemUser && runWorkers) {
1915
1971
  RecordingAssemblyScheduler.Instance.Start({ Provider: provider, SystemUser: systemUser, GraceMs: graceMs });
1916
1972
  }
1917
- else {
1973
+ else if (!systemUser) {
1918
1974
  LogError('[Realtime] Recording assembly scheduler not started: no system user; the session janitor assembles recordings instead');
1919
1975
  }
1920
1976
  app.use(ApiRoute(REALTIME_RECORDING_MOUNT_PATH), cors(), CreateRealtimeRecordingRouter({
@@ -1923,7 +1979,7 @@ function mountRealtimeRecordingRoutes(app) {
1923
1979
  return user ? { ContextUser: user, Provider: provider } : null;
1924
1980
  },
1925
1981
  LoadOwnedSession: LoadOwnedRealtimeSession,
1926
- LoadConversationExternalID: LoadSessionConversationExternalID,
1982
+ LoadConversationScope: LoadSessionConversationScope,
1927
1983
  CreateLedger: (ledgerProvider, contextUser) => new SqlRealtimeRecordingLedger(ledgerProvider, contextUser),
1928
1984
  Scheduler: RecordingAssemblyScheduler.Instance,
1929
1985
  GraceMs: graceMs,