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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. package/README.md +30 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentSessions/BridgeHostInstance.d.ts +25 -0
  4. package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -0
  5. package/dist/agentSessions/BridgeHostInstance.js +30 -0
  6. package/dist/agentSessions/BridgeHostInstance.js.map +1 -0
  7. package/dist/agentSessions/HostInstance.d.ts +75 -11
  8. package/dist/agentSessions/HostInstance.d.ts.map +1 -1
  9. package/dist/agentSessions/HostInstance.js +99 -28
  10. package/dist/agentSessions/HostInstance.js.map +1 -1
  11. package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
  12. package/dist/agentSessions/ReturningVisitorRecap.js +7 -3
  13. package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
  14. package/dist/agentSessions/SessionJanitor.d.ts +173 -25
  15. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  16. package/dist/agentSessions/SessionJanitor.js +452 -54
  17. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  18. package/dist/agentSessions/SessionManager.d.ts +43 -2
  19. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  20. package/dist/agentSessions/SessionManager.js +99 -8
  21. package/dist/agentSessions/SessionManager.js.map +1 -1
  22. package/dist/agentSessions/SessionRunIDVerifier.d.ts +63 -0
  23. package/dist/agentSessions/SessionRunIDVerifier.d.ts.map +1 -0
  24. package/dist/agentSessions/SessionRunIDVerifier.js +129 -0
  25. package/dist/agentSessions/SessionRunIDVerifier.js.map +1 -0
  26. package/dist/agentSessions/index.d.ts +2 -0
  27. package/dist/agentSessions/index.d.ts.map +1 -1
  28. package/dist/agentSessions/index.js +10 -3
  29. package/dist/agentSessions/index.js.map +1 -1
  30. package/dist/auth/actionAuthorization.d.ts +40 -0
  31. package/dist/auth/actionAuthorization.d.ts.map +1 -0
  32. package/dist/auth/actionAuthorization.js +94 -0
  33. package/dist/auth/actionAuthorization.js.map +1 -0
  34. package/dist/auth/index.d.ts.map +1 -1
  35. package/dist/auth/index.js +3 -10
  36. package/dist/auth/index.js.map +1 -1
  37. package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
  38. package/dist/auth/magicLink/MagicLinkService.js +6 -3
  39. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  40. package/dist/auth/newUsers.d.ts +10 -0
  41. package/dist/auth/newUsers.d.ts.map +1 -1
  42. package/dist/auth/newUsers.js +80 -11
  43. package/dist/auth/newUsers.js.map +1 -1
  44. package/dist/config.d.ts +4567 -71
  45. package/dist/config.d.ts.map +1 -1
  46. package/dist/config.js +246 -3
  47. package/dist/config.js.map +1 -1
  48. package/dist/context.d.ts +8 -0
  49. package/dist/context.d.ts.map +1 -1
  50. package/dist/context.js +25 -34
  51. package/dist/context.js.map +1 -1
  52. package/dist/generated/graphql-schemas/__mj.d.ts +1073 -10
  53. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  54. package/dist/generated/graphql-schemas/__mj.js +9188 -3649
  55. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  56. package/dist/generic/OrphanedConversationDetailReconciler.js +3 -3
  57. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
  58. package/dist/generic/ResolverBase.d.ts +62 -6
  59. package/dist/generic/ResolverBase.d.ts.map +1 -1
  60. package/dist/generic/ResolverBase.js +179 -35
  61. package/dist/generic/ResolverBase.js.map +1 -1
  62. package/dist/generic/RunViewResolver.d.ts +4 -0
  63. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  64. package/dist/generic/RunViewResolver.js +37 -1
  65. package/dist/generic/RunViewResolver.js.map +1 -1
  66. package/dist/index.d.ts +7 -0
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +214 -159
  69. package/dist/index.js.map +1 -1
  70. package/dist/isolatedProvider.d.ts +20 -0
  71. package/dist/isolatedProvider.d.ts.map +1 -0
  72. package/dist/isolatedProvider.js +22 -0
  73. package/dist/isolatedProvider.js.map +1 -0
  74. package/dist/postgresqlCompat.d.ts +8 -0
  75. package/dist/postgresqlCompat.d.ts.map +1 -0
  76. package/dist/postgresqlCompat.js +19 -0
  77. package/dist/postgresqlCompat.js.map +1 -0
  78. package/dist/postgresqlPoolSettings.d.ts +108 -0
  79. package/dist/postgresqlPoolSettings.d.ts.map +1 -0
  80. package/dist/postgresqlPoolSettings.js +134 -0
  81. package/dist/postgresqlPoolSettings.js.map +1 -0
  82. package/dist/realtimeProxy/RealtimeProxyServer.d.ts +44 -4
  83. package/dist/realtimeProxy/RealtimeProxyServer.d.ts.map +1 -1
  84. package/dist/realtimeProxy/RealtimeProxyServer.js +121 -16
  85. package/dist/realtimeProxy/RealtimeProxyServer.js.map +1 -1
  86. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts +171 -0
  87. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts.map +1 -0
  88. package/dist/realtimeProxy/RealtimeRelayTunnel.js +532 -0
  89. package/dist/realtimeProxy/RealtimeRelayTunnel.js.map +1 -0
  90. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts +148 -0
  91. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts.map +1 -0
  92. package/dist/realtimeSessions/RealtimeSessionEventService.js +191 -0
  93. package/dist/realtimeSessions/RealtimeSessionEventService.js.map +1 -0
  94. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts +66 -0
  95. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -0
  96. package/dist/realtimeSessions/RealtimeSessionVerificationService.js +138 -0
  97. package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -0
  98. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts +38 -0
  99. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -0
  100. package/dist/realtimeSessions/RealtimeVerifyRouter.js +98 -0
  101. package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -0
  102. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts +61 -0
  103. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -0
  104. package/dist/realtimeSessions/SessionVerificationPortsBase.js +149 -0
  105. package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -0
  106. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts +57 -0
  107. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts.map +1 -0
  108. package/dist/realtimeSessions/SlidingWindowRateLimiter.js +69 -0
  109. package/dist/realtimeSessions/SlidingWindowRateLimiter.js.map +1 -0
  110. package/dist/realtimeSessions/index.d.ts +17 -0
  111. package/dist/realtimeSessions/index.d.ts.map +1 -0
  112. package/dist/realtimeSessions/index.js +17 -0
  113. package/dist/realtimeSessions/index.js.map +1 -0
  114. package/dist/realtimeSessions/sessionAccess.d.ts +86 -0
  115. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -0
  116. package/dist/realtimeSessions/sessionAccess.js +90 -0
  117. package/dist/realtimeSessions/sessionAccess.js.map +1 -0
  118. package/dist/realtimeSessions/sessionConfigStamps.d.ts +70 -0
  119. package/dist/realtimeSessions/sessionConfigStamps.d.ts.map +1 -0
  120. package/dist/realtimeSessions/sessionConfigStamps.js +93 -0
  121. package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -0
  122. package/dist/realtimeSessions/subscriptionAuthorization.d.ts +65 -0
  123. package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -0
  124. package/dist/realtimeSessions/subscriptionAuthorization.js +71 -0
  125. package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -0
  126. package/dist/realtimeSessions/verificationCore.d.ts +243 -0
  127. package/dist/realtimeSessions/verificationCore.d.ts.map +1 -0
  128. package/dist/realtimeSessions/verificationCore.js +356 -0
  129. package/dist/realtimeSessions/verificationCore.js.map +1 -0
  130. package/dist/realtimeSessions/verificationPages.d.ts +66 -0
  131. package/dist/realtimeSessions/verificationPages.d.ts.map +1 -0
  132. package/dist/realtimeSessions/verificationPages.js +110 -0
  133. package/dist/realtimeSessions/verificationPages.js.map +1 -0
  134. package/dist/realtimeSessions/verificationPolicy.d.ts +147 -0
  135. package/dist/realtimeSessions/verificationPolicy.d.ts.map +1 -0
  136. package/dist/realtimeSessions/verificationPolicy.js +249 -0
  137. package/dist/realtimeSessions/verificationPolicy.js.map +1 -0
  138. package/dist/realtimeSessions/verificationWorkflow.d.ts +263 -0
  139. package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -0
  140. package/dist/realtimeSessions/verificationWorkflow.js +435 -0
  141. package/dist/realtimeSessions/verificationWorkflow.js.map +1 -0
  142. package/dist/realtimeWidget/widgetGuestElevation.d.ts +20 -2
  143. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  144. package/dist/realtimeWidget/widgetGuestElevation.js +31 -2
  145. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  146. package/dist/resolvers/ActionResolver.d.ts +31 -5
  147. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  148. package/dist/resolvers/ActionResolver.js +75 -14
  149. package/dist/resolvers/ActionResolver.js.map +1 -1
  150. package/dist/resolvers/AdhocQueryResolver.d.ts +35 -17
  151. package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
  152. package/dist/resolvers/AdhocQueryResolver.js +92 -166
  153. package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
  154. package/dist/resolvers/CacheStatsResolver.d.ts +27 -0
  155. package/dist/resolvers/CacheStatsResolver.d.ts.map +1 -1
  156. package/dist/resolvers/CacheStatsResolver.js +113 -2
  157. package/dist/resolvers/CacheStatsResolver.js.map +1 -1
  158. package/dist/resolvers/ClientToolRequestResolver.d.ts +4 -2
  159. package/dist/resolvers/ClientToolRequestResolver.d.ts.map +1 -1
  160. package/dist/resolvers/ClientToolRequestResolver.js +28 -10
  161. package/dist/resolvers/ClientToolRequestResolver.js.map +1 -1
  162. package/dist/resolvers/EntityRecordNameResolver.d.ts +7 -23
  163. package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
  164. package/dist/resolvers/EntityRecordNameResolver.js +9 -47
  165. package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
  166. package/dist/resolvers/FetchEntityVectorsResolver.d.ts +12 -1
  167. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  168. package/dist/resolvers/FetchEntityVectorsResolver.js +83 -2
  169. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  170. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  171. package/dist/resolvers/GetDataResolver.js +9 -0
  172. package/dist/resolvers/GetDataResolver.js.map +1 -1
  173. package/dist/resolvers/HumanHandoffResolver.d.ts +107 -0
  174. package/dist/resolvers/HumanHandoffResolver.d.ts.map +1 -0
  175. package/dist/resolvers/HumanHandoffResolver.js +330 -0
  176. package/dist/resolvers/HumanHandoffResolver.js.map +1 -0
  177. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  178. package/dist/resolvers/MCPResolver.js +9 -4
  179. package/dist/resolvers/MCPResolver.js.map +1 -1
  180. package/dist/resolvers/MeetingResolver.d.ts +69 -0
  181. package/dist/resolvers/MeetingResolver.d.ts.map +1 -0
  182. package/dist/resolvers/MeetingResolver.js +381 -0
  183. package/dist/resolvers/MeetingResolver.js.map +1 -0
  184. package/dist/resolvers/RealtimeBridgeResolver.d.ts +88 -3
  185. package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
  186. package/dist/resolvers/RealtimeBridgeResolver.js +352 -12
  187. package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
  188. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +156 -108
  189. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  190. package/dist/resolvers/RealtimeClientSessionResolver.js +395 -293
  191. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  192. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts +61 -0
  193. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts.map +1 -0
  194. package/dist/resolvers/RealtimeSessionEventsResolver.js +130 -0
  195. package/dist/resolvers/RealtimeSessionEventsResolver.js.map +1 -0
  196. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts +85 -0
  197. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts.map +1 -0
  198. package/dist/resolvers/RealtimeSessionVerificationResolver.js +188 -0
  199. package/dist/resolvers/RealtimeSessionVerificationResolver.js.map +1 -0
  200. package/dist/resolvers/RemoteBrowserActionResolver.d.ts +2 -0
  201. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  202. package/dist/resolvers/RemoteBrowserActionResolver.js +5 -1
  203. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  204. package/dist/resolvers/RunAIAgentResolver.d.ts +10 -0
  205. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  206. package/dist/resolvers/RunAIAgentResolver.js +68 -11
  207. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  208. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  209. package/dist/resolvers/RunTemplateResolver.js +12 -11
  210. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  211. package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
  212. package/dist/resolvers/SyncDataResolver.js +6 -2
  213. package/dist/resolvers/SyncDataResolver.js.map +1 -1
  214. package/dist/resolvers/SyncRolesUsersResolver.d.ts +2 -0
  215. package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
  216. package/dist/resolvers/SyncRolesUsersResolver.js +23 -6
  217. package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
  218. package/dist/resolvers/UserAvatarResolver.d.ts +16 -0
  219. package/dist/resolvers/UserAvatarResolver.d.ts.map +1 -0
  220. package/dist/resolvers/UserAvatarResolver.js +124 -0
  221. package/dist/resolvers/UserAvatarResolver.js.map +1 -0
  222. package/dist/resolvers/UserResolver.d.ts.map +1 -1
  223. package/dist/resolvers/UserResolver.js +2 -17
  224. package/dist/resolvers/UserResolver.js.map +1 -1
  225. package/dist/resolvers/adhocTimeout.d.ts +7 -0
  226. package/dist/resolvers/adhocTimeout.d.ts.map +1 -0
  227. package/dist/resolvers/adhocTimeout.js +12 -0
  228. package/dist/resolvers/adhocTimeout.js.map +1 -0
  229. package/dist/resolvers/agentVisionConsentAudit.d.ts +37 -0
  230. package/dist/resolvers/agentVisionConsentAudit.d.ts.map +1 -0
  231. package/dist/resolvers/agentVisionConsentAudit.js +63 -0
  232. package/dist/resolvers/agentVisionConsentAudit.js.map +1 -0
  233. package/dist/resolvers/avatarInputValidation.d.ts +40 -0
  234. package/dist/resolvers/avatarInputValidation.d.ts.map +1 -0
  235. package/dist/resolvers/avatarInputValidation.js +97 -0
  236. package/dist/resolvers/avatarInputValidation.js.map +1 -0
  237. package/dist/resolvers/currentUserRoles.d.ts +29 -0
  238. package/dist/resolvers/currentUserRoles.d.ts.map +1 -1
  239. package/dist/resolvers/currentUserRoles.js +30 -0
  240. package/dist/resolvers/currentUserRoles.js.map +1 -1
  241. package/dist/resolvers/meetings/index.d.ts +5 -0
  242. package/dist/resolvers/meetings/index.d.ts.map +1 -0
  243. package/dist/resolvers/meetings/index.js +5 -0
  244. package/dist/resolvers/meetings/index.js.map +1 -0
  245. package/dist/resolvers/meetings/meetingHelpers.d.ts +17 -0
  246. package/dist/resolvers/meetings/meetingHelpers.d.ts.map +1 -0
  247. package/dist/resolvers/meetings/meetingHelpers.js +212 -0
  248. package/dist/resolvers/meetings/meetingHelpers.js.map +1 -0
  249. package/dist/resolvers/meetings/meetingMutations.d.ts +18 -0
  250. package/dist/resolvers/meetings/meetingMutations.d.ts.map +1 -0
  251. package/dist/resolvers/meetings/meetingMutations.js +439 -0
  252. package/dist/resolvers/meetings/meetingMutations.js.map +1 -0
  253. package/dist/resolvers/meetings/meetingQueries.d.ts +7 -0
  254. package/dist/resolvers/meetings/meetingQueries.d.ts.map +1 -0
  255. package/dist/resolvers/meetings/meetingQueries.js +113 -0
  256. package/dist/resolvers/meetings/meetingQueries.js.map +1 -0
  257. package/dist/resolvers/meetings/meetingTypes.d.ts +89 -0
  258. package/dist/resolvers/meetings/meetingTypes.d.ts.map +1 -0
  259. package/dist/resolvers/meetings/meetingTypes.js +345 -0
  260. package/dist/resolvers/meetings/meetingTypes.js.map +1 -0
  261. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  262. package/dist/rest/ViewOperationsHandler.js +8 -5
  263. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  264. package/dist/services/TaskGraphActionRunner.d.ts +8 -0
  265. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  266. package/dist/services/TaskGraphActionRunner.js +27 -1
  267. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  268. package/dist/services/TaskGraphContinuationDeliverer.d.ts +4 -3
  269. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  270. package/dist/services/TaskGraphContinuationDeliverer.js +13 -7
  271. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  272. package/dist/services/WorkQueueHostService.d.ts +36 -0
  273. package/dist/services/WorkQueueHostService.d.ts.map +1 -0
  274. package/dist/services/WorkQueueHostService.js +97 -0
  275. package/dist/services/WorkQueueHostService.js.map +1 -0
  276. package/dist/services/workQueueConfig.d.ts +103 -0
  277. package/dist/services/workQueueConfig.d.ts.map +1 -0
  278. package/dist/services/workQueueConfig.js +48 -0
  279. package/dist/services/workQueueConfig.js.map +1 -0
  280. package/dist/sharedCache.d.ts +105 -0
  281. package/dist/sharedCache.d.ts.map +1 -0
  282. package/dist/sharedCache.js +276 -0
  283. package/dist/sharedCache.js.map +1 -0
  284. package/dist/types.d.ts +11 -0
  285. package/dist/types.d.ts.map +1 -1
  286. package/dist/types.js.map +1 -1
  287. package/package.json +97 -94
  288. package/src/__tests__/ActionResolver.authorization.test.ts +353 -0
  289. package/src/__tests__/AdhocQueryResolver.bugs.test.ts +14 -35
  290. package/src/__tests__/AdhocQueryResolver.pagination.test.ts +6 -2
  291. package/src/__tests__/AdhocQueryResolver.scopeGuard.test.ts +3 -3
  292. package/src/__tests__/AdhocQueryResolver.sqlAuthorizer.test.ts +104 -0
  293. package/src/__tests__/BridgeHostInstance.test.ts +232 -0
  294. package/src/__tests__/ClientToolRequestResolver.test.ts +116 -0
  295. package/src/__tests__/EntityRecordNameResolver.fieldSecurity.test.ts +27 -72
  296. package/src/__tests__/FetchEntityVectorsResolver.test.ts +285 -0
  297. package/src/__tests__/HostInstance.test.ts +84 -0
  298. package/src/__tests__/HumanHandoffResolver.test.ts +250 -0
  299. package/src/__tests__/MeetingResolver.test.ts +448 -0
  300. package/src/__tests__/RealtimeBridgeResolver.test.ts +651 -4
  301. package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +383 -0
  302. package/src/__tests__/RealtimeClientSessionResolver.test.ts +682 -58
  303. package/src/__tests__/RealtimeProxyServer.test.ts +16 -1
  304. package/src/__tests__/RealtimeRelay.test.ts +876 -0
  305. package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +129 -0
  306. package/src/__tests__/ResolverBase.adhocReadScope.test.ts +96 -0
  307. package/src/__tests__/ResolverBase.aggregateScreen.test.ts +174 -0
  308. package/src/__tests__/ResolverBase.clientOldValues.test.ts +6 -3
  309. package/src/__tests__/ResolverBase.filterEscaping.test.ts +21 -2
  310. package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +291 -0
  311. package/src/__tests__/ReturningVisitorRecap.test.ts +115 -0
  312. package/src/__tests__/RunAIAgentResolver.branch.test.ts +169 -0
  313. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +4 -4
  314. package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +166 -0
  315. package/src/__tests__/RunTemplateResolver.test.ts +132 -0
  316. package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +63 -0
  317. package/src/__tests__/SessionJanitor.test.ts +845 -18
  318. package/src/__tests__/SessionManager.test.ts +213 -17
  319. package/src/__tests__/SessionRunIDVerifier.test.ts +251 -0
  320. package/src/__tests__/SyncRolesUsersResolver.userRoles.test.ts +97 -0
  321. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +41 -0
  322. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +50 -3
  323. package/src/__tests__/UserAvatarResolver.test.ts +255 -0
  324. package/src/__tests__/UserResolver.currentUser.test.ts +16 -1
  325. package/src/__tests__/WorkQueueHostService.test.ts +133 -0
  326. package/src/__tests__/actionAuthorization.test.ts +130 -0
  327. package/src/__tests__/adhocTimeoutClamp.test.ts +26 -0
  328. package/src/__tests__/agentVisionConsentAudit.test.ts +118 -0
  329. package/src/__tests__/avatarInputValidation.test.ts +160 -0
  330. package/src/__tests__/isolatedProviderTransactions.test.ts +169 -0
  331. package/src/__tests__/magicLinkService.consume.test.ts +6 -0
  332. package/src/__tests__/magicLinkService.provisionLog.test.ts +5 -0
  333. package/src/__tests__/newUsers.template.test.ts +151 -0
  334. package/src/__tests__/newUsers.test.ts +74 -5
  335. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +17 -2
  336. package/src/__tests__/postgresqlPoolSettings.test.ts +131 -0
  337. package/src/__tests__/realtimeSessions/RealtimeSessionEventService.test.ts +201 -0
  338. package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +215 -0
  339. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationResolver.test.ts +102 -0
  340. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationService.test.ts +349 -0
  341. package/src/__tests__/realtimeSessions/RealtimeVerifyRouter.test.ts +131 -0
  342. package/src/__tests__/realtimeSessions/SlidingWindowRateLimiter.test.ts +56 -0
  343. package/src/__tests__/realtimeSessions/helpers.ts +4 -0
  344. package/src/__tests__/realtimeSessions/sessionAccess.test.ts +129 -0
  345. package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +124 -0
  346. package/src/__tests__/realtimeSessions/verificationCore.test.ts +355 -0
  347. package/src/__tests__/realtimeSessions/verificationPages.test.ts +84 -0
  348. package/src/__tests__/realtimeSessions/verificationPolicy.test.ts +226 -0
  349. package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +633 -0
  350. package/src/__tests__/resolverBase.fls.test.ts +87 -4
  351. package/src/__tests__/serverExtensionReservedRoots.test.ts +2 -0
  352. package/src/__tests__/sharedCache.test.ts +310 -0
  353. package/src/__tests__/translateBracketsToPG.test.ts +20 -0
  354. package/src/__tests__/widgetGuestElevation.test.ts +44 -0
  355. package/src/agentSessions/BridgeHostInstance.ts +32 -0
  356. package/src/agentSessions/HostInstance.ts +124 -28
  357. package/src/agentSessions/ReturningVisitorRecap.ts +7 -3
  358. package/src/agentSessions/SessionJanitor.ts +543 -57
  359. package/src/agentSessions/SessionManager.ts +125 -25
  360. package/src/agentSessions/SessionRunIDVerifier.ts +171 -0
  361. package/src/agentSessions/index.ts +10 -3
  362. package/src/auth/actionAuthorization.ts +116 -0
  363. package/src/auth/index.ts +3 -8
  364. package/src/auth/magicLink/MagicLinkService.ts +6 -3
  365. package/src/auth/newUsers.ts +99 -11
  366. package/src/config.ts +255 -3
  367. package/src/context.ts +26 -34
  368. package/src/generated/graphql-schemas/__mj.ts +22701 -18838
  369. package/src/generic/OrphanedConversationDetailReconciler.ts +3 -3
  370. package/src/generic/ResolverBase.ts +210 -36
  371. package/src/generic/RunViewResolver.ts +37 -2
  372. package/src/index.ts +236 -170
  373. package/src/isolatedProvider.ts +22 -0
  374. package/src/postgresqlCompat.ts +21 -0
  375. package/src/postgresqlPoolSettings.ts +213 -0
  376. package/src/realtimeProxy/RealtimeProxyServer.ts +148 -16
  377. package/src/realtimeProxy/RealtimeRelayTunnel.ts +645 -0
  378. package/src/realtimeSessions/README.md +179 -0
  379. package/src/realtimeSessions/RealtimeSessionEventService.ts +274 -0
  380. package/src/realtimeSessions/RealtimeSessionVerificationService.ts +167 -0
  381. package/src/realtimeSessions/RealtimeVerifyRouter.ts +108 -0
  382. package/src/realtimeSessions/SessionVerificationPortsBase.ts +189 -0
  383. package/src/realtimeSessions/SlidingWindowRateLimiter.ts +92 -0
  384. package/src/realtimeSessions/index.ts +16 -0
  385. package/src/realtimeSessions/sessionAccess.ts +141 -0
  386. package/src/realtimeSessions/sessionConfigStamps.ts +123 -0
  387. package/src/realtimeSessions/subscriptionAuthorization.ts +116 -0
  388. package/src/realtimeSessions/verificationCore.ts +502 -0
  389. package/src/realtimeSessions/verificationPages.ts +149 -0
  390. package/src/realtimeSessions/verificationPolicy.ts +321 -0
  391. package/src/realtimeSessions/verificationWorkflow.ts +702 -0
  392. package/src/realtimeWidget/widgetGuestElevation.ts +34 -2
  393. package/src/resolvers/ActionResolver.ts +84 -21
  394. package/src/resolvers/AdhocQueryResolver.ts +105 -187
  395. package/src/resolvers/CacheStatsResolver.ts +89 -2
  396. package/src/resolvers/ClientToolRequestResolver.ts +25 -7
  397. package/src/resolvers/EntityRecordNameResolver.ts +9 -51
  398. package/src/resolvers/FetchEntityVectorsResolver.ts +97 -2
  399. package/src/resolvers/GetDataResolver.ts +10 -0
  400. package/src/resolvers/HumanHandoffResolver.ts +312 -0
  401. package/src/resolvers/MCPResolver.ts +8 -5
  402. package/src/resolvers/MeetingResolver.ts +438 -0
  403. package/src/resolvers/RealtimeBridgeResolver.ts +385 -19
  404. package/src/resolvers/RealtimeClientSessionResolver.ts +503 -344
  405. package/src/resolvers/RealtimeSessionEventsResolver.ts +133 -0
  406. package/src/resolvers/RealtimeSessionVerificationResolver.ts +174 -0
  407. package/src/resolvers/RemoteBrowserActionResolver.ts +11 -1
  408. package/src/resolvers/RunAIAgentResolver.ts +78 -11
  409. package/src/resolvers/RunTemplateResolver.ts +13 -12
  410. package/src/resolvers/SyncDataResolver.ts +6 -2
  411. package/src/resolvers/SyncRolesUsersResolver.ts +24 -6
  412. package/src/resolvers/UserAvatarResolver.ts +111 -0
  413. package/src/resolvers/UserResolver.ts +2 -16
  414. package/src/resolvers/adhocTimeout.ts +12 -0
  415. package/src/resolvers/agentVisionConsentAudit.ts +82 -0
  416. package/src/resolvers/avatarInputValidation.ts +123 -0
  417. package/src/resolvers/currentUserRoles.ts +32 -1
  418. package/src/resolvers/meetings/index.ts +4 -0
  419. package/src/resolvers/meetings/meetingHelpers.ts +307 -0
  420. package/src/resolvers/meetings/meetingMutations.ts +556 -0
  421. package/src/resolvers/meetings/meetingQueries.ts +172 -0
  422. package/src/resolvers/meetings/meetingTypes.ts +238 -0
  423. package/src/rest/ViewOperationsHandler.ts +8 -5
  424. package/src/services/TaskGraphActionRunner.ts +29 -1
  425. package/src/services/TaskGraphContinuationDeliverer.ts +13 -7
  426. package/src/services/WorkQueueHostService.ts +129 -0
  427. package/src/services/workQueueConfig.ts +52 -0
  428. package/src/sharedCache.ts +302 -0
  429. package/src/types.ts +12 -0
  430. package/dist/resolvers/adhoc-query-helpers.d.ts +0 -33
  431. package/dist/resolvers/adhoc-query-helpers.d.ts.map +0 -1
  432. package/dist/resolvers/adhoc-query-helpers.js +0 -50
  433. package/dist/resolvers/adhoc-query-helpers.js.map +0 -1
  434. package/src/__tests__/adhoc-query-helpers.test.ts +0 -50
  435. package/src/resolvers/adhoc-query-helpers.ts +0 -67
