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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (543) hide show
  1. package/README.md +20 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentSessions/BridgeHostInstance.d.ts +25 -0
  4. package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -0
  5. package/dist/agentSessions/BridgeHostInstance.js +30 -0
  6. package/dist/agentSessions/BridgeHostInstance.js.map +1 -0
  7. package/dist/agentSessions/HostInstance.d.ts +75 -11
  8. package/dist/agentSessions/HostInstance.d.ts.map +1 -1
  9. package/dist/agentSessions/HostInstance.js +99 -28
  10. package/dist/agentSessions/HostInstance.js.map +1 -1
  11. package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
  12. package/dist/agentSessions/ReturningVisitorRecap.js +7 -3
  13. package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
  14. package/dist/agentSessions/SessionJanitor.d.ts +236 -27
  15. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  16. package/dist/agentSessions/SessionJanitor.js +682 -54
  17. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  18. package/dist/agentSessions/SessionManager.d.ts +48 -3
  19. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  20. package/dist/agentSessions/SessionManager.js +112 -9
  21. package/dist/agentSessions/SessionManager.js.map +1 -1
  22. package/dist/agentSessions/SessionRunIDVerifier.d.ts +63 -0
  23. package/dist/agentSessions/SessionRunIDVerifier.d.ts.map +1 -0
  24. package/dist/agentSessions/SessionRunIDVerifier.js +129 -0
  25. package/dist/agentSessions/SessionRunIDVerifier.js.map +1 -0
  26. package/dist/agentSessions/index.d.ts +2 -0
  27. package/dist/agentSessions/index.d.ts.map +1 -1
  28. package/dist/agentSessions/index.js +10 -3
  29. package/dist/agentSessions/index.js.map +1 -1
  30. package/dist/apiRoot.d.ts +32 -0
  31. package/dist/apiRoot.d.ts.map +1 -0
  32. package/dist/apiRoot.js +67 -0
  33. package/dist/apiRoot.js.map +1 -0
  34. package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
  35. package/dist/auth/AuthProviderCatalogRouter.js +25 -0
  36. package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
  37. package/dist/auth/LoginScreenEngine.d.ts +22 -0
  38. package/dist/auth/LoginScreenEngine.d.ts.map +1 -0
  39. package/dist/auth/LoginScreenEngine.js +57 -0
  40. package/dist/auth/LoginScreenEngine.js.map +1 -0
  41. package/dist/auth/actionAuthorization.d.ts +40 -0
  42. package/dist/auth/actionAuthorization.d.ts.map +1 -0
  43. package/dist/auth/actionAuthorization.js +94 -0
  44. package/dist/auth/actionAuthorization.js.map +1 -0
  45. package/dist/auth/index.d.ts +1 -0
  46. package/dist/auth/index.d.ts.map +1 -1
  47. package/dist/auth/index.js +4 -10
  48. package/dist/auth/index.js.map +1 -1
  49. package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
  50. package/dist/auth/magicLink/MagicLinkRouter.js +3 -2
  51. package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
  52. package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
  53. package/dist/auth/magicLink/MagicLinkService.js +6 -3
  54. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  55. package/dist/auth/newUsers.d.ts +10 -0
  56. package/dist/auth/newUsers.d.ts.map +1 -1
  57. package/dist/auth/newUsers.js +80 -11
  58. package/dist/auth/newUsers.js.map +1 -1
  59. package/dist/config.d.ts +2514 -22
  60. package/dist/config.d.ts.map +1 -1
  61. package/dist/config.js +166 -4
  62. package/dist/config.js.map +1 -1
  63. package/dist/context.d.ts +8 -0
  64. package/dist/context.d.ts.map +1 -1
  65. package/dist/context.js +14 -11
  66. package/dist/context.js.map +1 -1
  67. package/dist/coreRoutes.d.ts +29 -0
  68. package/dist/coreRoutes.d.ts.map +1 -0
  69. package/dist/coreRoutes.js +142 -0
  70. package/dist/coreRoutes.js.map +1 -0
  71. package/dist/generated/graphql-schemas/__mj.d.ts +504 -3
  72. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  73. package/dist/generated/graphql-schemas/__mj.js +2456 -7
  74. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  75. package/dist/generic/CacheInvalidationResolver.d.ts +43 -8
  76. package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
  77. package/dist/generic/CacheInvalidationResolver.js +59 -19
  78. package/dist/generic/CacheInvalidationResolver.js.map +1 -1
  79. package/dist/generic/OrphanedConversationDetailReconciler.js +3 -3
  80. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
  81. package/dist/generic/PushStatusResolver.js +1 -1
  82. package/dist/generic/PushStatusResolver.js.map +1 -1
  83. package/dist/generic/ResolverBase.d.ts +123 -48
  84. package/dist/generic/ResolverBase.d.ts.map +1 -1
  85. package/dist/generic/ResolverBase.js +293 -305
  86. package/dist/generic/ResolverBase.js.map +1 -1
  87. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  88. package/dist/generic/RunViewResolver.js +16 -0
  89. package/dist/generic/RunViewResolver.js.map +1 -1
  90. package/dist/globalCors.d.ts +33 -0
  91. package/dist/globalCors.d.ts.map +1 -0
  92. package/dist/globalCors.js +58 -0
  93. package/dist/globalCors.js.map +1 -0
  94. package/dist/index.d.ts +17 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +219 -278
  97. package/dist/index.js.map +1 -1
  98. package/dist/isolatedProvider.d.ts +20 -0
  99. package/dist/isolatedProvider.d.ts.map +1 -0
  100. package/dist/isolatedProvider.js +22 -0
  101. package/dist/isolatedProvider.js.map +1 -0
  102. package/dist/multiTenancy/index.d.ts.map +1 -1
  103. package/dist/multiTenancy/index.js +22 -2
  104. package/dist/multiTenancy/index.js.map +1 -1
  105. package/dist/realtimeProxy/RealtimeProxyServer.d.ts +44 -4
  106. package/dist/realtimeProxy/RealtimeProxyServer.d.ts.map +1 -1
  107. package/dist/realtimeProxy/RealtimeProxyServer.js +121 -16
  108. package/dist/realtimeProxy/RealtimeProxyServer.js.map +1 -1
  109. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts +171 -0
  110. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts.map +1 -0
  111. package/dist/realtimeProxy/RealtimeRelayTunnel.js +532 -0
  112. package/dist/realtimeProxy/RealtimeRelayTunnel.js.map +1 -0
  113. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts +148 -0
  114. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts.map +1 -0
  115. package/dist/realtimeSessions/RealtimeSessionEventService.js +191 -0
  116. package/dist/realtimeSessions/RealtimeSessionEventService.js.map +1 -0
  117. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts +66 -0
  118. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -0
  119. package/dist/realtimeSessions/RealtimeSessionVerificationService.js +139 -0
  120. package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -0
  121. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts +38 -0
  122. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -0
  123. package/dist/realtimeSessions/RealtimeVerifyRouter.js +99 -0
  124. package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -0
  125. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts +100 -0
  126. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts.map +1 -0
  127. package/dist/realtimeSessions/RecordingAssemblyScheduler.js +173 -0
  128. package/dist/realtimeSessions/RecordingAssemblyScheduler.js.map +1 -0
  129. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts +61 -0
  130. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -0
  131. package/dist/realtimeSessions/SessionVerificationPortsBase.js +149 -0
  132. package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -0
  133. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts +57 -0
  134. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts.map +1 -0
  135. package/dist/realtimeSessions/SlidingWindowRateLimiter.js +69 -0
  136. package/dist/realtimeSessions/SlidingWindowRateLimiter.js.map +1 -0
  137. package/dist/realtimeSessions/index.d.ts +19 -0
  138. package/dist/realtimeSessions/index.d.ts.map +1 -0
  139. package/dist/realtimeSessions/index.js +19 -0
  140. package/dist/realtimeSessions/index.js.map +1 -0
  141. package/dist/realtimeSessions/ownedRealtimeSession.d.ts +30 -0
  142. package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -0
  143. package/dist/realtimeSessions/ownedRealtimeSession.js +47 -0
  144. package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -0
  145. package/dist/realtimeSessions/sessionAccess.d.ts +92 -0
  146. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -0
  147. package/dist/realtimeSessions/sessionAccess.js +94 -0
  148. package/dist/realtimeSessions/sessionAccess.js.map +1 -0
  149. package/dist/realtimeSessions/sessionConfigStamps.d.ts +70 -0
  150. package/dist/realtimeSessions/sessionConfigStamps.d.ts.map +1 -0
  151. package/dist/realtimeSessions/sessionConfigStamps.js +93 -0
  152. package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -0
  153. package/dist/realtimeSessions/subscriptionAuthorization.d.ts +65 -0
  154. package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -0
  155. package/dist/realtimeSessions/subscriptionAuthorization.js +71 -0
  156. package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -0
  157. package/dist/realtimeSessions/verificationCore.d.ts +243 -0
  158. package/dist/realtimeSessions/verificationCore.d.ts.map +1 -0
  159. package/dist/realtimeSessions/verificationCore.js +356 -0
  160. package/dist/realtimeSessions/verificationCore.js.map +1 -0
  161. package/dist/realtimeSessions/verificationPages.d.ts +66 -0
  162. package/dist/realtimeSessions/verificationPages.d.ts.map +1 -0
  163. package/dist/realtimeSessions/verificationPages.js +110 -0
  164. package/dist/realtimeSessions/verificationPages.js.map +1 -0
  165. package/dist/realtimeSessions/verificationPolicy.d.ts +147 -0
  166. package/dist/realtimeSessions/verificationPolicy.d.ts.map +1 -0
  167. package/dist/realtimeSessions/verificationPolicy.js +249 -0
  168. package/dist/realtimeSessions/verificationPolicy.js.map +1 -0
  169. package/dist/realtimeSessions/verificationWorkflow.d.ts +263 -0
  170. package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -0
  171. package/dist/realtimeSessions/verificationWorkflow.js +435 -0
  172. package/dist/realtimeSessions/verificationWorkflow.js.map +1 -0
  173. package/dist/realtimeWidget/widgetGuestElevation.d.ts +20 -2
  174. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  175. package/dist/realtimeWidget/widgetGuestElevation.js +31 -2
  176. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  177. package/dist/resolvers/ActionResolver.d.ts +31 -5
  178. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  179. package/dist/resolvers/ActionResolver.js +75 -14
  180. package/dist/resolvers/ActionResolver.js.map +1 -1
  181. package/dist/resolvers/AdhocQueryResolver.d.ts +14 -1
  182. package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
  183. package/dist/resolvers/AdhocQueryResolver.js +21 -5
  184. package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
  185. package/dist/resolvers/ArtifactFileResolver.d.ts +5 -1
  186. package/dist/resolvers/ArtifactFileResolver.d.ts.map +1 -1
  187. package/dist/resolvers/ArtifactFileResolver.js +9 -7
  188. package/dist/resolvers/ArtifactFileResolver.js.map +1 -1
  189. package/dist/resolvers/CacheStatsResolver.d.ts +27 -0
  190. package/dist/resolvers/CacheStatsResolver.d.ts.map +1 -1
  191. package/dist/resolvers/CacheStatsResolver.js +113 -2
  192. package/dist/resolvers/CacheStatsResolver.js.map +1 -1
  193. package/dist/resolvers/ClientToolRequestResolver.d.ts +4 -2
  194. package/dist/resolvers/ClientToolRequestResolver.d.ts.map +1 -1
  195. package/dist/resolvers/ClientToolRequestResolver.js +28 -10
  196. package/dist/resolvers/ClientToolRequestResolver.js.map +1 -1
  197. package/dist/resolvers/ConversationRunEventsResolver.d.ts +8 -4
  198. package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
  199. package/dist/resolvers/ConversationRunEventsResolver.js +6 -6
  200. package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
  201. package/dist/resolvers/DatasetResolver.d.ts +24 -3
  202. package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
  203. package/dist/resolvers/DatasetResolver.js +57 -8
  204. package/dist/resolvers/DatasetResolver.js.map +1 -1
  205. package/dist/resolvers/EntityRecordNameResolver.d.ts +2 -1
  206. package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
  207. package/dist/resolvers/EntityRecordNameResolver.js +3 -2
  208. package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
  209. package/dist/resolvers/FetchEntityVectorsResolver.d.ts +27 -1
  210. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  211. package/dist/resolvers/FetchEntityVectorsResolver.js +148 -2
  212. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  213. package/dist/resolvers/FileResolver.d.ts +82 -11
  214. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  215. package/dist/resolvers/FileResolver.js +279 -101
  216. package/dist/resolvers/FileResolver.js.map +1 -1
  217. package/dist/resolvers/GetDataContextDataResolver.d.ts +33 -7
  218. package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
  219. package/dist/resolvers/GetDataContextDataResolver.js +117 -38
  220. package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
  221. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  222. package/dist/resolvers/GetDataResolver.js +6 -3
  223. package/dist/resolvers/GetDataResolver.js.map +1 -1
  224. package/dist/resolvers/HumanHandoffResolver.d.ts.map +1 -1
  225. package/dist/resolvers/HumanHandoffResolver.js +7 -1
  226. package/dist/resolvers/HumanHandoffResolver.js.map +1 -1
  227. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  228. package/dist/resolvers/IntegrationDiscoveryResolver.js +4 -2
  229. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  230. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  231. package/dist/resolvers/MCPResolver.js +9 -4
  232. package/dist/resolvers/MCPResolver.js.map +1 -1
  233. package/dist/resolvers/QueryResolver.d.ts +2 -0
  234. package/dist/resolvers/QueryResolver.d.ts.map +1 -1
  235. package/dist/resolvers/QueryResolver.js +13 -0
  236. package/dist/resolvers/QueryResolver.js.map +1 -1
  237. package/dist/resolvers/RealtimeBridgeResolver.d.ts +54 -2
  238. package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
  239. package/dist/resolvers/RealtimeBridgeResolver.js +155 -10
  240. package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
  241. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +157 -33
  242. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  243. package/dist/resolvers/RealtimeClientSessionResolver.js +404 -116
  244. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  245. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts +61 -0
  246. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts.map +1 -0
  247. package/dist/resolvers/RealtimeSessionEventsResolver.js +130 -0
  248. package/dist/resolvers/RealtimeSessionEventsResolver.js.map +1 -0
  249. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts +85 -0
  250. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts.map +1 -0
  251. package/dist/resolvers/RealtimeSessionVerificationResolver.js +188 -0
  252. package/dist/resolvers/RealtimeSessionVerificationResolver.js.map +1 -0
  253. package/dist/resolvers/RemoteBrowserActionResolver.d.ts +2 -0
  254. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  255. package/dist/resolvers/RemoteBrowserActionResolver.js +5 -1
  256. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  257. package/dist/resolvers/RunAIAgentResolver.d.ts +10 -0
  258. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  259. package/dist/resolvers/RunAIAgentResolver.js +100 -14
  260. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  261. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  262. package/dist/resolvers/RunTemplateResolver.js +12 -11
  263. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  264. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts +12 -1
  265. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts.map +1 -1
  266. package/dist/resolvers/SearchKnowledgeStreamResolver.js +15 -2
  267. package/dist/resolvers/SearchKnowledgeStreamResolver.js.map +1 -1
  268. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  269. package/dist/resolvers/SqlLoggingConfigResolver.js +2 -3
  270. package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
  271. package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
  272. package/dist/resolvers/SyncDataResolver.js +6 -2
  273. package/dist/resolvers/SyncDataResolver.js.map +1 -1
  274. package/dist/resolvers/SyncRolesUsersResolver.d.ts +2 -0
  275. package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
  276. package/dist/resolvers/SyncRolesUsersResolver.js +23 -6
  277. package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
  278. package/dist/resolvers/TaskGraphFrameResolver.d.ts +2 -1
  279. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
  280. package/dist/resolvers/TaskGraphFrameResolver.js +28 -1
  281. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
  282. package/dist/resolvers/TestQuerySQLResolver.d.ts +24 -0
  283. package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
  284. package/dist/resolvers/TestQuerySQLResolver.js +65 -13
  285. package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
  286. package/dist/resolvers/TransactionGroupResolver.d.ts +19 -2
  287. package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
  288. package/dist/resolvers/TransactionGroupResolver.js +102 -24
  289. package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
  290. package/dist/resolvers/UserAvatarResolver.d.ts +16 -0
  291. package/dist/resolvers/UserAvatarResolver.d.ts.map +1 -0
  292. package/dist/resolvers/UserAvatarResolver.js +124 -0
  293. package/dist/resolvers/UserAvatarResolver.js.map +1 -0
  294. package/dist/resolvers/UserResolver.d.ts.map +1 -1
  295. package/dist/resolvers/UserResolver.js +2 -17
  296. package/dist/resolvers/UserResolver.js.map +1 -1
  297. package/dist/resolvers/agent-run-data-guard.d.ts +31 -0
  298. package/dist/resolvers/agent-run-data-guard.d.ts.map +1 -0
  299. package/dist/resolvers/agent-run-data-guard.js +72 -0
  300. package/dist/resolvers/agent-run-data-guard.js.map +1 -0
  301. package/dist/resolvers/agentVisionConsentAudit.d.ts +37 -0
  302. package/dist/resolvers/agentVisionConsentAudit.d.ts.map +1 -0
  303. package/dist/resolvers/agentVisionConsentAudit.js +63 -0
  304. package/dist/resolvers/agentVisionConsentAudit.js.map +1 -0
  305. package/dist/resolvers/avatarInputValidation.d.ts +40 -0
  306. package/dist/resolvers/avatarInputValidation.d.ts.map +1 -0
  307. package/dist/resolvers/avatarInputValidation.js +97 -0
  308. package/dist/resolvers/avatarInputValidation.js.map +1 -0
  309. package/dist/resolvers/currentUserRoles.d.ts +29 -0
  310. package/dist/resolvers/currentUserRoles.d.ts.map +1 -1
  311. package/dist/resolvers/currentUserRoles.js +30 -0
  312. package/dist/resolvers/currentUserRoles.js.map +1 -1
  313. package/dist/resolvers/meetings/meetingMutations.d.ts +6 -0
  314. package/dist/resolvers/meetings/meetingMutations.d.ts.map +1 -1
  315. package/dist/resolvers/meetings/meetingMutations.js +21 -0
  316. package/dist/resolvers/meetings/meetingMutations.js.map +1 -1
  317. package/dist/rest/RealtimeRecordingHandler.d.ts +49 -0
  318. package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -0
  319. package/dist/rest/RealtimeRecordingHandler.js +383 -0
  320. package/dist/rest/RealtimeRecordingHandler.js.map +1 -0
  321. package/dist/rest/ViewOperationsHandler.d.ts +3 -1
  322. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  323. package/dist/rest/ViewOperationsHandler.js +21 -12
  324. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  325. package/dist/rest/setupRESTEndpoints.d.ts +6 -0
  326. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  327. package/dist/rest/setupRESTEndpoints.js +6 -0
  328. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  329. package/dist/serverExtensionReservedRoots.d.ts +12 -10
  330. package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
  331. package/dist/serverExtensionReservedRoots.js +14 -17
  332. package/dist/serverExtensionReservedRoots.js.map +1 -1
  333. package/dist/services/MJStorageBlobStore.d.ts +8 -1
  334. package/dist/services/MJStorageBlobStore.d.ts.map +1 -1
  335. package/dist/services/MJStorageBlobStore.js +25 -19
  336. package/dist/services/MJStorageBlobStore.js.map +1 -1
  337. package/dist/services/StartTaskGraphDispatcher.js +2 -2
  338. package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
  339. package/dist/services/TaskGraphActionRunner.d.ts +5 -3
  340. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  341. package/dist/services/TaskGraphActionRunner.js +27 -5
  342. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  343. package/dist/services/TaskGraphAgentRunner.d.ts +14 -2
  344. package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
  345. package/dist/services/TaskGraphAgentRunner.js +157 -9
  346. package/dist/services/TaskGraphAgentRunner.js.map +1 -1
  347. package/dist/services/TaskGraphContinuationDeliverer.d.ts +57 -4
  348. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  349. package/dist/services/TaskGraphContinuationDeliverer.js +607 -18
  350. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  351. package/dist/sharedCache.d.ts +105 -0
  352. package/dist/sharedCache.d.ts.map +1 -0
  353. package/dist/sharedCache.js +279 -0
  354. package/dist/sharedCache.js.map +1 -0
  355. package/dist/types.d.ts +6 -0
  356. package/dist/types.d.ts.map +1 -1
  357. package/dist/types.js.map +1 -1
  358. package/package.json +99 -96
  359. package/src/__tests__/ActionResolver.authorization.test.ts +353 -0
  360. package/src/__tests__/AdhocQueryResolver.sqlAuthorizer.test.ts +104 -0
  361. package/src/__tests__/BridgeHostInstance.test.ts +232 -0
  362. package/src/__tests__/ClientToolRequestResolver.test.ts +116 -0
  363. package/src/__tests__/DatasetResolver.itemFilters.test.ts +201 -0
  364. package/src/__tests__/EntityRecordNameResolver.rowSecurity.test.ts +152 -0
  365. package/src/__tests__/FetchEntityVectorsResolver.test.ts +433 -0
  366. package/src/__tests__/FileResolver.storageAccess.test.ts +562 -0
  367. package/src/__tests__/GetDataContextDataResolver.sqlItems.test.ts +416 -0
  368. package/src/__tests__/HostInstance.test.ts +84 -0
  369. package/src/__tests__/HumanHandoffResolver.test.ts +17 -0
  370. package/src/__tests__/ListOperationsResolver.adhocScreen.test.ts +137 -0
  371. package/src/__tests__/LoginScreenEngine.test.ts +86 -0
  372. package/src/__tests__/MJStorageBlobStore.storageGate.test.ts +63 -0
  373. package/src/__tests__/MeetingResolver.test.ts +75 -1
  374. package/src/__tests__/RealtimeBridgeResolver.test.ts +415 -6
  375. package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +383 -0
  376. package/src/__tests__/RealtimeClientSessionResolver.test.ts +682 -58
  377. package/src/__tests__/RealtimeProxyServer.test.ts +16 -1
  378. package/src/__tests__/RealtimeRelay.test.ts +876 -0
  379. package/src/__tests__/RecordingAssemblyScheduler.test.ts +178 -0
  380. package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +129 -0
  381. package/src/__tests__/ResolverBase.adhocReadScope.test.ts +133 -2
  382. package/src/__tests__/ResolverBase.aggregateScreen.test.ts +174 -0
  383. package/src/__tests__/ResolverBase.balancedClause.test.ts +155 -0
  384. package/src/__tests__/ResolverBase.clauseUnscopedRead.test.ts +127 -0
  385. package/src/__tests__/ResolverBase.clientOldValues.test.ts +212 -6
  386. package/src/__tests__/ResolverBase.filterEscaping.test.ts +5 -2
  387. package/src/__tests__/ReturningVisitorRecap.test.ts +115 -0
  388. package/src/__tests__/RunAIAgentResolver.branch.test.ts +170 -0
  389. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +6 -4
  390. package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +258 -0
  391. package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +166 -0
  392. package/src/__tests__/RunTemplateResolver.test.ts +132 -0
  393. package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +63 -0
  394. package/src/__tests__/RunViewResolver.cacheCheckScreen.test.ts +165 -0
  395. package/src/__tests__/SearchKnowledgeStreamResolver.test.ts +161 -0
  396. package/src/__tests__/SessionJanitor.test.ts +1203 -21
  397. package/src/__tests__/SessionManager.test.ts +240 -17
  398. package/src/__tests__/SessionRunIDVerifier.test.ts +251 -0
  399. package/src/__tests__/SyncRolesUsersResolver.userRoles.test.ts +97 -0
  400. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +25 -0
  401. package/src/__tests__/TaskGraphAgentRunner.test.ts +266 -0
  402. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +403 -22
  403. package/src/__tests__/TaskGraphFrameResolver.test.ts +22 -0
  404. package/src/__tests__/TestQuerySQLResolver.test.ts +274 -0
  405. package/src/__tests__/TransactionGroupResolver.refusals.test.ts +98 -1
  406. package/src/__tests__/UpdateMJDataContextItem.oldValues.test.ts +220 -0
  407. package/src/__tests__/UserAvatarResolver.test.ts +255 -0
  408. package/src/__tests__/UserResolver.currentUser.test.ts +16 -1
  409. package/src/__tests__/ViewOperationsHandler.clauseScreen.test.ts +157 -0
  410. package/src/__tests__/actionAuthorization.test.ts +130 -0
  411. package/src/__tests__/agent-run-data-guard.test.ts +130 -0
  412. package/src/__tests__/agentVisionConsentAudit.test.ts +118 -0
  413. package/src/__tests__/apiRootBoot.test.ts +202 -0
  414. package/src/__tests__/avatarInputValidation.test.ts +160 -0
  415. package/src/__tests__/cacheInvalidationRecordData.test.ts +64 -0
  416. package/src/__tests__/conversationRunEvents.test.ts +56 -14
  417. package/src/__tests__/globalCors.test.ts +217 -0
  418. package/src/__tests__/isolatedProviderTransactions.test.ts +169 -0
  419. package/src/__tests__/magicLinkService.consume.test.ts +6 -0
  420. package/src/__tests__/magicLinkService.provisionLog.test.ts +5 -0
  421. package/src/__tests__/multiTenancy.postgresRewrite.test.ts +181 -0
  422. package/src/__tests__/multiTenancy.security.test.ts +51 -0
  423. package/src/__tests__/multiTenancy.test.ts +1 -1
  424. package/src/__tests__/newUsers.template.test.ts +151 -0
  425. package/src/__tests__/newUsers.test.ts +74 -5
  426. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +17 -2
  427. package/src/__tests__/ownedRealtimeSession.test.ts +39 -0
  428. package/src/__tests__/pushStatusResolver.filter.test.ts +7 -0
  429. package/src/__tests__/realtimeRecordingHandler.test.ts +652 -0
  430. package/src/__tests__/realtimeSessions/RealtimeSessionEventService.test.ts +201 -0
  431. package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +215 -0
  432. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationResolver.test.ts +102 -0
  433. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationService.test.ts +349 -0
  434. package/src/__tests__/realtimeSessions/RealtimeVerifyRouter.test.ts +131 -0
  435. package/src/__tests__/realtimeSessions/SlidingWindowRateLimiter.test.ts +56 -0
  436. package/src/__tests__/realtimeSessions/helpers.ts +4 -0
  437. package/src/__tests__/realtimeSessions/sessionAccess.test.ts +129 -0
  438. package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +124 -0
  439. package/src/__tests__/realtimeSessions/verificationCore.test.ts +355 -0
  440. package/src/__tests__/realtimeSessions/verificationPages.test.ts +84 -0
  441. package/src/__tests__/realtimeSessions/verificationPolicy.test.ts +226 -0
  442. package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +633 -0
  443. package/src/__tests__/resolverBase.fls.test.ts +87 -4
  444. package/src/__tests__/serverExtensionHostOverlay.test.ts +66 -0
  445. package/src/__tests__/serverExtensionReservedRoots.test.ts +11 -96
  446. package/src/__tests__/sharedCache.test.ts +312 -0
  447. package/src/__tests__/widgetGuestElevation.test.ts +44 -0
  448. package/src/agentSessions/BridgeHostInstance.ts +32 -0
  449. package/src/agentSessions/HostInstance.ts +124 -28
  450. package/src/agentSessions/ReturningVisitorRecap.ts +7 -3
  451. package/src/agentSessions/SessionJanitor.ts +821 -59
  452. package/src/agentSessions/SessionManager.ts +138 -26
  453. package/src/agentSessions/SessionRunIDVerifier.ts +171 -0
  454. package/src/agentSessions/index.ts +10 -3
  455. package/src/apiRoot.ts +78 -0
  456. package/src/auth/AuthProviderCatalogRouter.ts +26 -0
  457. package/src/auth/LoginScreenEngine.ts +50 -0
  458. package/src/auth/actionAuthorization.ts +116 -0
  459. package/src/auth/index.ts +4 -8
  460. package/src/auth/magicLink/MagicLinkRouter.ts +3 -2
  461. package/src/auth/magicLink/MagicLinkService.ts +6 -3
  462. package/src/auth/newUsers.ts +99 -11
  463. package/src/config.ts +171 -5
  464. package/src/context.ts +15 -10
  465. package/src/coreRoutes.ts +166 -0
  466. package/src/generated/graphql-schemas/__mj.ts +1815 -57
  467. package/src/generic/CacheInvalidationResolver.ts +73 -18
  468. package/src/generic/OrphanedConversationDetailReconciler.ts +3 -3
  469. package/src/generic/PushStatusResolver.ts +1 -1
  470. package/src/generic/ResolverBase.ts +335 -326
  471. package/src/generic/RunViewResolver.ts +21 -0
  472. package/src/globalCors.ts +71 -0
  473. package/src/index.ts +231 -300
  474. package/src/isolatedProvider.ts +22 -0
  475. package/src/multiTenancy/index.ts +24 -2
  476. package/src/realtimeProxy/RealtimeProxyServer.ts +148 -16
  477. package/src/realtimeProxy/RealtimeRelayTunnel.ts +645 -0
  478. package/src/realtimeSessions/README.md +179 -0
  479. package/src/realtimeSessions/RealtimeSessionEventService.ts +274 -0
  480. package/src/realtimeSessions/RealtimeSessionVerificationService.ts +168 -0
  481. package/src/realtimeSessions/RealtimeVerifyRouter.ts +109 -0
  482. package/src/realtimeSessions/RecordingAssemblyScheduler.ts +234 -0
  483. package/src/realtimeSessions/SessionVerificationPortsBase.ts +189 -0
  484. package/src/realtimeSessions/SlidingWindowRateLimiter.ts +92 -0
  485. package/src/realtimeSessions/index.ts +18 -0
  486. package/src/realtimeSessions/ownedRealtimeSession.ts +55 -0
  487. package/src/realtimeSessions/sessionAccess.ts +145 -0
  488. package/src/realtimeSessions/sessionConfigStamps.ts +123 -0
  489. package/src/realtimeSessions/subscriptionAuthorization.ts +116 -0
  490. package/src/realtimeSessions/verificationCore.ts +502 -0
  491. package/src/realtimeSessions/verificationPages.ts +149 -0
  492. package/src/realtimeSessions/verificationPolicy.ts +321 -0
  493. package/src/realtimeSessions/verificationWorkflow.ts +702 -0
  494. package/src/realtimeWidget/widgetGuestElevation.ts +34 -2
  495. package/src/resolvers/ActionResolver.ts +84 -21
  496. package/src/resolvers/AdhocQueryResolver.ts +24 -6
  497. package/src/resolvers/ArtifactFileResolver.ts +9 -8
  498. package/src/resolvers/CacheStatsResolver.ts +89 -2
  499. package/src/resolvers/ClientToolRequestResolver.ts +25 -7
  500. package/src/resolvers/ConversationRunEventsResolver.ts +15 -11
  501. package/src/resolvers/DatasetResolver.ts +70 -10
  502. package/src/resolvers/EntityRecordNameResolver.ts +3 -2
  503. package/src/resolvers/FetchEntityVectorsResolver.ts +179 -2
  504. package/src/resolvers/FileResolver.ts +321 -106
  505. package/src/resolvers/GetDataContextDataResolver.ts +139 -41
  506. package/src/resolvers/GetDataResolver.ts +6 -3
  507. package/src/resolvers/HumanHandoffResolver.ts +8 -0
  508. package/src/resolvers/IntegrationDiscoveryResolver.ts +4 -2
  509. package/src/resolvers/MCPResolver.ts +8 -5
  510. package/src/resolvers/QueryResolver.ts +11 -0
  511. package/src/resolvers/RealtimeBridgeResolver.ts +163 -11
  512. package/src/resolvers/RealtimeClientSessionResolver.ts +511 -129
  513. package/src/resolvers/RealtimeSessionEventsResolver.ts +133 -0
  514. package/src/resolvers/RealtimeSessionVerificationResolver.ts +174 -0
  515. package/src/resolvers/RemoteBrowserActionResolver.ts +11 -1
  516. package/src/resolvers/RunAIAgentResolver.ts +116 -14
  517. package/src/resolvers/RunTemplateResolver.ts +13 -12
  518. package/src/resolvers/SearchKnowledgeStreamResolver.ts +19 -3
  519. package/src/resolvers/SqlLoggingConfigResolver.ts +2 -4
  520. package/src/resolvers/SyncDataResolver.ts +6 -2
  521. package/src/resolvers/SyncRolesUsersResolver.ts +24 -6
  522. package/src/resolvers/TaskGraphFrameResolver.ts +33 -1
  523. package/src/resolvers/TestQuerySQLResolver.ts +68 -13
  524. package/src/resolvers/TransactionGroupResolver.ts +131 -27
  525. package/src/resolvers/UserAvatarResolver.ts +111 -0
  526. package/src/resolvers/UserResolver.ts +2 -16
  527. package/src/resolvers/__tests__/GetDataResolver.validation.test.ts +95 -0
  528. package/src/resolvers/agent-run-data-guard.ts +89 -0
  529. package/src/resolvers/agentVisionConsentAudit.ts +82 -0
  530. package/src/resolvers/avatarInputValidation.ts +123 -0
  531. package/src/resolvers/currentUserRoles.ts +32 -1
  532. package/src/resolvers/meetings/meetingMutations.ts +21 -0
  533. package/src/rest/RealtimeRecordingHandler.ts +464 -0
  534. package/src/rest/ViewOperationsHandler.ts +29 -13
  535. package/src/rest/setupRESTEndpoints.ts +6 -0
  536. package/src/serverExtensionReservedRoots.ts +14 -17
  537. package/src/services/MJStorageBlobStore.ts +31 -30
  538. package/src/services/StartTaskGraphDispatcher.ts +2 -2
  539. package/src/services/TaskGraphActionRunner.ts +25 -5
  540. package/src/services/TaskGraphAgentRunner.ts +188 -11
  541. package/src/services/TaskGraphContinuationDeliverer.ts +713 -17
  542. package/src/sharedCache.ts +305 -0
  543. package/src/types.ts +7 -0
