@memberjunction/server 6.2.0-edge.3 → 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 (346) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/agentSessions/BridgeHostInstance.d.ts +25 -0
  3. package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -0
  4. package/dist/agentSessions/BridgeHostInstance.js +30 -0
  5. package/dist/agentSessions/BridgeHostInstance.js.map +1 -0
  6. package/dist/agentSessions/HostInstance.d.ts +75 -11
  7. package/dist/agentSessions/HostInstance.d.ts.map +1 -1
  8. package/dist/agentSessions/HostInstance.js +99 -28
  9. package/dist/agentSessions/HostInstance.js.map +1 -1
  10. package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
  11. package/dist/agentSessions/ReturningVisitorRecap.js +7 -3
  12. package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
  13. package/dist/agentSessions/SessionJanitor.d.ts +173 -25
  14. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  15. package/dist/agentSessions/SessionJanitor.js +452 -54
  16. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  17. package/dist/agentSessions/SessionManager.d.ts +43 -2
  18. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  19. package/dist/agentSessions/SessionManager.js +99 -8
  20. package/dist/agentSessions/SessionManager.js.map +1 -1
  21. package/dist/agentSessions/SessionRunIDVerifier.d.ts +63 -0
  22. package/dist/agentSessions/SessionRunIDVerifier.d.ts.map +1 -0
  23. package/dist/agentSessions/SessionRunIDVerifier.js +129 -0
  24. package/dist/agentSessions/SessionRunIDVerifier.js.map +1 -0
  25. package/dist/agentSessions/index.d.ts +2 -0
  26. package/dist/agentSessions/index.d.ts.map +1 -1
  27. package/dist/agentSessions/index.js +10 -3
  28. package/dist/agentSessions/index.js.map +1 -1
  29. package/dist/auth/actionAuthorization.d.ts +40 -0
  30. package/dist/auth/actionAuthorization.d.ts.map +1 -0
  31. package/dist/auth/actionAuthorization.js +94 -0
  32. package/dist/auth/actionAuthorization.js.map +1 -0
  33. package/dist/auth/index.d.ts.map +1 -1
  34. package/dist/auth/index.js +3 -10
  35. package/dist/auth/index.js.map +1 -1
  36. package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
  37. package/dist/auth/magicLink/MagicLinkService.js +6 -3
  38. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  39. package/dist/auth/newUsers.d.ts +10 -0
  40. package/dist/auth/newUsers.d.ts.map +1 -1
  41. package/dist/auth/newUsers.js +80 -11
  42. package/dist/auth/newUsers.js.map +1 -1
  43. package/dist/config.d.ts +2378 -0
  44. package/dist/config.d.ts.map +1 -1
  45. package/dist/config.js +123 -0
  46. package/dist/config.js.map +1 -1
  47. package/dist/context.d.ts +8 -0
  48. package/dist/context.d.ts.map +1 -1
  49. package/dist/context.js +14 -11
  50. package/dist/context.js.map +1 -1
  51. package/dist/generated/graphql-schemas/__mj.d.ts +135 -0
  52. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  53. package/dist/generated/graphql-schemas/__mj.js +706 -0
  54. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  55. package/dist/generic/OrphanedConversationDetailReconciler.js +3 -3
  56. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
  57. package/dist/generic/ResolverBase.d.ts +20 -4
  58. package/dist/generic/ResolverBase.d.ts.map +1 -1
  59. package/dist/generic/ResolverBase.js +39 -10
  60. package/dist/generic/ResolverBase.js.map +1 -1
  61. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  62. package/dist/generic/RunViewResolver.js +4 -0
  63. package/dist/generic/RunViewResolver.js.map +1 -1
  64. package/dist/index.d.ts +6 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +120 -131
  67. package/dist/index.js.map +1 -1
  68. package/dist/isolatedProvider.d.ts +20 -0
  69. package/dist/isolatedProvider.d.ts.map +1 -0
  70. package/dist/isolatedProvider.js +22 -0
  71. package/dist/isolatedProvider.js.map +1 -0
  72. package/dist/realtimeProxy/RealtimeProxyServer.d.ts +44 -4
  73. package/dist/realtimeProxy/RealtimeProxyServer.d.ts.map +1 -1
  74. package/dist/realtimeProxy/RealtimeProxyServer.js +121 -16
  75. package/dist/realtimeProxy/RealtimeProxyServer.js.map +1 -1
  76. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts +171 -0
  77. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts.map +1 -0
  78. package/dist/realtimeProxy/RealtimeRelayTunnel.js +532 -0
  79. package/dist/realtimeProxy/RealtimeRelayTunnel.js.map +1 -0
  80. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts +148 -0
  81. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts.map +1 -0
  82. package/dist/realtimeSessions/RealtimeSessionEventService.js +191 -0
  83. package/dist/realtimeSessions/RealtimeSessionEventService.js.map +1 -0
  84. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts +66 -0
  85. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -0
  86. package/dist/realtimeSessions/RealtimeSessionVerificationService.js +138 -0
  87. package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -0
  88. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts +38 -0
  89. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -0
  90. package/dist/realtimeSessions/RealtimeVerifyRouter.js +98 -0
  91. package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -0
  92. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts +61 -0
  93. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -0
  94. package/dist/realtimeSessions/SessionVerificationPortsBase.js +149 -0
  95. package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -0
  96. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts +57 -0
  97. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts.map +1 -0
  98. package/dist/realtimeSessions/SlidingWindowRateLimiter.js +69 -0
  99. package/dist/realtimeSessions/SlidingWindowRateLimiter.js.map +1 -0
  100. package/dist/realtimeSessions/index.d.ts +17 -0
  101. package/dist/realtimeSessions/index.d.ts.map +1 -0
  102. package/dist/realtimeSessions/index.js +17 -0
  103. package/dist/realtimeSessions/index.js.map +1 -0
  104. package/dist/realtimeSessions/sessionAccess.d.ts +86 -0
  105. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -0
  106. package/dist/realtimeSessions/sessionAccess.js +90 -0
  107. package/dist/realtimeSessions/sessionAccess.js.map +1 -0
  108. package/dist/realtimeSessions/sessionConfigStamps.d.ts +70 -0
  109. package/dist/realtimeSessions/sessionConfigStamps.d.ts.map +1 -0
  110. package/dist/realtimeSessions/sessionConfigStamps.js +93 -0
  111. package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -0
  112. package/dist/realtimeSessions/subscriptionAuthorization.d.ts +65 -0
  113. package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -0
  114. package/dist/realtimeSessions/subscriptionAuthorization.js +71 -0
  115. package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -0
  116. package/dist/realtimeSessions/verificationCore.d.ts +243 -0
  117. package/dist/realtimeSessions/verificationCore.d.ts.map +1 -0
  118. package/dist/realtimeSessions/verificationCore.js +356 -0
  119. package/dist/realtimeSessions/verificationCore.js.map +1 -0
  120. package/dist/realtimeSessions/verificationPages.d.ts +66 -0
  121. package/dist/realtimeSessions/verificationPages.d.ts.map +1 -0
  122. package/dist/realtimeSessions/verificationPages.js +110 -0
  123. package/dist/realtimeSessions/verificationPages.js.map +1 -0
  124. package/dist/realtimeSessions/verificationPolicy.d.ts +147 -0
  125. package/dist/realtimeSessions/verificationPolicy.d.ts.map +1 -0
  126. package/dist/realtimeSessions/verificationPolicy.js +249 -0
  127. package/dist/realtimeSessions/verificationPolicy.js.map +1 -0
  128. package/dist/realtimeSessions/verificationWorkflow.d.ts +263 -0
  129. package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -0
  130. package/dist/realtimeSessions/verificationWorkflow.js +435 -0
  131. package/dist/realtimeSessions/verificationWorkflow.js.map +1 -0
  132. package/dist/realtimeWidget/widgetGuestElevation.d.ts +20 -2
  133. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  134. package/dist/realtimeWidget/widgetGuestElevation.js +31 -2
  135. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  136. package/dist/resolvers/ActionResolver.d.ts +31 -5
  137. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  138. package/dist/resolvers/ActionResolver.js +75 -14
  139. package/dist/resolvers/ActionResolver.js.map +1 -1
  140. package/dist/resolvers/AdhocQueryResolver.d.ts +14 -1
  141. package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
  142. package/dist/resolvers/AdhocQueryResolver.js +21 -5
  143. package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
  144. package/dist/resolvers/CacheStatsResolver.d.ts +27 -0
  145. package/dist/resolvers/CacheStatsResolver.d.ts.map +1 -1
  146. package/dist/resolvers/CacheStatsResolver.js +113 -2
  147. package/dist/resolvers/CacheStatsResolver.js.map +1 -1
  148. package/dist/resolvers/ClientToolRequestResolver.d.ts +4 -2
  149. package/dist/resolvers/ClientToolRequestResolver.d.ts.map +1 -1
  150. package/dist/resolvers/ClientToolRequestResolver.js +28 -10
  151. package/dist/resolvers/ClientToolRequestResolver.js.map +1 -1
  152. package/dist/resolvers/FetchEntityVectorsResolver.d.ts +12 -1
  153. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  154. package/dist/resolvers/FetchEntityVectorsResolver.js +83 -2
  155. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  156. package/dist/resolvers/HumanHandoffResolver.d.ts.map +1 -1
  157. package/dist/resolvers/HumanHandoffResolver.js +7 -1
  158. package/dist/resolvers/HumanHandoffResolver.js.map +1 -1
  159. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  160. package/dist/resolvers/MCPResolver.js +9 -4
  161. package/dist/resolvers/MCPResolver.js.map +1 -1
  162. package/dist/resolvers/RealtimeBridgeResolver.d.ts +54 -2
  163. package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
  164. package/dist/resolvers/RealtimeBridgeResolver.js +155 -10
  165. package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
  166. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +155 -25
  167. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  168. package/dist/resolvers/RealtimeClientSessionResolver.js +394 -90
  169. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  170. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts +61 -0
  171. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts.map +1 -0
  172. package/dist/resolvers/RealtimeSessionEventsResolver.js +130 -0
  173. package/dist/resolvers/RealtimeSessionEventsResolver.js.map +1 -0
  174. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts +85 -0
  175. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts.map +1 -0
  176. package/dist/resolvers/RealtimeSessionVerificationResolver.js +188 -0
  177. package/dist/resolvers/RealtimeSessionVerificationResolver.js.map +1 -0
  178. package/dist/resolvers/RemoteBrowserActionResolver.d.ts +2 -0
  179. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  180. package/dist/resolvers/RemoteBrowserActionResolver.js +5 -1
  181. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  182. package/dist/resolvers/RunAIAgentResolver.d.ts +10 -0
  183. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  184. package/dist/resolvers/RunAIAgentResolver.js +68 -11
  185. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  186. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  187. package/dist/resolvers/RunTemplateResolver.js +12 -11
  188. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  189. package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
  190. package/dist/resolvers/SyncDataResolver.js +6 -2
  191. package/dist/resolvers/SyncDataResolver.js.map +1 -1
  192. package/dist/resolvers/SyncRolesUsersResolver.d.ts +2 -0
  193. package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
  194. package/dist/resolvers/SyncRolesUsersResolver.js +23 -6
  195. package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
  196. package/dist/resolvers/UserAvatarResolver.d.ts +16 -0
  197. package/dist/resolvers/UserAvatarResolver.d.ts.map +1 -0
  198. package/dist/resolvers/UserAvatarResolver.js +124 -0
  199. package/dist/resolvers/UserAvatarResolver.js.map +1 -0
  200. package/dist/resolvers/UserResolver.d.ts.map +1 -1
  201. package/dist/resolvers/UserResolver.js +2 -17
  202. package/dist/resolvers/UserResolver.js.map +1 -1
  203. package/dist/resolvers/agentVisionConsentAudit.d.ts +37 -0
  204. package/dist/resolvers/agentVisionConsentAudit.d.ts.map +1 -0
  205. package/dist/resolvers/agentVisionConsentAudit.js +63 -0
  206. package/dist/resolvers/agentVisionConsentAudit.js.map +1 -0
  207. package/dist/resolvers/avatarInputValidation.d.ts +40 -0
  208. package/dist/resolvers/avatarInputValidation.d.ts.map +1 -0
  209. package/dist/resolvers/avatarInputValidation.js +97 -0
  210. package/dist/resolvers/avatarInputValidation.js.map +1 -0
  211. package/dist/resolvers/currentUserRoles.d.ts +29 -0
  212. package/dist/resolvers/currentUserRoles.d.ts.map +1 -1
  213. package/dist/resolvers/currentUserRoles.js +30 -0
  214. package/dist/resolvers/currentUserRoles.js.map +1 -1
  215. package/dist/resolvers/meetings/meetingMutations.d.ts +6 -0
  216. package/dist/resolvers/meetings/meetingMutations.d.ts.map +1 -1
  217. package/dist/resolvers/meetings/meetingMutations.js +21 -0
  218. package/dist/resolvers/meetings/meetingMutations.js.map +1 -1
  219. package/dist/services/TaskGraphContinuationDeliverer.d.ts +4 -3
  220. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  221. package/dist/services/TaskGraphContinuationDeliverer.js +13 -7
  222. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  223. package/dist/sharedCache.d.ts +105 -0
  224. package/dist/sharedCache.d.ts.map +1 -0
  225. package/dist/sharedCache.js +276 -0
  226. package/dist/sharedCache.js.map +1 -0
  227. package/dist/types.d.ts +6 -0
  228. package/dist/types.d.ts.map +1 -1
  229. package/dist/types.js.map +1 -1
  230. package/package.json +97 -95
  231. package/src/__tests__/ActionResolver.authorization.test.ts +353 -0
  232. package/src/__tests__/AdhocQueryResolver.sqlAuthorizer.test.ts +104 -0
  233. package/src/__tests__/BridgeHostInstance.test.ts +232 -0
  234. package/src/__tests__/ClientToolRequestResolver.test.ts +116 -0
  235. package/src/__tests__/FetchEntityVectorsResolver.test.ts +285 -0
  236. package/src/__tests__/HostInstance.test.ts +84 -0
  237. package/src/__tests__/HumanHandoffResolver.test.ts +17 -0
  238. package/src/__tests__/MeetingResolver.test.ts +75 -1
  239. package/src/__tests__/RealtimeBridgeResolver.test.ts +415 -6
  240. package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +383 -0
  241. package/src/__tests__/RealtimeClientSessionResolver.test.ts +682 -58
  242. package/src/__tests__/RealtimeProxyServer.test.ts +16 -1
  243. package/src/__tests__/RealtimeRelay.test.ts +876 -0
  244. package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +129 -0
  245. package/src/__tests__/ResolverBase.aggregateScreen.test.ts +174 -0
  246. package/src/__tests__/ResolverBase.clientOldValues.test.ts +6 -3
  247. package/src/__tests__/ReturningVisitorRecap.test.ts +115 -0
  248. package/src/__tests__/RunAIAgentResolver.branch.test.ts +169 -0
  249. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +4 -4
  250. package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +166 -0
  251. package/src/__tests__/RunTemplateResolver.test.ts +132 -0
  252. package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +63 -0
  253. package/src/__tests__/SessionJanitor.test.ts +845 -18
  254. package/src/__tests__/SessionManager.test.ts +213 -17
  255. package/src/__tests__/SessionRunIDVerifier.test.ts +251 -0
  256. package/src/__tests__/SyncRolesUsersResolver.userRoles.test.ts +97 -0
  257. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +50 -3
  258. package/src/__tests__/UserAvatarResolver.test.ts +255 -0
  259. package/src/__tests__/UserResolver.currentUser.test.ts +16 -1
  260. package/src/__tests__/actionAuthorization.test.ts +130 -0
  261. package/src/__tests__/agentVisionConsentAudit.test.ts +118 -0
  262. package/src/__tests__/avatarInputValidation.test.ts +160 -0
  263. package/src/__tests__/isolatedProviderTransactions.test.ts +169 -0
  264. package/src/__tests__/magicLinkService.consume.test.ts +6 -0
  265. package/src/__tests__/magicLinkService.provisionLog.test.ts +5 -0
  266. package/src/__tests__/newUsers.template.test.ts +151 -0
  267. package/src/__tests__/newUsers.test.ts +74 -5
  268. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +17 -2
  269. package/src/__tests__/realtimeSessions/RealtimeSessionEventService.test.ts +201 -0
  270. package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +215 -0
  271. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationResolver.test.ts +102 -0
  272. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationService.test.ts +349 -0
  273. package/src/__tests__/realtimeSessions/RealtimeVerifyRouter.test.ts +131 -0
  274. package/src/__tests__/realtimeSessions/SlidingWindowRateLimiter.test.ts +56 -0
  275. package/src/__tests__/realtimeSessions/helpers.ts +4 -0
  276. package/src/__tests__/realtimeSessions/sessionAccess.test.ts +129 -0
  277. package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +124 -0
  278. package/src/__tests__/realtimeSessions/verificationCore.test.ts +355 -0
  279. package/src/__tests__/realtimeSessions/verificationPages.test.ts +84 -0
  280. package/src/__tests__/realtimeSessions/verificationPolicy.test.ts +226 -0
  281. package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +633 -0
  282. package/src/__tests__/resolverBase.fls.test.ts +87 -4
  283. package/src/__tests__/serverExtensionReservedRoots.test.ts +2 -0
  284. package/src/__tests__/sharedCache.test.ts +310 -0
  285. package/src/__tests__/widgetGuestElevation.test.ts +44 -0
  286. package/src/agentSessions/BridgeHostInstance.ts +32 -0
  287. package/src/agentSessions/HostInstance.ts +124 -28
  288. package/src/agentSessions/ReturningVisitorRecap.ts +7 -3
  289. package/src/agentSessions/SessionJanitor.ts +543 -57
  290. package/src/agentSessions/SessionManager.ts +125 -25
  291. package/src/agentSessions/SessionRunIDVerifier.ts +171 -0
  292. package/src/agentSessions/index.ts +10 -3
  293. package/src/auth/actionAuthorization.ts +116 -0
  294. package/src/auth/index.ts +3 -8
  295. package/src/auth/magicLink/MagicLinkService.ts +6 -3
  296. package/src/auth/newUsers.ts +99 -11
  297. package/src/config.ts +125 -0
  298. package/src/context.ts +15 -10
  299. package/src/generated/graphql-schemas/__mj.ts +496 -1
  300. package/src/generic/OrphanedConversationDetailReconciler.ts +3 -3
  301. package/src/generic/ResolverBase.ts +39 -9
  302. package/src/generic/RunViewResolver.ts +4 -0
  303. package/src/index.ts +132 -143
  304. package/src/isolatedProvider.ts +22 -0
  305. package/src/realtimeProxy/RealtimeProxyServer.ts +148 -16
  306. package/src/realtimeProxy/RealtimeRelayTunnel.ts +645 -0
  307. package/src/realtimeSessions/README.md +179 -0
  308. package/src/realtimeSessions/RealtimeSessionEventService.ts +274 -0
  309. package/src/realtimeSessions/RealtimeSessionVerificationService.ts +167 -0
  310. package/src/realtimeSessions/RealtimeVerifyRouter.ts +108 -0
  311. package/src/realtimeSessions/SessionVerificationPortsBase.ts +189 -0
  312. package/src/realtimeSessions/SlidingWindowRateLimiter.ts +92 -0
  313. package/src/realtimeSessions/index.ts +16 -0
  314. package/src/realtimeSessions/sessionAccess.ts +141 -0
  315. package/src/realtimeSessions/sessionConfigStamps.ts +123 -0
  316. package/src/realtimeSessions/subscriptionAuthorization.ts +116 -0
  317. package/src/realtimeSessions/verificationCore.ts +502 -0
  318. package/src/realtimeSessions/verificationPages.ts +149 -0
  319. package/src/realtimeSessions/verificationPolicy.ts +321 -0
  320. package/src/realtimeSessions/verificationWorkflow.ts +702 -0
  321. package/src/realtimeWidget/widgetGuestElevation.ts +34 -2
  322. package/src/resolvers/ActionResolver.ts +84 -21
  323. package/src/resolvers/AdhocQueryResolver.ts +24 -6
  324. package/src/resolvers/CacheStatsResolver.ts +89 -2
  325. package/src/resolvers/ClientToolRequestResolver.ts +25 -7
  326. package/src/resolvers/FetchEntityVectorsResolver.ts +97 -2
  327. package/src/resolvers/HumanHandoffResolver.ts +8 -0
  328. package/src/resolvers/MCPResolver.ts +8 -5
  329. package/src/resolvers/RealtimeBridgeResolver.ts +163 -11
  330. package/src/resolvers/RealtimeClientSessionResolver.ts +501 -96
  331. package/src/resolvers/RealtimeSessionEventsResolver.ts +133 -0
  332. package/src/resolvers/RealtimeSessionVerificationResolver.ts +174 -0
  333. package/src/resolvers/RemoteBrowserActionResolver.ts +11 -1
  334. package/src/resolvers/RunAIAgentResolver.ts +78 -11
  335. package/src/resolvers/RunTemplateResolver.ts +13 -12
  336. package/src/resolvers/SyncDataResolver.ts +6 -2
  337. package/src/resolvers/SyncRolesUsersResolver.ts +24 -6
  338. package/src/resolvers/UserAvatarResolver.ts +111 -0
  339. package/src/resolvers/UserResolver.ts +2 -16
  340. package/src/resolvers/agentVisionConsentAudit.ts +82 -0
  341. package/src/resolvers/avatarInputValidation.ts +123 -0
  342. package/src/resolvers/currentUserRoles.ts +32 -1
  343. package/src/resolvers/meetings/meetingMutations.ts +21 -0
  344. package/src/services/TaskGraphContinuationDeliverer.ts +13 -7
  345. package/src/sharedCache.ts +302 -0
  346. package/src/types.ts +7 -0