@@ -0,0 +1,98 @@
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
+ import { Router, urlencoded } from 'express';
28
+ import { rateLimit } from 'express-rate-limit';
29
+ import { LogError } from '@memberjunction/core';
30
+ import { configInfo } from '../config.js';
31
+ import { RealtimeSessionVerificationService } from './RealtimeSessionVerificationService.js';
32
+ import { BuildVerifyConfirmHtml, BuildVerifyErrorHtml, BuildVerifyFailureHtml, BuildVerifySuccessHtml } from './verificationPages.js';
33
+ /** Mount path of the public verify routes. Under `/realtime`, which is already reserved against server extensions. */
34
+ export const REALTIME_VERIFY_MOUNT_PATH = '/realtime/verify';
35
+ /** Headers every verify response carries. */
36
+ function setSecurityHeaders(res) {
37
+ res.setHeader('Cache-Control', 'no-store');
38
+ res.setHeader('Referrer-Policy', 'no-referrer');
39
+ res.setHeader('X-Content-Type-Options', 'nosniff');
40
+ res.setHeader('X-Frame-Options', 'DENY');
41
+ res.setHeader('Content-Security-Policy', "default-src 'none'; style-src 'unsafe-inline'; form-action 'self'; frame-ancestors 'none'; base-uri 'none'");
42
+ }
43
+ /** Sends an HTML page with the verify security headers. */
44
+ function sendPage(res, status, html) {
45
+ setSecurityHeaders(res);
46
+ res.status(status).type('html').send(html);
47
+ }
48
+ /**
49
+ * Builds the public verify router. Mount at {@link REALTIME_VERIFY_MOUNT_PATH} BEFORE the auth
50
+ * middleware.
51
+ *
52
+ * @param service - the verification service (injectable for tests; defaults to the process singleton)
53
+ */
54
+ export function CreateRealtimeVerifyRouter(service = RealtimeSessionVerificationService.Instance) {
55
+ const limits = configInfo.realtime?.identityVerification?.rateLimits;
56
+ // The route is public and a redemption does a database read + write, so it is throttled per IP — the
57
+ // same posture as the magic-link redeem endpoint. The message is the failure page, not JSON: this
58
+ // route talks to a browser.
59
+ const limiter = rateLimit({
60
+ windowMs: limits?.redeemWindowMs ?? 60_000,
61
+ limit: limits?.redeemPerIp ?? 30,
62
+ standardHeaders: 'draft-7',
63
+ legacyHeaders: false,
64
+ handler: (_req, res) => sendPage(res, 429, BuildVerifyFailureHtml()),
65
+ });
66
+ const router = Router();
67
+ // SAFE: renders the confirmation button. Never consumes the token (see the module header).
68
+ router.get('/:token', limiter, (req, res) => {
69
+ const token = typeof req.params.token === 'string' ? req.params.token : '';
70
+ sendPage(res, 200, BuildVerifyConfirmHtml(token, REALTIME_VERIFY_MOUNT_PATH));
71
+ });
72
+ // The side-effecting redemption, gated by a human gesture.
73
+ router.post('/', limiter, urlencoded({ extended: false, limit: '4kb' }), async (req, res) => {
74
+ const body = (req.body ?? {});
75
+ const token = typeof body.token === 'string' ? body.token : '';
76
+ try {
77
+ const result = await service.RedeemLink(token, req.ip);
78
+ if (result.Success) {
79
+ sendPage(res, 200, BuildVerifySuccessHtml());
80
+ }
81
+ else if (result.ErrorCode === 'persist_failed') {
82
+ // A server fault after a VALID token: the link is still redeemable, so say "try again".
83
+ sendPage(res, 500, BuildVerifyErrorHtml());
84
+ }
85
+ else {
86
+ // 410 for every other refusal: the page and status are identical whether the token was unknown,
87
+ // malformed, expired or used, so the route cannot be used to probe sessions.
88
+ sendPage(res, 410, BuildVerifyFailureHtml());
89
+ }
90
+ }
91
+ catch (error) {
92
+ LogError(`RealtimeVerifyRouter: redemption threw: ${error instanceof Error ? error.message : String(error)}`);
93
+ sendPage(res, 500, BuildVerifyErrorHtml());
94
+ }
95
+ });
96
+ return router;
97
+ }
98
+ //# sourceMappingURL=RealtimeVerifyRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RealtimeVerifyRouter.js","sourceRoot":"","sources":["../../src/realtimeSessions/RealtimeVerifyRouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
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
+ import { type UserInfo } from '@memberjunction/core';
26
+ import type { IdentityVerifiedEventPayload } from '@memberjunction/ai-core-plus';
27
+ import { type ConfigMutation, type ConfigMutationResult, type OutboundEmail, type SessionSnapshot, type VerificationAuditEntry, type VerificationCaller, type VerificationPorts, type VerificationSettings } from './verificationWorkflow.js';
28
+ /** The seeded audit-log type (see `metadata/audit-log-types/.realtime-session-audit-types.json`). */
29
+ export declare const REALTIME_IDENTITY_VERIFIED_AUDIT_TYPE = "Realtime Identity Verified";
30
+ /**
31
+ * The session-facing {@link VerificationPorts}, minus configuration. Subclasses supply the settings, the
32
+ * service principal and the mail delivery.
33
+ */
34
+ export declare abstract class SessionVerificationPortsBase implements VerificationPorts {
35
+ /** The live settings. */
36
+ abstract GetSettings(): VerificationSettings;
37
+ /** Delivers an email. Must not throw; reports failure in the result. */
38
+ abstract SendEmail(email: OutboundEmail): Promise<{
39
+ Success: boolean;
40
+ ErrorMessage?: string;
41
+ }>;
42
+ /** The principal state writes (and the link caller's reads) run as; null when none is available. */
43
+ protected abstract ResolveServiceUser(): UserInfo | null;
44
+ Now(): number;
45
+ LoadSession(agentSessionId: string, caller: VerificationCaller): Promise<SessionSnapshot | null>;
46
+ MutateSessionConfig<T>(agentSessionId: string, caller: VerificationCaller, mutate: ConfigMutation<T>): Promise<ConfigMutationResult<T>>;
47
+ PublishVerified(routing: {
48
+ AgentSessionID: string;
49
+ OwnerUserID: string;
50
+ ScopeKey: string | null;
51
+ }, payload: IdentityVerifiedEventPayload): {
52
+ Success: boolean;
53
+ ErrorMessage?: string;
54
+ };
55
+ WriteAudit(entry: VerificationAuditEntry): Promise<void>;
56
+ /** The identity + provider an authorization read runs under. */
57
+ private readerFor;
58
+ /** The identity + provider a state write runs under: always the service principal. */
59
+ private writerFor;
60
+ }
61
+ //# sourceMappingURL=SessionVerificationPortsBase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionVerificationPortsBase.d.ts","sourceRoot":"","sources":["../../src/realtimeSessions/SessionVerificationPortsBase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAA8C,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGjG,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAGjF,OAAO,EACH,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC5B,MAAM,2BAA2B,CAAC;AAEnC,qGAAqG;AACrG,eAAO,MAAM,qCAAqC,+BAA+B,CAAC;AAsBlF;;;GAGG;AACH,8BAAsB,4BAA6B,YAAW,iBAAiB;IAC3E,yBAAyB;aACT,WAAW,IAAI,oBAAoB;IAEnD,wEAAwE;aACxD,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAErG,oGAAoG;IACpG,SAAS,CAAC,QAAQ,CAAC,kBAAkB,IAAI,QAAQ,GAAG,IAAI;IAEjD,GAAG,IAAI,MAAM;IAIP,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAShG,mBAAmB,CAAC,CAAC,EAC9B,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;IA8B5B,eAAe,CAClB,OAAO,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EACjF,OAAO,EAAE,4BAA4B,GACtC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE;IAIjC,UAAU,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsCrE,gEAAgE;IAChE,OAAO,CAAC,SAAS;IAQjB,sFAAsF;IACtF,OAAO,CAAC,SAAS;CAOpB"}
@@ -0,0 +1,149 @@
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
+ import { LogError, Metadata } from '@memberjunction/core';
26
+ import { RunWithTrustedSessionConfigWrites } from '@memberjunction/core-entities-server';
27
+ import { LoadSessionForAccess } from './sessionAccess.js';
28
+ import { RealtimeSessionEventService } from './RealtimeSessionEventService.js';
29
+ /** The seeded audit-log type (see `metadata/audit-log-types/.realtime-session-audit-types.json`). */
30
+ export const REALTIME_IDENTITY_VERIFIED_AUDIT_TYPE = 'Realtime Identity Verified';
31
+ const AUDIT_LOG_ENTITY = 'MJ: Audit Logs';
32
+ const SESSION_ENTITY_NAME = 'MJ: AI Agent Sessions';
33
+ /** Reduces a loaded session to the snapshot the workflow reasons about. */
34
+ function toSnapshot(loaded) {
35
+ const { Session } = loaded;
36
+ return {
37
+ AgentSessionID: Session.ID,
38
+ OwnerUserID: Session.UserID,
39
+ ConversationExternalID: loaded.ConversationExternalID,
40
+ Status: Session.Status,
41
+ ConfigRaw: Session.Config_,
42
+ // `__mj_CreatedAt` is the row's creation instant — i.e. the session start. It is read-only and
43
+ // set by the database, so a client cannot move it.
44
+ StartedAtMs: Session.__mj_CreatedAt instanceof Date ? Session.__mj_CreatedAt.getTime() : Date.now(),
45
+ };
46
+ }
47
+ /**
48
+ * The session-facing {@link VerificationPorts}, minus configuration. Subclasses supply the settings, the
49
+ * service principal and the mail delivery.
50
+ */
51
+ export class SessionVerificationPortsBase {
52
+ Now() {
53
+ return Date.now();
54
+ }
55
+ async LoadSession(agentSessionId, caller) {
56
+ const reader = this.readerFor(caller);
57
+ if (!reader) {
58
+ return null;
59
+ }
60
+ const loaded = await LoadSessionForAccess(agentSessionId, reader.User, reader.Provider);
61
+ return loaded ? toSnapshot(loaded) : null;
62
+ }
63
+ async MutateSessionConfig(agentSessionId, caller, mutate) {
64
+ const writer = this.writerFor(caller);
65
+ if (!writer) {
66
+ return { Persisted: false, ErrorMessage: 'No service principal is available to record verification state.' };
67
+ }
68
+ try {
69
+ const loaded = await LoadSessionForAccess(agentSessionId, writer.User, writer.Provider);
70
+ if (!loaded) {
71
+ return { Persisted: false, ErrorMessage: `Session ${agentSessionId} could not be read.` };
72
+ }
73
+ const session = toSnapshot(loaded);
74
+ const { NextConfigRaw, Outcome } = mutate(session);
75
+ if (NextConfigRaw === null) {
76
+ return { Session: session, Outcome, Persisted: false };
77
+ }
78
+ loaded.Session.Config_ = NextConfigRaw;
79
+ const saved = await RunWithTrustedSessionConfigWrites(() => loaded.Session.Save());
80
+ if (!saved) {
81
+ const detail = loaded.Session.LatestResult?.CompleteMessage ?? 'unknown error';
82
+ LogError(`RealtimeSessionVerification: saving session ${agentSessionId} failed: ${detail}`);
83
+ return { Session: session, Outcome, Persisted: false, ErrorMessage: detail };
84
+ }
85
+ return { Session: session, Outcome, Persisted: true };
86
+ }
87
+ catch (error) {
88
+ const message = error instanceof Error ? error.message : String(error);
89
+ LogError(`RealtimeSessionVerification: updating session ${agentSessionId} threw: ${message}`);
90
+ return { Persisted: false, ErrorMessage: message };
91
+ }
92
+ }
93
+ PublishVerified(routing, payload) {
94
+ return RealtimeSessionEventService.Instance.PublishRouted(routing, 'identity.verified', payload);
95
+ }
96
+ async WriteAudit(entry) {
97
+ const writer = this.ResolveServiceUser();
98
+ const provider = Metadata.Provider; // global-provider-ok: server-side audit write under the server's single default provider
99
+ const type = provider?.AuditLogTypes?.find((t) => t.Name?.trim().toLowerCase() === REALTIME_IDENTITY_VERIFIED_AUDIT_TYPE.toLowerCase());
100
+ const sessionEntityId = provider?.EntityByName(SESSION_ENTITY_NAME)?.ID;
101
+ if (!writer || !type) {
102
+ // The audit type ships as metadata (a release seed); without it, fall back to the server log so
103
+ // the verification is still recorded somewhere durable-ish rather than silently unaudited.
104
+ LogError(`RealtimeSessionVerification: audit entry not written for session ${entry.AgentSessionID} ` +
105
+ `(${writer ? `audit log type '${REALTIME_IDENTITY_VERIFIED_AUDIT_TYPE}' is not seeded` : 'no service principal'}): ` +
106
+ `${entry.Email} via ${entry.Method}.`);
107
+ return;
108
+ }
109
+ try {
110
+ const row = await provider.GetEntityObject(AUDIT_LOG_ENTITY, writer);
111
+ row.NewRecord();
112
+ row.UserID = entry.OwnerUserID;
113
+ row.AuditLogTypeID = type.ID;
114
+ row.Status = 'Success';
115
+ row.EntityID = sessionEntityId ?? null;
116
+ row.RecordID = entry.AgentSessionID;
117
+ row.Description = `Realtime session verified ${entry.Email} by ${entry.Method === 'link' ? 'emailed link' : 'typed code'}.`;
118
+ row.Details = JSON.stringify({
119
+ email: entry.Email,
120
+ method: entry.Method,
121
+ ipAddress: entry.ClientIp ?? null,
122
+ maxSessionDeadlineIso: entry.MaxSessionDeadlineIso ?? null,
123
+ });
124
+ if (!(await row.Save())) {
125
+ LogError(`RealtimeSessionVerification: audit row save failed for session ${entry.AgentSessionID}: ${row.LatestResult?.CompleteMessage ?? 'unknown error'}`);
126
+ }
127
+ }
128
+ catch (error) {
129
+ LogError(`RealtimeSessionVerification: audit write threw for session ${entry.AgentSessionID}: ${error instanceof Error ? error.message : String(error)}`);
130
+ }
131
+ }
132
+ /** The identity + provider an authorization read runs under. */
133
+ readerFor(caller) {
134
+ if (caller.Kind === 'principal') {
135
+ return { User: caller.ContextUser, Provider: caller.Provider };
136
+ }
137
+ const user = this.ResolveServiceUser();
138
+ return user ? { User: user, Provider: Metadata.Provider } : null; // global-provider-ok: public verify route has no request-scoped provider
139
+ }
140
+ /** The identity + provider a state write runs under: always the service principal. */
141
+ writerFor(caller) {
142
+ const user = this.ResolveServiceUser();
143
+ if (!user) {
144
+ return null;
145
+ }
146
+ return { User: user, Provider: caller.Kind === 'principal' ? caller.Provider : Metadata.Provider }; // global-provider-ok: public verify route has no request-scoped provider
147
+ }
148
+ }
149
+ //# sourceMappingURL=SessionVerificationPortsBase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionVerificationPortsBase.js","sourceRoot":"","sources":["../../src/realtimeSessions/SessionVerificationPortsBase.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
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
+ /** Outcome of {@link SlidingWindowRateLimiter.TryConsume}. */
18
+ export interface RateLimitDecision {
19
+ /** True when the event fits the budget (and was counted). */
20
+ Allowed: boolean;
21
+ /** When refused, ms until the oldest counted event leaves the window. 0 when allowed. */
22
+ RetryAfterMs: number;
23
+ }
24
+ /** Construction options. */
25
+ export interface SlidingWindowRateLimiterOptions {
26
+ /** Events allowed per key per window. A limit of 0 or less disables the limiter (everything allowed). */
27
+ Limit: number;
28
+ /** Window length in ms. */
29
+ WindowMs: number;
30
+ /** Upper bound on distinct keys held in memory; the oldest-seen keys are evicted past it. Default 10 000. */
31
+ MaxKeys?: number;
32
+ }
33
+ /**
34
+ * Counts events per key over a sliding window.
35
+ *
36
+ * Memory is bounded two ways: a key's timestamps older than the window are dropped whenever the key is
37
+ * touched, and when the number of keys exceeds `MaxKeys` the least-recently-inserted keys are evicted
38
+ * (an evicted key simply starts a fresh window — the limiter fails open by forgetting, never closed).
39
+ */
40
+ export declare class SlidingWindowRateLimiter {
41
+ private readonly options;
42
+ private readonly events;
43
+ private readonly maxKeys;
44
+ constructor(options: SlidingWindowRateLimiterOptions);
45
+ /**
46
+ * Counts one event for `key` if the budget allows.
47
+ *
48
+ * @param key - what is being limited (an IP, a domain, a session id…); callers normalise it
49
+ * @param nowMs - the current time, epoch ms
50
+ */
51
+ TryConsume(key: string, nowMs: number): RateLimitDecision;
52
+ /** Number of keys currently tracked (exposed for tests and diagnostics). */
53
+ get TrackedKeyCount(): number;
54
+ /** Re-inserts `key` (moving it to the newest position) and evicts the oldest keys past the bound. */
55
+ private store;
56
+ }
57
+ //# sourceMappingURL=SlidingWindowRateLimiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlidingWindowRateLimiter.d.ts","sourceRoot":"","sources":["../../src/realtimeSessions/SlidingWindowRateLimiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,8DAA8D;AAC9D,MAAM,WAAW,iBAAiB;IAC9B,6DAA6D;IAC7D,OAAO,EAAE,OAAO,CAAC;IACjB,yFAAyF;IACzF,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,4BAA4B;AAC5B,MAAM,WAAW,+BAA+B;IAC5C,yGAAyG;IACzG,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,6GAA6G;IAC7G,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD;;;;;;GAMG;AACH,qBAAa,wBAAwB;IAIrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IACtD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAEJ,OAAO,EAAE,+BAA+B;IAIrE;;;;;OAKG;IACI,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,iBAAiB;IAehE,4EAA4E;IAC5E,IAAW,eAAe,IAAI,MAAM,CAEnC;IAED,qGAAqG;IACrG,OAAO,CAAC,KAAK;CAWhB"}
@@ -0,0 +1,69 @@
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
+ /** Default bound on distinct keys held. */
18
+ const DEFAULT_MAX_KEYS = 10_000;
19
+ /**
20
+ * Counts events per key over a sliding window.
21
+ *
22
+ * Memory is bounded two ways: a key's timestamps older than the window are dropped whenever the key is
23
+ * touched, and when the number of keys exceeds `MaxKeys` the least-recently-inserted keys are evicted
24
+ * (an evicted key simply starts a fresh window — the limiter fails open by forgetting, never closed).
25
+ */
26
+ export class SlidingWindowRateLimiter {
27
+ constructor(options) {
28
+ this.options = options;
29
+ this.events = new Map();
30
+ this.maxKeys = options.MaxKeys ?? DEFAULT_MAX_KEYS;
31
+ }
32
+ /**
33
+ * Counts one event for `key` if the budget allows.
34
+ *
35
+ * @param key - what is being limited (an IP, a domain, a session id…); callers normalise it
36
+ * @param nowMs - the current time, epoch ms
37
+ */
38
+ TryConsume(key, nowMs) {
39
+ if (this.options.Limit <= 0) {
40
+ return { Allowed: true, RetryAfterMs: 0 };
41
+ }
42
+ const windowStart = nowMs - this.options.WindowMs;
43
+ const live = (this.events.get(key) ?? []).filter((t) => t > windowStart);
44
+ if (live.length >= this.options.Limit) {
45
+ this.store(key, live);
46
+ return { Allowed: false, RetryAfterMs: Math.max(0, live[0] + this.options.WindowMs - nowMs) };
47
+ }
48
+ live.push(nowMs);
49
+ this.store(key, live);
50
+ return { Allowed: true, RetryAfterMs: 0 };
51
+ }
52
+ /** Number of keys currently tracked (exposed for tests and diagnostics). */
53
+ get TrackedKeyCount() {
54
+ return this.events.size;
55
+ }
56
+ /** Re-inserts `key` (moving it to the newest position) and evicts the oldest keys past the bound. */
57
+ store(key, timestamps) {
58
+ this.events.delete(key);
59
+ this.events.set(key, timestamps);
60
+ while (this.events.size > this.maxKeys) {
61
+ const oldest = this.events.keys().next();
62
+ if (oldest.done) {
63
+ break;
64
+ }
65
+ this.events.delete(oldest.value);
66
+ }
67
+ }
68
+ }
69
+ //# sourceMappingURL=SlidingWindowRateLimiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlidingWindowRateLimiter.js","sourceRoot":"","sources":["../../src/realtimeSessions/SlidingWindowRateLimiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAoBH,2CAA2C;AAC3C,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEhC;;;;;;GAMG;AACH,MAAM,OAAO,wBAAwB;IAIjC,YAA6B,OAAwC;QAAxC,YAAO,GAAP,OAAO,CAAiC;QAHpD,WAAM,GAAG,IAAI,GAAG,EAAoB,CAAC;QAIlD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC;IACvD,CAAC;IAED;;;;;OAKG;IACI,UAAU,CAAC,GAAW,EAAE,KAAa;QACxC,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;QAC9C,CAAC;QACD,MAAM,WAAW,GAAG,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QAClD,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC;QACzE,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACpC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACtB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC,EAAE,CAAC;QAClG,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjB,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACtB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IAC9C,CAAC;IAED,4EAA4E;IAC5E,IAAW,eAAe;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IAC5B,CAAC;IAED,qGAAqG;IAC7F,KAAK,CAAC,GAAW,EAAE,UAAoB;QAC3C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YACzC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBACd,MAAM;YACV,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;IACL,CAAC;CACJ"}
@@ -0,0 +1,17 @@
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
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/realtimeSessions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,mCAAmC,CAAC;AAClD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,17 @@
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
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/realtimeSessions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,mCAAmC,CAAC;AAClD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * @fileoverview Who may see and act on ONE realtime session.
3
+ *
4
+ * One pure decision ({@link AuthorizeSessionAccess}) shared by everything that addresses a live
5
+ * session on behalf of a caller: the `RealtimeSessionEvents` subscription (at subscribe time AND for
6
+ * every delivered event), the verification mutations, and the status query. Keeping it in one place
7
+ * is what stops "who owns this session?" from being re-derived — slightly differently — in each.
8
+ *
9
+ * ## The two ownership rules
10
+ *
11
+ * 1. **Owner.** The session's `UserID` must be the caller's user.
12
+ * 2. **Scope.** A *named* user is fully identified by (1). An **anonymous widget guest** is not:
13
+ * every guest authenticates as the one shared Anonymous user, so (1) alone would let any guest
14
+ * address any other guest's session. What separates guests is the signed per-session scope in
15
+ * their token (`MagicLinkScope.ResourceID`), which `SessionManager` stamps onto the session's
16
+ * Conversation as `ExternalID`. So a principal that carries a scope must match it, and an
17
+ * anonymous principal that carries NO scope is refused outright — it cannot be told apart from
18
+ * every other anonymous principal.
19
+ *
20
+ * The decision is deliberately pure (no I/O) so it can be applied identically to a freshly loaded
21
+ * row at subscribe time and to the owner/scope snapshot carried inside each published event.
22
+ *
23
+ * @module @memberjunction/server/realtimeSessions
24
+ */
25
+ import { IMetadataProvider, UserInfo } from '@memberjunction/core';
26
+ import type { MJAIAgentSessionEntity } from '@memberjunction/core-entities';
27
+ /** What the decision needs to know about the session. */
28
+ export interface SessionAccessSubject {
29
+ /** `AIAgentSession.UserID`. */
30
+ SessionUserID: string;
31
+ /**
32
+ * `Conversation.ExternalID` of the session's conversation — the signed per-session scope id for an
33
+ * anonymous guest. `null`/`undefined` when the conversation has none (a named user's session) or
34
+ * could not be loaded.
35
+ */
36
+ ConversationExternalID: string | null | undefined;
37
+ }
38
+ /** What the decision needs to know about the caller (a subset of `UserInfo`). */
39
+ export interface SessionAccessPrincipal {
40
+ /** The caller's user id. */
41
+ ID: string;
42
+ /** True for the shared-Anonymous-user principal of a public-widget guest. */
43
+ IsMagicLinkAnonymous?: boolean;
44
+ /** The signed per-session scope carried by the caller's token, when any. */
45
+ MagicLinkScope?: {
46
+ ResourceID?: string;
47
+ } | undefined;
48
+ }
49
+ /** Why access was refused. Callers log the reason; clients get a uniform refusal. */
50
+ export type SessionAccessRefusal = 'not_owner' | 'scope_missing' | 'scope_mismatch';
51
+ /** Outcome of {@link AuthorizeSessionAccess}. */
52
+ export type SessionAccessDecision = {
53
+ Allowed: true;
54
+ } | {
55
+ Allowed: false;
56
+ Reason: SessionAccessRefusal;
57
+ };
58
+ /**
59
+ * Decides whether `principal` may address the session described by `subject`.
60
+ *
61
+ * Fails closed: anything that cannot be positively matched is refused.
62
+ *
63
+ * @param subject - owner + scope of the session
64
+ * @param principal - the authenticated caller (from the server-built `UserInfo`, never from client args)
65
+ */
66
+ export declare function AuthorizeSessionAccess(subject: SessionAccessSubject, principal: SessionAccessPrincipal | null | undefined): SessionAccessDecision;
67
+ /** A session row together with the one fact about its conversation the decision needs. */
68
+ export interface LoadedSessionForAccess {
69
+ /** The session entity, loaded under the caller's own identity (so RLS applied to the read). */
70
+ Session: MJAIAgentSessionEntity;
71
+ /** The session's conversation `ExternalID` (anonymous scope id), or null. */
72
+ ConversationExternalID: string | null;
73
+ }
74
+ /**
75
+ * Loads a session (and its conversation's scope id) under `contextUser`'s identity.
76
+ *
77
+ * Loading as the caller — rather than as a privileged user — means the entity layer's row-level
78
+ * security (`Widget Guest: Own Agent Sessions`, `UI: Own Agent Sessions`) is the FIRST gate; the
79
+ * explicit {@link AuthorizeSessionAccess} check that follows is defence in depth.
80
+ *
81
+ * @returns the loaded session, or `null` when the id is malformed, the row does not exist, or the
82
+ * caller cannot read it. Failure to read the conversation yields `ConversationExternalID: null`,
83
+ * which {@link AuthorizeSessionAccess} then treats as "no scope to match" (refused for a scoped caller).
84
+ */
85
+ export declare function LoadSessionForAccess(agentSessionId: string, contextUser: UserInfo, provider: IMetadataProvider): Promise<LoadedSessionForAccess | null>;
86
+ //# sourceMappingURL=sessionAccess.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionAccess.d.ts","sourceRoot":"","sources":["../../src/realtimeSessions/sessionAccess.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,iBAAiB,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE7E,OAAO,KAAK,EAAE,sBAAsB,EAAwB,MAAM,+BAA+B,CAAC;AAMlG,yDAAyD;AACzD,MAAM,WAAW,oBAAoB;IACjC,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,sBAAsB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACrD;AAED,iFAAiF;AACjF,MAAM,WAAW,sBAAsB;IACnC,4BAA4B;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,6EAA6E;IAC7E,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,4EAA4E;IAC5E,cAAc,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACxD;AAED,qFAAqF;AACrF,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,eAAe,GAAG,gBAAgB,CAAC;AAEpF,iDAAiD;AACjD,MAAM,MAAM,qBAAqB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAEzG;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,oBAAoB,EAC7B,SAAS,EAAE,sBAAsB,GAAG,IAAI,GAAG,SAAS,GACrD,qBAAqB,CAYvB;AAED,0FAA0F;AAC1F,MAAM,WAAW,sBAAsB;IACnC,+FAA+F;IAC/F,OAAO,EAAE,sBAAsB,CAAC;IAChC,6EAA6E;IAC7E,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACtC,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,QAAQ,EACrB,QAAQ,EAAE,iBAAiB,GAC5B,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CASxC"}