@@ -0,0 +1,116 @@
1
+ import { AuthorizationInfo, AuthorizationRoleInfo, AuthorizationRoleType, IMetadataProvider, UserInfo } from '@memberjunction/core';
2
+ import { FilterByUUIDs, IndexByUUID, NormalizeUUID, UUIDMap, UUIDsEqual } from '@memberjunction/global';
3
+
4
+ /** The outcome of {@link EvaluateActionRunAuthorization}. */
5
+ export interface ActionRunAuthorization {
6
+ /** True when the user may run the action. */
7
+ Allowed: boolean;
8
+ /** Why the run is allowed or refused. */
9
+ Reason: string;
10
+ }
11
+
12
+ /** One provider's authorization tree and the role grants on it. */
13
+ export type AuthorizationMetadata = Pick<IMetadataProvider, 'Authorizations' | 'AuthorizationRoles'>;
14
+
15
+ /**
16
+ * True when the user is an Owner, MJ's superuser type. The column is nchar, so the stored value is
17
+ * padded.
18
+ */
19
+ export function IsOwner(user: UserInfo): boolean {
20
+ return user.Type?.trim().toLowerCase() === 'owner';
21
+ }
22
+
23
+ /**
24
+ * Decides whether a user may run an action through a public entry point such as the `RunAction`
25
+ * mutation. It fails closed:
26
+ *
27
+ * - An Owner may run any action.
28
+ * - An action with `MJ: Action Authorizations` rows runs for a user who holds at least one of the
29
+ * linked authorizations. A linked authorization counts only when it is active and none of the
30
+ * user's roles is denied it; the user may then hold it directly or through an ancestor.
31
+ * - An action with no such rows runs for any user when its class authorizes its caller itself
32
+ * (`BaseAction.AuthorizesCaller`), so the action's own check decides. Otherwise it runs for
33
+ * Owners only.
34
+ *
35
+ * The authorizations, their parents and their role grants are read only from `metadata`, never
36
+ * from the global provider. Pass the provider the `MJ: Action Authorizations` rows were read from.
37
+ *
38
+ * Refuse scope-limited sessions before calling this; see `IsScopeLimitedPrincipal`.
39
+ *
40
+ * @param user the caller
41
+ * @param actionAuthorizationIDs the AuthorizationID of each `MJ: Action Authorizations` row for the action
42
+ * @param metadata the provider whose authorizations and role grants decide
43
+ * @param actionAuthorizesCaller true when the action's class authorizes its caller itself
44
+ * @returns whether the run is allowed, and why
45
+ */
46
+ export function EvaluateActionRunAuthorization(
47
+ user: UserInfo,
48
+ actionAuthorizationIDs: readonly string[],
49
+ metadata: AuthorizationMetadata,
50
+ actionAuthorizesCaller: boolean
51
+ ): ActionRunAuthorization {
52
+ if (IsOwner(user)) {
53
+ return { Allowed: true, Reason: 'The user is an Owner.' };
54
+ }
55
+ if (actionAuthorizationIDs.length === 0) {
56
+ return actionAuthorizesCaller
57
+ ? { Allowed: true, Reason: 'The action authorizes its caller itself.' }
58
+ : { Allowed: false, Reason: 'No Action Authorization grants this action to any role, and the action does not authorize its caller itself; only an Owner may run it.' };
59
+ }
60
+ const authorizationsByID = IndexByUUID(metadata.Authorizations);
61
+ const userGrants = grantsToUserRoles(user, metadata.AuthorizationRoles);
62
+ const granted = actionAuthorizationIDs
63
+ .map((id) => authorizationsByID.Get(id))
64
+ .filter((auth): auth is AuthorizationInfo => auth !== undefined)
65
+ .find((auth) => holdsLinkedAuthorization(auth, authorizationsByID, userGrants));
66
+ return granted
67
+ ? { Allowed: true, Reason: `The user holds the "${granted.Name}" authorization.` }
68
+ : { Allowed: false, Reason: 'None of your roles holds an authorization this action requires.' };
69
+ }
70
+
71
+ /** The role grants that name one of the user's roles. */
72
+ function grantsToUserRoles(user: UserInfo, grants: readonly AuthorizationRoleInfo[]): AuthorizationRoleInfo[] {
73
+ const userRoleIDs = (user.UserRoles ?? []).map((userRole) => userRole.RoleID);
74
+ return FilterByUUIDs(grants, userRoleIDs, (grant) => grant.RoleID);
75
+ }
76
+
77
+ /**
78
+ * True when the user holds a linked authorization: it is active, none of the user's roles is denied
79
+ * it, and the user holds it directly or through an ancestor. The first two are checked on the linked
80
+ * authorization itself, because the ancestor walk would otherwise grant it through the parent.
81
+ */
82
+ function holdsLinkedAuthorization(auth: AuthorizationInfo, authorizationsByID: UUIDMap<AuthorizationInfo>, userGrants: readonly AuthorizationRoleInfo[]): boolean {
83
+ if (!auth.IsActive || grantTypes(auth, userGrants).includes(AuthorizationRoleType.Deny)) {
84
+ return false;
85
+ }
86
+ return holdsDirectlyOrThroughAncestor(auth, authorizationsByID, userGrants);
87
+ }
88
+
89
+ /**
90
+ * True when the user holds the authorization or one of its ancestors, following `ParentID` within
91
+ * `authorizationsByID`. This is the walk `AuthorizationEvaluator.UserCanExecuteWithAncestors` does,
92
+ * with the role grants taken from the same provider as the authorizations.
93
+ */
94
+ function holdsDirectlyOrThroughAncestor(auth: AuthorizationInfo, authorizationsByID: UUIDMap<AuthorizationInfo>, userGrants: readonly AuthorizationRoleInfo[]): boolean {
95
+ const visited = new Set<string>();
96
+ let node: AuthorizationInfo | undefined = auth;
97
+ while (node && !visited.has(NormalizeUUID(node.ID))) {
98
+ if (holdsDirectly(node, userGrants)) {
99
+ return true;
100
+ }
101
+ visited.add(NormalizeUUID(node.ID));
102
+ node = node.ParentID ? authorizationsByID.Get(node.ParentID) : undefined;
103
+ }
104
+ return false;
105
+ }
106
+
107
+ /** True when the authorization is active and the user's roles have an Allow and no Deny on it. */
108
+ function holdsDirectly(auth: AuthorizationInfo, userGrants: readonly AuthorizationRoleInfo[]): boolean {
109
+ const types = grantTypes(auth, userGrants);
110
+ return auth.IsActive && types.includes(AuthorizationRoleType.Allow) && !types.includes(AuthorizationRoleType.Deny);
111
+ }
112
+
113
+ /** Allow or Deny, for each of the user's role grants on the authorization. */
114
+ function grantTypes(auth: AuthorizationInfo, userGrants: readonly AuthorizationRoleInfo[]): AuthorizationRoleType[] {
115
+ return userGrants.filter((grant) => UUIDsEqual(grant.AuthorizationID, auth.ID)).map((grant) => grant.AuthorizationType());
116
+ }
package/src/auth/index.ts CHANGED
@@ -13,6 +13,7 @@ export * from './APIKeyScopeAuth.js';
13
13
  export * from './scopeLimitedPrincipal.js';
