@memberjunction/server 6.2.0-edge.3 → 6.2.0-edge.5

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 (543) hide show
  1. package/README.md +20 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentSessions/BridgeHostInstance.d.ts +25 -0
  4. package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -0
  5. package/dist/agentSessions/BridgeHostInstance.js +30 -0
  6. package/dist/agentSessions/BridgeHostInstance.js.map +1 -0
  7. package/dist/agentSessions/HostInstance.d.ts +75 -11
  8. package/dist/agentSessions/HostInstance.d.ts.map +1 -1
  9. package/dist/agentSessions/HostInstance.js +99 -28
  10. package/dist/agentSessions/HostInstance.js.map +1 -1
  11. package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
  12. package/dist/agentSessions/ReturningVisitorRecap.js +7 -3
  13. package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
  14. package/dist/agentSessions/SessionJanitor.d.ts +236 -27
  15. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  16. package/dist/agentSessions/SessionJanitor.js +682 -54
  17. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  18. package/dist/agentSessions/SessionManager.d.ts +48 -3
  19. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  20. package/dist/agentSessions/SessionManager.js +112 -9
  21. package/dist/agentSessions/SessionManager.js.map +1 -1
  22. package/dist/agentSessions/SessionRunIDVerifier.d.ts +63 -0
  23. package/dist/agentSessions/SessionRunIDVerifier.d.ts.map +1 -0
  24. package/dist/agentSessions/SessionRunIDVerifier.js +129 -0
  25. package/dist/agentSessions/SessionRunIDVerifier.js.map +1 -0
  26. package/dist/agentSessions/index.d.ts +2 -0
  27. package/dist/agentSessions/index.d.ts.map +1 -1
  28. package/dist/agentSessions/index.js +10 -3
  29. package/dist/agentSessions/index.js.map +1 -1
  30. package/dist/apiRoot.d.ts +32 -0
  31. package/dist/apiRoot.d.ts.map +1 -0
  32. package/dist/apiRoot.js +67 -0
  33. package/dist/apiRoot.js.map +1 -0
  34. package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
  35. package/dist/auth/AuthProviderCatalogRouter.js +25 -0
  36. package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
  37. package/dist/auth/LoginScreenEngine.d.ts +22 -0
  38. package/dist/auth/LoginScreenEngine.d.ts.map +1 -0
  39. package/dist/auth/LoginScreenEngine.js +57 -0
  40. package/dist/auth/LoginScreenEngine.js.map +1 -0
  41. package/dist/auth/actionAuthorization.d.ts +40 -0
  42. package/dist/auth/actionAuthorization.d.ts.map +1 -0
  43. package/dist/auth/actionAuthorization.js +94 -0
  44. package/dist/auth/actionAuthorization.js.map +1 -0
  45. package/dist/auth/index.d.ts +1 -0
  46. package/dist/auth/index.d.ts.map +1 -1
  47. package/dist/auth/index.js +4 -10
  48. package/dist/auth/index.js.map +1 -1
  49. package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
  50. package/dist/auth/magicLink/MagicLinkRouter.js +3 -2
  51. package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
  52. package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
  53. package/dist/auth/magicLink/MagicLinkService.js +6 -3
  54. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  55. package/dist/auth/newUsers.d.ts +10 -0
  56. package/dist/auth/newUsers.d.ts.map +1 -1
  57. package/dist/auth/newUsers.js +80 -11
  58. package/dist/auth/newUsers.js.map +1 -1
  59. package/dist/config.d.ts +2514 -22
  60. package/dist/config.d.ts.map +1 -1
  61. package/dist/config.js +166 -4
  62. package/dist/config.js.map +1 -1
  63. package/dist/context.d.ts +8 -0
  64. package/dist/context.d.ts.map +1 -1
  65. package/dist/context.js +14 -11
  66. package/dist/context.js.map +1 -1
  67. package/dist/coreRoutes.d.ts +29 -0
  68. package/dist/coreRoutes.d.ts.map +1 -0
  69. package/dist/coreRoutes.js +142 -0
  70. package/dist/coreRoutes.js.map +1 -0
  71. package/dist/generated/graphql-schemas/__mj.d.ts +504 -3
  72. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  73. package/dist/generated/graphql-schemas/__mj.js +2456 -7
  74. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  75. package/dist/generic/CacheInvalidationResolver.d.ts +43 -8
  76. package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
  77. package/dist/generic/CacheInvalidationResolver.js +59 -19
  78. package/dist/generic/CacheInvalidationResolver.js.map +1 -1
  79. package/dist/generic/OrphanedConversationDetailReconciler.js +3 -3
  80. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
  81. package/dist/generic/PushStatusResolver.js +1 -1
  82. package/dist/generic/PushStatusResolver.js.map +1 -1
  83. package/dist/generic/ResolverBase.d.ts +123 -48
  84. package/dist/generic/ResolverBase.d.ts.map +1 -1
  85. package/dist/generic/ResolverBase.js +293 -305
  86. package/dist/generic/ResolverBase.js.map +1 -1
  87. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  88. package/dist/generic/RunViewResolver.js +16 -0
  89. package/dist/generic/RunViewResolver.js.map +1 -1
  90. package/dist/globalCors.d.ts +33 -0
  91. package/dist/globalCors.d.ts.map +1 -0
  92. package/dist/globalCors.js +58 -0
  93. package/dist/globalCors.js.map +1 -0
  94. package/dist/index.d.ts +17 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +219 -278
  97. package/dist/index.js.map +1 -1
  98. package/dist/isolatedProvider.d.ts +20 -0
  99. package/dist/isolatedProvider.d.ts.map +1 -0
  100. package/dist/isolatedProvider.js +22 -0
  101. package/dist/isolatedProvider.js.map +1 -0
  102. package/dist/multiTenancy/index.d.ts.map +1 -1
  103. package/dist/multiTenancy/index.js +22 -2
  104. package/dist/multiTenancy/index.js.map +1 -1
  105. package/dist/realtimeProxy/RealtimeProxyServer.d.ts +44 -4
  106. package/dist/realtimeProxy/RealtimeProxyServer.d.ts.map +1 -1
  107. package/dist/realtimeProxy/RealtimeProxyServer.js +121 -16
  108. package/dist/realtimeProxy/RealtimeProxyServer.js.map +1 -1
  109. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts +171 -0
  110. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts.map +1 -0
  111. package/dist/realtimeProxy/RealtimeRelayTunnel.js +532 -0
  112. package/dist/realtimeProxy/RealtimeRelayTunnel.js.map +1 -0
  113. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts +148 -0
  114. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts.map +1 -0
  115. package/dist/realtimeSessions/RealtimeSessionEventService.js +191 -0
  116. package/dist/realtimeSessions/RealtimeSessionEventService.js.map +1 -0
  117. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts +66 -0
  118. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -0
  119. package/dist/realtimeSessions/RealtimeSessionVerificationService.js +139 -0
  120. package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -0
  121. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts +38 -0
  122. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -0
  123. package/dist/realtimeSessions/RealtimeVerifyRouter.js +99 -0
  124. package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -0
  125. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts +100 -0
  126. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts.map +1 -0
  127. package/dist/realtimeSessions/RecordingAssemblyScheduler.js +173 -0
  128. package/dist/realtimeSessions/RecordingAssemblyScheduler.js.map +1 -0
  129. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts +61 -0
  130. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -0
  131. package/dist/realtimeSessions/SessionVerificationPortsBase.js +149 -0
  132. package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -0
  133. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts +57 -0
  134. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts.map +1 -0
  135. package/dist/realtimeSessions/SlidingWindowRateLimiter.js +69 -0
  136. package/dist/realtimeSessions/SlidingWindowRateLimiter.js.map +1 -0
  137. package/dist/realtimeSessions/index.d.ts +19 -0
  138. package/dist/realtimeSessions/index.d.ts.map +1 -0
  139. package/dist/realtimeSessions/index.js +19 -0
  140. package/dist/realtimeSessions/index.js.map +1 -0
  141. package/dist/realtimeSessions/ownedRealtimeSession.d.ts +30 -0
  142. package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -0
  143. package/dist/realtimeSessions/ownedRealtimeSession.js +47 -0
  144. package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -0
  145. package/dist/realtimeSessions/sessionAccess.d.ts +92 -0
  146. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -0
  147. package/dist/realtimeSessions/sessionAccess.js +94 -0
  148. package/dist/realtimeSessions/sessionAccess.js.map +1 -0
  149. package/dist/realtimeSessions/sessionConfigStamps.d.ts +70 -0
  150. package/dist/realtimeSessions/sessionConfigStamps.d.ts.map +1 -0
  151. package/dist/realtimeSessions/sessionConfigStamps.js +93 -0
  152. package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -0
  153. package/dist/realtimeSessions/subscriptionAuthorization.d.ts +65 -0
  154. package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -0
  155. package/dist/realtimeSessions/subscriptionAuthorization.js +71 -0
  156. package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -0
  157. package/dist/realtimeSessions/verificationCore.d.ts +243 -0
  158. package/dist/realtimeSessions/verificationCore.d.ts.map +1 -0
  159. package/dist/realtimeSessions/verificationCore.js +356 -0
  160. package/dist/realtimeSessions/verificationCore.js.map +1 -0
  161. package/dist/realtimeSessions/verificationPages.d.ts +66 -0
  162. package/dist/realtimeSessions/verificationPages.d.ts.map +1 -0
  163. package/dist/realtimeSessions/verificationPages.js +110 -0
  164. package/dist/realtimeSessions/verificationPages.js.map +1 -0
  165. package/dist/realtimeSessions/verificationPolicy.d.ts +147 -0
  166. package/dist/realtimeSessions/verificationPolicy.d.ts.map +1 -0
  167. package/dist/realtimeSessions/verificationPolicy.js +249 -0
  168. package/dist/realtimeSessions/verificationPolicy.js.map +1 -0
  169. package/dist/realtimeSessions/verificationWorkflow.d.ts +263 -0
  170. package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -0
  171. package/dist/realtimeSessions/verificationWorkflow.js +435 -0
  172. package/dist/realtimeSessions/verificationWorkflow.js.map +1 -0
  173. package/dist/realtimeWidget/widgetGuestElevation.d.ts +20 -2
  174. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  175. package/dist/realtimeWidget/widgetGuestElevation.js +31 -2
  176. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  177. package/dist/resolvers/ActionResolver.d.ts +31 -5
  178. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  179. package/dist/resolvers/ActionResolver.js +75 -14
  180. package/dist/resolvers/ActionResolver.js.map +1 -1
  181. package/dist/resolvers/AdhocQueryResolver.d.ts +14 -1
  182. package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
  183. package/dist/resolvers/AdhocQueryResolver.js +21 -5
  184. package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
  185. package/dist/resolvers/ArtifactFileResolver.d.ts +5 -1
  186. package/dist/resolvers/ArtifactFileResolver.d.ts.map +1 -1
  187. package/dist/resolvers/ArtifactFileResolver.js +9 -7
  188. package/dist/resolvers/ArtifactFileResolver.js.map +1 -1
  189. package/dist/resolvers/CacheStatsResolver.d.ts +27 -0
  190. package/dist/resolvers/CacheStatsResolver.d.ts.map +1 -1
  191. package/dist/resolvers/CacheStatsResolver.js +113 -2
  192. package/dist/resolvers/CacheStatsResolver.js.map +1 -1
  193. package/dist/resolvers/ClientToolRequestResolver.d.ts +4 -2
  194. package/dist/resolvers/ClientToolRequestResolver.d.ts.map +1 -1
  195. package/dist/resolvers/ClientToolRequestResolver.js +28 -10
  196. package/dist/resolvers/ClientToolRequestResolver.js.map +1 -1
  197. package/dist/resolvers/ConversationRunEventsResolver.d.ts +8 -4
  198. package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
  199. package/dist/resolvers/ConversationRunEventsResolver.js +6 -6
  200. package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
  201. package/dist/resolvers/DatasetResolver.d.ts +24 -3
  202. package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
  203. package/dist/resolvers/DatasetResolver.js +57 -8
  204. package/dist/resolvers/DatasetResolver.js.map +1 -1
  205. package/dist/resolvers/EntityRecordNameResolver.d.ts +2 -1
  206. package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
  207. package/dist/resolvers/EntityRecordNameResolver.js +3 -2
  208. package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
  209. package/dist/resolvers/FetchEntityVectorsResolver.d.ts +27 -1
  210. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  211. package/dist/resolvers/FetchEntityVectorsResolver.js +148 -2
  212. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  213. package/dist/resolvers/FileResolver.d.ts +82 -11
  214. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  215. package/dist/resolvers/FileResolver.js +279 -101
  216. package/dist/resolvers/FileResolver.js.map +1 -1
  217. package/dist/resolvers/GetDataContextDataResolver.d.ts +33 -7
  218. package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
  219. package/dist/resolvers/GetDataContextDataResolver.js +117 -38
  220. package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
  221. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  222. package/dist/resolvers/GetDataResolver.js +6 -3
  223. package/dist/resolvers/GetDataResolver.js.map +1 -1
  224. package/dist/resolvers/HumanHandoffResolver.d.ts.map +1 -1
  225. package/dist/resolvers/HumanHandoffResolver.js +7 -1
  226. package/dist/resolvers/HumanHandoffResolver.js.map +1 -1
  227. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  228. package/dist/resolvers/IntegrationDiscoveryResolver.js +4 -2
  229. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  230. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  231. package/dist/resolvers/MCPResolver.js +9 -4
  232. package/dist/resolvers/MCPResolver.js.map +1 -1
  233. package/dist/resolvers/QueryResolver.d.ts +2 -0
  234. package/dist/resolvers/QueryResolver.d.ts.map +1 -1
  235. package/dist/resolvers/QueryResolver.js +13 -0
  236. package/dist/resolvers/QueryResolver.js.map +1 -1
  237. package/dist/resolvers/RealtimeBridgeResolver.d.ts +54 -2
  238. package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
  239. package/dist/resolvers/RealtimeBridgeResolver.js +155 -10
  240. package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
  241. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +157 -33
  242. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  243. package/dist/resolvers/RealtimeClientSessionResolver.js +404 -116
  244. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  245. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts +61 -0
  246. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts.map +1 -0
  247. package/dist/resolvers/RealtimeSessionEventsResolver.js +130 -0
  248. package/dist/resolvers/RealtimeSessionEventsResolver.js.map +1 -0
  249. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts +85 -0
  250. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts.map +1 -0
  251. package/dist/resolvers/RealtimeSessionVerificationResolver.js +188 -0
  252. package/dist/resolvers/RealtimeSessionVerificationResolver.js.map +1 -0
  253. package/dist/resolvers/RemoteBrowserActionResolver.d.ts +2 -0
  254. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  255. package/dist/resolvers/RemoteBrowserActionResolver.js +5 -1
  256. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  257. package/dist/resolvers/RunAIAgentResolver.d.ts +10 -0
  258. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  259. package/dist/resolvers/RunAIAgentResolver.js +100 -14
  260. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  261. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  262. package/dist/resolvers/RunTemplateResolver.js +12 -11
  263. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  264. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts +12 -1
  265. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts.map +1 -1
  266. package/dist/resolvers/SearchKnowledgeStreamResolver.js +15 -2
  267. package/dist/resolvers/SearchKnowledgeStreamResolver.js.map +1 -1
  268. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  269. package/dist/resolvers/SqlLoggingConfigResolver.js +2 -3
  270. package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
  271. package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
  272. package/dist/resolvers/SyncDataResolver.js +6 -2
  273. package/dist/resolvers/SyncDataResolver.js.map +1 -1
  274. package/dist/resolvers/SyncRolesUsersResolver.d.ts +2 -0
  275. package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
  276. package/dist/resolvers/SyncRolesUsersResolver.js +23 -6
  277. package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
  278. package/dist/resolvers/TaskGraphFrameResolver.d.ts +2 -1
  279. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
  280. package/dist/resolvers/TaskGraphFrameResolver.js +28 -1
  281. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
  282. package/dist/resolvers/TestQuerySQLResolver.d.ts +24 -0
  283. package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
  284. package/dist/resolvers/TestQuerySQLResolver.js +65 -13
  285. package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
  286. package/dist/resolvers/TransactionGroupResolver.d.ts +19 -2
  287. package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
  288. package/dist/resolvers/TransactionGroupResolver.js +102 -24
  289. package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
  290. package/dist/resolvers/UserAvatarResolver.d.ts +16 -0
  291. package/dist/resolvers/UserAvatarResolver.d.ts.map +1 -0
  292. package/dist/resolvers/UserAvatarResolver.js +124 -0
  293. package/dist/resolvers/UserAvatarResolver.js.map +1 -0
  294. package/dist/resolvers/UserResolver.d.ts.map +1 -1
  295. package/dist/resolvers/UserResolver.js +2 -17
  296. package/dist/resolvers/UserResolver.js.map +1 -1
  297. package/dist/resolvers/agent-run-data-guard.d.ts +31 -0
  298. package/dist/resolvers/agent-run-data-guard.d.ts.map +1 -0
  299. package/dist/resolvers/agent-run-data-guard.js +72 -0
  300. package/dist/resolvers/agent-run-data-guard.js.map +1 -0
  301. package/dist/resolvers/agentVisionConsentAudit.d.ts +37 -0
  302. package/dist/resolvers/agentVisionConsentAudit.d.ts.map +1 -0
  303. package/dist/resolvers/agentVisionConsentAudit.js +63 -0
  304. package/dist/resolvers/agentVisionConsentAudit.js.map +1 -0
  305. package/dist/resolvers/avatarInputValidation.d.ts +40 -0
  306. package/dist/resolvers/avatarInputValidation.d.ts.map +1 -0
  307. package/dist/resolvers/avatarInputValidation.js +97 -0
  308. package/dist/resolvers/avatarInputValidation.js.map +1 -0
  309. package/dist/resolvers/currentUserRoles.d.ts +29 -0
  310. package/dist/resolvers/currentUserRoles.d.ts.map +1 -1
  311. package/dist/resolvers/currentUserRoles.js +30 -0
  312. package/dist/resolvers/currentUserRoles.js.map +1 -1
  313. package/dist/resolvers/meetings/meetingMutations.d.ts +6 -0
  314. package/dist/resolvers/meetings/meetingMutations.d.ts.map +1 -1
  315. package/dist/resolvers/meetings/meetingMutations.js +21 -0
  316. package/dist/resolvers/meetings/meetingMutations.js.map +1 -1
  317. package/dist/rest/RealtimeRecordingHandler.d.ts +49 -0
  318. package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -0
  319. package/dist/rest/RealtimeRecordingHandler.js +383 -0
  320. package/dist/rest/RealtimeRecordingHandler.js.map +1 -0
  321. package/dist/rest/ViewOperationsHandler.d.ts +3 -1
  322. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  323. package/dist/rest/ViewOperationsHandler.js +21 -12
  324. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  325. package/dist/rest/setupRESTEndpoints.d.ts +6 -0
  326. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  327. package/dist/rest/setupRESTEndpoints.js +6 -0
  328. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  329. package/dist/serverExtensionReservedRoots.d.ts +12 -10
  330. package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
  331. package/dist/serverExtensionReservedRoots.js +14 -17
  332. package/dist/serverExtensionReservedRoots.js.map +1 -1
  333. package/dist/services/MJStorageBlobStore.d.ts +8 -1
  334. package/dist/services/MJStorageBlobStore.d.ts.map +1 -1
  335. package/dist/services/MJStorageBlobStore.js +25 -19
  336. package/dist/services/MJStorageBlobStore.js.map +1 -1
  337. package/dist/services/StartTaskGraphDispatcher.js +2 -2
  338. package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
  339. package/dist/services/TaskGraphActionRunner.d.ts +5 -3
  340. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  341. package/dist/services/TaskGraphActionRunner.js +27 -5
  342. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  343. package/dist/services/TaskGraphAgentRunner.d.ts +14 -2
  344. package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
  345. package/dist/services/TaskGraphAgentRunner.js +157 -9
  346. package/dist/services/TaskGraphAgentRunner.js.map +1 -1
  347. package/dist/services/TaskGraphContinuationDeliverer.d.ts +57 -4
  348. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  349. package/dist/services/TaskGraphContinuationDeliverer.js +607 -18
  350. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  351. package/dist/sharedCache.d.ts +105 -0
  352. package/dist/sharedCache.d.ts.map +1 -0
  353. package/dist/sharedCache.js +279 -0
  354. package/dist/sharedCache.js.map +1 -0
  355. package/dist/types.d.ts +6 -0
  356. package/dist/types.d.ts.map +1 -1
  357. package/dist/types.js.map +1 -1
  358. package/package.json +99 -96
  359. package/src/__tests__/ActionResolver.authorization.test.ts +353 -0
  360. package/src/__tests__/AdhocQueryResolver.sqlAuthorizer.test.ts +104 -0
  361. package/src/__tests__/BridgeHostInstance.test.ts +232 -0
  362. package/src/__tests__/ClientToolRequestResolver.test.ts +116 -0
  363. package/src/__tests__/DatasetResolver.itemFilters.test.ts +201 -0
  364. package/src/__tests__/EntityRecordNameResolver.rowSecurity.test.ts +152 -0
  365. package/src/__tests__/FetchEntityVectorsResolver.test.ts +433 -0
  366. package/src/__tests__/FileResolver.storageAccess.test.ts +562 -0
  367. package/src/__tests__/GetDataContextDataResolver.sqlItems.test.ts +416 -0
  368. package/src/__tests__/HostInstance.test.ts +84 -0
  369. package/src/__tests__/HumanHandoffResolver.test.ts +17 -0
  370. package/src/__tests__/ListOperationsResolver.adhocScreen.test.ts +137 -0
  371. package/src/__tests__/LoginScreenEngine.test.ts +86 -0
  372. package/src/__tests__/MJStorageBlobStore.storageGate.test.ts +63 -0
  373. package/src/__tests__/MeetingResolver.test.ts +75 -1
  374. package/src/__tests__/RealtimeBridgeResolver.test.ts +415 -6
  375. package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +383 -0
  376. package/src/__tests__/RealtimeClientSessionResolver.test.ts +682 -58
  377. package/src/__tests__/RealtimeProxyServer.test.ts +16 -1
  378. package/src/__tests__/RealtimeRelay.test.ts +876 -0
  379. package/src/__tests__/RecordingAssemblyScheduler.test.ts +178 -0
  380. package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +129 -0
  381. package/src/__tests__/ResolverBase.adhocReadScope.test.ts +133 -2
  382. package/src/__tests__/ResolverBase.aggregateScreen.test.ts +174 -0
  383. package/src/__tests__/ResolverBase.balancedClause.test.ts +155 -0
  384. package/src/__tests__/ResolverBase.clauseUnscopedRead.test.ts +127 -0
  385. package/src/__tests__/ResolverBase.clientOldValues.test.ts +212 -6
  386. package/src/__tests__/ResolverBase.filterEscaping.test.ts +5 -2
  387. package/src/__tests__/ReturningVisitorRecap.test.ts +115 -0
  388. package/src/__tests__/RunAIAgentResolver.branch.test.ts +170 -0
  389. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +6 -4
  390. package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +258 -0
  391. package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +166 -0
  392. package/src/__tests__/RunTemplateResolver.test.ts +132 -0
  393. package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +63 -0
  394. package/src/__tests__/RunViewResolver.cacheCheckScreen.test.ts +165 -0
  395. package/src/__tests__/SearchKnowledgeStreamResolver.test.ts +161 -0
  396. package/src/__tests__/SessionJanitor.test.ts +1203 -21
  397. package/src/__tests__/SessionManager.test.ts +240 -17
  398. package/src/__tests__/SessionRunIDVerifier.test.ts +251 -0
  399. package/src/__tests__/SyncRolesUsersResolver.userRoles.test.ts +97 -0
  400. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +25 -0
  401. package/src/__tests__/TaskGraphAgentRunner.test.ts +266 -0
  402. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +403 -22
  403. package/src/__tests__/TaskGraphFrameResolver.test.ts +22 -0
  404. package/src/__tests__/TestQuerySQLResolver.test.ts +274 -0
  405. package/src/__tests__/TransactionGroupResolver.refusals.test.ts +98 -1
  406. package/src/__tests__/UpdateMJDataContextItem.oldValues.test.ts +220 -0
  407. package/src/__tests__/UserAvatarResolver.test.ts +255 -0
  408. package/src/__tests__/UserResolver.currentUser.test.ts +16 -1
  409. package/src/__tests__/ViewOperationsHandler.clauseScreen.test.ts +157 -0
  410. package/src/__tests__/actionAuthorization.test.ts +130 -0
  411. package/src/__tests__/agent-run-data-guard.test.ts +130 -0
  412. package/src/__tests__/agentVisionConsentAudit.test.ts +118 -0
  413. package/src/__tests__/apiRootBoot.test.ts +202 -0
  414. package/src/__tests__/avatarInputValidation.test.ts +160 -0
  415. package/src/__tests__/cacheInvalidationRecordData.test.ts +64 -0
  416. package/src/__tests__/conversationRunEvents.test.ts +56 -14
  417. package/src/__tests__/globalCors.test.ts +217 -0
  418. package/src/__tests__/isolatedProviderTransactions.test.ts +169 -0
  419. package/src/__tests__/magicLinkService.consume.test.ts +6 -0
  420. package/src/__tests__/magicLinkService.provisionLog.test.ts +5 -0
  421. package/src/__tests__/multiTenancy.postgresRewrite.test.ts +181 -0
  422. package/src/__tests__/multiTenancy.security.test.ts +51 -0
  423. package/src/__tests__/multiTenancy.test.ts +1 -1
  424. package/src/__tests__/newUsers.template.test.ts +151 -0
  425. package/src/__tests__/newUsers.test.ts +74 -5
  426. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +17 -2
  427. package/src/__tests__/ownedRealtimeSession.test.ts +39 -0
  428. package/src/__tests__/pushStatusResolver.filter.test.ts +7 -0
  429. package/src/__tests__/realtimeRecordingHandler.test.ts +652 -0
  430. package/src/__tests__/realtimeSessions/RealtimeSessionEventService.test.ts +201 -0
  431. package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +215 -0
  432. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationResolver.test.ts +102 -0
  433. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationService.test.ts +349 -0
  434. package/src/__tests__/realtimeSessions/RealtimeVerifyRouter.test.ts +131 -0
  435. package/src/__tests__/realtimeSessions/SlidingWindowRateLimiter.test.ts +56 -0
  436. package/src/__tests__/realtimeSessions/helpers.ts +4 -0
  437. package/src/__tests__/realtimeSessions/sessionAccess.test.ts +129 -0
  438. package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +124 -0
  439. package/src/__tests__/realtimeSessions/verificationCore.test.ts +355 -0
  440. package/src/__tests__/realtimeSessions/verificationPages.test.ts +84 -0
  441. package/src/__tests__/realtimeSessions/verificationPolicy.test.ts +226 -0
  442. package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +633 -0
  443. package/src/__tests__/resolverBase.fls.test.ts +87 -4
  444. package/src/__tests__/serverExtensionHostOverlay.test.ts +66 -0
  445. package/src/__tests__/serverExtensionReservedRoots.test.ts +11 -96
  446. package/src/__tests__/sharedCache.test.ts +312 -0
  447. package/src/__tests__/widgetGuestElevation.test.ts +44 -0
  448. package/src/agentSessions/BridgeHostInstance.ts +32 -0
  449. package/src/agentSessions/HostInstance.ts +124 -28
  450. package/src/agentSessions/ReturningVisitorRecap.ts +7 -3
  451. package/src/agentSessions/SessionJanitor.ts +821 -59
  452. package/src/agentSessions/SessionManager.ts +138 -26
  453. package/src/agentSessions/SessionRunIDVerifier.ts +171 -0
  454. package/src/agentSessions/index.ts +10 -3
  455. package/src/apiRoot.ts +78 -0
  456. package/src/auth/AuthProviderCatalogRouter.ts +26 -0
  457. package/src/auth/LoginScreenEngine.ts +50 -0
  458. package/src/auth/actionAuthorization.ts +116 -0
  459. package/src/auth/index.ts +4 -8
  460. package/src/auth/magicLink/MagicLinkRouter.ts +3 -2
  461. package/src/auth/magicLink/MagicLinkService.ts +6 -3
  462. package/src/auth/newUsers.ts +99 -11
  463. package/src/config.ts +171 -5
  464. package/src/context.ts +15 -10
  465. package/src/coreRoutes.ts +166 -0
  466. package/src/generated/graphql-schemas/__mj.ts +1815 -57
  467. package/src/generic/CacheInvalidationResolver.ts +73 -18
  468. package/src/generic/OrphanedConversationDetailReconciler.ts +3 -3
  469. package/src/generic/PushStatusResolver.ts +1 -1
  470. package/src/generic/ResolverBase.ts +335 -326
  471. package/src/generic/RunViewResolver.ts +21 -0
  472. package/src/globalCors.ts +71 -0
  473. package/src/index.ts +231 -300
  474. package/src/isolatedProvider.ts +22 -0
  475. package/src/multiTenancy/index.ts +24 -2
  476. package/src/realtimeProxy/RealtimeProxyServer.ts +148 -16
  477. package/src/realtimeProxy/RealtimeRelayTunnel.ts +645 -0
  478. package/src/realtimeSessions/README.md +179 -0
  479. package/src/realtimeSessions/RealtimeSessionEventService.ts +274 -0
  480. package/src/realtimeSessions/RealtimeSessionVerificationService.ts +168 -0
  481. package/src/realtimeSessions/RealtimeVerifyRouter.ts +109 -0
  482. package/src/realtimeSessions/RecordingAssemblyScheduler.ts +234 -0
  483. package/src/realtimeSessions/SessionVerificationPortsBase.ts +189 -0
  484. package/src/realtimeSessions/SlidingWindowRateLimiter.ts +92 -0
  485. package/src/realtimeSessions/index.ts +18 -0
  486. package/src/realtimeSessions/ownedRealtimeSession.ts +55 -0
  487. package/src/realtimeSessions/sessionAccess.ts +145 -0
  488. package/src/realtimeSessions/sessionConfigStamps.ts +123 -0
  489. package/src/realtimeSessions/subscriptionAuthorization.ts +116 -0
  490. package/src/realtimeSessions/verificationCore.ts +502 -0
  491. package/src/realtimeSessions/verificationPages.ts +149 -0
  492. package/src/realtimeSessions/verificationPolicy.ts +321 -0
  493. package/src/realtimeSessions/verificationWorkflow.ts +702 -0
  494. package/src/realtimeWidget/widgetGuestElevation.ts +34 -2
  495. package/src/resolvers/ActionResolver.ts +84 -21
  496. package/src/resolvers/AdhocQueryResolver.ts +24 -6
  497. package/src/resolvers/ArtifactFileResolver.ts +9 -8
  498. package/src/resolvers/CacheStatsResolver.ts +89 -2
  499. package/src/resolvers/ClientToolRequestResolver.ts +25 -7
  500. package/src/resolvers/ConversationRunEventsResolver.ts +15 -11
  501. package/src/resolvers/DatasetResolver.ts +70 -10
  502. package/src/resolvers/EntityRecordNameResolver.ts +3 -2
  503. package/src/resolvers/FetchEntityVectorsResolver.ts +179 -2
  504. package/src/resolvers/FileResolver.ts +321 -106
  505. package/src/resolvers/GetDataContextDataResolver.ts +139 -41
  506. package/src/resolvers/GetDataResolver.ts +6 -3
  507. package/src/resolvers/HumanHandoffResolver.ts +8 -0
  508. package/src/resolvers/IntegrationDiscoveryResolver.ts +4 -2
  509. package/src/resolvers/MCPResolver.ts +8 -5
  510. package/src/resolvers/QueryResolver.ts +11 -0
  511. package/src/resolvers/RealtimeBridgeResolver.ts +163 -11
  512. package/src/resolvers/RealtimeClientSessionResolver.ts +511 -129
  513. package/src/resolvers/RealtimeSessionEventsResolver.ts +133 -0
  514. package/src/resolvers/RealtimeSessionVerificationResolver.ts +174 -0
  515. package/src/resolvers/RemoteBrowserActionResolver.ts +11 -1
  516. package/src/resolvers/RunAIAgentResolver.ts +116 -14
  517. package/src/resolvers/RunTemplateResolver.ts +13 -12
  518. package/src/resolvers/SearchKnowledgeStreamResolver.ts +19 -3
  519. package/src/resolvers/SqlLoggingConfigResolver.ts +2 -4
  520. package/src/resolvers/SyncDataResolver.ts +6 -2
  521. package/src/resolvers/SyncRolesUsersResolver.ts +24 -6
  522. package/src/resolvers/TaskGraphFrameResolver.ts +33 -1
  523. package/src/resolvers/TestQuerySQLResolver.ts +68 -13
  524. package/src/resolvers/TransactionGroupResolver.ts +131 -27
  525. package/src/resolvers/UserAvatarResolver.ts +111 -0
  526. package/src/resolvers/UserResolver.ts +2 -16
  527. package/src/resolvers/__tests__/GetDataResolver.validation.test.ts +95 -0
  528. package/src/resolvers/agent-run-data-guard.ts +89 -0
  529. package/src/resolvers/agentVisionConsentAudit.ts +82 -0
  530. package/src/resolvers/avatarInputValidation.ts +123 -0
  531. package/src/resolvers/currentUserRoles.ts +32 -1
  532. package/src/resolvers/meetings/meetingMutations.ts +21 -0
  533. package/src/rest/RealtimeRecordingHandler.ts +464 -0
  534. package/src/rest/ViewOperationsHandler.ts +29 -13
  535. package/src/rest/setupRESTEndpoints.ts +6 -0
  536. package/src/serverExtensionReservedRoots.ts +14 -17
  537. package/src/services/MJStorageBlobStore.ts +31 -30
  538. package/src/services/StartTaskGraphDispatcher.ts +2 -2
  539. package/src/services/TaskGraphActionRunner.ts +25 -5
  540. package/src/services/TaskGraphAgentRunner.ts +188 -11
  541. package/src/services/TaskGraphContinuationDeliverer.ts +713 -17
  542. package/src/sharedCache.ts +305 -0
  543. package/src/types.ts +7 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @fileoverview The PUBLIC verify-link routes of mid-session identity verification.
