@memberjunction/server 6.1.4 → 6.2.0-edge.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/agentSessions/ReturningVisitorRecap.d.ts +2 -0
  3. package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
  4. package/dist/agentSessions/ReturningVisitorRecap.js +5 -1
  5. package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
  6. package/dist/agentSessions/SessionManager.js +2 -2
  7. package/dist/agentSessions/remoteBrowserGoalEngine.d.ts +8 -0
  8. package/dist/agentSessions/remoteBrowserGoalEngine.d.ts.map +1 -1
  9. package/dist/agentSessions/remoteBrowserGoalEngine.js +21 -5
  10. package/dist/agentSessions/remoteBrowserGoalEngine.js.map +1 -1
  11. package/dist/auth/AuthProviderCatalogRouter.d.ts +2 -0
  12. package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
  13. package/dist/auth/AuthProviderCatalogRouter.js +5 -1
  14. package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
  15. package/dist/auth/exampleNewUserSubClass.js +2 -1
  16. package/dist/auth/exampleNewUserSubClass.js.map +1 -1
  17. package/dist/auth/index.d.ts +20 -1
  18. package/dist/auth/index.d.ts.map +1 -1
  19. package/dist/auth/index.js +20 -10
  20. package/dist/auth/index.js.map +1 -1
  21. package/dist/auth/initializeProviders.d.ts +8 -0
  22. package/dist/auth/initializeProviders.d.ts.map +1 -1
  23. package/dist/auth/initializeProviders.js +21 -5
  24. package/dist/auth/initializeProviders.js.map +1 -1
  25. package/dist/auth/magicLink/MagicLinkRouter.d.ts +9 -0
  26. package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
  27. package/dist/auth/magicLink/MagicLinkRouter.js +22 -10
  28. package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
  29. package/dist/auth/magicLink/MagicLinkService.d.ts +17 -15
  30. package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
  31. package/dist/auth/magicLink/MagicLinkService.js +65 -51
  32. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  33. package/dist/auth/magicLink/index.d.ts +2 -2
  34. package/dist/auth/magicLink/index.d.ts.map +1 -1
  35. package/dist/auth/magicLink/index.js +2 -2
  36. package/dist/auth/magicLink/index.js.map +1 -1
  37. package/dist/auth/magicLink/magicLinkCore.d.ts +54 -33
  38. package/dist/auth/magicLink/magicLinkCore.d.ts.map +1 -1
  39. package/dist/auth/magicLink/magicLinkCore.js +61 -61
  40. package/dist/auth/magicLink/magicLinkCore.js.map +1 -1
  41. package/dist/auth/magicLink/redeemLanding.d.ts +4 -0
  42. package/dist/auth/magicLink/redeemLanding.d.ts.map +1 -1
  43. package/dist/auth/magicLink/redeemLanding.js +12 -4
  44. package/dist/auth/magicLink/redeemLanding.js.map +1 -1
  45. package/dist/auth/magicLink/types.d.ts +4 -4
  46. package/dist/auth/principals.d.ts +2 -0
  47. package/dist/auth/principals.d.ts.map +1 -1
  48. package/dist/auth/principals.js +6 -2
  49. package/dist/auth/principals.js.map +1 -1
  50. package/dist/cache.d.ts +2 -0
  51. package/dist/cache.d.ts.map +1 -1
  52. package/dist/cache.js +3 -1
  53. package/dist/cache.js.map +1 -1
  54. package/dist/config.d.ts +293 -2
  55. package/dist/config.d.ts.map +1 -1
  56. package/dist/config.js +11 -4
  57. package/dist/config.js.map +1 -1
  58. package/dist/context.d.ts +20 -0
  59. package/dist/context.d.ts.map +1 -1
  60. package/dist/context.js +27 -19
  61. package/dist/context.js.map +1 -1
  62. package/dist/directives/Public.d.ts +2 -0
  63. package/dist/directives/Public.d.ts.map +1 -1
  64. package/dist/directives/Public.js +3 -1
  65. package/dist/directives/Public.js.map +1 -1
  66. package/dist/directives/RequireSystemUser.d.ts +2 -0
  67. package/dist/directives/RequireSystemUser.d.ts.map +1 -1
  68. package/dist/directives/RequireSystemUser.js +3 -1
  69. package/dist/directives/RequireSystemUser.js.map +1 -1
  70. package/dist/generated/graphql-schemas/__mj.d.ts +266 -4
  71. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  72. package/dist/generated/graphql-schemas/__mj.js +1304 -0
  73. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  74. package/dist/generic/CacheInvalidationResolver.d.ts +8 -2
  75. package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
  76. package/dist/generic/CacheInvalidationResolver.js +7 -3
  77. package/dist/generic/CacheInvalidationResolver.js.map +1 -1
  78. package/dist/generic/FireAndForgetHeartbeat.d.ts +3 -1
  79. package/dist/generic/FireAndForgetHeartbeat.d.ts.map +1 -1
  80. package/dist/generic/FireAndForgetHeartbeat.js +8 -4
  81. package/dist/generic/FireAndForgetHeartbeat.js.map +1 -1
  82. package/dist/generic/PushStatusResolver.d.ts +10 -1
  83. package/dist/generic/PushStatusResolver.d.ts.map +1 -1
  84. package/dist/generic/PushStatusResolver.js +11 -3
  85. package/dist/generic/PushStatusResolver.js.map +1 -1
  86. package/dist/generic/ResolverBase.d.ts +27 -1
  87. package/dist/generic/ResolverBase.d.ts.map +1 -1
  88. package/dist/generic/ResolverBase.js +64 -6
  89. package/dist/generic/ResolverBase.js.map +1 -1
  90. package/dist/index.d.ts +6 -0
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +29 -6
  93. package/dist/index.js.map +1 -1
  94. package/dist/integration/CustomColumnPromoter.d.ts +2 -0
  95. package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
  96. package/dist/integration/CustomColumnPromoter.js +5 -1
  97. package/dist/integration/CustomColumnPromoter.js.map +1 -1
  98. package/dist/integration/EntityMapLifecycle.d.ts +4 -0
  99. package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
  100. package/dist/integration/EntityMapLifecycle.js +10 -2
  101. package/dist/integration/EntityMapLifecycle.js.map +1 -1
  102. package/dist/logging/NoLog.d.ts +4 -0
  103. package/dist/logging/NoLog.d.ts.map +1 -1
  104. package/dist/logging/NoLog.js +10 -2
  105. package/dist/logging/NoLog.js.map +1 -1
  106. package/dist/logging/StartupLogger.d.ts +2 -0
  107. package/dist/logging/StartupLogger.d.ts.map +1 -1
  108. package/dist/logging/StartupLogger.js +5 -1
  109. package/dist/logging/StartupLogger.js.map +1 -1
  110. package/dist/logging/bootAudit.d.ts +11 -7
  111. package/dist/logging/bootAudit.d.ts.map +1 -1
  112. package/dist/logging/bootAudit.js +15 -7
  113. package/dist/logging/bootAudit.js.map +1 -1
  114. package/dist/logging/boundaryLogPayload.d.ts +4 -0
  115. package/dist/logging/boundaryLogPayload.d.ts.map +1 -1
  116. package/dist/logging/boundaryLogPayload.js +5 -1
  117. package/dist/logging/boundaryLogPayload.js.map +1 -1
  118. package/dist/logging/secretRedactor.d.ts +2 -0
  119. package/dist/logging/secretRedactor.d.ts.map +1 -1
  120. package/dist/logging/secretRedactor.js +8 -4
  121. package/dist/logging/secretRedactor.js.map +1 -1
  122. package/dist/logging/shortenForLog.d.ts +2 -0
  123. package/dist/logging/shortenForLog.d.ts.map +1 -1
  124. package/dist/logging/shortenForLog.js +7 -3
  125. package/dist/logging/shortenForLog.js.map +1 -1
  126. package/dist/logging/variablesLoggingMiddleware.d.ts +2 -0
  127. package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
  128. package/dist/logging/variablesLoggingMiddleware.js +8 -6
  129. package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
  130. package/dist/metadataRefreshSignal.d.ts +19 -0
  131. package/dist/metadataRefreshSignal.d.ts.map +1 -0
  132. package/dist/metadataRefreshSignal.js +45 -0
  133. package/dist/metadataRefreshSignal.js.map +1 -0
  134. package/dist/middleware/MJTenantFilterMiddleware.js +4 -4
  135. package/dist/multiTenancy/index.d.ts +8 -0
  136. package/dist/multiTenancy/index.d.ts.map +1 -1
  137. package/dist/multiTenancy/index.js +21 -5
  138. package/dist/multiTenancy/index.js.map +1 -1
  139. package/dist/realtimeWidget/WidgetRouter.d.ts +5 -0
  140. package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
  141. package/dist/realtimeWidget/WidgetRouter.js +14 -10
  142. package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
  143. package/dist/realtimeWidget/WidgetSessionService.d.ts +6 -6
  144. package/dist/realtimeWidget/WidgetSessionService.js +27 -27
  145. package/dist/realtimeWidget/host-identity.d.ts +5 -1
  146. package/dist/realtimeWidget/host-identity.d.ts.map +1 -1
  147. package/dist/realtimeWidget/host-identity.js +11 -3
  148. package/dist/realtimeWidget/host-identity.js.map +1 -1
  149. package/dist/realtimeWidget/index.d.ts +2 -2
  150. package/dist/realtimeWidget/index.d.ts.map +1 -1
  151. package/dist/realtimeWidget/index.js +2 -2
  152. package/dist/realtimeWidget/index.js.map +1 -1
  153. package/dist/realtimeWidget/visitorIdentity.d.ts +21 -1
  154. package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
  155. package/dist/realtimeWidget/visitorIdentity.js +16 -4
  156. package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
  157. package/dist/realtimeWidget/widgetCore.d.ts +48 -0
  158. package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
  159. package/dist/realtimeWidget/widgetCore.js +38 -10
  160. package/dist/realtimeWidget/widgetCore.js.map +1 -1
  161. package/dist/realtimeWidget/widgetGuestElevation.d.ts +10 -6
  162. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  163. package/dist/realtimeWidget/widgetGuestElevation.js +14 -6
  164. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  165. package/dist/resolvers/AdhocQueryResolver.js +3 -3
  166. package/dist/resolvers/FetchEntityVectorsResolver.js +2 -2
  167. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  168. package/dist/resolvers/FileResolver.js +3 -3
  169. package/dist/resolvers/GeoResolver.d.ts +2 -2
  170. package/dist/resolvers/GeoResolver.js +4 -4
  171. package/dist/resolvers/GetDataResolver.d.ts +14 -0
  172. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  173. package/dist/resolvers/GetDataResolver.js +43 -15
  174. package/dist/resolvers/GetDataResolver.js.map +1 -1
  175. package/dist/resolvers/IntegrationDiscoveryResolver.js +2 -2
  176. package/dist/resolvers/ListOperationsResolver.d.ts +20 -0
  177. package/dist/resolvers/ListOperationsResolver.d.ts.map +1 -1
  178. package/dist/resolvers/ListOperationsResolver.js +68 -28
  179. package/dist/resolvers/ListOperationsResolver.js.map +1 -1
  180. package/dist/resolvers/MCPResolver.d.ts +11 -1
  181. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  182. package/dist/resolvers/MCPResolver.js +7 -3
  183. package/dist/resolvers/MCPResolver.js.map +1 -1
  184. package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
  185. package/dist/resolvers/QuerySystemUserResolver.js +2 -1
  186. package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
  187. package/dist/resolvers/RealtimeBridgeResolver.js +3 -3
  188. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +37 -0
  189. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  190. package/dist/resolvers/RealtimeClientSessionResolver.js +101 -11
  191. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  192. package/dist/resolvers/RemoteBrowserActionResolver.js +5 -5
  193. package/dist/resolvers/RunAIAgentResolver.d.ts +10 -4
  194. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  195. package/dist/resolvers/RunAIAgentResolver.js +74 -42
  196. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  197. package/dist/resolvers/RunAIPromptResolver.d.ts +1 -1
  198. package/dist/resolvers/RunAIPromptResolver.js +2 -2
  199. package/dist/resolvers/RunTestResolver.js +5 -5
  200. package/dist/resolvers/SearchEntitiesResolver.d.ts.map +1 -1
  201. package/dist/resolvers/SearchEntitiesResolver.js +3 -1
  202. package/dist/resolvers/SearchEntitiesResolver.js.map +1 -1
  203. package/dist/resolvers/SearchKnowledgeResolver.d.ts +1 -0
  204. package/dist/resolvers/SearchKnowledgeResolver.d.ts.map +1 -1
  205. package/dist/resolvers/SearchKnowledgeResolver.js +5 -0
  206. package/dist/resolvers/SearchKnowledgeResolver.js.map +1 -1
  207. package/dist/resolvers/SearchKnowledgeSystemUserResolver.d.ts.map +1 -1
  208. package/dist/resolvers/SearchKnowledgeSystemUserResolver.js +1 -0
  209. package/dist/resolvers/SearchKnowledgeSystemUserResolver.js.map +1 -1
  210. package/dist/resolvers/SqlLoggingConfigResolver.d.ts +8 -4
  211. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  212. package/dist/resolvers/SqlLoggingConfigResolver.js +5 -5
  213. package/dist/resolvers/TaskGraphFrameResolver.d.ts +8 -1
  214. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
  215. package/dist/resolvers/TaskGraphFrameResolver.js +6 -2
  216. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
  217. package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
  218. package/dist/resolvers/TransactionGroupResolver.js +53 -4
  219. package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
  220. package/dist/resolvers/adhoc-query-helpers.d.ts +6 -0
  221. package/dist/resolvers/adhoc-query-helpers.d.ts.map +1 -1
  222. package/dist/resolvers/adhoc-query-helpers.js +10 -2
  223. package/dist/resolvers/adhoc-query-helpers.js.map +1 -1
  224. package/dist/resolvers/artifact-routing.d.ts +8 -8
  225. package/dist/resolvers/artifact-routing.js +2 -2
  226. package/dist/resolvers/artifact-routing.js.map +1 -1
  227. package/dist/resolvers/meetingRecordingRegistration.d.ts +10 -2
  228. package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
  229. package/dist/resolvers/meetingRecordingRegistration.js +24 -8
  230. package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
  231. package/dist/resolvers/peaksSidecar.d.ts +4 -0
  232. package/dist/resolvers/peaksSidecar.d.ts.map +1 -1
  233. package/dist/resolvers/peaksSidecar.js +10 -2
  234. package/dist/resolvers/peaksSidecar.js.map +1 -1
  235. package/dist/rest/EntityCRUDHandler.d.ts +28 -0
  236. package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
  237. package/dist/rest/EntityCRUDHandler.js +20 -4
  238. package/dist/rest/EntityCRUDHandler.js.map +1 -1
  239. package/dist/rest/MediaStreamHandler.d.ts +2 -0
  240. package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
  241. package/dist/rest/MediaStreamHandler.js +10 -6
  242. package/dist/rest/MediaStreamHandler.js.map +1 -1
  243. package/dist/rest/OAuthCallbackHandler.d.ts +9 -0
  244. package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
  245. package/dist/rest/OAuthCallbackHandler.js +15 -3
  246. package/dist/rest/OAuthCallbackHandler.js.map +1 -1
  247. package/dist/rest/RESTEndpointHandler.d.ts +6 -4
  248. package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
  249. package/dist/rest/RESTEndpointHandler.js +15 -11
  250. package/dist/rest/RESTEndpointHandler.js.map +1 -1
  251. package/dist/rest/RealtimeSdpBrokerHandler.d.ts +5 -1
  252. package/dist/rest/RealtimeSdpBrokerHandler.d.ts.map +1 -1
  253. package/dist/rest/RealtimeSdpBrokerHandler.js +12 -4
  254. package/dist/rest/RealtimeSdpBrokerHandler.js.map +1 -1
  255. package/dist/rest/SignatureWebhookHandler.d.ts +2 -0
  256. package/dist/rest/SignatureWebhookHandler.d.ts.map +1 -1
  257. package/dist/rest/SignatureWebhookHandler.js +5 -1
  258. package/dist/rest/SignatureWebhookHandler.js.map +1 -1
  259. package/dist/rest/UploadTokenManager.d.ts +24 -8
  260. package/dist/rest/UploadTokenManager.d.ts.map +1 -1
  261. package/dist/rest/UploadTokenManager.js +53 -21
  262. package/dist/rest/UploadTokenManager.js.map +1 -1
  263. package/dist/rest/ViewOperationsHandler.d.ts +20 -0
  264. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  265. package/dist/rest/ViewOperationsHandler.js +20 -4
  266. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  267. package/dist/rest/mediaRange.d.ts +4 -0
  268. package/dist/rest/mediaRange.d.ts.map +1 -1
  269. package/dist/rest/mediaRange.js +10 -2
  270. package/dist/rest/mediaRange.js.map +1 -1
  271. package/dist/rest/setupRESTEndpoints.d.ts +4 -0
  272. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  273. package/dist/rest/setupRESTEndpoints.js +13 -7
  274. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  275. package/dist/serverExtensionReservedRoots.d.ts +2 -0
  276. package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
  277. package/dist/serverExtensionReservedRoots.js +5 -1
  278. package/dist/serverExtensionReservedRoots.js.map +1 -1
  279. package/dist/services/MJStorageBlobStore.d.ts +41 -0
  280. package/dist/services/MJStorageBlobStore.d.ts.map +1 -0
  281. package/dist/services/MJStorageBlobStore.js +160 -0
  282. package/dist/services/MJStorageBlobStore.js.map +1 -0
  283. package/dist/services/TaskGraphActionRunner.d.ts +13 -8
  284. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  285. package/dist/services/TaskGraphActionRunner.js +16 -15
  286. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  287. package/dist/types.d.ts +2 -0
  288. package/dist/types.d.ts.map +1 -1
  289. package/dist/types.js +7 -3
  290. package/dist/types.js.map +1 -1
  291. package/dist/util.d.ts +12 -3
  292. package/dist/util.d.ts.map +1 -1
  293. package/dist/util.js +19 -8
  294. package/dist/util.js.map +1 -1
  295. package/package.json +92 -92
  296. package/src/__tests__/FileResolverPeaks.test.ts +13 -13
  297. package/src/__tests__/ListOperationsResolver.test.ts +17 -17
  298. package/src/__tests__/MediaStreamHandler.test.ts +28 -28
  299. package/src/__tests__/NoLog.test.ts +11 -11
  300. package/src/__tests__/PrimaryKeyAlwaysMapped.test.ts +10 -10
  301. package/src/__tests__/RESTEndpointHandler.test.ts +14 -14
  302. package/src/__tests__/RealtimeBridgeResolver.test.ts +4 -2
  303. package/src/__tests__/RealtimeClientSessionResolver.test.ts +229 -0
  304. package/src/__tests__/RealtimeSdpBrokerHandler.test.ts +6 -6
  305. package/src/__tests__/RefreshAdoptsNewColumns.test.ts +8 -8
  306. package/src/__tests__/RemoteBrowserGoalEngine.test.ts +18 -18
  307. package/src/__tests__/ResolverBase.isaPromotionCreate.test.ts +412 -0
  308. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +228 -0
  309. package/src/__tests__/SearchEntitiesResolver.readOnlyFallback.test.ts +78 -0
  310. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +129 -0
  311. package/src/__tests__/TaskGraphFrameResolver.test.ts +2 -2
  312. package/src/__tests__/TransactionGroupResolver.refusals.test.ts +290 -0
  313. package/src/__tests__/WidgetSessionService.test.ts +8 -4
  314. package/src/__tests__/adhoc-query-helpers.test.ts +21 -21
  315. package/src/__tests__/bootAudit.test.ts +11 -11
  316. package/src/__tests__/boundaryLogPayload.test.ts +6 -6
  317. package/src/__tests__/databaseAbstraction.test.ts +12 -6
  318. package/src/__tests__/getDataTokenRedaction.test.ts +7 -7
  319. package/src/__tests__/initializeProviders.refresh.test.ts +4 -4
  320. package/src/__tests__/magicLink.test.ts +73 -134
  321. package/src/__tests__/magicLinkService.consume.test.ts +224 -0
  322. package/src/__tests__/meetingRecordingRegistration.test.ts +12 -12
  323. package/src/__tests__/metadataRefreshSignal.test.ts +78 -0
  324. package/src/__tests__/multiTenancy.security.test.ts +40 -40
  325. package/src/__tests__/multiTenancy.test.ts +18 -18
  326. package/src/__tests__/newUsers.test.ts +24 -23
  327. package/src/__tests__/principals.test.ts +22 -22
  328. package/src/__tests__/pushStatusResolver.filter.test.ts +8 -8
  329. package/src/__tests__/secretRedactor.failOpen.test.ts +12 -12
  330. package/src/__tests__/secretRedactor.test.ts +12 -12
  331. package/src/__tests__/serverExtensionReservedRoots.test.ts +7 -7
  332. package/src/__tests__/subscriptionRedaction.test.ts +5 -5
  333. package/src/__tests__/unifiedAuth.test.ts +15 -9
  334. package/src/__tests__/visitorIdentity.resolve.test.ts +6 -6
  335. package/src/__tests__/widget.test.ts +45 -45
  336. package/src/__tests__/widgetGuestElevation.test.ts +7 -7
  337. package/src/__tests__/widgetHostIdentity.test.ts +14 -14
  338. package/src/agentSessions/ReturningVisitorRecap.ts +12 -1
  339. package/src/agentSessions/SessionManager.ts +2 -2
  340. package/src/agentSessions/remoteBrowserGoalEngine.ts +30 -5
  341. package/src/auth/AuthProviderCatalogRouter.ts +6 -1
  342. package/src/auth/__tests__/backward-compatibility.test.ts +3 -3
  343. package/src/auth/exampleNewUserSubClass.ts +2 -2
  344. package/src/auth/index.ts +43 -28
  345. package/src/auth/initializeProviders.ts +25 -5
  346. package/src/auth/magicLink/MagicLinkRouter.ts +28 -10
  347. package/src/auth/magicLink/MagicLinkService.ts +71 -52
  348. package/src/auth/magicLink/index.ts +7 -7
  349. package/src/auth/magicLink/magicLinkCore.ts +96 -64
  350. package/src/auth/magicLink/redeemLanding.ts +14 -4
  351. package/src/auth/magicLink/types.ts +54 -54
  352. package/src/auth/newUsers.ts +1 -1
  353. package/src/auth/principals.ts +11 -2
  354. package/src/cache.ts +4 -1
  355. package/src/config.ts +14 -4
  356. package/src/context.ts +37 -24
  357. package/src/directives/Public.ts +4 -1
  358. package/src/directives/RequireSystemUser.ts +4 -1
  359. package/src/generated/graphql-schemas/__mj.ts +933 -5
  360. package/src/generic/CacheInvalidationResolver.ts +12 -4
  361. package/src/generic/FireAndForgetHeartbeat.ts +19 -14
  362. package/src/generic/PushStatusResolver.ts +21 -7
  363. package/src/generic/ResolverBase.ts +66 -5
  364. package/src/generic/RunViewResolver.ts +22 -22
  365. package/src/generic/__tests__/FireAndForgetHeartbeat.test.ts +7 -7
  366. package/src/index.ts +34 -7
  367. package/src/integration/CustomColumnPromoter.ts +6 -1
  368. package/src/integration/EntityMapLifecycle.ts +20 -2
  369. package/src/logging/NoLog.ts +16 -2
  370. package/src/logging/StartupLogger.ts +6 -1
  371. package/src/logging/bootAudit.ts +26 -16
  372. package/src/logging/boundaryLogPayload.ts +8 -1
  373. package/src/logging/secretRedactor.ts +14 -9
  374. package/src/logging/shortenForLog.ts +8 -3
  375. package/src/logging/variablesLoggingMiddleware.ts +9 -6
  376. package/src/metadataRefreshSignal.ts +45 -0
  377. package/src/middleware/MJTenantFilterMiddleware.ts +4 -4
  378. package/src/multiTenancy/index.ts +29 -5
  379. package/src/realtimeWidget/WidgetRouter.ts +15 -10
  380. package/src/realtimeWidget/WidgetSessionService.ts +76 -76
  381. package/src/realtimeWidget/host-identity.ts +24 -10
  382. package/src/realtimeWidget/index.ts +3 -3
  383. package/src/realtimeWidget/visitorIdentity.ts +39 -8
  384. package/src/realtimeWidget/widgetCore.ts +75 -10
  385. package/src/realtimeWidget/widgetGuestElevation.ts +25 -12
  386. package/src/resolvers/AdhocQueryResolver.ts +3 -3
  387. package/src/resolvers/AgentSessionResolver.ts +3 -3
  388. package/src/resolvers/ColorResolver.ts +6 -6
  389. package/src/resolvers/ComponentRegistryResolver.ts +36 -36
  390. package/src/resolvers/EntityCommunicationsResolver.ts +4 -4
  391. package/src/resolvers/ExecuteRemoteOperationResolver.ts +9 -9
  392. package/src/resolvers/FetchEntityVectorsResolver.ts +2 -2
  393. package/src/resolvers/FileResolver.ts +42 -42
  394. package/src/resolvers/GeoResolver.ts +4 -4
  395. package/src/resolvers/GetDataResolver.ts +50 -15
  396. package/src/resolvers/IntegrationDiscoveryResolver.ts +2 -2
  397. package/src/resolvers/ListOperationsResolver.ts +78 -28
  398. package/src/resolvers/MCPResolver.ts +30 -15
  399. package/src/resolvers/QueryResolver.ts +13 -13
  400. package/src/resolvers/QuerySystemUserResolver.ts +2 -1
  401. package/src/resolvers/RealtimeBridgeResolver.ts +3 -3
  402. package/src/resolvers/RealtimeClientSessionResolver.ts +126 -13
  403. package/src/resolvers/RemoteBrowserActionResolver.ts +5 -5
  404. package/src/resolvers/RunAIAgentResolver.ts +118 -76
  405. package/src/resolvers/RunAIPromptResolver.ts +22 -22
  406. package/src/resolvers/RunTemplateResolver.ts +4 -4
  407. package/src/resolvers/RunTestResolver.ts +25 -25
  408. package/src/resolvers/SearchEntitiesResolver.ts +3 -1
  409. package/src/resolvers/SearchKnowledgeResolver.ts +4 -0
  410. package/src/resolvers/SearchKnowledgeSystemUserResolver.ts +1 -0
  411. package/src/resolvers/SqlLoggingConfigResolver.ts +56 -56
  412. package/src/resolvers/TaskGraphFrameResolver.ts +37 -28
  413. package/src/resolvers/TelemetryResolver.ts +79 -79
  414. package/src/resolvers/TransactionGroupResolver.ts +57 -4
  415. package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +40 -38
  416. package/src/resolvers/__tests__/artifact-routing.test.ts +23 -23
  417. package/src/resolvers/adhoc-query-helpers.ts +19 -2
  418. package/src/resolvers/artifact-routing.ts +19 -19
  419. package/src/resolvers/meetingRecordingRegistration.ts +44 -10
  420. package/src/resolvers/peaksSidecar.ts +12 -2
  421. package/src/rest/EntityCRUDHandler.ts +24 -4
  422. package/src/rest/MediaStreamHandler.ts +11 -6
  423. package/src/rest/OAuthCallbackHandler.ts +25 -7
  424. package/src/rest/RESTEndpointHandler.ts +20 -15
  425. package/src/rest/RealtimeSdpBrokerHandler.ts +14 -4
  426. package/src/rest/SignatureWebhookHandler.ts +6 -1
  427. package/src/rest/UploadTokenManager.ts +66 -30
  428. package/src/rest/ViewOperationsHandler.ts +24 -4
  429. package/src/rest/mediaRange.ts +16 -6
  430. package/src/rest/setupRESTEndpoints.ts +24 -12
  431. package/src/serverExtensionReservedRoots.ts +6 -1
  432. package/src/services/MJStorageBlobStore.ts +209 -0
  433. package/src/services/TaskGraphActionRunner.ts +16 -15
  434. package/src/types.ts +21 -16
  435. package/src/util.ts +22 -9