14
14
  export * from './actingContextResolver.js';
15
15
  export * from './AuthProviderEngine.js';
16
+ export * from './LoginScreenEngine.js';
16
17
  export * from './AuthProviderCatalogRouter.js';
17
18
  export { InitializeAuthProviders, initializeAuthProviders, InitializeAuthProvidersFromMetadata, initializeAuthProvidersFromMetadata, RefreshAuthProviders, refreshAuthProviders, ValidateAuthProvidersRegistered, validateAuthProvidersRegistered } from './initializeProviders.js';
18
19
 
@@ -253,14 +254,9 @@ export const VerifyUserRecord = async (
253
254
  ): Promise<UserInfo | undefined> => {
254
255
  if (!email) return undefined;
255
256
 
256
- let user = UserCache.Instance.Users.find((u) => {
257
- if (!u.Email || u.Email.trim() === '') {
258
- // this condition should never occur. If it doesn throw a console error including the user id
259
- // DB requires non-null but this is just an extra check and we could in theory have a blank string in the DB
260
- console.error(`SYSTEM METADATA ISSUE: User ${u.ID} has no email address`);
261
- return false;
262
- } else return u.Email.toLowerCase().trim() === email.toLowerCase().trim();
263
- });
257
+ // FindUser, not Users.find: a user this process has not loaded yet (created seconds ago on
258
+ // another server) is looked up in the database instead of being treated as nonexistent.
259
+ let user = await UserCache.Instance.FindUser({ Email: email });
264
260
 
265
261
  if (!user) {
266
262
  // NOTE: `requestDomain` (parsed from the spoofable `Origin` header) is deliberately NOT part of
@@ -17,6 +17,7 @@ import { MagicLinkKeyManager } from './MagicLinkKeys.js';
17
17
  import { MagicLinkService } from './MagicLinkService.js';
18
18
  import { BuildRedeemLandingHtml } from './redeemLanding.js';
19
19
  import type { CreateMagicLinkInviteParams, RedeemMagicLinkResult } from './types.js';
20
+ import { ApiRoute } from '../../apiRoot.js';
20
21
 
21
22
  /** The mount path for both routers (`/magic-link`). */
22
23
  export const MAGIC_LINK_MOUNT_PATH = '/magic-link';
@@ -107,13 +108,13 @@ export function CreateMagicLinkHandler(publicUrl: string, config: MagicLinkConfi
107
108
  }
108
109
  // API callers must POST — GET never redeems.
109
110
  if (req.query.format === 'json') {
110
- res.status(405).json({ success: false, error: 'Redemption requires POST.', method: 'POST', path: `${MAGIC_LINK_MOUNT_PATH}/redeem` });
111
+ res.status(405).json({ success: false, error: 'Redemption requires POST.', method: 'POST', path: ApiRoute(`${MAGIC_LINK_MOUNT_PATH}/redeem`) });
111
112
  return;
112
113
  }
113
114
  res
114
115
  .status(200)
115
116
  .type('html')
116
- .send(BuildRedeemLandingHtml(token, `${MAGIC_LINK_MOUNT_PATH}/redeem`));
117
+ .send(BuildRedeemLandingHtml(token, ApiRoute(`${MAGIC_LINK_MOUNT_PATH}/redeem`)));
117
118
  });