@@ -0,0 +1,90 @@
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 { LogError } from '@memberjunction/core';
26
+ import { IsValidUUID, UUIDsEqual } from '@memberjunction/global';
27
+ /** Entity names, centralised so the `MJ: ` prefix convention lives in one place. */
28
+ const SESSION_ENTITY = 'MJ: AI Agent Sessions';
29
+ const CONVERSATION_ENTITY = 'MJ: Conversations';
30
+ /**
31
+ * Decides whether `principal` may address the session described by `subject`.
32
+ *
33
+ * Fails closed: anything that cannot be positively matched is refused.
34
+ *
35
+ * @param subject - owner + scope of the session
36
+ * @param principal - the authenticated caller (from the server-built `UserInfo`, never from client args)
37
+ */
38
+ export function AuthorizeSessionAccess(subject, principal) {
39
+ if (!principal?.ID || !subject.SessionUserID || !UUIDsEqual(subject.SessionUserID, principal.ID)) {
40
+ return { Allowed: false, Reason: 'not_owner' };
41
+ }
42
+ const scopeId = principal.MagicLinkScope?.ResourceID;
43
+ if (!scopeId) {
44
+ // An anonymous principal without a per-session scope is indistinguishable from every other
45
+ // anonymous principal: owning "the Anonymous user's" session proves nothing.
46
+ return principal.IsMagicLinkAnonymous ? { Allowed: false, Reason: 'scope_missing' } : { Allowed: true };
47
+ }
48
+ // Scope ids are opaque base64url strings (case-significant), so compare exactly — not UUIDsEqual.
49
+ return subject.ConversationExternalID === scopeId ? { Allowed: true } : { Allowed: false, Reason: 'scope_mismatch' };
50
+ }
51
+ /**
52
+ * Loads a session (and its conversation's scope id) under `contextUser`'s identity.
53
+ *
54
+ * Loading as the caller — rather than as a privileged user — means the entity layer's row-level
55
+ * security (`Widget Guest: Own Agent Sessions`, `UI: Own Agent Sessions`) is the FIRST gate; the
56
+ * explicit {@link AuthorizeSessionAccess} check that follows is defence in depth.
57
+ *
58
+ * @returns the loaded session, or `null` when the id is malformed, the row does not exist, or the
59
+ * caller cannot read it. Failure to read the conversation yields `ConversationExternalID: null`,
60
+ * which {@link AuthorizeSessionAccess} then treats as "no scope to match" (refused for a scoped caller).
61
+ */
62
+ export async function LoadSessionForAccess(agentSessionId, contextUser, provider) {
63
+ if (!IsValidUUID(agentSessionId)) {
64
+ return null;
65
+ }
66
+ const session = await provider.GetEntityObject(SESSION_ENTITY, contextUser);
67
+ if (!(await session.Load(agentSessionId))) {
68
+ return null;
69
+ }
70
+ return { Session: session, ConversationExternalID: await loadConversationExternalID(session, contextUser, provider) };
71
+ }
72
+ /** Reads the session conversation's `ExternalID`; null when there is no conversation or it cannot be read. */
73
+ async function loadConversationExternalID(session, contextUser, provider) {
74
+ if (!session.ConversationID) {
75
+ return null;
76
+ }
77
+ try {
78
+ const conversation = await provider.GetEntityObject(CONVERSATION_ENTITY, contextUser);
79
+ if (!(await conversation.Load(session.ConversationID))) {
80
+ return null;
81
+ }
82
+ return conversation.ExternalID ?? null;
83
+ }
84
+ catch (error) {
85
+ const message = error instanceof Error ? error.message : String(error);
86
+ LogError(`LoadSessionForAccess: could not read conversation ${session.ConversationID} of session ${session.ID}: ${message}`);
87
+ return null;
88
+ }
89
+ }
90
+ //# sourceMappingURL=sessionAccess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionAccess.js","sourceRoot":"","sources":["../../src/realtimeSessions/sessionAccess.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAqB,QAAQ,EAAY,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGjE,oFAAoF;AACpF,MAAM,cAAc,GAAG,uBAAuB,CAAC;AAC/C,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AA8BhD;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAClC,OAA6B,EAC7B,SAAoD;IAEpD,IAAI,CAAC,SAAS,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,aAAa,EAAE,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC;QAC/F,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACnD,CAAC;IACD,MAAM,OAAO,GAAG,SAAS,CAAC,cAAc,EAAE,UAAU,CAAC;IACrD,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,2FAA2F;QAC3F,6EAA6E;QAC7E,OAAO,SAAS,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC5G,CAAC;IACD,kGAAkG;IAClG,OAAO,OAAO,CAAC,sBAAsB,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;AACzH,CAAC;AAUD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACtC,cAAsB,EACtB,WAAqB,EACrB,QAA2B;IAE3B,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAyB,cAAc,EAAE,WAAW,CAAC,CAAC;IACpG,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,CAAC;AAC1H,CAAC;AAED,8GAA8G;AAC9G,KAAK,UAAU,0BAA0B,CACrC,OAA+B,EAC/B,WAAqB,EACrB,QAA2B;IAE3B,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAuB,mBAAmB,EAAE,WAAW,CAAC,CAAC;QAC5G,IAAI,CAAC,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,OAAO,YAAY,CAAC,UAAU,IAAI,IAAI,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,QAAQ,CAAC,qDAAqD,OAAO,CAAC,cAAc,eAAe,OAAO,CAAC,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC;QAC7H,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * @fileoverview What the session-start path stamps into a new realtime session's `Config` for identity
3
+ * verification: the policy snapshot, the unverified duration cap, and any verified identity carried
4
+ * forward from the session being resumed.
5
+ *
6
+ * Split in two so the decision is testable without a database:
7
+ *
8
+ * - {@link BuildMintConfigStamps} — **pure**. Given the resolved realtime config, the existing `Config`
9
+ * and an optional inherited identity, returns the `Config` to write (or `null` when there is nothing
10
+ * to stamp).
11
+ * - {@link LoadInheritedVerifiedIdentity} — the one read: the prior session's verified identity, only
12
+ * when the new caller is authorized on that prior session.
13
+ *
14
+ * Everything stamped here lives under server-authoritative keys (`identityVerification`,
15
+ * `maxSessionDeadlineIso`); the caller writes it inside `RunWithTrustedSessionConfigWrites`.
16
+ *
17
+ * ## Resume after the cap
18
+ *
19
+ * If an unverified session hits its cap before the person verifies, the janitor closes it. A verify link
20
+ * redeemed afterwards still records the verification on that (closed) session, and a **new** session
21
+ * started with `lastSessionId` pointing at it inherits the verified identity (and, with it, the
22
+ * `verifiedMaxSeconds` cap instead of the unverified one). Inheritance requires the same ownership/scope
23
+ * authorization as any other access to the prior session, so a stranger cannot adopt someone else's
24
+ * verification by naming their session id.
25
+ *
26
+ * @module @memberjunction/server/realtimeSessions
27
+ */
28
+ import type { IMetadataProvider, UserInfo } from '@memberjunction/core';
29
+ import { type VerifiedIdentity } from './verificationCore.js';
30
+ /** The `Config` to persist at session start. */
31
+ export interface MintConfigStampPlan {
32
+ NextConfigRaw: string;
33
+ }
34
+ /**
35
+ * Decides what to stamp into a freshly created session's `Config`.
36
+ *
37
+ * - **Policy snapshot.** The cascade's verification layer (`channels.config.IdentityVerification` plus the
38
+ * duration caps) is copied onto the session, so the rules a person is held to are fixed at mint,
39
+ * server-side, and cannot be chosen by the caller later.
40
+ * - **Duration cap.** When the cascade configures `unverifiedMaxSeconds` (or, for a session that inherited
41
+ * a verified identity, `verifiedMaxSeconds`), the session's absolute deadline is set to now + cap —
42
+ * applied to ANY principal, not only widget guests — and never loosens a tighter deadline already
43
+ * stamped (the widget voice cap).
44
+ * - **Inherited identity.** A verified identity carried forward from the resumed session.
45
+ *
46
+ * @param args.EffectiveRealtime - `EffectiveConfig.realtime` of the resolved config (any shape; read defensively)
47
+ * @param args.ExistingConfigRaw - the session's current `Config`
48
+ * @param args.InheritedVerified - verified identity from the session being resumed, if any
49
+ * @param args.NowMs - the current time, epoch ms
50
+ * @returns the `Config` to write, or `null` when nothing needs stamping
51
+ */
52
+ export declare function BuildMintConfigStamps(args: {
53
+ EffectiveRealtime: unknown;
54
+ ExistingConfigRaw: string | null;
55
+ InheritedVerified?: VerifiedIdentity;
56
+ NowMs: number;
57
+ }): MintConfigStampPlan | null;
58
+ /**
59
+ * The verified identity of the session being resumed, when the caller may inherit it.
60
+ *
61
+ * Reads the prior session as the caller and requires {@link AuthorizeSessionAccess} to allow it; any
62
+ * failure (no such session, not the caller's, unreadable) yields `undefined` — inheritance is a
63
+ * convenience and must never block a session start.
64
+ *
65
+ * @param lastSessionId - the `lastSessionId` the client supplied at start
66
+ * @param contextUser - the starting caller
67
+ * @param provider - request-scoped provider
68
+ */
69
+ export declare function LoadInheritedVerifiedIdentity(lastSessionId: string | undefined, contextUser: UserInfo, provider: IMetadataProvider): Promise<VerifiedIdentity | undefined>;
70
+ //# sourceMappingURL=sessionConfigStamps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionConfigStamps.d.ts","sourceRoot":"","sources":["../../src/realtimeSessions/sessionConfigStamps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAOxE,OAAO,EAKH,KAAK,gBAAgB,EACxB,MAAM,uBAAuB,CAAC;AAE/B,gDAAgD;AAChD,MAAM,WAAW,mBAAmB;IAChC,aAAa,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IACxC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iBAAiB,CAAC,EAAE,gBAAgB,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;CACjB,GAAG,mBAAmB,GAAG,IAAI,CAkB7B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,6BAA6B,CAC/C,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,WAAW,EAAE,QAAQ,EACrB,QAAQ,EAAE,iBAAiB,GAC5B,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAgBvC"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @fileoverview What the session-start path stamps into a new realtime session's `Config` for identity
3
+ * verification: the policy snapshot, the unverified duration cap, and any verified identity carried
4
+ * forward from the session being resumed.
5
+ *
6
+ * Split in two so the decision is testable without a database:
7
+ *
8
+ * - {@link BuildMintConfigStamps} — **pure**. Given the resolved realtime config, the existing `Config`
9
+ * and an optional inherited identity, returns the `Config` to write (or `null` when there is nothing
10
+ * to stamp).
11
+ * - {@link LoadInheritedVerifiedIdentity} — the one read: the prior session's verified identity, only
12
+ * when the new caller is authorized on that prior session.
13
+ *
14
+ * Everything stamped here lives under server-authoritative keys (`identityVerification`,
15
+ * `maxSessionDeadlineIso`); the caller writes it inside `RunWithTrustedSessionConfigWrites`.
16
+ *
17
+ * ## Resume after the cap
18
+ *
19
+ * If an unverified session hits its cap before the person verifies, the janitor closes it. A verify link
20
+ * redeemed afterwards still records the verification on that (closed) session, and a **new** session
21
+ * started with `lastSessionId` pointing at it inherits the verified identity (and, with it, the
22
+ * `verifiedMaxSeconds` cap instead of the unverified one). Inheritance requires the same ownership/scope
23
+ * authorization as any other access to the prior session, so a stranger cannot adopt someone else's
24
+ * verification by naming their session id.
25
+ *
26
+ * @module @memberjunction/server/realtimeSessions
27
+ */
28
+ import { AuthorizeSessionAccess, LoadSessionForAccess } from './sessionAccess.js';
29
+ import { ExtractIdentityVerificationPolicyFromRealtimeConfig, ReadIdentityVerificationPolicyLayer, TightenSessionDeadline, } from './verificationPolicy.js';
30
+ import { ParseConfigObject, ReadIdentityVerificationState, WriteIdentityVerificationState, } from './verificationCore.js';
31
+ /**
32
+ * Decides what to stamp into a freshly created session's `Config`.
33
+ *
34
+ * - **Policy snapshot.** The cascade's verification layer (`channels.config.IdentityVerification` plus the
35
+ * duration caps) is copied onto the session, so the rules a person is held to are fixed at mint,
36
+ * server-side, and cannot be chosen by the caller later.
37
+ * - **Duration cap.** When the cascade configures `unverifiedMaxSeconds` (or, for a session that inherited
38
+ * a verified identity, `verifiedMaxSeconds`), the session's absolute deadline is set to now + cap —
39
+ * applied to ANY principal, not only widget guests — and never loosens a tighter deadline already
40
+ * stamped (the widget voice cap).
41
+ * - **Inherited identity.** A verified identity carried forward from the resumed session.
42
+ *
43
+ * @param args.EffectiveRealtime - `EffectiveConfig.realtime` of the resolved config (any shape; read defensively)
44
+ * @param args.ExistingConfigRaw - the session's current `Config`
45
+ * @param args.InheritedVerified - verified identity from the session being resumed, if any
46
+ * @param args.NowMs - the current time, epoch ms
47
+ * @returns the `Config` to write, or `null` when nothing needs stamping
48
+ */
49
+ export function BuildMintConfigStamps(args) {
50
+ const layer = ExtractIdentityVerificationPolicyFromRealtimeConfig(args.EffectiveRealtime);
51
+ const hasPolicy = Object.keys(layer).length > 0;
52
+ if (!hasPolicy && !args.InheritedVerified) {
53
+ return null;
54
+ }
55
+ const existingState = ReadIdentityVerificationState(args.ExistingConfigRaw, ReadIdentityVerificationPolicyLayer);
56
+ const state = {
57
+ ...existingState,
58
+ ...(hasPolicy ? { Policy: layer } : {}),
59
+ ...(args.InheritedVerified ? { Verified: args.InheritedVerified } : {}),
60
+ };
61
+ const capSeconds = args.InheritedVerified ? (layer.verifiedMaxSeconds ?? layer.unverifiedMaxSeconds) : layer.unverifiedMaxSeconds;
62
+ const existingDeadline = ParseConfigObject(args.ExistingConfigRaw)['maxSessionDeadlineIso'];
63
+ const deadlineIso = capSeconds
64
+ ? TightenSessionDeadline(typeof existingDeadline === 'string' ? existingDeadline : undefined, args.NowMs + capSeconds * 1000)
65
+ : undefined;
66
+ return { NextConfigRaw: WriteIdentityVerificationState(args.ExistingConfigRaw, state, deadlineIso) };
67
+ }
68
+ /**
69
+ * The verified identity of the session being resumed, when the caller may inherit it.
70
+ *
71
+ * Reads the prior session as the caller and requires {@link AuthorizeSessionAccess} to allow it; any
72
+ * failure (no such session, not the caller's, unreadable) yields `undefined` — inheritance is a
73
+ * convenience and must never block a session start.
74
+ *
75
+ * @param lastSessionId - the `lastSessionId` the client supplied at start
76
+ * @param contextUser - the starting caller
77
+ * @param provider - request-scoped provider
78
+ */
79
+ export async function LoadInheritedVerifiedIdentity(lastSessionId, contextUser, provider) {
80
+ if (!lastSessionId) {
81
+ return undefined;
82
+ }
83
+ const prior = await LoadSessionForAccess(lastSessionId, contextUser, provider);
84
+ if (!prior) {
85
+ return undefined;
86
+ }
87
+ const decision = AuthorizeSessionAccess({ SessionUserID: prior.Session.UserID, ConversationExternalID: prior.ConversationExternalID }, contextUser);
88
+ if (decision.Allowed === false) {
89
+ return undefined;
90
+ }
91
+ return ReadIdentityVerificationState(prior.Session.Config_, ReadIdentityVerificationPolicyLayer).Verified;
92
+ }
93
+ //# sourceMappingURL=sessionConfigStamps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionConfigStamps.js","sourceRoot":"","sources":["../../src/realtimeSessions/sessionConfigStamps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EACH,mDAAmD,EACnD,mCAAmC,EACnC,sBAAsB,GACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACH,iBAAiB,EACjB,6BAA6B,EAC7B,8BAA8B,GAGjC,MAAM,uBAAuB,CAAC;AAO/B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAKrC;IACG,MAAM,KAAK,GAAG,mDAAmD,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC1F,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAChD,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,MAAM,aAAa,GAAG,6BAA6B,CAAC,IAAI,CAAC,iBAAiB,EAAE,mCAAmC,CAAC,CAAC;IACjH,MAAM,KAAK,GAA8B;QACrC,GAAG,aAAa;QAChB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC;IACF,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC;IAClI,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,uBAAuB,CAAC,CAAC;IAC5F,MAAM,WAAW,GAAG,UAAU;QAC1B,CAAC,CAAC,sBAAsB,CAAC,OAAO,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,GAAG,UAAU,GAAG,IAAI,CAAC;QAC7H,CAAC,CAAC,SAAS,CAAC;IAChB,OAAO,EAAE,aAAa,EAAE,8BAA8B,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC;AACzG,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAC/C,aAAiC,EACjC,WAAqB,EACrB,QAA2B;IAE3B,IAAI,CAAC,aAAa,EAAE,CAAC;QACjB,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,oBAAoB,CAAC,aAAa,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC/E,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,MAAM,QAAQ,GAAG,sBAAsB,CACnC,EAAE,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,sBAAsB,EAAE,KAAK,CAAC,sBAAsB,EAAE,EAC7F,WAAW,CACd,CAAC;IACF,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QAC7B,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,OAAO,6BAA6B,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,mCAAmC,CAAC,CAAC,QAAQ,CAAC;AAC9G,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @fileoverview The authorization of the `RealtimeSessionEvents` subscription, free of GraphQL schema
3
+ * decorators and server configuration so it can be exercised — and reused — without loading either.
4
+ *
5
+ * It is applied twice on purpose (see `RealtimeSessionEventsResolver`): once when the subscription is
6
+ * opened ({@link AuthorizeRealtimeSessionSubscription}) and once for every event
7
+ * ({@link RealtimeSessionEventsFilter}). In neither check does a client-supplied value decide who
8
+ * receives anything: `agentSessionId` only selects WHICH of the caller's own sessions to listen to; the
9
+ * identity it is checked against comes from the server-authenticated connection context.
10
+ *
11
+ * @module @memberjunction/server/realtimeSessions
12
+ */
13
+ import { IMetadataProvider, UserInfo } from '@memberjunction/core';
14
+ import type { UserPayload } from '../types.js';
15
+ import { type LoadedSessionForAccess } from './sessionAccess.js';
16
+ import type { RealtimeSessionEventTopicPayload } from './RealtimeSessionEventService.js';
17
+ /**
18
+ * Arguments of the subscription. `agentSessionId` is camelCase because it is the GraphQL argument name
19
+ * graphql-js hands to `subscribe` and to the filter — it is the wire contract, not an API of ours.
20
+ */
21
+ export interface RealtimeSessionEventsArgs {
22
+ agentSessionId?: string;
23
+ }
24
+ /**
25
+ * The slice of the WebSocket connection context the authorization reads. `userPayload` is camelCase to
26
+ * match `AppContext.userPayload`, the member graphql-ws populates and every resolver already destructures.
27
+ */
28
+ export interface RealtimeSessionEventsContext {
29
+ userPayload?: UserPayload;
30
+ }
31
+ /**
32
+ * Per-event filter. Exported because it is the security-critical gate and must be testable in isolation.
33
+ *
34
+ * An event reaches a subscriber only when BOTH hold:
35
+ * 1. it is addressed to the session the subscriber asked for, and
36
+ * 2. the event's owner/scope snapshot passes {@link AuthorizeSessionAccess} for the connection's
37
+ * authenticated principal.
38
+ *
39
+ * Fails closed: a missing connection identity, a missing owner on the event, or a missing argument never matches.
40
+ */
41
+ export declare function RealtimeSessionEventsFilter(data: {
42
+ payload: RealtimeSessionEventTopicPayload;
43
+ args: RealtimeSessionEventsArgs;
44
+ context: RealtimeSessionEventsContext | undefined;
45
+ }): boolean;
46
+ /** Dependencies of {@link AuthorizeRealtimeSessionSubscription}, injectable for tests. */
47
+ export interface SubscriptionAuthorizationDeps {
48
+ /** Loads a session under the caller's identity. */
49
+ LoadSession: (agentSessionId: string, user: UserInfo, provider: IMetadataProvider) => Promise<LoadedSessionForAccess | null>;
50
+ /** The provider to read with (a WebSocket context carries no request-scoped providers). */
51
+ GetProvider: () => IMetadataProvider;
52
+ }
53
+ /** Production dependencies. */
54
+ export declare const DEFAULT_SUBSCRIPTION_AUTHORIZATION_DEPS: SubscriptionAuthorizationDeps;
55
+ /**
56
+ * Subscribe-time authorization: loads the session as the connection's principal and requires
57
+ * {@link AuthorizeSessionAccess} to allow it. Throws {@link REFUSAL_MESSAGE} (uniformly) otherwise.
58
+ *
59
+ * @param args - the subscription arguments
60
+ * @param context - the connection context (server-authenticated)
61
+ * @param deps - injectable dependencies (tests)
62
+ * @returns the validated session id
63
+ */
64
+ export declare function AuthorizeRealtimeSessionSubscription(args: RealtimeSessionEventsArgs, context: RealtimeSessionEventsContext | undefined, deps?: SubscriptionAuthorizationDeps): Promise<string>;
65
+ //# sourceMappingURL=subscriptionAuthorization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptionAuthorization.d.ts","sourceRoot":"","sources":["../../src/realtimeSessions/subscriptionAuthorization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,iBAAiB,EAAsB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEvF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAgD,KAAK,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC/G,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,kCAAkC,CAAC;AAEzF;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,4BAA4B;IACzC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC7B;AAUD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAC9C,OAAO,EAAE,gCAAgC,CAAC;IAC1C,IAAI,EAAE,yBAAyB,CAAC;IAChC,OAAO,EAAE,4BAA4B,GAAG,SAAS,CAAC;CACrD,GAAG,OAAO,CAUV;AAED,0FAA0F;AAC1F,MAAM,WAAW,6BAA6B;IAC1C,mDAAmD;IACnD,WAAW,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,KAAK,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IAC7H,2FAA2F;IAC3F,WAAW,EAAE,MAAM,iBAAiB,CAAC;CACxC;AAED,+BAA+B;AAC/B,eAAO,MAAM,uCAAuC,EAAE,6BAGrD,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,oCAAoC,CACtD,IAAI,EAAE,yBAAyB,EAC/B,OAAO,EAAE,4BAA4B,GAAG,SAAS,EACjD,IAAI,GAAE,6BAAuE,GAC9E,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @fileoverview The authorization of the `RealtimeSessionEvents` subscription, free of GraphQL schema
3
+ * decorators and server configuration so it can be exercised — and reused — without loading either.
4
+ *
5
+ * It is applied twice on purpose (see `RealtimeSessionEventsResolver`): once when the subscription is
6
+ * opened ({@link AuthorizeRealtimeSessionSubscription}) and once for every event
7
+ * ({@link RealtimeSessionEventsFilter}). In neither check does a client-supplied value decide who
8
+ * receives anything: `agentSessionId` only selects WHICH of the caller's own sessions to listen to; the
9
+ * identity it is checked against comes from the server-authenticated connection context.
10
+ *
11
+ * @module @memberjunction/server/realtimeSessions
12
+ */
13
+ import { LogError, Metadata } from '@memberjunction/core';
14
+ import { IsValidUUID, UUIDsEqual } from '@memberjunction/global';
15
+ import { AuthorizeSessionAccess, LoadSessionForAccess } from './sessionAccess.js';
16
+ /** Why a subscription request was refused (logged; the client always gets the same message). */
17
+ const REFUSAL_MESSAGE = 'Realtime session not found.';
18
+ /** The principal the connection authenticated as, or undefined. */
19
+ function connectionPrincipal(context) {
20
+ return context?.userPayload?.userRecord;
21
+ }
22
+ /**
23
+ * Per-event filter. Exported because it is the security-critical gate and must be testable in isolation.
24
+ *
25
+ * An event reaches a subscriber only when BOTH hold:
26
+ * 1. it is addressed to the session the subscriber asked for, and
27
+ * 2. the event's owner/scope snapshot passes {@link AuthorizeSessionAccess} for the connection's
28
+ * authenticated principal.
29
+ *
30
+ * Fails closed: a missing connection identity, a missing owner on the event, or a missing argument never matches.
31
+ */
32
+ export function RealtimeSessionEventsFilter(data) {
33
+ const { payload, args, context } = data;
34
+ if (typeof args?.agentSessionId !== 'string' || !payload?.AgentSessionID || !UUIDsEqual(payload.AgentSessionID, args.agentSessionId)) {
35
+ return false;
36
+ }
37
+ const decision = AuthorizeSessionAccess({ SessionUserID: payload.OwnerUserID, ConversationExternalID: payload.ScopeKey }, connectionPrincipal(context));
38
+ return decision.Allowed;
39
+ }
40
+ /** Production dependencies. */
41
+ export const DEFAULT_SUBSCRIPTION_AUTHORIZATION_DEPS = {
42
+ LoadSession: LoadSessionForAccess,
43
+ GetProvider: () => Metadata.Provider, // global-provider-ok: a WebSocket subscription context has no per-request providers
44
+ };
45
+ /**
46
+ * Subscribe-time authorization: loads the session as the connection's principal and requires
47
+ * {@link AuthorizeSessionAccess} to allow it. Throws {@link REFUSAL_MESSAGE} (uniformly) otherwise.
48
+ *
49
+ * @param args - the subscription arguments
50
+ * @param context - the connection context (server-authenticated)
51
+ * @param deps - injectable dependencies (tests)
52
+ * @returns the validated session id
53
+ */
54
+ export async function AuthorizeRealtimeSessionSubscription(args, context, deps = DEFAULT_SUBSCRIPTION_AUTHORIZATION_DEPS) {
55
+ const principal = connectionPrincipal(context);
56
+ const agentSessionId = args?.agentSessionId;
57
+ if (!principal || typeof agentSessionId !== 'string' || !IsValidUUID(agentSessionId)) {
58
+ throw new Error(REFUSAL_MESSAGE);
59
+ }
60
+ const loaded = await deps.LoadSession(agentSessionId, principal, deps.GetProvider());
61
+ if (!loaded) {
62
+ throw new Error(REFUSAL_MESSAGE);
63
+ }
64
+ const decision = AuthorizeSessionAccess({ SessionUserID: loaded.Session.UserID, ConversationExternalID: loaded.ConversationExternalID }, principal);
65
+ if (decision.Allowed === false) {
66
+ LogError(`RealtimeSessionEvents: refused subscription by user ${principal.ID} to session ${agentSessionId} (${decision.Reason}).`);
67
+ throw new Error(REFUSAL_MESSAGE);
68
+ }
69
+ return agentSessionId;
70
+ }
71
+ //# sourceMappingURL=subscriptionAuthorization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptionAuthorization.js","sourceRoot":"","sources":["../../src/realtimeSessions/subscriptionAuthorization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAqB,QAAQ,EAAE,QAAQ,EAAY,MAAM,sBAAsB,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEjE,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAA+B,MAAM,oBAAoB,CAAC;AAmB/G,gGAAgG;AAChG,MAAM,eAAe,GAAG,6BAA6B,CAAC;AAEtD,mEAAmE;AACnE,SAAS,mBAAmB,CAAC,OAAiD;IAC1E,OAAO,OAAO,EAAE,WAAW,EAAE,UAAkC,CAAC;AACpE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAI3C;IACG,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACxC,IAAI,OAAO,IAAI,EAAE,cAAc,KAAK,QAAQ,IAAI,CAAC,OAAO,EAAE,cAAc,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;QACnI,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,MAAM,QAAQ,GAAG,sBAAsB,CACnC,EAAE,aAAa,EAAE,OAAO,CAAC,WAAW,EAAE,sBAAsB,EAAE,OAAO,CAAC,QAAQ,EAAE,EAChF,mBAAmB,CAAC,OAAO,CAAC,CAC/B,CAAC;IACF,OAAO,QAAQ,CAAC,OAAO,CAAC;AAC5B,CAAC;AAUD,+BAA+B;AAC/B,MAAM,CAAC,MAAM,uCAAuC,GAAkC;IAClF,WAAW,EAAE,oBAAoB;IACjC,WAAW,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,oFAAoF;CAC7H,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,oCAAoC,CACtD,IAA+B,EAC/B,OAAiD,EACjD,OAAsC,uCAAuC;IAE7E,MAAM,SAAS,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,cAAc,GAAG,IAAI,EAAE,cAAc,CAAC;IAC5C,IAAI,CAAC,SAAS,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC;QACnF,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE,SAAS,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACrF,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,QAAQ,GAAG,sBAAsB,CACnC,EAAE,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,sBAAsB,EAAE,MAAM,CAAC,sBAAsB,EAAE,EAC/F,SAAS,CACZ,CAAC;IACF,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QAC7B,QAAQ,CAAC,uDAAuD,SAAS,CAAC,EAAE,eAAe,cAAc,KAAK,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;QACnI,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,cAAc,CAAC;AAC1B,CAAC"}