@@ -7,11 +7,11 @@
7
7
  */
8
8
  import { describe, it, expect, vi } from 'vitest';
9
9
  import {
10
- createTenantPreRunViewHook,
11
- createTenantPreSaveHook,
12
- createTenantMiddleware,
10
+ CreateTenantPreRunViewHook,
11
+ CreateTenantPreSaveHook,
12
+ CreateTenantMiddleware,
13
13
  IsValidTenantId,
14
- attachTenantContext,
14
+ AttachTenantContext,
15
15
  } from '../multiTenancy/index.js';
16
16
  import type { MultiTenancyConfig } from '../config.js';
17
17
  import { Metadata } from '@memberjunction/core';
@@ -76,7 +76,7 @@ function makeConfig(overrides: Partial<MultiTenancyConfig> = {}): MultiTenancyCo
76
76
  };
77
77
  }
78
78
 
79
- type MockUser = Parameters<ReturnType<typeof createTenantPreRunViewHook>>[1];
79
+ type MockUser = Parameters<ReturnType<typeof CreateTenantPreRunViewHook>>[1];
80
80
 
81
81
  function makeUser(tenantId?: string, roles: string[] = []): MockUser {
82
82
  return {
@@ -91,7 +91,7 @@ function makeUser(tenantId?: string, roles: string[] = []): MockUser {
91
91
  describe('Multi-Tenancy Security Edge Cases', () => {
92
92
  describe('SQL injection in tenant ID', () => {
93
93
  it('should escape quotes so an injection attempt stays INSIDE the string literal', () => {
94
- const hook = createTenantPreRunViewHook(makeConfig());
94
+ const hook = CreateTenantPreRunViewHook(makeConfig());
95
95
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
96
96
  const user = makeUser("' OR 1=1 --");
97
97
 
@@ -105,7 +105,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
105
105
  });
106
106
 
107
107
  it('should escape quotes in a UNION attack payload', () => {
108
- const hook = createTenantPreRunViewHook(makeConfig());
108
+ const hook = CreateTenantPreRunViewHook(makeConfig());
109
109
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
110
110
  const user = makeUser("' UNION SELECT * FROM Users --");
111
111
 
@@ -115,7 +115,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
115
115
  });
116
116
 
117
117
  it('should escape quotes in a stacked-statement payload', () => {
118
- const hook = createTenantPreRunViewHook(makeConfig());
118
+ const hook = CreateTenantPreRunViewHook(makeConfig());
119
119
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
120
120
  const user = makeUser("abc'; DROP TABLE Customers; --");
121
121
 
@@ -177,19 +177,19 @@ describe('Multi-Tenancy Security Edge Cases', () => {
177
177
 
178
178
  it('throws on an invalid tenant id instead of attaching it', () => {
179
179
  const user = makePlainUser();
180
- expect(() => attachTenantContext(user, "x' OR '1'='1", 'header')).toThrow(/Invalid tenant identifier/);
180
+ expect(() => AttachTenantContext(user, "x' OR '1'='1", 'header')).toThrow(/Invalid tenant identifier/);
181
181
  expect(user.TenantContext).toBeUndefined();
182
182
  });
183
183
 
184
184
  it('throws on empty and oversized tenant ids', () => {
185
185
  const user = makePlainUser();
186
- expect(() => attachTenantContext(user, '', 'custom')).toThrow(/Invalid tenant identifier/);
187
- expect(() => attachTenantContext(user, 'a'.repeat(129), 'custom')).toThrow(/Invalid tenant identifier/);
186
+ expect(() => AttachTenantContext(user, '', 'custom')).toThrow(/Invalid tenant identifier/);
187
+ expect(() => AttachTenantContext(user, 'a'.repeat(129), 'custom')).toThrow(/Invalid tenant identifier/);
188
188
  });
189
189
 
190
190
  it('attaches a valid tenant id with the given source', () => {
191
191
  const user = makePlainUser();
192
- attachTenantContext(user, 'tenant_1.a-b', 'linkedEntity');
192
+ AttachTenantContext(user, 'tenant_1.a-b', 'linkedEntity');
193
193
  expect(user.TenantContext).toEqual<TenantContext>({ TenantID: 'tenant_1.a-b', Source: 'linkedEntity' });
194
194
  });
195
195
  });
@@ -198,7 +198,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
198
198
 
199
199
  describe('tenant column must resolve to a stored field', () => {
200
200
  it('produces an escaped-value predicate with a quoted identifier for a valid setup', () => {
201
- const hook = createTenantPreRunViewHook(makeConfig());
201
+ const hook = CreateTenantPreRunViewHook(makeConfig());
202
202
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
203
203
  const user = makeUser("t'1"); // legal only via non-header sources; must still be escaped
204
204
 
@@ -207,7 +207,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
207
207
  });
208
208
 
209
209
  it('throws when the configured tenant column does not exist on the entity', () => {
210
- const hook = createTenantPreRunViewHook(makeConfig({ defaultTenantColumn: 'NoSuchColumn' }));
210
+ const hook = CreateTenantPreRunViewHook(makeConfig({ defaultTenantColumn: 'NoSuchColumn' }));
211
211
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
212
212
  const user = makeUser('tenant-1');
213
213
 
@@ -215,7 +215,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
215
215
  });
216
216
 
217
217
  it('throws when the tenant column resolves only to a VIRTUAL field', () => {
218
- const hook = createTenantPreRunViewHook(makeConfig({ defaultTenantColumn: 'OrganizationName' }));
218
+ const hook = CreateTenantPreRunViewHook(makeConfig({ defaultTenantColumn: 'OrganizationName' }));
219
219
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
220
220
  const user = makeUser('tenant-1');
221
221
 
@@ -223,7 +223,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
223
223
  });
224
224
 
225
225
  it('throws when an entityColumnMappings override points at a nonexistent column', () => {
226
- const hook = createTenantPreRunViewHook(makeConfig({
226
+ const hook = CreateTenantPreRunViewHook(makeConfig({
227
227
  entityColumnMappings: { 'Customers': "Bad]Column" },
228
228
  }));
229
229
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
@@ -237,7 +237,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
237
237
  // @ts-expect-error — simulating the no-provider-available case
238
238
  Metadata.Provider = undefined;
239
239
  try {
240
- const hook = createTenantPreRunViewHook(makeConfig());
240
+ const hook = CreateTenantPreRunViewHook(makeConfig());
241
241
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
242
242
  const user = makeUser('tenant-1');
243
243
 
@@ -255,7 +255,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
255
255
 
256
256
  describe('Tenant ID boundary values', () => {
257
257
  it('should not filter when tenant ID is empty string (falsy)', () => {
258
- const hook = createTenantPreRunViewHook(makeConfig());
258
+ const hook = CreateTenantPreRunViewHook(makeConfig());
259
259
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
260
260
  // Empty string is falsy → makeUser sets TenantContext = undefined
261
261
  // This matches createTenantMiddleware behavior: `if (tenantId)` skips empty strings
@@ -267,7 +267,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
267
267
 
268
268
  it('should handle very long tenant ID', () => {
269
269
  const longId = 'a'.repeat(1000);
270
- const hook = createTenantPreRunViewHook(makeConfig());
270
+ const hook = CreateTenantPreRunViewHook(makeConfig());
271
271
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
272
272
  const user = makeUser(longId);
273
273
 
@@ -277,7 +277,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
277
277
 
278
278
  it('should handle UUID tenant ID (standard format)', () => {
279
279
  const uuid = '550e8400-e29b-41d4-a716-446655440000';
280
- const hook = createTenantPreRunViewHook(makeConfig());
280
+ const hook = CreateTenantPreRunViewHook(makeConfig());
281
281
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
282
282
  const user = makeUser(uuid);
283
283
 
@@ -286,7 +286,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
286
286
  });
287
287
 
288
288
  it('should handle tenant ID with special characters', () => {
289
- const hook = createTenantPreRunViewHook(makeConfig());
289
+ const hook = CreateTenantPreRunViewHook(makeConfig());
290
290
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
291
291
  const user = makeUser('tenant<script>alert(1)</script>');
292
292
 
@@ -299,7 +299,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
299
299
 
300
300
  describe('Admin role matching', () => {
301
301
  it('should be case-insensitive for admin role matching', () => {
302
- const hook = createTenantPreRunViewHook(makeConfig({ adminRoles: ['Admin'] }));
302
+ const hook = CreateTenantPreRunViewHook(makeConfig({ adminRoles: ['Admin'] }));
303
303
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
304
304
 
305
305
  // User role is 'admin' (lowercase), config has 'Admin'
@@ -309,7 +309,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
309
309
  });
310
310
 
311
311
  it('should handle whitespace in role names', () => {
312
- const hook = createTenantPreRunViewHook(makeConfig({ adminRoles: [' Admin '] }));
312
+ const hook = CreateTenantPreRunViewHook(makeConfig({ adminRoles: [' Admin '] }));
313
313
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
314
314
 
315
315
  const user = makeUser('tenant-1', ['Admin']);
@@ -318,7 +318,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
318
318
  });
319
319
 
320
320
  it('should not bypass for non-admin roles', () => {
321
- const hook = createTenantPreRunViewHook(makeConfig({ adminRoles: ['Admin'] }));
321
+ const hook = CreateTenantPreRunViewHook(makeConfig({ adminRoles: ['Admin'] }));
322
322
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
323
323
 
324
324
  const user = makeUser('tenant-1', ['User', 'Editor']);
@@ -327,7 +327,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
327
327
  });
328
328
 
329
329
  it('should handle user with empty roles array', () => {
330
- const hook = createTenantPreRunViewHook(makeConfig());
330
+ const hook = CreateTenantPreRunViewHook(makeConfig());
331
331
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
332
332
 
333
333
  const user = makeUser('tenant-1', []);
@@ -340,7 +340,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
340
340
 
341
341
  describe('Entity name matching', () => {
342
342
  it('should be case-insensitive for entity names in allowlist', () => {
343
- const hook = createTenantPreRunViewHook(makeConfig({
343
+ const hook = CreateTenantPreRunViewHook(makeConfig({
344
344
  scopingStrategy: 'allowlist',
345
345
  scopedEntities: ['customers'],
346
346
  }));
@@ -352,7 +352,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
352
352
  });
353
353
 
354
354
  it('should handle whitespace in entity names', () => {
355
- const hook = createTenantPreRunViewHook(makeConfig({
355
+ const hook = CreateTenantPreRunViewHook(makeConfig({
356
356
  scopingStrategy: 'allowlist',
357
357
  scopedEntities: [' Customers '],
358
358
  }));
@@ -364,7 +364,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
364
364
  });
365
365
 
366
366
  it('should not filter when EntityName is missing from params', () => {
367
- const hook = createTenantPreRunViewHook(makeConfig());
367
+ const hook = CreateTenantPreRunViewHook(makeConfig());
368
368
  const params = { ExtraFilter: '' } as RunViewParams;
369
369
  const user = makeUser('tenant-1');
370
370
 
@@ -377,7 +377,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
377
377
 
378
378
  describe('createTenantMiddleware', () => {
379
379
  it('should skip tenant resolution when no userPayload on request', () => {
380
- const middleware = createTenantMiddleware(makeConfig());
380
+ const middleware = CreateTenantMiddleware(makeConfig());
381
381
  const req = { headers: { 'x-tenant-id': 'tenant-1' } } as unknown as Parameters<typeof middleware>[0];
382
382
  const res = {} as Parameters<typeof middleware>[1];
383
383
  const next = vi.fn();
@@ -388,7 +388,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
388
388
  });
389
389
 
390
390
  it('should attach TenantContext to a CLONED userRecord when userPayload and header are present', () => {
391
- const middleware = createTenantMiddleware(makeConfig());
391
+ const middleware = CreateTenantMiddleware(makeConfig());
392
392
  const userRecord = { ID: 'u1' } as Record<string, unknown>;
393
393
  const userPayload = { userRecord, email: 'test@test.com', sessionId: 's1' };
394
394
  const req = {
@@ -414,7 +414,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
414
414
  });
415
415
 
416
416
  it('should reject an invalid tenant header with 400 and never attach or continue', () => {
417
- const middleware = createTenantMiddleware(makeConfig());
417
+ const middleware = CreateTenantMiddleware(makeConfig());
418
418
  const userRecord = { ID: 'u1' } as Record<string, unknown>;
419
419
  const userPayload = { userRecord, email: 'test@test.com', sessionId: 's1' };
420
420
  const req = {
@@ -437,7 +437,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
437
437
  });
438
438
 
439
439
  it('should handle case-insensitive header name', () => {
440
- const middleware = createTenantMiddleware(makeConfig({ tenantHeader: 'X-Tenant-ID' }));
440
+ const middleware = CreateTenantMiddleware(makeConfig({ tenantHeader: 'X-Tenant-ID' }));
441
441
  const userRecord = { ID: 'u1' } as Record<string, unknown>;
442
442
  const userPayload = { userRecord, email: 'test@test.com', sessionId: 's1' };
443
443
  const req = {
@@ -457,7 +457,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
457
457
  });
458
458
 
459
459
  it('should not set TenantContext when header is missing', () => {
460
- const middleware = createTenantMiddleware(makeConfig());
460
+ const middleware = CreateTenantMiddleware(makeConfig());
461
461
  const userRecord = { ID: 'u1' } as Record<string, unknown>;
462
462
  const req = {
463
463
  headers: {},
@@ -472,7 +472,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
472
472
  });
473
473
 
474
474
  it('should reject a repeated header (array value) with 400 rather than guessing which value applies', () => {
475
- const middleware = createTenantMiddleware(makeConfig());
475
+ const middleware = CreateTenantMiddleware(makeConfig());
476
476
  const userRecord = { ID: 'u1' } as Record<string, unknown>;
477
477
  const userPayload = { userRecord, email: 'test@test.com', sessionId: 's1' };
478
478
  const req = {
@@ -494,7 +494,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
494
494
  });
495
495
 
496
496
  it('two concurrent requests for the same shared user with different headers do not cross-contaminate', () => {
497
- const middleware = createTenantMiddleware(makeConfig());
497
+ const middleware = CreateTenantMiddleware(makeConfig());
498
498
  const sharedUserRecord = { ID: 'u1', UserRoles: [] } as unknown as Record<string, unknown>;
499
499
 
500
500
  const reqA = {
@@ -527,11 +527,11 @@ describe('Multi-Tenancy Security Edge Cases', () => {
527
527
  IsSaved: isSaved,
528
528
  Get: vi.fn((col: string) => col === 'OrganizationID' ? tenantValue : null),
529
529
  Set: vi.fn(),
530
- } as unknown as Parameters<ReturnType<typeof createTenantPreSaveHook>>[0];
530
+ } as unknown as Parameters<ReturnType<typeof CreateTenantPreSaveHook>>[0];
531
531
  }
532
532
 
533
533
  it('should reject save with SQL injection in entity tenant column', () => {
534
- const hook = createTenantPreSaveHook(makeConfig());
534
+ const hook = CreateTenantPreSaveHook(makeConfig());
535
535
  const entity = makeEntity('Customers', "' OR 1=1 --", true);
536
536
  const user = makeUser('tenant-abc');
537
537
 
@@ -541,13 +541,13 @@ describe('Multi-Tenancy Security Edge Cases', () => {
541
541
  });
542
542
 
543
543
  it('should auto-assign tenant for new record even when entity has no EntityInfo', () => {
544
- const hook = createTenantPreSaveHook(makeConfig());
544
+ const hook = CreateTenantPreSaveHook(makeConfig());
545
545
  const entity = {
546
546
  EntityInfo: undefined,
547
547
  IsSaved: false,
548
548
  Get: vi.fn(() => null),
549
549
  Set: vi.fn(),
550
- } as unknown as Parameters<ReturnType<typeof createTenantPreSaveHook>>[0];
550
+ } as unknown as Parameters<ReturnType<typeof CreateTenantPreSaveHook>>[0];
551
551
  const user = makeUser('tenant-abc');
552
552
 
553
553
  // No EntityInfo → no entity name → not scoped → allow
@@ -556,7 +556,7 @@ describe('Multi-Tenancy Security Edge Cases', () => {
556
556
  });
557
557
 
558
558
  it('should handle null contextUser gracefully', () => {
559
- const hook = createTenantPreSaveHook(makeConfig());
559
+ const hook = CreateTenantPreSaveHook(makeConfig());
560
560
  const entity = makeEntity('Customers', 'tenant-abc', true);
561
561
 
562
562
  const result = hook(entity, undefined);
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { createTenantPreRunViewHook, createTenantPreSaveHook } from '../multiTenancy/index.js';
2
+ import { CreateTenantPreRunViewHook, CreateTenantPreSaveHook } from '../multiTenancy/index.js';
3
3
  import type { MultiTenancyConfig } from '../config.js';
4
4
  import type { RunViewParams } from '@memberjunction/core';
5
5
 
@@ -66,13 +66,13 @@ function makeUser(tenantId?: string, roles: string[] = []) {
66
66
  ID: 'user-1',
67
67
  TenantContext: tenantId ? { TenantID: tenantId, Source: 'header' as const } : undefined,
68
68
  UserRoles: roles.map(r => ({ Role: r, RoleID: `role-${r}`, UserID: 'user-1' })),
69
- } as Parameters<ReturnType<typeof createTenantPreRunViewHook>>[1];
69
+ } as Parameters<ReturnType<typeof CreateTenantPreRunViewHook>>[1];
70
70
  }
71
71
 
72
72
  describe('Multi-Tenancy Hooks', () => {
73
73
  describe('createTenantPreRunViewHook', () => {
74
74
  it('should inject tenant filter for scoped entity', () => {
75
- const hook = createTenantPreRunViewHook(makeConfig());
75
+ const hook = CreateTenantPreRunViewHook(makeConfig());
76
76
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
77
77
  const user = makeUser('tenant-abc');
78
78
 
@@ -81,7 +81,7 @@ describe('Multi-Tenancy Hooks', () => {
81
81
  });
82
82
 
83
83
  it('should AND with existing filter', () => {
84
- const hook = createTenantPreRunViewHook(makeConfig());
84
+ const hook = CreateTenantPreRunViewHook(makeConfig());
85
85
  const params = { EntityName: 'Customers', ExtraFilter: "Status = 'Active'" } as RunViewParams;
86
86
  const user = makeUser('tenant-abc');
87
87
 
@@ -92,7 +92,7 @@ describe('Multi-Tenancy Hooks', () => {
92
92
  });
93
93
 
94
94
  it('should skip core __mj entities when autoExcludeCoreEntities is true', () => {
95
- const hook = createTenantPreRunViewHook(makeConfig());
95
+ const hook = CreateTenantPreRunViewHook(makeConfig());
96
96
  const params = { EntityName: 'AI Models', ExtraFilter: '' } as RunViewParams;
97
97
  const user = makeUser('tenant-abc');
98
98
 
@@ -101,7 +101,7 @@ describe('Multi-Tenancy Hooks', () => {
101
101
  });
102
102
 
103
103
  it('should not filter when user has no TenantContext', () => {
104
- const hook = createTenantPreRunViewHook(makeConfig());
104
+ const hook = CreateTenantPreRunViewHook(makeConfig());
105
105
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
106
106
  const user = makeUser(undefined);
107
107
 
@@ -110,7 +110,7 @@ describe('Multi-Tenancy Hooks', () => {
110
110
  });
111
111
 
112
112
  it('should bypass filtering for admin users', () => {
113
- const hook = createTenantPreRunViewHook(makeConfig());
113
+ const hook = CreateTenantPreRunViewHook(makeConfig());
114
114
  const params = { EntityName: 'Customers', ExtraFilter: '' } as RunViewParams;
115
115
  const user = makeUser('tenant-abc', ['Admin']);
116
116
 
@@ -119,7 +119,7 @@ describe('Multi-Tenancy Hooks', () => {
119
119
  });
120
120
 
121
121
  it('should use entity column mapping override', () => {
122
- const hook = createTenantPreRunViewHook(makeConfig({
122
+ const hook = CreateTenantPreRunViewHook(makeConfig({
123
123
  entityColumnMappings: { 'Orders': 'TenantID' },
124
124
  }));
125
125
  const params = { EntityName: 'Orders', ExtraFilter: '' } as RunViewParams;
@@ -130,7 +130,7 @@ describe('Multi-Tenancy Hooks', () => {
130
130
  });
131
131
 
132
132
  it('should respect allowlist scoping strategy', () => {
133
- const hook = createTenantPreRunViewHook(makeConfig({
133
+ const hook = CreateTenantPreRunViewHook(makeConfig({
134
134
  scopingStrategy: 'allowlist',
135
135
  scopedEntities: ['Customers'],
136
136
  }));
@@ -148,7 +148,7 @@ describe('Multi-Tenancy Hooks', () => {
148
148
  });
149
149
 
150
150
  it('should respect denylist scoping strategy', () => {
151
- const hook = createTenantPreRunViewHook(makeConfig({
151
+ const hook = CreateTenantPreRunViewHook(makeConfig({
152
152
  scopingStrategy: 'denylist',
153
153
  scopedEntities: ['Orders'],
154
154
  }));
@@ -173,11 +173,11 @@ describe('Multi-Tenancy Hooks', () => {
173
173
  IsSaved: isSaved,
174
174
  Get: vi.fn((col: string) => col === 'OrganizationID' ? tenantValue : null),
175
175
  Set: vi.fn(),
176
- } as unknown as Parameters<ReturnType<typeof createTenantPreSaveHook>>[0];
176
+ } as unknown as Parameters<ReturnType<typeof CreateTenantPreSaveHook>>[0];
177
177
  }
178
178
 
179
179
  it('should allow save when tenant matches', () => {
180
- const hook = createTenantPreSaveHook(makeConfig());
180
+ const hook = CreateTenantPreSaveHook(makeConfig());
181
181
  const entity = makeEntity('Customers', 'tenant-abc', true);
182
182
  const user = makeUser('tenant-abc');
183
183
 
@@ -186,7 +186,7 @@ describe('Multi-Tenancy Hooks', () => {
186
186
  });
187
187
 
188
188
  it('should reject save in strict mode when tenant mismatches', () => {
189
- const hook = createTenantPreSaveHook(makeConfig());
189
+ const hook = CreateTenantPreSaveHook(makeConfig());
190
190
  const entity = makeEntity('Customers', 'tenant-other', true);
191
191
  const user = makeUser('tenant-abc');
192
192
 
@@ -197,7 +197,7 @@ describe('Multi-Tenancy Hooks', () => {
197
197
 
198
198
  it('should warn but allow in log mode when tenant mismatches', () => {
199
199
  const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
200
- const hook = createTenantPreSaveHook(makeConfig({ writeProtection: 'log' }));
200
+ const hook = CreateTenantPreSaveHook(makeConfig({ writeProtection: 'log' }));
201
201
  const entity = makeEntity('Customers', 'tenant-other', true);
202
202
  const user = makeUser('tenant-abc');
203
203
 
@@ -208,7 +208,7 @@ describe('Multi-Tenancy Hooks', () => {
208
208
  });
209
209
 
210
210
  it('should allow when writeProtection is off', () => {
211
- const hook = createTenantPreSaveHook(makeConfig({ writeProtection: 'off' }));
211
+ const hook = CreateTenantPreSaveHook(makeConfig({ writeProtection: 'off' }));
212
212
  const entity = makeEntity('Customers', 'tenant-other', true);
213
213
  const user = makeUser('tenant-abc');
214
214
 
@@ -217,7 +217,7 @@ describe('Multi-Tenancy Hooks', () => {
217
217
  });
218
218
 
219
219
  it('should auto-assign tenant for new records without tenant value', () => {
220
- const hook = createTenantPreSaveHook(makeConfig());
220
+ const hook = CreateTenantPreSaveHook(makeConfig());
221
221
  const entity = makeEntity('Customers', null, false);
222
222
  const user = makeUser('tenant-abc');
223
223
 
@@ -227,7 +227,7 @@ describe('Multi-Tenancy Hooks', () => {
227
227
  });
228
228
 
229
229
  it('should bypass validation for admin users', () => {
230
- const hook = createTenantPreSaveHook(makeConfig());
230
+ const hook = CreateTenantPreSaveHook(makeConfig());
231
231
  const entity = makeEntity('Customers', 'tenant-other', true);
232
232
  const user = makeUser('tenant-abc', ['Admin']);
233
233
 
@@ -236,7 +236,7 @@ describe('Multi-Tenancy Hooks', () => {
236
236
  });
237
237
 
238
238
  it('should skip core __mj entities', () => {
239
- const hook = createTenantPreSaveHook(makeConfig());
239
+ const hook = CreateTenantPreSaveHook(makeConfig());
240
240
  const entity = makeEntity('AI Models', 'any-tenant', true);
241
241
  const user = makeUser('tenant-abc');
242
242
 
@@ -168,7 +168,8 @@ vi.mock('@memberjunction/global', async (importOriginal) => {
168
168
  };
169
169
  });
170
170
 
171
- vi.mock('../auth/initializeProviders.js', () => ({ initializeAuthProviders: vi.fn() }));
171
+ vi.mock('../auth/initializeProviders.js', () => ({ InitializeAuthProviders: vi.fn(),
172
+ get initializeAuthProviders() { return this.InitializeAuthProviders; } }));
172
173
 
173
174
  vi.mock('@memberjunction/auth-providers', () => ({
174
175
  AuthProviderFactory: {
@@ -195,7 +196,7 @@ vi.mock('@memberjunction/api-keys', () => ({
195
196
 
196
197
  // ─── Import after mocks ─────────────────────────────────────────────────────
197
198
  import { NewUserBase } from '../auth/newUsers.js';
198
- import { verifyUserRecord } from '../auth/index.js';
199
+ import { VerifyUserRecord } from '../auth/index.js';
199
200
 
200
201
  // ─── Mock-entity plumbing ───────────────────────────────────────────────────
201
202
 
@@ -557,7 +558,7 @@ describe('verifyUserRecord', () => {
557
558
  }
558
559
 
559
560
  it('returns undefined when no email is supplied', async () => {
560
- const user = await verifyUserRecord(undefined, 'A', 'B');
561
+ const user = await VerifyUserRecord(undefined, 'A', 'B');
561
562
 
562
563
  expect(user).toBeUndefined();
563
564
  expect(mockGetEntityObject).not.toHaveBeenCalled();
@@ -566,7 +567,7 @@ describe('verifyUserRecord', () => {
566
567
  it('returns the cached user, matching email case-insensitively and trimmed', async () => {
567
568
  addCacheUser('someone@example.com');
568
569
 
569
- const user = await verifyUserRecord(' SomeOne@Example.COM ', 'A', 'B');
570
+ const user = await VerifyUserRecord(' SomeOne@Example.COM ', 'A', 'B');
570
571
 
571
572
  expect(user).toBeDefined();
572
573
  expect((user as unknown as { Email: string }).Email).toBe('someone@example.com');
@@ -577,7 +578,7 @@ describe('verifyUserRecord', () => {
577
578
  mockCacheUsers.push({ ID: 'broken-1', Name: 'Broken', Email: ' ', Type: 'User' });
578
579
  const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined);
579
580
 
580
- const user = await verifyUserRecord('missing@example.com', undefined, undefined);
581
+ const user = await VerifyUserRecord('missing@example.com', undefined, undefined);
581
582
 
582
583
  expect(user).toBeUndefined();
583
584
  expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining('broken-1'));
@@ -587,15 +588,15 @@ describe('verifyUserRecord', () => {
587
588
  it('does NOT create a user when autoCreateNewUsers is false', async () => {
588
589
  mockConfig.userHandling.autoCreateNewUsers = false;
589
590
 
590
- const user = await verifyUserRecord('new@example.com', 'New', 'User');
591
+ const user = await VerifyUserRecord('new@example.com', 'New', 'User');
591
592
 
592
593
  expect(user).toBeUndefined();
593
594
  expect(mockGetEntityObject).not.toHaveBeenCalled();
594
595
  });
595
596
 
596
597
  it('does NOT create a user when firstName or lastName is missing', async () => {
597
- const missingFirst = await verifyUserRecord('new@example.com', undefined, 'User');
598
- const missingLast = await verifyUserRecord('new@example.com', 'New', undefined);
598
+ const missingFirst = await VerifyUserRecord('new@example.com', undefined, 'User');
599
+ const missingLast = await VerifyUserRecord('new@example.com', 'New', undefined);
599
600
 
600
601
  expect(missingFirst).toBeUndefined();
601
602
  expect(missingLast).toBeUndefined();
@@ -605,7 +606,7 @@ describe('verifyUserRecord', () => {
605
606
  it('creates the user when enabled and domains are unrestricted, stamping config roles onto the returned UserInfo', async () => {
606
607
  mockConfig.userHandling.newUserRoles = ['UI', 'Developer'];
607
608
 
608
- const user = await verifyUserRecord('new@example.com', 'New', 'User');
609
+ const user = await VerifyUserRecord('new@example.com', 'New', 'User');
609
610
 
610
611
  expect(user).toBeDefined();
611
612
  const stamped = user as unknown as { Email: string; UserRoles: Array<{ Role: string; RoleID: string; UserID: string }> };
@@ -621,7 +622,7 @@ describe('verifyUserRecord', () => {
621
622
  it('returns undefined when the underlying createNewUser fails', async () => {
622
623
  saveBehavior['MJ: Users'] = () => false;
623
624
 
624
- const user = await verifyUserRecord('new@example.com', 'New', 'User');
625
+ const user = await VerifyUserRecord('new@example.com', 'New', 'User');
625
626
 
626
627
  expect(user).toBeUndefined();
627
628
  // The cache is no longer empty at rest (it holds the configured context user), so
@@ -637,35 +638,35 @@ describe('verifyUserRecord', () => {
637
638
  });
638
639
 
639
640
  it('creates the user when the email domain is authorized', async () => {
640
- const user = await verifyUserRecord('new@example.com', 'New', 'User');
641
+ const user = await VerifyUserRecord('new@example.com', 'New', 'User');
641
642
 
642
643
  expect(user).toBeDefined();
643
644
  expect(entitiesOf('MJ: Users')).toHaveLength(1);
644
645
  });
645
646
 
646
647
  it('does NOT create when the email domain is not authorized', async () => {
647
- const user = await verifyUserRecord('new@evil.com', 'New', 'User');
648
+ const user = await VerifyUserRecord('new@evil.com', 'New', 'User');
648
649
 
649
650
  expect(user).toBeUndefined();
650
651
  expect(mockGetEntityObject).not.toHaveBeenCalled();
651
652
  });
652
653
 
653
654
  it('creates when restricted and no request Origin is supplied, if the email domain is authorized', async () => {
654
- const user = await verifyUserRecord('new@example.com', 'New', 'User', undefined);
655
+ const user = await VerifyUserRecord('new@example.com', 'New', 'User', undefined);
655
656
 
656
657
  expect(user).toBeDefined();
657
658
  expect(entitiesOf('MJ: Users')).toHaveLength(1);
658
659
  });
659
660
 
660
661
  it('does NOT create when a forged Origin is authorized but the email domain is not', async () => {
661
- const user = await verifyUserRecord('new@evil.com', 'New', 'User', 'example.com');
662
+ const user = await VerifyUserRecord('new@evil.com', 'New', 'User', 'example.com');
662
663
 
663
664
  expect(user).toBeUndefined();
664
665
  expect(mockGetEntityObject).not.toHaveBeenCalled();
665
666
  });
666
667
 
667
668
  it('matches email domains case-insensitively', async () => {
668
- const user = await verifyUserRecord('new@EXAMPLE.COM', 'New', 'User');
669
+ const user = await VerifyUserRecord('new@EXAMPLE.COM', 'New', 'User');
669
670
 
670
671
  expect(user).toBeDefined();
671
672
  });
@@ -673,7 +674,7 @@ describe('verifyUserRecord', () => {
673
674
  it('supports wildcard patterns for email subdomains', async () => {
674
675
  mockConfig.userHandling.newUserAuthorizedDomains = ['*.example.com'];
675
676
 
676
- const user = await verifyUserRecord('new@mail.example.com', 'New', 'User');
677
+ const user = await VerifyUserRecord('new@mail.example.com', 'New', 'User');
677
678
 
678
679
  expect(user).toBeDefined();
679
680
  });
@@ -681,7 +682,7 @@ describe('verifyUserRecord', () => {
681
682
  it('does NOT match the apex against "*.example.com" (pattern is matched in full)', async () => {
682
683
  mockConfig.userHandling.newUserAuthorizedDomains = ['*.example.com'];
683
684
 
684
- const user = await verifyUserRecord('new@example.com', 'New', 'User');
685
+ const user = await VerifyUserRecord('new@example.com', 'New', 'User');
685
686
 
686
687
  expect(user).toBeUndefined();
687
688
  expect(mockGetEntityObject).not.toHaveBeenCalled();
@@ -690,27 +691,27 @@ describe('verifyUserRecord', () => {
690
691
  it('rejects prefix confusion: "*.example.com" does not match "evilexample.com" (dot is escaped)', async () => {
691
692
  mockConfig.userHandling.newUserAuthorizedDomains = ['*.example.com'];
692
693
 
693
- const user = await verifyUserRecord('new@evilexample.com', 'New', 'User');
694
+ const user = await VerifyUserRecord('new@evilexample.com', 'New', 'User');
694
695
 
695
696
  expect(user).toBeUndefined();
696
697
  expect(mockGetEntityObject).not.toHaveBeenCalled();
697
698
  });
698
699
 
699
700
  it('rejects suffix confusion: the pattern is anchored, so "example.com.evil.com" is not authorized', async () => {
700
- const user = await verifyUserRecord('new@example.com.evil.com', 'New', 'User');
701
+ const user = await VerifyUserRecord('new@example.com.evil.com', 'New', 'User');
701
702
 
702
703
  expect(user).toBeUndefined();
703
704
  expect(mockGetEntityObject).not.toHaveBeenCalled();
704
705
  });
705
706
 
706
707
  it('rejects "evilexample.com" against the plain "example.com" pattern (anchored at both ends)', async () => {
707
- const user = await verifyUserRecord('x@evilexample.com', 'New', 'User');
708
+ const user = await VerifyUserRecord('x@evilexample.com', 'New', 'User');
708
709
 
709
710
  expect(user).toBeUndefined();
710
711
  });
711
712
 
712
713
  it('does NOT create when the identity has no email domain (username-only IdP)', async () => {
713
- const user = await verifyUserRecord('bare-username', 'New', 'User');
714
+ const user = await VerifyUserRecord('bare-username', 'New', 'User');
714
715
 
715
716
  expect(user).toBeUndefined();
716
717
  expect(mockGetEntityObject).not.toHaveBeenCalled();
@@ -727,7 +728,7 @@ describe('verifyUserRecord', () => {
727
728
  });
728
729
  const dataSource = {} as unknown as import('mssql').ConnectionPool;
729
730
 
730
- const user = await verifyUserRecord('late@example.com', undefined, undefined, undefined, dataSource);
731
+ const user = await VerifyUserRecord('late@example.com', undefined, undefined, undefined, dataSource);
731
732
 
732
733
  expect(user).toBeDefined();
733
734
  expect((user as unknown as { Email: string }).Email).toBe('late@example.com');
@@ -739,7 +740,7 @@ describe('verifyUserRecord', () => {
739
740
  mockConfig.userHandling.updateCacheWhenNotFound = true;
740
741
  const dataSource = {} as unknown as import('mssql').ConnectionPool;
741
742
 
742
- const user = await verifyUserRecord('never@example.com', undefined, undefined, undefined, dataSource);
743
+ const user = await VerifyUserRecord('never@example.com', undefined, undefined, undefined, dataSource);
743
744
 
744
745
  expect(user).toBeUndefined();
745
746
  expect(mockRefresh).toHaveBeenCalledTimes(1);