3
+ *
4
+ * Mounted BEFORE the unified auth middleware (the person opening the emailed link — often on another
5
+ * device — holds no MJ token; the single-use token IS the capability).
6
+ *
7
+ * | Route | Effect |
8
+ * |---|---|
9
+ * | `GET /realtime/verify/:token` | Renders a one-button confirmation page. **No side effects.** |
10
+ * | `POST /realtime/verify` (form field `token`) | Redeems the token; renders "You're verified" or the uniform failure page. |
11
+ *
12
+ * ## Why the redemption is a POST
13
+ *
14
+ * Mail scanners and link previewers GET every URL in a message. A GET that consumed the single-use token
15
+ * would let a scanner burn it before the human clicks. The magic-link redeem endpoint made the same
16
+ * choice. The human's click submits the form.
17
+ *
18
+ * ## What the responses reveal
19
+ *
20
+ * Nothing about any session. A malformed token, an unknown session, an expired link, a used link and a
21
+ * voided verification all render the SAME page with the SAME status; success is a bare "You're verified".
22
+ * Responses are `no-store`, never framed, sent with `Referrer-Policy: no-referrer` (the token is in the
23
+ * URL of the GET), and carry a CSP that forbids everything but the page's own inline style.
24
+ *
25
+ * @module @memberjunction/server/realtimeSessions
26
+ */
27
+
28
+ import { Router, urlencoded, type Request, type Response } from 'express';
29
+ import { rateLimit } from 'express-rate-limit';
30
+ import { LogError } from '@memberjunction/core';
31
+ import { configInfo } from '../config.js';
32
+ import { RealtimeSessionVerificationService } from './RealtimeSessionVerificationService.js';
33
+ import { BuildVerifyConfirmHtml, BuildVerifyErrorHtml, BuildVerifyFailureHtml, BuildVerifySuccessHtml } from './verificationPages.js';
34
+ import { ApiRoute } from '../apiRoot.js';
35
+
36
+ /** Mount path of the public verify routes. Under `/realtime`, which is already reserved against server extensions. */
37
+ export const REALTIME_VERIFY_MOUNT_PATH = '/realtime/verify';
38
+
39
+ /** Headers every verify response carries. */
40
+ function setSecurityHeaders(res: Response): void {
41
+ res.setHeader('Cache-Control', 'no-store');
42
+ res.setHeader('Referrer-Policy', 'no-referrer');
43
+ res.setHeader('X-Content-Type-Options', 'nosniff');
44
+ res.setHeader('X-Frame-Options', 'DENY');
45
+ res.setHeader(
46
+ 'Content-Security-Policy',
47
+ "default-src 'none'; style-src 'unsafe-inline'; form-action 'self'; frame-ancestors 'none'; base-uri 'none'",
48
+ );
49
+ }
50
+
51
+ /** Sends an HTML page with the verify security headers. */
52
+ function sendPage(res: Response, status: number, html: string): void {
53
+ setSecurityHeaders(res);
54
+ res.status(status).type('html').send(html);
55
+ }
56
+
57
+ /**
58
+ * Builds the public verify router. Mount at {@link REALTIME_VERIFY_MOUNT_PATH} BEFORE the auth
59
+ * middleware.
60
+ *
61
+ * @param service - the verification service (injectable for tests; defaults to the process singleton)
62
+ */
63
+ export function CreateRealtimeVerifyRouter(
64
+ service: Pick<RealtimeSessionVerificationService, 'RedeemLink'> = RealtimeSessionVerificationService.Instance,
65
+ ): Router {
66
+ const limits = configInfo.realtime?.identityVerification?.rateLimits;
67
+ // The route is public and a redemption does a database read + write, so it is throttled per IP — the
68
+ // same posture as the magic-link redeem endpoint. The message is the failure page, not JSON: this
69
+ // route talks to a browser.
70
+ const limiter = rateLimit({
71
+ windowMs: limits?.redeemWindowMs ?? 60_000,
72
+ limit: limits?.redeemPerIp ?? 30,
73
+ standardHeaders: 'draft-7',
74
+ legacyHeaders: false,
75
+ handler: (_req: Request, res: Response) => sendPage(res, 429, BuildVerifyFailureHtml()),
76
+ });
77
+
78
+ const router = Router();
79
+
80
+ // SAFE: renders the confirmation button. Never consumes the token (see the module header).
81
+ router.get('/:token', limiter, (req: Request, res: Response) => {
82
+ const token = typeof req.params.token === 'string' ? req.params.token : '';
83
+ sendPage(res, 200, BuildVerifyConfirmHtml(token, ApiRoute(REALTIME_VERIFY_MOUNT_PATH)));
84
+ });
85
+
86
+ // The side-effecting redemption, gated by a human gesture.
87
+ router.post('/', limiter, urlencoded({ extended: false, limit: '4kb' }), async (req: Request, res: Response) => {
88
+ const body = (req.body ?? {}) as { token?: unknown };
89
+ const token = typeof body.token === 'string' ? body.token : '';
90
+ try {
91
+ const result = await service.RedeemLink(token, req.ip);
92
+ if (result.Success) {
93
+ sendPage(res, 200, BuildVerifySuccessHtml());
94
+ } else if (result.ErrorCode === 'persist_failed') {
95
+ // A server fault after a VALID token: the link is still redeemable, so say "try again".
96
+ sendPage(res, 500, BuildVerifyErrorHtml());
97
+ } else {
98
+ // 410 for every other refusal: the page and status are identical whether the token was unknown,
99
+ // malformed, expired or used, so the route cannot be used to probe sessions.
100
+ sendPage(res, 410, BuildVerifyFailureHtml());
101
+ }
102
+ } catch (error) {
103
+ LogError(`RealtimeVerifyRouter: redemption threw: ${error instanceof Error ? error.message : String(error)}`);
104
+ sendPage(res, 500, BuildVerifyErrorHtml());
105
+ }
106
+ });
107
+
108
+ return router;
109
+ }
@@ -0,0 +1,234 @@
1
+ /**
2
+ * @fileoverview Per-session timers that assemble a client-direct realtime recording from its shard ledger
3
+ * off the request path.
4
+ *
5
+ * The recording REST routes only record shards and the terminal signal; they never decode. When a route
6
+ * learns a session is ready (every expected shard present) it asks for an assembly now; when shards are
7
+ * missing it asks for one after the grace period, forced to `Partial`. This scheduler turns those requests
8
+ * into at most one pending timer and at most one running assembly per session in this process.
9
+ *
10
+ * Correctness across processes does not depend on it: every run starts with the ledger's atomic
11
+ * `ClaimAssembly`, so of two instances (or two timers) only the claim winner assembles. The per-session
12
+ * guard here only avoids wasted claims. A run that dies with the process leaves the session `Assembling`,
13
+ * and the session janitor's stale re-claim is the backstop for that and for any request dropped here.
14
+ *
15
+ * @module @memberjunction/server/realtimeSessions
16
+ */
17
+ import { DatabaseProviderBase, LogError, LogStatus, UserInfo } from '@memberjunction/core';
18
+ import { BaseSingleton, IShutdownable, ShutdownRegistry } from '@memberjunction/global';
19
+ import {
20
+ AssembleRealtimeRecordingFromLedger, AssembleRealtimeRecordingInput, AssembleRealtimeRecordingOutcome,
21
+ IRealtimeRecordingLedger, SqlRealtimeRecordingLedger,
22
+ } from '@memberjunction/ai-agents';
23
+
24
+ /** A cancellable one-shot timer. */
25
+ export interface RecordingAssemblyTimer {
26
+ Cancel(): void;
27
+ }
28
+
29
+ /** Time source of the scheduler; injectable so tests can drive it. */
30
+ export interface RecordingAssemblyClock {
31
+ /** Milliseconds since the epoch. */
32
+ Now(): number;
33
+ /** Runs `callback` once after `delayMs`. The timer must not keep the process alive. */
34
+ StartTimer(callback: () => void, delayMs: number): RecordingAssemblyTimer;
35
+ }
36
+
37
+ /** The narrow scheduling contract the recording routes depend on. */
38
+ export interface IRecordingAssemblyScheduler {
39
+ /**
40
+ * Requests an assembly of `sessionID` after `delayMs`. `forcePartial` assembles what exists even when
41
+ * shards are missing (the grace period ran out). See {@link RecordingAssemblyScheduler.ScheduleAssembly}.
42
+ */
43
+ ScheduleAssembly(sessionID: string, delayMs: number, forcePartial: boolean): void;
44
+ }
45
+
46
+ /** What {@link RecordingAssemblyScheduler.Start} needs. */
47
+ export interface RecordingAssemblySchedulerOptions {
48
+ /** The server's own provider; assembly is server-owned background work, not a request. */
49
+ Provider: DatabaseProviderBase;
50
+ /** The user assembly runs as (the system user). */
51
+ SystemUser: UserInfo;
52
+ /** Grace before a `Deferred` (incomplete) assembly is retried as forced `Partial`. */
53
+ GraceMs: () => number;
54
+ /** Defaults to {@link SqlRealtimeRecordingLedger}. */
55
+ CreateLedger?: (provider: DatabaseProviderBase, contextUser: UserInfo) => IRealtimeRecordingLedger;
56
+ /** Defaults to {@link AssembleRealtimeRecordingFromLedger}. */
57
+ Assemble?: (input: AssembleRealtimeRecordingInput) => Promise<AssembleRealtimeRecordingOutcome>;
58
+ /** Defaults to `Date.now` and unref'd `setTimeout`. */
59
+ Clock?: RecordingAssemblyClock;
60
+ }
61
+
62
+ interface PendingAssembly {
63
+ DueAt: number;
64
+ ForcePartial: boolean;
65
+ Timer: RecordingAssemblyTimer;
66
+ }
67
+
68
+ const NODE_CLOCK: RecordingAssemblyClock = {
69
+ Now: () => Date.now(),
70
+ StartTimer: (callback, delayMs) => {
71
+ const handle = setTimeout(callback, delayMs);
72
+ handle.unref?.();
73
+ return { Cancel: () => clearTimeout(handle) };
74
+ },
75
+ };
76
+
77
+ /**
78
+ * Process-wide scheduler of recording assemblies (see the file overview). Call {@link Start} once at
79
+ * server startup; requests made before it (or after {@link Shutdown}) are logged and dropped, leaving the
80
+ * session to the janitor.
81
+ */
82
+ export class RecordingAssemblyScheduler extends BaseSingleton<RecordingAssemblyScheduler> implements IShutdownable, IRecordingAssemblyScheduler {
83
+ private _options: Required<RecordingAssemblySchedulerOptions> | null = null;
84
+ private _registered = false;
85
+ /** Pending timers keyed by lowercase session id. */
86
+ private readonly pending = new Map<string, PendingAssembly>();
87
+ /** Lowercase ids of sessions with an assembly running in this process. */
88
+ private readonly running = new Set<string>();
89
+ /** Sessions asked for again while running, with the ForcePartial to re-run with. */
90
+ private readonly rerun = new Map<string, boolean>();
91
+
92
+ protected constructor() {
93
+ super();
94
+ }
95
+
96
+ /** Process-wide singleton accessor. */
97
+ public static get Instance(): RecordingAssemblyScheduler {
98
+ return super.getInstance<RecordingAssemblyScheduler>();
99
+ }
100
+
101
+ /** Identifier surfaced in graceful-shutdown logs. */
102
+ public readonly ShutdownName = 'RecordingAssemblyScheduler';
103
+
104
+ /** Configures the scheduler and enables it; calling again replaces the configuration. */
105
+ public Start(options: RecordingAssemblySchedulerOptions): void {
106
+ this._options = {
107
+ CreateLedger: (provider, contextUser) => new SqlRealtimeRecordingLedger(provider, contextUser),
108
+ Assemble: AssembleRealtimeRecordingFromLedger,
109
+ Clock: NODE_CLOCK,
110
+ ...options,
111
+ };
112
+ if (!this._registered) {
113
+ ShutdownRegistry.Instance.Register(this);
114
+ this._registered = true;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Requests an assembly of `sessionID` after `delayMs`. One pending timer per session: a request
120
+ * replaces the pending one only when it would fire sooner (at the same time, the merged request keeps
121
+ * `forcePartial` if either had it). A timer that fires while the session's previous run is still going
122
+ * is remembered and run right after it, never alongside it.
123
+ *
124
+ * Trade-off: a sooner un-forced request replaces a pending forced one. If that run comes back
125
+ * `Deferred` (still incomplete), the forced `Partial` is re-scheduled a full grace from then, so a
126
+ * forced Partial can land up to ~2× the grace after the first terminal signal. Accepted: the sooner
127
+ * run completes the recording outright whenever the missing shards did arrive.
128
+ */
129
+ public ScheduleAssembly(sessionID: string, delayMs: number, forcePartial: boolean): void {
130
+ const options = this._options;
131
+ if (!options) {
132
+ LogError(`RecordingAssemblyScheduler: not running; dropped the assembly request for session ${sessionID} (the session janitor will assemble it)`);
133
+ return;
134
+ }
135
+ const key = sessionID.toLowerCase();
136
+ const dueAt = options.Clock.Now() + Math.max(0, delayMs);
137
+ const existing = this.pending.get(key);
138
+ if (existing && existing.DueAt < dueAt) {
139
+ return;
140
+ }
141
+ if (existing && existing.DueAt === dueAt) {
142
+ existing.ForcePartial = existing.ForcePartial || forcePartial;
143
+ return;
144
+ }
145
+ existing?.Timer.Cancel();
146
+ const timer = options.Clock.StartTimer(() => this.onTimer(key, sessionID), dueAt - options.Clock.Now());
147
+ this.pending.set(key, { DueAt: dueAt, ForcePartial: forcePartial, Timer: timer });
148
+ }
149
+
150
+ /**
151
+ * Cancels every pending timer and stops accepting requests until the next {@link Start}. A running
152
+ * assembly is not awaited: if the process exits under it, the session stays `Assembling` and the
153
+ * janitor's stale re-claim finishes it. Idempotent.
154
+ */
155
+ public Shutdown(): void {
156
+ for (const entry of this.pending.values()) {
157
+ entry.Timer.Cancel();
158
+ }
159
+ this.pending.clear();
160
+ this.rerun.clear();
161
+ this._options = null;
162
+ }
163
+
164
+ private onTimer(key: string, sessionID: string): void {
165
+ const entry = this.pending.get(key);
166
+ if (!entry) {
167
+ return;
168
+ }
169
+ this.pending.delete(key);
170
+ if (this.running.has(key)) {
171
+ this.rerun.set(key, (this.rerun.get(key) ?? false) || entry.ForcePartial);
172
+ return;
173
+ }
174
+ void this.runUntilSettled(key, sessionID, entry.ForcePartial);
175
+ }
176
+
177
+ /** Runs the session's assembly, then any re-run requested meanwhile. Never rejects. */
178
+ private async runUntilSettled(key: string, sessionID: string, forcePartial: boolean): Promise<void> {
179
+ this.running.add(key);
180
+ try {
181
+ let next: boolean | undefined = forcePartial;
182
+ while (next !== undefined) {
183
+ await this.runOnce(sessionID, next);
184
+ next = this.rerun.get(key);
185
+ this.rerun.delete(key);
186
+ }
187
+ } finally {
188
+ this.running.delete(key);
189
+ }
190
+ }
191
+
192
+ /** One claim + assembly. Logs every failure with the session id; never throws. */
193
+ private async runOnce(sessionID: string, forcePartial: boolean): Promise<void> {
194
+ const options = this._options;
195
+ if (!options) {
196
+ LogStatus(`RecordingAssemblyScheduler: shut down before session ${sessionID} could assemble; the session janitor will assemble it`);
197
+ return;
198
+ }
199
+ try {
200
+ const ledger = options.CreateLedger(options.Provider, options.SystemUser);
201
+ const version = await ledger.ClaimAssembly(sessionID, null);
202
+ if (version === null) {
203
+ LogStatus(`RecordingAssemblyScheduler: session ${sessionID} not claimable (assembled, assembling elsewhere, or failed); skipping`);
204
+ return;
205
+ }
206
+ const outcome = await options.Assemble({
207
+ SessionID: sessionID, Version: version, Ledger: ledger,
208
+ ContextUser: options.SystemUser, Provider: options.Provider, ForcePartial: forcePartial,
209
+ });
210
+ this.handleOutcome(sessionID, version, outcome, options);
211
+ } catch (error) {
212
+ LogError(`RecordingAssemblyScheduler: assembly of session ${sessionID} failed: ${error instanceof Error ? error.message : String(error)}`);
213
+ }
214
+ }
215
+
216
+ private handleOutcome(
217
+ sessionID: string,
218
+ version: number,
219
+ outcome: AssembleRealtimeRecordingOutcome,
220
+ options: Required<RecordingAssemblySchedulerOptions>,
221
+ ): void {
222
+ if (outcome === 'Deferred') {
223
+ // Incomplete and not forced: give missing shards the grace period, then assemble what exists.
224
+ LogStatus(`RecordingAssemblyScheduler: session ${sessionID} (version ${version}) is missing shards; assembling as Partial after the grace period`);
225
+ this.ScheduleAssembly(sessionID, options.GraceMs(), true);
226
+ return;
227
+ }
228
+ if (outcome === 'Retry') {
229
+ LogError(`RecordingAssemblyScheduler: assembly of session ${sessionID} (version ${version}) hit a transient error; the session janitor re-claims it later`);
230
+ return;
231
+ }
232
+ LogStatus(`RecordingAssemblyScheduler: session ${sessionID} (version ${version}) assembly finished: ${outcome}`);
233
+ }
234
+ }
@@ -0,0 +1,189 @@
1
+ /**
2
+ * @fileoverview {@link SessionVerificationPortsBase} — the config-free half of the production
3
+ * {@link VerificationPorts}: reading and writing a session, publishing `identity.verified`, and the
4
+ * audit entry. Everything that depends on server configuration (the settings, the service principal,
5
+ * the mail provider) is left abstract.
6
+ *
7
+ * The split exists so the DB-facing behaviour can be exercised with real sessions by anything that
8
+ * cannot — or must not — load the server's configuration at import time (the integration-test bundle
9
+ * subclasses it with captured email and a fixed principal). `RuntimeVerificationPorts`, in
10
+ * `RealtimeSessionVerificationService.ts`, is the production subclass that supplies the configuration.
11
+ *
12
+ * ## Which identity performs the writes, and why
13
+ *
14
+ * Reads of the session for **authorization** run as the CALLER, so row-level security is the first gate
15
+ * (a widget guest cannot even load another guest's session). Every **write** of server-decided state
16
+ * runs as a service principal ({@link SessionVerificationPortsBase.ResolveServiceUser}), inside
17
+ * `RunWithTrustedSessionConfigWrites`. That is not a convenience: the session owner can already `Update`
18
+ * their own session row, which is exactly why `MJAIAgentSessionEntityServer` refuses owner writes to
19
+ * `identityVerification` and `maxSessionDeadlineIso`. Server-decided state must be written by the server,
20
+ * after the caller was authorized, in a scope no remote caller can enter. The verify link has no caller
21
+ * identity at all (the token is the capability), so it needs the service principal for its reads too.
22
+ *
23
+ * @module @memberjunction/server/realtimeSessions
24
+ */
25
+
26
+ import { LogError, Metadata, type IMetadataProvider, type UserInfo } from '@memberjunction/core';
27
+ import { RunWithTrustedSessionConfigWrites } from '@memberjunction/core-entities-server';
28
+ import type { MJAuditLogEntity } from '@memberjunction/core-entities';
29
+ import type { IdentityVerifiedEventPayload } from '@memberjunction/ai-core-plus';
30
+ import { LoadSessionForAccess, type LoadedSessionForAccess } from './sessionAccess.js';
31
+ import { RealtimeSessionEventService } from './RealtimeSessionEventService.js';
32
+ import {
33
+ type ConfigMutation,
34
+ type ConfigMutationResult,
35
+ type OutboundEmail,
36
+ type SessionSnapshot,
37
+ type VerificationAuditEntry,
38
+ type VerificationCaller,
39
+ type VerificationPorts,
40
+ type VerificationSettings,
41
+ } from './verificationWorkflow.js';
42
+
43
+ /** The seeded audit-log type (see `metadata/audit-log-types/.realtime-session-audit-types.json`). */
44
+ export const REALTIME_IDENTITY_VERIFIED_AUDIT_TYPE = 'Realtime Identity Verified';
45
+
46
+ const AUDIT_LOG_ENTITY = 'MJ: Audit Logs';
47
+ const SESSION_ENTITY_NAME = 'MJ: AI Agent Sessions';
48
+
49
+
50
+ /** Reduces a loaded session to the snapshot the workflow reasons about. */
51
+ function toSnapshot(loaded: LoadedSessionForAccess): SessionSnapshot {
52
+ const { Session } = loaded;
53
+ return {
54
+ AgentSessionID: Session.ID,
55
+ OwnerUserID: Session.UserID,
56
+ ConversationExternalID: loaded.ConversationExternalID,
57
+ Status: Session.Status,
58
+ ConfigRaw: Session.Config_,
59
+ // `__mj_CreatedAt` is the row's creation instant — i.e. the session start. It is read-only and
60
+ // set by the database, so a client cannot move it.
61
+ StartedAtMs: Session.__mj_CreatedAt instanceof Date ? Session.__mj_CreatedAt.getTime() : Date.now(),
62
+ };
63
+ }
64
+
65
+
66
+ /**
67
+ * The session-facing {@link VerificationPorts}, minus configuration. Subclasses supply the settings, the
68
+ * service principal and the mail delivery.
69
+ */
70
+ export abstract class SessionVerificationPortsBase implements VerificationPorts {
71
+ /** The live settings. */
72
+ public abstract GetSettings(): VerificationSettings;
73
+
74
+ /** Delivers an email. Must not throw; reports failure in the result. */
75
+ public abstract SendEmail(email: OutboundEmail): Promise<{ Success: boolean; ErrorMessage?: string }>;
76
+
77
+ /** The principal state writes (and the link caller's reads) run as; null when none is available. */
78
+ protected abstract ResolveServiceUser(): UserInfo | null;
79
+
80
+ public Now(): number {
81
+ return Date.now();
82
+ }
83
+
84
+ public async LoadSession(agentSessionId: string, caller: VerificationCaller): Promise<SessionSnapshot | null> {
85
+ const reader = this.readerFor(caller);
86
+ if (!reader) {
87
+ return null;
88
+ }
89
+ const loaded = await LoadSessionForAccess(agentSessionId, reader.User, reader.Provider);
90
+ return loaded ? toSnapshot(loaded) : null;
91
+ }
92
+
93
+ public async MutateSessionConfig<T>(
94
+ agentSessionId: string,
95
+ caller: VerificationCaller,
96
+ mutate: ConfigMutation<T>,
97
+ ): Promise<ConfigMutationResult<T>> {
98
+ const writer = this.writerFor(caller);
99
+ if (!writer) {
100
+ return { Persisted: false, ErrorMessage: 'No service principal is available to record verification state.' };
101
+ }
102
+ try {
103
+ const loaded = await LoadSessionForAccess(agentSessionId, writer.User, writer.Provider);
104
+ if (!loaded) {
105
+ return { Persisted: false, ErrorMessage: `Session ${agentSessionId} could not be read.` };
106
+ }
107
+ const session = toSnapshot(loaded);
108
+ const { NextConfigRaw, Outcome } = mutate(session);
109
+ if (NextConfigRaw === null) {
110
+ return { Session: session, Outcome, Persisted: false };
111
+ }
112
+ loaded.Session.Config_ = NextConfigRaw;
113
+ const saved = await RunWithTrustedSessionConfigWrites(() => loaded.Session.Save());
114
+ if (!saved) {
115
+ const detail = loaded.Session.LatestResult?.CompleteMessage ?? 'unknown error';
116
+ LogError(`RealtimeSessionVerification: saving session ${agentSessionId} failed: ${detail}`);
117
+ return { Session: session, Outcome, Persisted: false, ErrorMessage: detail };
118
+ }
119
+ return { Session: session, Outcome, Persisted: true };
120
+ } catch (error) {
121
+ const message = error instanceof Error ? error.message : String(error);
122
+ LogError(`RealtimeSessionVerification: updating session ${agentSessionId} threw: ${message}`);
123
+ return { Persisted: false, ErrorMessage: message };
124
+ }
125
+ }
126
+
127
+ public PublishVerified(
128
+ routing: { AgentSessionID: string; OwnerUserID: string; ScopeKey: string | null },
129
+ payload: IdentityVerifiedEventPayload,
130
+ ): { Success: boolean; ErrorMessage?: string } {
131
+ return RealtimeSessionEventService.Instance.PublishRouted(routing, 'identity.verified', payload);
132
+ }
133
+
134
+ public async WriteAudit(entry: VerificationAuditEntry): Promise<void> {
135
+ const writer = this.ResolveServiceUser();
136
+ const provider = Metadata.Provider; // global-provider-ok: server-side audit write under the server's single default provider
137
+ const type = provider?.AuditLogTypes?.find((t) => t.Name?.trim().toLowerCase() === REALTIME_IDENTITY_VERIFIED_AUDIT_TYPE.toLowerCase());
138
+ const sessionEntityId = provider?.EntityByName(SESSION_ENTITY_NAME)?.ID;
139
+ if (!writer || !type) {
140
+ // The audit type ships as metadata (a release seed); without it, fall back to the server log so
141
+ // the verification is still recorded somewhere durable-ish rather than silently unaudited.
142
+ LogError(
143
+ `RealtimeSessionVerification: audit entry not written for session ${entry.AgentSessionID} ` +
144
+ `(${writer ? `audit log type '${REALTIME_IDENTITY_VERIFIED_AUDIT_TYPE}' is not seeded` : 'no service principal'}): ` +
145
+ `${entry.Email} via ${entry.Method}.`,
146
+ );
147
+ return;
148
+ }
149
+ try {
150
+ const row = await provider.GetEntityObject<MJAuditLogEntity>(AUDIT_LOG_ENTITY, writer);
151
+ row.NewRecord();
152
+ row.UserID = entry.OwnerUserID;
153
+ row.AuditLogTypeID = type.ID;
154
+ row.Status = 'Success';
155
+ row.EntityID = sessionEntityId ?? null;
156
+ row.RecordID = entry.AgentSessionID;
157
+ row.Description = `Realtime session verified ${entry.Email} by ${entry.Method === 'link' ? 'emailed link' : 'typed code'}.`;
158
+ row.Details = JSON.stringify({
159
+ email: entry.Email,
160
+ method: entry.Method,
161
+ ipAddress: entry.ClientIp ?? null,
162
+ maxSessionDeadlineIso: entry.MaxSessionDeadlineIso ?? null,
163
+ });
164
+ if (!(await row.Save())) {
165
+ LogError(`RealtimeSessionVerification: audit row save failed for session ${entry.AgentSessionID}: ${row.LatestResult?.CompleteMessage ?? 'unknown error'}`);
166
+ }
167
+ } catch (error) {
168
+ LogError(`RealtimeSessionVerification: audit write threw for session ${entry.AgentSessionID}: ${error instanceof Error ? error.message : String(error)}`);
169
+ }
170
+ }
171
+
172
+ /** The identity + provider an authorization read runs under. */
173
+ private readerFor(caller: VerificationCaller): { User: UserInfo; Provider: IMetadataProvider } | null {
174
+ if (caller.Kind === 'principal') {
175
+ return { User: caller.ContextUser, Provider: caller.Provider };
176
+ }
177
+ const user = this.ResolveServiceUser();
178
+ return user ? { User: user, Provider: Metadata.Provider } : null; // global-provider-ok: public verify route has no request-scoped provider
179
+ }
180
+
181
+ /** The identity + provider a state write runs under: always the service principal. */
182
+ private writerFor(caller: VerificationCaller): { User: UserInfo; Provider: IMetadataProvider } | null {
183
+ const user = this.ResolveServiceUser();
184
+ if (!user) {
185
+ return null;
186
+ }
187
+ return { User: user, Provider: caller.Kind === 'principal' ? caller.Provider : Metadata.Provider }; // global-provider-ok: public verify route has no request-scoped provider
188
+ }
189
+ }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * @fileoverview A small in-memory sliding-window rate limiter keyed by string, with an injectable
3
+ * clock so it is deterministic under test.
4
+ *
5
+ * Used for the limits that the HTTP-layer `express-rate-limit` cannot express because the request is a
6
+ * GraphQL mutation (per IP / per email domain / per recipient on verification sends, and per session on
7
+ * code attempts). The HTTP verify route uses `express-rate-limit` directly, the same way the widget
8
+ * and magic-link routers do.
9
+ *
10
+ * **Per-instance, best-effort.** State is in process memory, so with several server replicas each
11
+ * enforces its own budget. That is the same trade the widget mint limiter makes. The limits that must
12
+ * hold across replicas — sends per session and code attempts per verification — are NOT here: they are
13
+ * persisted on the session (`identityVerification`) and enforced from the database.
14
+ *
15
+ * @module @memberjunction/server/realtimeSessions
16
+ */
17
+
18
+ /** Outcome of {@link SlidingWindowRateLimiter.TryConsume}. */
19
+ export interface RateLimitDecision {
20
+ /** True when the event fits the budget (and was counted). */
21
+ Allowed: boolean;
22
+ /** When refused, ms until the oldest counted event leaves the window. 0 when allowed. */
23
+ RetryAfterMs: number;
24
+ }
25
+
26
+ /** Construction options. */
27
+ export interface SlidingWindowRateLimiterOptions {
28
+ /** Events allowed per key per window. A limit of 0 or less disables the limiter (everything allowed). */
29
+ Limit: number;
30
+ /** Window length in ms. */
31
+ WindowMs: number;
32
+ /** Upper bound on distinct keys held in memory; the oldest-seen keys are evicted past it. Default 10 000. */
33
+ MaxKeys?: number;
34
+ }
35
+
36
+ /** Default bound on distinct keys held. */
37
+ const DEFAULT_MAX_KEYS = 10_000;
38
+
39
+ /**
40
+ * Counts events per key over a sliding window.
41
+ *
42
+ * Memory is bounded two ways: a key's timestamps older than the window are dropped whenever the key is
43
+ * touched, and when the number of keys exceeds `MaxKeys` the least-recently-inserted keys are evicted
44
+ * (an evicted key simply starts a fresh window — the limiter fails open by forgetting, never closed).
45
+ */
46
+ export class SlidingWindowRateLimiter {
47
+ private readonly events = new Map<string, number[]>();
48
+ private readonly maxKeys: number;
49
+
50
+ constructor(private readonly options: SlidingWindowRateLimiterOptions) {
51
+ this.maxKeys = options.MaxKeys ?? DEFAULT_MAX_KEYS;
52
+ }
53
+
54
+ /**
55
+ * Counts one event for `key` if the budget allows.
56
+ *
57
+ * @param key - what is being limited (an IP, a domain, a session id…); callers normalise it
58
+ * @param nowMs - the current time, epoch ms
59
+ */
60
+ public TryConsume(key: string, nowMs: number): RateLimitDecision {
61
+ if (this.options.Limit <= 0) {
62
+ return { Allowed: true, RetryAfterMs: 0 };
63
+ }
64
+ const windowStart = nowMs - this.options.WindowMs;
65
+ const live = (this.events.get(key) ?? []).filter((t) => t > windowStart);
66
+ if (live.length >= this.options.Limit) {
67
+ this.store(key, live);
68
+ return { Allowed: false, RetryAfterMs: Math.max(0, live[0] + this.options.WindowMs - nowMs) };
69
+ }
70
+ live.push(nowMs);
71
+ this.store(key, live);
72
+ return { Allowed: true, RetryAfterMs: 0 };
73
+ }
74
+
75
+ /** Number of keys currently tracked (exposed for tests and diagnostics). */
76
+ public get TrackedKeyCount(): number {
77
+ return this.events.size;
78
+ }
79
+
80
+ /** Re-inserts `key` (moving it to the newest position) and evicts the oldest keys past the bound. */
81
+ private store(key: string, timestamps: number[]): void {
82
+ this.events.delete(key);
83
+ this.events.set(key, timestamps);
84
+ while (this.events.size > this.maxKeys) {
85
+ const oldest = this.events.keys().next();
86
+ if (oldest.done) {
87
+ break;
88
+ }
89
+ this.events.delete(oldest.value);
90
+ }
91
+ }
92
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @fileoverview Realtime session events + mid-session identity verification — module barrel.
3
+ * @module @memberjunction/server/realtimeSessions
4
+ */
5
+ export * from './sessionAccess.js';
6
+ export * from './subscriptionAuthorization.js';
7
+ export * from './RealtimeSessionEventService.js';
8
+ export * from './verificationPolicy.js';
9
+ export * from './verificationCore.js';
10
+ export * from './SlidingWindowRateLimiter.js';
11
+ export * from './verificationPages.js';
12
+ export * from './verificationWorkflow.js';
13
+ export * from './sessionConfigStamps.js';
14
+ export * from './SessionVerificationPortsBase.js';
15
+ export * from './RealtimeSessionVerificationService.js';
16
+ export * from './RealtimeVerifyRouter.js';
17
+ export * from './ownedRealtimeSession.js';
18
+ export * from './RecordingAssemblyScheduler.js';