118
119
 
119
120
  // POST /redeem performs the actual (side-effectful) redemption. Token arrives
@@ -34,6 +34,7 @@ import { ResolveConfiguredPrincipal } from '../principals.js';
34
34
  import { CommunicationEngine } from '@memberjunction/communication-engine';
35
35
  import { Message } from '@memberjunction/communication-types';
36
36
  import { configInfo, type MagicLinkConfig } from '../../config.js';
37
+ import { CreateIsolatedProvider } from '../../isolatedProvider.js';
37
38
  import { MagicLinkKeyManager } from './MagicLinkKeys.js';
38
39
  import { GenerateRawToken, GenerateSessionId, HashToken, EvaluateInvite, BuildSessionClaims, BuildConsumeInvitePostgresSQL, CanIssueInvites, IsRoleGrantable, MAGIC_LINK_TOKEN_PREFIX } from './magicLinkCore.js';
39
40
  import type {
@@ -521,9 +522,11 @@ export class MagicLinkService {
521
522
  /** Creates a new user with exactly the restricted role + single app, transactionally. */
522
523
  private async createScopedUser(invite: MJMagicLinkInviteEntity, role: RoleInfo, contextUser: UserInfo): Promise<ProvisionResult> {
523
524
  // Single provider for BOTH the transaction and the entity writes, so the
524
- // BeginTransaction/Save/Commit are provably on the same connection.
525
- // global-provider-ok: redemption runs in the pre-auth flow, no per-request provider yet.
526
- const provider = Metadata.Provider as DatabaseProviderBase; // global-provider-ok: server-side magic-link service; runs under the server's single default provider
525
+ // BeginTransaction/Save/Commit are provably on the same connection. Redemption runs
526
+ // pre-auth, with no per-request provider yet, and the global Metadata.Provider is shared
527
+ // by every concurrent request: a transaction opened there nests into anyone else's and
528
+ // swallows their writes. So it gets its own (see CreateIsolatedProvider).
529
+ const provider = await CreateIsolatedProvider();
527
530
  const email = invite.Email;
528
531
  // The invite does not persist a name; provision a sensible default. (The
529
532
  // create-invite params accept first/last name but there is no column to
@@ -1,7 +1,9 @@
1
- import { ApplicationInfo, DatabaseProviderBase, EntitySaveOptions, LogError, LogStatus, Metadata, RunView, RunViewResult, UserInfo } from "@memberjunction/core";
1
+ import { ApplicationInfo, CompositeKey, EntitySaveOptions, IMetadataProvider, LogError, LogStatus, RunView, RunViewResult, UserInfo } from "@memberjunction/core";
2
+ import { RecordCloneEngine } from "@memberjunction/record-cloning";
2
3
  import { RegisterClass } from "@memberjunction/global";
3
4
  import { ResolveConfiguredPrincipal } from "./principals.js";
4
5
  import { configInfo } from "../config.js";
6
+ import { CreateIsolatedProvider } from "../isolatedProvider.js";
5
7
  import { MJUserEntity, MJUserRoleEntity, MJUserApplicationEntity, MJUserApplicationEntityEntity, MJApplicationEntityType, MJApplicationEntityEntityType, UserInfoEngine } from "@memberjunction/core-entities";
6
8
 
7
9
  export class NewUserBase {
@@ -16,8 +18,21 @@ export class NewUserBase {
16
18
  return null;
17
19
  }
18
20
 
19
- const md: Metadata = new Metadata(); // global-provider-ok: new-user creation runs in the JWT auth flow, before AppContext.providers is built
20
- const user = await md.GetEntityObject<MJUserEntity>('MJ: Users', contextUser) // To-Do - change this to be a different defined user for the user creation process
21
+ // Everything here, metadata lookups, entity objects and the transaction, goes through ONE
22
+ // isolated provider. This runs in the JWT auth flow, before AppContext.providers exists, and
23
+ // the global Metadata.Provider is shared by every concurrent request: a transaction opened
24
+ // there nests into anyone else's and swallows their writes (see CreateIsolatedProvider).
25
+ const provider = await CreateIsolatedProvider();
26
+
27
+ // A configured template user is copied whole; a plain user is created only if it can't be.
28
+ const template = configInfo?.userHandling?.newUserTemplate;
29
+ if (template?.email) {
30
+ const fromTemplate = await this.createFromTemplate(provider, contextUser, template.email, template.preset, firstName, lastName, email, linkedRecordType, linkedEntityId, linkedEntityRecordId);
31
+ if (fromTemplate) return fromTemplate;
32
+ LogError(`Could not create ${email} from template user ${template.email}; creating a plain user instead`);
33
+ }
34
+
35
+ const user = await provider.GetEntityObject<MJUserEntity>('MJ: Users', contextUser) // To-Do - change this to be a different defined user for the user creation process
21
36
  user.NewRecord();
22
37
  user.Name = email;
23
38
  user.IsActive = true;
@@ -38,7 +53,6 @@ export class NewUserBase {
38
53
  // Create the user and all of its role/application/app-entity records atomically.
39
54
  // If any Save fails partway through, the whole provisioning rolls back so we never
40
55
  // leave a half-created user with partial roles/applications behind.
41
- const provider = Metadata.Provider as DatabaseProviderBase; // global-provider-ok: new-user creation runs in the JWT auth flow, before AppContext.providers is built
42
56
  await provider.BeginTransaction();
43
57
  try {
44
58
  if (!await user.Save()) {
@@ -48,13 +62,13 @@ export class NewUserBase {
48
62
  if(configInfo.userHandling && configInfo.userHandling.newUserRoles){
49
63
  LogStatus(`User ${user.Email} created, assigning roles`);
50
64
  for (const role of configInfo.userHandling.newUserRoles) {
51
- const userRole = md.Roles.find(r => r.Name === role);
65
+ const userRole = provider.Roles.find(r => r.Name === role);
52
66
  if (!userRole) {
53
67
  LogError(`Role ${role} not found in the database, cannot assign to new user ${user.Name}`);
54
68
  continue;
55
69
  }
56
70
 
57
- const userRoleEntity: MJUserRoleEntity = await md.GetEntityObject<MJUserRoleEntity>('MJ: User Roles', contextUser);
71
+ const userRoleEntity: MJUserRoleEntity = await provider.GetEntityObject<MJUserRoleEntity>('MJ: User Roles', contextUser);
58
72
  userRoleEntity.NewRecord();
59
73
  userRoleEntity.UserID = user.ID;
60
74
  userRoleEntity.RoleID = userRole.ID;
@@ -73,7 +87,7 @@ export class NewUserBase {
73
87
  if (configInfo.userHandling.UserApplications && configInfo.userHandling.UserApplications.length > 0) {
74
88
  for (const appName of configInfo.userHandling.UserApplications) {
75
89
  const toLowerCase: string = appName.trim().toLocaleLowerCase();
76
- const application: ApplicationInfo | undefined = md.Applications.find(a => a.Name.trim().toLocaleLowerCase() === toLowerCase);
90
+ const application: ApplicationInfo | undefined = provider.Applications.find(a => a.Name.trim().toLocaleLowerCase() === toLowerCase);
77
91
  if (application) {
78
92
  applicationsToCreate.push(application);
79
93
  } else {
@@ -85,12 +99,12 @@ export class NewUserBase {
85
99
  // Bug F2: use the shared selector, which filters to Active apps flagged
86
100
  // DefaultForNewUser (in DefaultSequence order). This path previously omitted the
87
101
  // Status = 'Active' check, so an inactive default app could be provisioned here.
88
- applicationsToCreate = UserInfoEngine.GetDefaultApplicationsForNewUser(md);
102
+ applicationsToCreate = UserInfoEngine.GetDefaultApplicationsForNewUser(provider);
89
103
  LogStatus(`Found ${applicationsToCreate.length} active applications with DefaultForNewUser=true`);
90
104
  }
91
105
 
92
106
  for (const [appIndex, application] of applicationsToCreate.entries()) {
93
- const userApplication: MJUserApplicationEntity = await md.GetEntityObject<MJUserApplicationEntity>('MJ: User Applications', contextUser);
107
+ const userApplication: MJUserApplicationEntity = await provider.GetEntityObject<MJUserApplicationEntity>('MJ: User Applications', contextUser);
94
108
  userApplication.NewRecord();
95
109
  userApplication.UserID = user.ID;
96
110
  userApplication.ApplicationID = application.ID;
@@ -102,7 +116,7 @@ export class NewUserBase {
102
116
  }
103
117
  LogStatus(`Created User Application ${application.Name} for new user ${user.Name}`);
104
118
 
105
- const rv: RunView = new RunView();
119
+ const rv: RunView = RunView.FromMetadataProvider(provider);
106
120
  // Boolean literal goes through the active provider's dialect:
107
121
  // SQL Server emits `= 1`, PostgreSQL emits `= TRUE`.
108
122
  // This keeps the filter server-side (no client-side `.filter()`
@@ -125,7 +139,7 @@ export class NewUserBase {
125
139
  LogStatus(`Creating ${defaultForNewUserEntities.length} User Application Entities for User Application ${application.Name} for new user ${user.Name}`);
126
140
 
127
141
  for(const [index, appEntity] of defaultForNewUserEntities.entries()){
128
- const userAppEntity: MJUserApplicationEntityEntity = await md.GetEntityObject<MJUserApplicationEntityEntity>('MJ: User Application Entities', contextUser);
142
+ const userAppEntity: MJUserApplicationEntityEntity = await provider.GetEntityObject<MJUserApplicationEntityEntity>('MJ: User Application Entities', contextUser);
129
143
  userAppEntity.NewRecord();
130
144
  userAppEntity.UserApplicationID = userApplication.ID;
131
145
  userAppEntity.EntityID = appEntity.EntityID;
@@ -153,4 +167,78 @@ export class NewUserBase {
153
167
  return undefined;
154
168
  }
155
169
  }
170
+
171
+ /**
172
+ * Creates the new user as a copy of the template user `templateEmail`, through the `MJ: Users`
173
+ * clone `preset`: its roles, apps, views, settings, dashboards and conversations come with it, owned
174
+ * by the new user. The clone engine creates users inactive for review; a user signing in is active.
175
+ *
176
+ * @returns the new user, or null when the template is missing, isn't flagged IsTemplate, or the copy
177
+ * fails (the reason is logged and the caller falls back to a plain user).
178
+ */
179
+ protected async createFromTemplate(
180
+ provider: IMetadataProvider,
181
+ contextUser: UserInfo,
182
+ templateEmail: string,
183
+ preset: string,
184
+ firstName: string,
185
+ lastName: string,
186
+ email: string,
187
+ linkedRecordType: string,
188
+ linkedEntityId?: string,
189
+ linkedEntityRecordId?: string
190
+ ): Promise<MJUserEntity | null> {
191
+ const lookup = await RunView.FromMetadataProvider(provider).RunView<{ ID: string; IsTemplate: boolean }>(
192
+ {
193
+ EntityName: 'MJ: Users',
194
+ ExtraFilter: `Email = '${templateEmail.replace(/'/g, "''")}'`,
195
+ Fields: ['ID', 'IsTemplate'],
196
+ ResultType: 'simple',
197
+ MaxRows: 1,
198
+ },
199
+ contextUser
200
+ );
201
+ const templateUser = lookup.Success ? lookup.Results[0] : undefined;
202
+ if (!templateUser) {
203
+ LogError(`userHandling.newUserTemplate: no user has the email ${templateEmail}`);
204
+ return null;
205
+ }
206
+ if (!templateUser.IsTemplate) {
207
+ LogError(`userHandling.newUserTemplate: ${templateEmail} is not marked as a template user (IsTemplate)`);
208
+ return null;
209
+ }
210
+
211
+ const result = await new RecordCloneEngine(provider).Clone(
212
+ {
213
+ EntityName: 'MJ: Users',
214
+ SourceRecordKey: CompositeKey.FromID(templateUser.ID),
215
+ Preset: preset,
216
+ PromptedValues: { Email: email, FirstName: firstName, LastName: lastName },
217
+ Options: { Reason: `New user ${email} created at first sign-in from template ${templateEmail}` },
218
+ },
219
+ contextUser
220
+ );
221
+ const newKey = result.Roots?.[0]?.TargetKey.KeyValuePairs.find((kvp) => kvp.FieldName === 'ID')?.Value;
222
+ if (!result.Success || !newKey) {
223
+ const reasons = result.Warnings.filter((w) => w.Severity === 'Error').map((w) => w.Message);
224
+ LogError(`userHandling.newUserTemplate: copying ${templateEmail} failed: ${result.ErrorMessage || reasons.join('; ') || result.ResultCode}`);
225
+ return null;
226
+ }
227
+
228
+ const user = await provider.GetEntityObject<MJUserEntity>('MJ: Users', contextUser);
229
+ if (!(await user.Load(String(newKey)))) {
230
+ LogError(`userHandling.newUserTemplate: the copy of ${templateEmail} for ${email} could not be loaded`);
231
+ return null;
232
+ }
233
+ user.IsActive = true;
234
+ user.LinkedRecordType = linkedRecordType;
235
+ if (linkedEntityId) user.LinkedEntityID = linkedEntityId;
236
+ if (linkedEntityRecordId) user.LinkedEntityRecordID = linkedEntityRecordId;
237
+ if (!(await user.Save())) {
238
+ LogError(`userHandling.newUserTemplate: could not activate ${email}: ${user.LatestResult?.CompleteMessage ?? 'unknown error'}`);
239
+ return null;
240
+ }
241
+ LogStatus(`Created user ${email} from template ${templateEmail} (${result.RecordsCloned ?? result.Created?.length ?? 0} records copied)`);
242
+ return user;
243
+ }
156
244
  }
package/src/config.ts CHANGED
@@ -38,6 +38,19 @@ const userHandlingInfoSchema = z.object({
38
38
  contextUserForNewUserCreation: z.string().optional().default(''),
39
39
  CreateUserApplicationRecords: z.boolean().optional().default(false),
40
40
  UserApplications: z.array(z.string()).optional().default([]),
41
+ /**
42
+ * Build each auto-created user as a copy of a template user (`User.IsTemplate`), so new people start
43
+ * with its pinned apps, views, settings, dashboards and conversations. `email` names the template;
44
+ * `preset` is the `MJ: Users` clone preset to apply (default `template`). The copy takes the roles
45
+ * and apps of the template, so `newUserRoles`, `CreateUserApplicationRecords` and `UserApplications`
46
+ * apply only when the template can't be used, in which case a plain user is created as before.
47
+ */
48
+ newUserTemplate: z
49
+ .object({
50
+ email: z.string(),
51
+ preset: z.string().optional().default('template'),
52
+ })
53
+ .optional(),
41
54
  });
42
55
 
43
56
  const databaseSettingsInfoSchema = z.object({
@@ -213,10 +226,19 @@ const telemetrySchema = z.object({
213
226
  level: z.enum(['minimal', 'standard', 'verbose', 'debug']).optional().default('standard'),
214
227
  });
215
228
 
216
- const serverExtensionSchema = z.object({
217
- Enabled: z.boolean().default(true),
229
+ /**
230
+ * A host `mj.config.cjs` `serverExtensions[]` entry. Only `DriverClass` is required: an entry whose
231
+ * DriverClass an Open App package already publishes is an OVERLAY (MergeServerExtensionConfigs) and
232
+ * may set just the fields it overrides — `{ DriverClass: 'X', OwnsCORS: false }` — without repeating
233
+ * `RootPath`. `Enabled` has no schema default for the same reason: a defaulted `true` would silently
234
+ * re-enable an extension the package ships disabled. Whether the MERGED entry is complete (a valid
235
+ * `RootPath`; `Enabled` defaults to true) is validated after the merge, by prepareServerExtensionConfigs,
236
+ * which reports an incomplete host-only entry instead of mounting it.
237
+ */
238
+ export const ServerExtensionSchema = z.object({
239
+ Enabled: z.boolean().optional(),
218
240
  DriverClass: z.string(),
219
- RootPath: z.string(),
241
+ RootPath: z.string().optional(),
220
242
  Settings: z.record(z.unknown()).default({})
221
243
  }).passthrough();
222
244
 
@@ -225,6 +247,14 @@ const cacheSettingsSchema = z.object({
225
247
  maxMemoryMB: z.number().optional().default(150),
226
248
  /** Maximum percentage of total cache memory that any single entity can occupy. Default: 50. Set to 0 to disable. */
227
249
  maxPercentOfCachePerEntity: z.number().optional().default(50),
250
+ /**
251
+ * Ceiling on any ONE cache entry. 'auto' (the default) derives it from maxMemoryMB, so the
252
+ * largest entity the server caches scales with the memory the cache was given; a number is an
253
+ * explicit stricter percentage of maxMemoryMB; 0 removes the ceiling. Leave it on 'auto' unless
254
+ * a specific entry must be kept out of the cache — an entry declined by the ceiling is re-read
255
+ * from the database on every call, and the server logs which maxMemoryMB would admit it.
256
+ */
257
+ maxEntryPercentOfCache: z.union([z.number(), z.literal('auto')]).optional().default('auto'),
228
258
  /** Default TTL in seconds. 0 = no TTL, rely on event-based invalidation. Default: 0. */
229
259
  defaultTTLSeconds: z.number().optional().default(0),
230
260
  /** Interval in seconds for periodic eviction sweep. 0 = disabled. Default: 300 (5 minutes). */
@@ -254,6 +284,38 @@ const cacheSettingsSchema = z.object({
254
284
  * every signed-in user may read every row of every entity.
255
285
  */
256
286
  recordDataBroadcastEntities: z.array(z.string()).optional().default([]),
287
+ /**
288
+ * Expiry, in seconds, of entries in the shared Redis cache (used when REDIS_URL is set). The
289
+ * REDIS_TTL_SECONDS environment variable overrides it. 0 stores entries without expiry. When
290
+ * neither is set, the Redis provider's default applies (one hour).
291
+ */
292
+ sharedCacheTTLSeconds: z.number().int().nonnegative().optional(),
293
+ /**
294
+ * How often, in seconds, loaded engines compare their rows with the database and reload what
295
+ * changed without an MJ event (direct SQL, other applications). With a shared cache one server
296
+ * does it per interval. 0 = disabled. Default: 300 (5 minutes).
297
+ */
298
+ engineSweepIntervalSeconds: z.number().int().nonnegative().optional().default(300),
299
+ /**
300
+ * How often, in seconds, the user cache compares two row counts and the newest update timestamp
301
+ * with the database and reloads only when they differ. The cache already refreshes on MJ writes
302
+ * (locally and, with a shared cache, on other servers); this covers changes made outside MJ.
303
+ * 0 = disabled. Default: 300 (5 minutes).
304
+ */
305
+ userCacheCheckIntervalSeconds: z.number().int().nonnegative().optional().default(300),
306
+ /**
307
+ * How often to compare this process's metadata with the database, in seconds (0 disables).
308
+ * Costs nothing unless an entity the metadata is built from declares
309
+ * `TrustServerCacheCompletely = false`; see `ProviderBase.SweepMetadataAgainstDatabase`.
310
+ */
311
+ metadataSweepIntervalSeconds: z.number().int().nonnegative().optional().default(300),
312
+ /**
313
+ * How long, in seconds, a server holds the shared warm-up turn while it loads its engines, so
314
+ * servers starting together load one at a time and the rest find the cache warm. The lease is
315
+ * renewed while the load runs; this value is both its expiry and how long another server waits
316
+ * for it. 0 disables the turn-taking. Default: 30.
317
+ */
318
+ startupWarmupLeaseSeconds: z.number().int().nonnegative().optional().default(30),
257
319
  });
258
320
 
259
321
  const loggingSettingsSchema = z.object({
@@ -271,6 +333,15 @@ const loggingSettingsSchema = z.object({
271
333
  }).optional().default({}),
272
334
  });
273
335
 
336
+ const aiPromptRunsSchema = z.object({
337
+ /**
338
+ * Server default for which template inputs prompt runs store in AIPromptRun.Messages:
339
+ * 'None' (key sizes only), 'Referenced' (keys the templates read) or 'Full'.
340
+ * AIPrompt.TemplateDataCapture and AIPromptParams.TemplateDataCapture override it.
341
+ */
342
+ templateDataCapture: z.enum(['None', 'Referenced', 'Full']).optional(),
343
+ });
344
+
274
345
  const corsSchema = z.object({
275
346
  /** Allowed origins for CORS. Default ['*'] preserves backward-compatible "allow all" behavior. */
276
347
  allowedOrigins: z.array(z.string()).default(['*']),
@@ -684,9 +755,92 @@ const telephonySchema = z.object({
684
755
  teams: teamsMeetingsSchema.optional(),
685
756
  }).passthrough();
686
757
 
758
+ /**
759
+ * Mid-session identity verification for realtime sessions (see `src/realtimeSessions/README.md`).
760
+ *
761
+ * A person talking to an agent proves they control an email address WITHOUT leaving the conversation:
762
+ * the server emails a one-time link plus a short code, records the verification on the session, extends
763
+ * the session's limits, and tells the live session through a session event. The session's principal is
764
+ * never changed.
765
+ *
766
+ * Off by default: nothing is emailed and `/realtime/verify` is not mounted until `enabled` is true AND a
767
+ * `communicationProvider` is configured. Policy set here is the BASE layer; the config cascade
768
+ * (`channels.config.IdentityVerification`) snapshotted onto each session at mint overrides it per knob.
769
+ */
770
+ const identityVerificationSchema = z.object({
771
+ /** Master switch. When false the verify routes are not mounted and the GraphQL operations refuse. */
772
+ enabled: zodBooleanWithTransforms().default(false),
773
+ /** CommunicationEngine provider that delivers the verification email (e.g. 'SendGrid', 'Microsoft Graph'). Required to send. */
774
+ communicationProvider: z.string().optional(),
775
+ /** From address of the verification email. */
776
+ fromAddress: z.string().optional(),
777
+ /**
778
+ * Server-only secret the typed verification code is HMAC'd under before it is stored on the session
779
+ * (at least 16 characters; 32+ random characters recommended). REQUIRED: without it verification is
780
+ * unavailable, because a session's owner can read their own session row and a bare hash of a six-digit
781
+ * code can be reversed offline. Never exposed to clients. Rotating it voids pending verifications only.
782
+ */
783
+ hmacSecret: z.string().optional().default(process.env.MJ_REALTIME_VERIFICATION_SECRET || ''),
784
+ /**
785
+ * `send` (default) delivers the email. `dry-run` builds and logs the message through the communication
786
+ * provider WITHOUT delivering it — for rehearsal and integration environments, where a test reads the
787
+ * emailed link and code from the `MJ: Communication Logs` row. Never use `dry-run` in production: the
788
+ * Communication Log then holds live credentials and no one is emailed.
789
+ */
790
+ deliveryMode: z.enum(['send', 'dry-run']).optional().default('send'),
791
+ /**
792
+ * Base URL the emailed link is built from (`<publicBaseUrl>/realtime/verify/<token>`). Defaults to the
793
+ * server's `publicUrl`, or `baseUrl:graphqlPort` when that is unset — the same derivation magic links use.
794
+ */
795
+ publicBaseUrl: z.string().optional(),
796
+ /**
797
+ * The internal user the server acts as to read/write the session, send the email and write the audit
798
+ * row, matched against `User.Name` then `User.Email` (falls back to the system user, then the lowest-ID
799
+ * active Owner). The verify link is public, so it has no caller identity of its own.
800
+ */
801
+ contextUserForVerification: z.string().optional(),
802
+ /** Base policy layer; each knob here is overridden by the per-session cascade layer. */
803
+ policy: z.object({
804
+ requireBusinessDomain: z.boolean().optional(),
805
+ blockedDomains: z.array(z.string()).optional(),
806
+ consumerDomains: z.array(z.string()).optional(),
807
+ linkTtlMinutes: z.coerce.number().optional(),
808
+ maxSendsPerSession: z.coerce.number().optional(),
809
+ maxCodeAttempts: z.coerce.number().optional(),
810
+ unverifiedMaxSeconds: z.coerce.number().optional(),
811
+ verifiedMaxSeconds: z.coerce.number().optional(),
812
+ }).optional().default({}),
813
+ /** Send-side and attempt-side limits (per instance, in memory; per-session limits are persisted and exact). */
814
+ rateLimits: z.object({
815
+ /** Window (ms) for the three send limits. Default 1 hour. */
816
+ sendWindowMs: z.coerce.number().optional().default(3_600_000),
817
+ /** Verification emails per client IP per window. Default 10. 0 disables. */
818
+ perIpSends: z.coerce.number().optional().default(10),
819
+ /** Verification emails per recipient domain per window. Default 30. 0 disables. */
820
+ perEmailDomainSends: z.coerce.number().optional().default(30),
821
+ /** Verification emails per recipient address per window — stops the feature being used to mail-bomb one inbox. Default 3. 0 disables. */
822
+ perEmailSends: z.coerce.number().optional().default(3),
823
+ /** Window (ms) for code attempts. Default 10 minutes. */
824
+ codeAttemptWindowMs: z.coerce.number().optional().default(600_000),
825
+ /** Code submissions per session per window. Default 10. 0 disables. */
826
+ perSessionCodeAttempts: z.coerce.number().optional().default(10),
827
+ /** Window (ms) of the public `/realtime/verify` route limiter. Default 60s. */
828
+ redeemWindowMs: z.coerce.number().optional().default(60_000),
829
+ /** `/realtime/verify` requests per IP per window. Default 30. */
830
+ redeemPerIp: z.coerce.number().optional().default(30),
831
+ }).optional().default({}),
832
+ }).passthrough();
833
+
687
834
  const realtimeSchema = z.object({
688
835
  /** Master switch. When false, the WebRTC SDP broker router is not mounted. Defaults to true. */
689
836
  enabled: zodBooleanWithTransforms().default(true),
837
+ /** Mid-session identity verification (off by default). */
838
+ identityVerification: identityVerificationSchema.optional().default({}),
839
+ /**
840
+ * Seconds a client-direct call's recording waits for missing shards after its terminal signal before it
841
+ * is assembled anyway as `Partial` (gaps become silence). Defaults to 90.
842
+ */
843
+ recordingAssemblyGraceSeconds: z.coerce.number().positive().optional().default(90),
690
844
  }).passthrough();
691
845
 
692
846
  const configInfoSchema = z.object({
@@ -707,9 +861,10 @@ const configInfoSchema = z.object({
707
861
  telemetry: telemetrySchema.optional().default({}),
708
862
  queryDialects: queryDialectSchema.optional().default({}),
709
863
  multiTenancy: multiTenancySchema.optional().default({}),
710
- serverExtensions: z.array(serverExtensionSchema).optional().default([]),
864
+ serverExtensions: z.array(ServerExtensionSchema).optional().default([]),
711
865
  cacheSettings: cacheSettingsSchema.optional().default({}),
712
866
  loggingSettings: loggingSettingsSchema.optional().default({}),
867
+ aiPromptRuns: aiPromptRunsSchema.optional(),
713
868
  feedbackSettings: feedbackSettingsSchema.optional().default({}),
714
869
  cors: corsSchema.optional().default({}),
715
870
  rateLimiting: rateLimitSchema.optional().default({}),
@@ -737,6 +892,12 @@ const configInfoSchema = z.object({
737
892
  ___codeGenAPIPort: z.coerce.number().optional().default(3999),
738
893
  ___codeGenAPISubmissionDelay: z.coerce.number().optional().default(5000),
739
894
  graphqlRootPath: z.string().optional().default('/'),
895
+ /**
896
+ * Path prefix MJAPI mounts every route it serves under (core routes and server extensions), on its own
897
+ * listener. `/` unless a proxy forwards a prefix WITHOUT stripping it (e.g. CloudFront `/api/*` → MJAPI):
898
+ * then set `MJAPI_BASE_PATH=/api`. Independent of `graphqlRootPath`, which is only Apollo's path. MJ #5674.
899
+ */
900
+ apiBasePath: z.string().optional().default('/'),
740
901
  enableIntrospection: z.coerce.boolean().optional().default(false),
741
902
  websiteRunFromPackage: z.coerce.number().optional(),
742
903
  userEmailMap: z
@@ -751,6 +912,7 @@ export type MagicLinkConfig = z.infer<typeof magicLinkSchema>;
751
912
  export type WidgetConfig = z.infer<typeof widgetSchema>;
752
913
  export type TelephonyConfig = z.infer<typeof telephonySchema>;
753
914
  export type RealtimeConfig = z.infer<typeof realtimeSchema>;
915
+ export type IdentityVerificationConfig = z.infer<typeof identityVerificationSchema>;
754
916
  export type TwilioTelephonyConfig = z.infer<typeof twilioTelephonySchema>;
755
917
  export type VonageTelephonyConfig = z.infer<typeof vonageTelephonySchema>;
756
918
  export type RingCentralTelephonyConfig = z.infer<typeof ringcentralTelephonySchema>;
@@ -769,9 +931,10 @@ export type { WorkQueueConfig } from './services/workQueueConfig.js';
769
931
  export type TelemetryConfig = z.infer<typeof telemetrySchema>;
770
932
  export type QueryDialectConfig = z.infer<typeof queryDialectSchema>;
771
933
  export type MultiTenancyConfig = z.infer<typeof multiTenancySchema>;
772
- export type ServerExtensionConfig = z.infer<typeof serverExtensionSchema>;
934
+ export type ServerExtensionConfig = z.infer<typeof ServerExtensionSchema>;
773
935
  export type CacheSettingsConfig = z.infer<typeof cacheSettingsSchema>;
774
936
  export type LoggingSettingsConfig = z.infer<typeof loggingSettingsSchema>;
937
+ export type AIPromptRunsConfig = z.infer<typeof aiPromptRunsSchema>;
775
938
  export type FeedbackGithubSettingsConfig = z.infer<typeof feedbackGithubSettingsSchema>;
776
939
  export type FeedbackSettingsConfig = z.infer<typeof feedbackSettingsSchema>;
777
940
  export type CorsConfig = z.infer<typeof corsSchema>;
@@ -807,6 +970,7 @@ export const DEFAULT_SERVER_CONFIG: Partial<ConfigInfo> = {
807
970
  // GraphQL server settings (environment-driven with defaults)
808
971
  graphqlPort: process.env.GRAPHQL_PORT ? parseInt(process.env.GRAPHQL_PORT, 10) : 4000,
809
972
  graphqlRootPath: process.env.GRAPHQL_ROOT_PATH ?? '/',
973
+ apiBasePath: process.env.MJAPI_BASE_PATH ?? '/',
810
974
  baseUrl: process.env.GRAPHQL_BASE_URL ?? 'http://localhost',
811
975
  publicUrl: process.env.MJAPI_PUBLIC_URL,
812
976
  enableIntrospection: process.env.ENABLE_INTROSPECTION === 'true',
@@ -923,9 +1087,11 @@ export const DEFAULT_SERVER_CONFIG: Partial<ConfigInfo> = {
923
1087
  cacheSettings: {
924
1088
  maxMemoryMB: 150,
925
1089
  maxPercentOfCachePerEntity: 50,
1090
+ maxEntryPercentOfCache: 'auto',
926
1091
  defaultTTLSeconds: 0,
927
1092
  evictionSweepIntervalSeconds: 300,
928
1093
  verboseLogging: false,
1094
+ engineSweepIntervalSeconds: 300,
929
1095
  },
930
1096
 
931
1097
  // Logging settings defaults — variables logging is always off unless the operator