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

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 (459) 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/index.d.ts +20 -1
  16. package/dist/auth/index.d.ts.map +1 -1
  17. package/dist/auth/index.js +20 -10
  18. package/dist/auth/index.js.map +1 -1
  19. package/dist/auth/initializeProviders.d.ts +8 -0
  20. package/dist/auth/initializeProviders.d.ts.map +1 -1
  21. package/dist/auth/initializeProviders.js +21 -5
  22. package/dist/auth/initializeProviders.js.map +1 -1
  23. package/dist/auth/magicLink/MagicLinkRouter.d.ts +9 -0
  24. package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
  25. package/dist/auth/magicLink/MagicLinkRouter.js +22 -10
  26. package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
  27. package/dist/auth/magicLink/MagicLinkService.d.ts +17 -15
  28. package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
  29. package/dist/auth/magicLink/MagicLinkService.js +65 -51
  30. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  31. package/dist/auth/magicLink/index.d.ts +2 -2
  32. package/dist/auth/magicLink/index.d.ts.map +1 -1
  33. package/dist/auth/magicLink/index.js +2 -2
  34. package/dist/auth/magicLink/index.js.map +1 -1
  35. package/dist/auth/magicLink/magicLinkCore.d.ts +54 -33
  36. package/dist/auth/magicLink/magicLinkCore.d.ts.map +1 -1
  37. package/dist/auth/magicLink/magicLinkCore.js +61 -61
  38. package/dist/auth/magicLink/magicLinkCore.js.map +1 -1
  39. package/dist/auth/magicLink/redeemLanding.d.ts +4 -0
  40. package/dist/auth/magicLink/redeemLanding.d.ts.map +1 -1
  41. package/dist/auth/magicLink/redeemLanding.js +12 -4
  42. package/dist/auth/magicLink/redeemLanding.js.map +1 -1
  43. package/dist/auth/magicLink/types.d.ts +4 -4
  44. package/dist/auth/principals.d.ts +2 -0
  45. package/dist/auth/principals.d.ts.map +1 -1
  46. package/dist/auth/principals.js +6 -2
  47. package/dist/auth/principals.js.map +1 -1
  48. package/dist/cache.d.ts +2 -0
  49. package/dist/cache.d.ts.map +1 -1
  50. package/dist/cache.js +3 -1
  51. package/dist/cache.js.map +1 -1
  52. package/dist/config.d.ts +346 -2
  53. package/dist/config.d.ts.map +1 -1
  54. package/dist/config.js +34 -4
  55. package/dist/config.js.map +1 -1
  56. package/dist/context.d.ts +20 -0
  57. package/dist/context.d.ts.map +1 -1
  58. package/dist/context.js +27 -19
  59. package/dist/context.js.map +1 -1
  60. package/dist/directives/Public.d.ts +2 -0
  61. package/dist/directives/Public.d.ts.map +1 -1
  62. package/dist/directives/Public.js +3 -1
  63. package/dist/directives/Public.js.map +1 -1
  64. package/dist/directives/RequireSystemUser.d.ts +2 -0
  65. package/dist/directives/RequireSystemUser.d.ts.map +1 -1
  66. package/dist/directives/RequireSystemUser.js +3 -1
  67. package/dist/directives/RequireSystemUser.js.map +1 -1
  68. package/dist/generated/graphql-schemas/__mj.d.ts +1021 -0
  69. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  70. package/dist/generated/graphql-schemas/__mj.js +7368 -2145
  71. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  72. package/dist/generic/CacheInvalidationResolver.d.ts +94 -4
  73. package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
  74. package/dist/generic/CacheInvalidationResolver.js +122 -3
  75. package/dist/generic/CacheInvalidationResolver.js.map +1 -1
  76. package/dist/generic/DeleteOptionsInput.d.ts +8 -1
  77. package/dist/generic/DeleteOptionsInput.d.ts.map +1 -1
  78. package/dist/generic/DeleteOptionsInput.js +1 -1
  79. package/dist/generic/DeleteOptionsInput.js.map +1 -1
  80. package/dist/generic/FireAndForgetHeartbeat.d.ts +18 -2
  81. package/dist/generic/FireAndForgetHeartbeat.d.ts.map +1 -1
  82. package/dist/generic/FireAndForgetHeartbeat.js +24 -6
  83. package/dist/generic/FireAndForgetHeartbeat.js.map +1 -1
  84. package/dist/generic/OrphanedConversationDetailReconciler.d.ts +31 -0
  85. package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -0
  86. package/dist/generic/OrphanedConversationDetailReconciler.js +215 -0
  87. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -0
  88. package/dist/generic/PushStatusResolver.d.ts +48 -1
  89. package/dist/generic/PushStatusResolver.d.ts.map +1 -1
  90. package/dist/generic/PushStatusResolver.js +95 -4
  91. package/dist/generic/PushStatusResolver.js.map +1 -1
  92. package/dist/generic/ResolverBase.d.ts +18 -2
  93. package/dist/generic/ResolverBase.d.ts.map +1 -1
  94. package/dist/generic/ResolverBase.js +64 -55
  95. package/dist/generic/ResolverBase.js.map +1 -1
  96. package/dist/index.d.ts +9 -0
  97. package/dist/index.d.ts.map +1 -1
  98. package/dist/index.js +120 -11
  99. package/dist/index.js.map +1 -1
  100. package/dist/integration/CustomColumnPromoter.d.ts +2 -0
  101. package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
  102. package/dist/integration/CustomColumnPromoter.js +5 -1
  103. package/dist/integration/CustomColumnPromoter.js.map +1 -1
  104. package/dist/integration/EntityMapLifecycle.d.ts +4 -0
  105. package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
  106. package/dist/integration/EntityMapLifecycle.js +10 -2
  107. package/dist/integration/EntityMapLifecycle.js.map +1 -1
  108. package/dist/logging/NoLog.d.ts +4 -0
  109. package/dist/logging/NoLog.d.ts.map +1 -1
  110. package/dist/logging/NoLog.js +10 -2
  111. package/dist/logging/NoLog.js.map +1 -1
  112. package/dist/logging/StartupLogger.d.ts +2 -0
  113. package/dist/logging/StartupLogger.d.ts.map +1 -1
  114. package/dist/logging/StartupLogger.js +5 -1
  115. package/dist/logging/StartupLogger.js.map +1 -1
  116. package/dist/logging/bootAudit.d.ts +11 -7
  117. package/dist/logging/bootAudit.d.ts.map +1 -1
  118. package/dist/logging/bootAudit.js +15 -7
  119. package/dist/logging/bootAudit.js.map +1 -1
  120. package/dist/logging/boundaryLogPayload.d.ts +4 -0
  121. package/dist/logging/boundaryLogPayload.d.ts.map +1 -1
  122. package/dist/logging/boundaryLogPayload.js +5 -1
  123. package/dist/logging/boundaryLogPayload.js.map +1 -1
  124. package/dist/logging/secretRedactor.d.ts +2 -0
  125. package/dist/logging/secretRedactor.d.ts.map +1 -1
  126. package/dist/logging/secretRedactor.js +8 -4
  127. package/dist/logging/secretRedactor.js.map +1 -1
  128. package/dist/logging/shortenForLog.d.ts +2 -0
  129. package/dist/logging/shortenForLog.d.ts.map +1 -1
  130. package/dist/logging/shortenForLog.js +7 -3
  131. package/dist/logging/shortenForLog.js.map +1 -1
  132. package/dist/logging/variablesLoggingMiddleware.d.ts +2 -0
  133. package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
  134. package/dist/logging/variablesLoggingMiddleware.js +8 -6
  135. package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
  136. package/dist/metadataRefreshSignal.d.ts +19 -0
  137. package/dist/metadataRefreshSignal.d.ts.map +1 -0
  138. package/dist/metadataRefreshSignal.js +45 -0
  139. package/dist/metadataRefreshSignal.js.map +1 -0
  140. package/dist/middleware/MJTenantFilterMiddleware.js +4 -4
  141. package/dist/multiTenancy/index.d.ts +8 -0
  142. package/dist/multiTenancy/index.d.ts.map +1 -1
  143. package/dist/multiTenancy/index.js +21 -5
  144. package/dist/multiTenancy/index.js.map +1 -1
  145. package/dist/realtimeWidget/WidgetRouter.d.ts +5 -0
  146. package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
  147. package/dist/realtimeWidget/WidgetRouter.js +14 -10
  148. package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
  149. package/dist/realtimeWidget/WidgetSessionService.d.ts +6 -6
  150. package/dist/realtimeWidget/WidgetSessionService.js +27 -27
  151. package/dist/realtimeWidget/host-identity.d.ts +5 -1
  152. package/dist/realtimeWidget/host-identity.d.ts.map +1 -1
  153. package/dist/realtimeWidget/host-identity.js +11 -3
  154. package/dist/realtimeWidget/host-identity.js.map +1 -1
  155. package/dist/realtimeWidget/index.d.ts +2 -2
  156. package/dist/realtimeWidget/index.d.ts.map +1 -1
  157. package/dist/realtimeWidget/index.js +2 -2
  158. package/dist/realtimeWidget/index.js.map +1 -1
  159. package/dist/realtimeWidget/visitorIdentity.d.ts +21 -1
  160. package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
  161. package/dist/realtimeWidget/visitorIdentity.js +16 -4
  162. package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
  163. package/dist/realtimeWidget/widgetCore.d.ts +48 -0
  164. package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
  165. package/dist/realtimeWidget/widgetCore.js +38 -10
  166. package/dist/realtimeWidget/widgetCore.js.map +1 -1
  167. package/dist/realtimeWidget/widgetGuestElevation.d.ts +10 -6
  168. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  169. package/dist/realtimeWidget/widgetGuestElevation.js +14 -6
  170. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  171. package/dist/resolvers/AdhocQueryResolver.js +3 -3
  172. package/dist/resolvers/AgentRunStatusPublisher.d.ts +55 -0
  173. package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -0
  174. package/dist/resolvers/AgentRunStatusPublisher.js +141 -0
  175. package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -0
  176. package/dist/resolvers/ConversationRunEventsResolver.d.ts +90 -0
  177. package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -0
  178. package/dist/resolvers/ConversationRunEventsResolver.js +283 -0
  179. package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -0
  180. package/dist/resolvers/DuplicateEntryCheckResolver.d.ts +98 -0
  181. package/dist/resolvers/DuplicateEntryCheckResolver.d.ts.map +1 -0
  182. package/dist/resolvers/DuplicateEntryCheckResolver.js +227 -0
  183. package/dist/resolvers/DuplicateEntryCheckResolver.js.map +1 -0
  184. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  185. package/dist/resolvers/FetchEntityVectorsResolver.js +2 -1
  186. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  187. package/dist/resolvers/FileResolver.js +3 -3
  188. package/dist/resolvers/GeoResolver.d.ts +2 -2
  189. package/dist/resolvers/GeoResolver.js +4 -4
  190. package/dist/resolvers/GetDataResolver.d.ts +14 -0
  191. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  192. package/dist/resolvers/GetDataResolver.js +43 -15
  193. package/dist/resolvers/GetDataResolver.js.map +1 -1
  194. package/dist/resolvers/IntegrationDiscoveryResolver.js +2 -2
  195. package/dist/resolvers/ListOperationsResolver.d.ts +20 -0
  196. package/dist/resolvers/ListOperationsResolver.d.ts.map +1 -1
  197. package/dist/resolvers/ListOperationsResolver.js +68 -28
  198. package/dist/resolvers/ListOperationsResolver.js.map +1 -1
  199. package/dist/resolvers/MCPResolver.d.ts +11 -1
  200. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  201. package/dist/resolvers/MCPResolver.js +7 -3
  202. package/dist/resolvers/MCPResolver.js.map +1 -1
  203. package/dist/resolvers/MergeRecordsResolver.d.ts +7 -0
  204. package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
  205. package/dist/resolvers/MergeRecordsResolver.js +16 -2
  206. package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
  207. package/dist/resolvers/RealtimeBridgeResolver.js +3 -3
  208. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +44 -6
  209. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  210. package/dist/resolvers/RealtimeClientSessionResolver.js +93 -37
  211. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  212. package/dist/resolvers/RemoteBrowserActionResolver.js +5 -5
  213. package/dist/resolvers/RunAIAgentResolver.d.ts +8 -18
  214. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  215. package/dist/resolvers/RunAIAgentResolver.js +85 -184
  216. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  217. package/dist/resolvers/RunAIPromptResolver.d.ts +1 -1
  218. package/dist/resolvers/RunAIPromptResolver.js +2 -2
  219. package/dist/resolvers/RunDecisionResolver.d.ts +149 -0
  220. package/dist/resolvers/RunDecisionResolver.d.ts.map +1 -0
  221. package/dist/resolvers/RunDecisionResolver.js +396 -0
  222. package/dist/resolvers/RunDecisionResolver.js.map +1 -0
  223. package/dist/resolvers/RunTestResolver.js +5 -5
  224. package/dist/resolvers/SqlLoggingConfigResolver.d.ts +8 -4
  225. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  226. package/dist/resolvers/SqlLoggingConfigResolver.js +5 -5
  227. package/dist/resolvers/TaskGraphFrameResolver.d.ts +8 -1
  228. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
  229. package/dist/resolvers/TaskGraphFrameResolver.js +6 -2
  230. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
  231. package/dist/resolvers/VectorizeEntityResolver.d.ts +1 -1
  232. package/dist/resolvers/VectorizeEntityResolver.d.ts.map +1 -1
  233. package/dist/resolvers/VectorizeEntityResolver.js +14 -10
  234. package/dist/resolvers/VectorizeEntityResolver.js.map +1 -1
  235. package/dist/resolvers/adhoc-query-helpers.d.ts +6 -0
  236. package/dist/resolvers/adhoc-query-helpers.d.ts.map +1 -1
  237. package/dist/resolvers/adhoc-query-helpers.js +10 -2
  238. package/dist/resolvers/adhoc-query-helpers.js.map +1 -1
  239. package/dist/resolvers/artifact-routing.d.ts +8 -8
  240. package/dist/resolvers/artifact-routing.js +2 -2
  241. package/dist/resolvers/artifact-routing.js.map +1 -1
  242. package/dist/resolvers/meetingRecordingRegistration.d.ts +10 -2
  243. package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
  244. package/dist/resolvers/meetingRecordingRegistration.js +24 -8
  245. package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
  246. package/dist/resolvers/peaksSidecar.d.ts +4 -0
  247. package/dist/resolvers/peaksSidecar.d.ts.map +1 -1
  248. package/dist/resolvers/peaksSidecar.js +10 -2
  249. package/dist/resolvers/peaksSidecar.js.map +1 -1
  250. package/dist/rest/EntityCRUDHandler.d.ts +28 -0
  251. package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
  252. package/dist/rest/EntityCRUDHandler.js +20 -4
  253. package/dist/rest/EntityCRUDHandler.js.map +1 -1
  254. package/dist/rest/MediaStreamHandler.d.ts +2 -0
  255. package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
  256. package/dist/rest/MediaStreamHandler.js +10 -6
  257. package/dist/rest/MediaStreamHandler.js.map +1 -1
  258. package/dist/rest/OAuthCallbackHandler.d.ts +9 -0
  259. package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
  260. package/dist/rest/OAuthCallbackHandler.js +15 -3
  261. package/dist/rest/OAuthCallbackHandler.js.map +1 -1
  262. package/dist/rest/RESTEndpointHandler.d.ts +6 -4
  263. package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
  264. package/dist/rest/RESTEndpointHandler.js +15 -11
  265. package/dist/rest/RESTEndpointHandler.js.map +1 -1
  266. package/dist/rest/RealtimeSdpBrokerHandler.d.ts +5 -1
  267. package/dist/rest/RealtimeSdpBrokerHandler.d.ts.map +1 -1
  268. package/dist/rest/RealtimeSdpBrokerHandler.js +12 -4
  269. package/dist/rest/RealtimeSdpBrokerHandler.js.map +1 -1
  270. package/dist/rest/SignatureWebhookHandler.d.ts +2 -0
  271. package/dist/rest/SignatureWebhookHandler.d.ts.map +1 -1
  272. package/dist/rest/SignatureWebhookHandler.js +5 -1
  273. package/dist/rest/SignatureWebhookHandler.js.map +1 -1
  274. package/dist/rest/UploadTokenManager.d.ts +24 -8
  275. package/dist/rest/UploadTokenManager.d.ts.map +1 -1
  276. package/dist/rest/UploadTokenManager.js +53 -21
  277. package/dist/rest/UploadTokenManager.js.map +1 -1
  278. package/dist/rest/ViewOperationsHandler.d.ts +20 -0
  279. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  280. package/dist/rest/ViewOperationsHandler.js +20 -4
  281. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  282. package/dist/rest/mediaRange.d.ts +4 -0
  283. package/dist/rest/mediaRange.d.ts.map +1 -1
  284. package/dist/rest/mediaRange.js +10 -2
  285. package/dist/rest/mediaRange.js.map +1 -1
  286. package/dist/rest/setupRESTEndpoints.d.ts +4 -0
  287. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  288. package/dist/rest/setupRESTEndpoints.js +13 -7
  289. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  290. package/dist/serverExtensionReservedRoots.d.ts +2 -0
  291. package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
  292. package/dist/serverExtensionReservedRoots.js +5 -1
  293. package/dist/serverExtensionReservedRoots.js.map +1 -1
  294. package/dist/services/TaskGraphActionRunner.d.ts +13 -8
  295. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  296. package/dist/services/TaskGraphActionRunner.js +16 -15
  297. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  298. package/dist/types.d.ts +2 -0
  299. package/dist/types.d.ts.map +1 -1
  300. package/dist/types.js +7 -3
  301. package/dist/types.js.map +1 -1
  302. package/dist/util.d.ts +6 -0
  303. package/dist/util.d.ts.map +1 -1
  304. package/dist/util.js +13 -5
  305. package/dist/util.js.map +1 -1
  306. package/package.json +94 -92
  307. package/src/__tests__/AgentRunStatusPublisher.test.ts +175 -0
  308. package/src/__tests__/DeleteOptionsInput.wireShape.test.ts +62 -0
  309. package/src/__tests__/DuplicateEntryCheckResolver.test.ts +300 -0
  310. package/src/__tests__/FileResolverPeaks.test.ts +13 -13
  311. package/src/__tests__/ListOperationsResolver.test.ts +17 -17
  312. package/src/__tests__/MediaStreamHandler.test.ts +28 -28
  313. package/src/__tests__/NoLog.test.ts +11 -11
  314. package/src/__tests__/PrimaryKeyAlwaysMapped.test.ts +10 -10
  315. package/src/__tests__/RESTEndpointHandler.test.ts +14 -14
  316. package/src/__tests__/RealtimeBridgeResolver.test.ts +4 -2
  317. package/src/__tests__/RealtimeClientSessionResolver.test.ts +216 -2
  318. package/src/__tests__/RealtimeSdpBrokerHandler.test.ts +6 -6
  319. package/src/__tests__/RefreshAdoptsNewColumns.test.ts +8 -8
  320. package/src/__tests__/RemoteBrowserActionRecovery.test.ts +7 -1
  321. package/src/__tests__/RemoteBrowserAudioStream.test.ts +7 -1
  322. package/src/__tests__/RemoteBrowserGoalEngine.test.ts +18 -18
  323. package/src/__tests__/RemoteBrowserSnapshot.test.ts +7 -1
  324. package/src/__tests__/ResolverBase.clientOldValues.test.ts +52 -0
  325. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +398 -0
  326. package/src/__tests__/RunAIAgentResolver.streaming.test.ts +18 -27
  327. package/src/__tests__/RunDecisionResolver.test.ts +699 -0
  328. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +131 -0
  329. package/src/__tests__/TaskGraphFrameResolver.test.ts +2 -2
  330. package/src/__tests__/VectorizeEntityResolver.test.ts +106 -0
  331. package/src/__tests__/WidgetSessionService.test.ts +8 -4
  332. package/src/__tests__/adhoc-query-helpers.test.ts +21 -21
  333. package/src/__tests__/bootAudit.test.ts +11 -11
  334. package/src/__tests__/boundaryLogPayload.test.ts +6 -6
  335. package/src/__tests__/cacheInvalidationRecordData.test.ts +177 -0
  336. package/src/__tests__/conversationRunEvents.test.ts +399 -0
  337. package/src/__tests__/databaseAbstraction.test.ts +12 -6
  338. package/src/__tests__/getDataTokenRedaction.test.ts +7 -7
  339. package/src/__tests__/initializeProviders.refresh.test.ts +4 -4
  340. package/src/__tests__/magicLink.test.ts +73 -134
  341. package/src/__tests__/magicLinkService.consume.test.ts +224 -0
  342. package/src/__tests__/meetingRecordingRegistration.test.ts +12 -12
  343. package/src/__tests__/metadataRefreshSignal.test.ts +78 -0
  344. package/src/__tests__/multiTenancy.security.test.ts +40 -40
  345. package/src/__tests__/multiTenancy.test.ts +18 -18
  346. package/src/__tests__/newUsers.test.ts +24 -23
  347. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +283 -0
  348. package/src/__tests__/principals.test.ts +22 -22
  349. package/src/__tests__/pushStatusFanOut.test.ts +206 -0
  350. package/src/__tests__/pushStatusResolver.filter.test.ts +8 -8
  351. package/src/__tests__/secretRedactor.failOpen.test.ts +12 -12
  352. package/src/__tests__/secretRedactor.test.ts +12 -12
  353. package/src/__tests__/serverExtensionReservedRoots.test.ts +7 -7
  354. package/src/__tests__/subscriptionRedaction.test.ts +5 -5
  355. package/src/__tests__/unifiedAuth.test.ts +15 -9
  356. package/src/__tests__/visitorIdentity.resolve.test.ts +6 -6
  357. package/src/__tests__/widget.test.ts +45 -45
  358. package/src/__tests__/widgetGuestElevation.test.ts +7 -7
  359. package/src/__tests__/widgetHostIdentity.test.ts +14 -14
  360. package/src/agentSessions/ReturningVisitorRecap.ts +12 -1
  361. package/src/agentSessions/SessionManager.ts +2 -2
  362. package/src/agentSessions/remoteBrowserGoalEngine.ts +30 -5
  363. package/src/auth/AuthProviderCatalogRouter.ts +6 -1
  364. package/src/auth/__tests__/backward-compatibility.test.ts +4 -3
  365. package/src/auth/index.ts +43 -28
  366. package/src/auth/initializeProviders.ts +25 -5
  367. package/src/auth/magicLink/MagicLinkRouter.ts +28 -10
  368. package/src/auth/magicLink/MagicLinkService.ts +71 -52
  369. package/src/auth/magicLink/index.ts +7 -7
  370. package/src/auth/magicLink/magicLinkCore.ts +96 -64
  371. package/src/auth/magicLink/redeemLanding.ts +14 -4
  372. package/src/auth/magicLink/types.ts +54 -54
  373. package/src/auth/newUsers.ts +1 -1
  374. package/src/auth/principals.ts +11 -2
  375. package/src/cache.ts +4 -1
  376. package/src/config.ts +37 -4
  377. package/src/context.ts +37 -24
  378. package/src/directives/Public.ts +4 -1
  379. package/src/directives/RequireSystemUser.ts +4 -1
  380. package/src/generated/graphql-schemas/__mj.ts +3674 -4
  381. package/src/generic/CacheInvalidationResolver.ts +148 -4
  382. package/src/generic/DeleteOptionsInput.ts +9 -2
  383. package/src/generic/FireAndForgetHeartbeat.ts +35 -16
  384. package/src/generic/OrphanedConversationDetailReconciler.ts +267 -0
  385. package/src/generic/PushStatusResolver.ts +118 -8
  386. package/src/generic/ResolverBase.ts +65 -57
  387. package/src/generic/RunViewResolver.ts +22 -22
  388. package/src/generic/__tests__/FireAndForgetHeartbeat.test.ts +7 -7
  389. package/src/index.ts +137 -11
  390. package/src/integration/CustomColumnPromoter.ts +6 -1
  391. package/src/integration/EntityMapLifecycle.ts +20 -2
  392. package/src/logging/NoLog.ts +16 -2
  393. package/src/logging/StartupLogger.ts +6 -1
  394. package/src/logging/bootAudit.ts +26 -16
  395. package/src/logging/boundaryLogPayload.ts +8 -1
  396. package/src/logging/secretRedactor.ts +14 -9
  397. package/src/logging/shortenForLog.ts +8 -3
  398. package/src/logging/variablesLoggingMiddleware.ts +9 -6
  399. package/src/metadataRefreshSignal.ts +45 -0
  400. package/src/middleware/MJTenantFilterMiddleware.ts +4 -4
  401. package/src/multiTenancy/index.ts +29 -5
  402. package/src/realtimeWidget/WidgetRouter.ts +15 -10
  403. package/src/realtimeWidget/WidgetSessionService.ts +76 -76
  404. package/src/realtimeWidget/host-identity.ts +24 -10
  405. package/src/realtimeWidget/index.ts +3 -3
  406. package/src/realtimeWidget/visitorIdentity.ts +39 -8
  407. package/src/realtimeWidget/widgetCore.ts +75 -10
  408. package/src/realtimeWidget/widgetGuestElevation.ts +25 -12
  409. package/src/resolvers/AdhocQueryResolver.ts +3 -3
  410. package/src/resolvers/AgentRunStatusPublisher.ts +175 -0
  411. package/src/resolvers/AgentSessionResolver.ts +3 -3
  412. package/src/resolvers/ColorResolver.ts +6 -6
  413. package/src/resolvers/ComponentRegistryResolver.ts +36 -36
  414. package/src/resolvers/ConversationRunEventsResolver.ts +308 -0
  415. package/src/resolvers/DuplicateEntryCheckResolver.ts +232 -0
  416. package/src/resolvers/EntityCommunicationsResolver.ts +4 -4
  417. package/src/resolvers/ExecuteRemoteOperationResolver.ts +9 -9
  418. package/src/resolvers/FetchEntityVectorsResolver.ts +2 -1
  419. package/src/resolvers/FileResolver.ts +42 -42
  420. package/src/resolvers/GeoResolver.ts +4 -4
  421. package/src/resolvers/GetDataResolver.ts +50 -15
  422. package/src/resolvers/IntegrationDiscoveryResolver.ts +2 -2
  423. package/src/resolvers/ListOperationsResolver.ts +78 -28
  424. package/src/resolvers/MCPResolver.ts +30 -15
  425. package/src/resolvers/MergeRecordsResolver.ts +14 -2
  426. package/src/resolvers/QueryResolver.ts +13 -13
  427. package/src/resolvers/RealtimeBridgeResolver.ts +3 -3
  428. package/src/resolvers/RealtimeClientSessionResolver.ts +96 -38
  429. package/src/resolvers/RemoteBrowserActionResolver.ts +5 -5
  430. package/src/resolvers/RunAIAgentResolver.ts +134 -239
  431. package/src/resolvers/RunAIPromptResolver.ts +22 -22
  432. package/src/resolvers/RunDecisionResolver.ts +435 -0
  433. package/src/resolvers/RunTemplateResolver.ts +4 -4
  434. package/src/resolvers/RunTestResolver.ts +25 -25
  435. package/src/resolvers/SqlLoggingConfigResolver.ts +56 -56
  436. package/src/resolvers/TaskGraphFrameResolver.ts +37 -28
  437. package/src/resolvers/TelemetryResolver.ts +79 -79
  438. package/src/resolvers/VectorizeEntityResolver.ts +16 -11
  439. package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +40 -38
  440. package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +93 -0
  441. package/src/resolvers/__tests__/artifact-routing.test.ts +23 -23
  442. package/src/resolvers/adhoc-query-helpers.ts +19 -2
  443. package/src/resolvers/artifact-routing.ts +19 -19
  444. package/src/resolvers/meetingRecordingRegistration.ts +44 -10
  445. package/src/resolvers/peaksSidecar.ts +12 -2
  446. package/src/rest/EntityCRUDHandler.ts +24 -4
  447. package/src/rest/MediaStreamHandler.ts +11 -6
  448. package/src/rest/OAuthCallbackHandler.ts +25 -7
  449. package/src/rest/RESTEndpointHandler.ts +20 -15
  450. package/src/rest/RealtimeSdpBrokerHandler.ts +14 -4
  451. package/src/rest/SignatureWebhookHandler.ts +6 -1
  452. package/src/rest/UploadTokenManager.ts +66 -30
  453. package/src/rest/ViewOperationsHandler.ts +24 -4
  454. package/src/rest/mediaRange.ts +16 -6
  455. package/src/rest/setupRESTEndpoints.ts +24 -12
  456. package/src/serverExtensionReservedRoots.ts +6 -1
  457. package/src/services/TaskGraphActionRunner.ts +16 -15
  458. package/src/types.ts +21 -16
  459. package/src/util.ts +16 -6
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Tests for cross-instance fan-out of push-status updates (MJ #4222).
3
+ *
4
+ * Behind a load balancer the browser's WebSocket lives on one replica while the mutation driving
5
+ * the agent may be handled by another, so a completion can be published to a topic that has no
6
+ * subscriber. Replicating progress and completion closes that.
7
+ *
8
+ * Three properties are pinned here because each one, if wrong, produces a bug that looks like
9
+ * something else entirely:
10
+ *
11
+ * - **Streaming content is not replicated.** It is hundreds of messages per second, each carrying
12
+ * a full serialized agent run. Replicating it would look like a network problem, not a bug here.
13
+ * - **Every publish carries `SourceServerId`.** Without it, echo suppression on the receiving side
14
+ * has nothing to match and every push is delivered twice.
15
+ * - **A hook that throws does not break local delivery.** The message bus is an optimization over
16
+ * the durable tail query; the local path must work when it is down.
17
+ */
18
+ import 'reflect-metadata';
19
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
20
+ import {
21
+ publishStatusUpdate,
22
+ ParseReplicatedStatusUpdate,
23
+ ShouldReplicateStatusUpdate,
24
+ SetPushStatusPublishHook,
25
+ type PushStatusNotificationPayload,
26
+ } from '../generic/PushStatusResolver.js';
27
+ import { MJGlobal } from '@memberjunction/global';
28
+ import type { PubSubEngine } from 'type-graphql';
29
+
30
+ const SESSION = 'session-1';
31
+ const OWNER = 'U0000000-0000-0000-0000-000000000000';
32
+
33
+ function fakePubSub() {
34
+ const published: Array<{ topic: string; payload: PushStatusNotificationPayload }> = [];
35
+ const engine = {
36
+ publish: (topic: string, payload: PushStatusNotificationPayload) => {
37
+ published.push({ topic, payload });
38
+ return Promise.resolve();
39
+ },
40
+ } as unknown as PubSubEngine;
41
+ return { engine, published };
42
+ }
43
+
44
+ const envelope = (type: string) => JSON.stringify({ resolver: 'RunAIAgentResolver', type, status: 'ok', data: {} });
45
+
46
+ afterEach(() => {
47
+ SetPushStatusPublishHook(undefined);
48
+ });
49
+
50
+ describe('ShouldReplicateStatusUpdate', () => {
51
+ it('replicates execution progress', () => {
52
+ expect(ShouldReplicateStatusUpdate(envelope('ExecutionProgress'))).toBe(true);
53
+ });
54
+
55
+ it('does not replicate streaming content', () => {
56
+ expect(ShouldReplicateStatusUpdate(envelope('StreamingContent'))).toBe(false);
57
+ });
58
+
59
+ it('replicates a plain-string message, which is rare and low-rate', () => {
60
+ expect(ShouldReplicateStatusUpdate('agent finished')).toBe(true);
61
+ });
62
+
63
+ it('does not replicate an empty message', () => {
64
+ expect(ShouldReplicateStatusUpdate(undefined)).toBe(false);
65
+ expect(ShouldReplicateStatusUpdate('')).toBe(false);
66
+ });
67
+
68
+ it('replicates JSON that is not the resolver envelope', () => {
69
+ expect(ShouldReplicateStatusUpdate(JSON.stringify({ hello: 'world' }))).toBe(true);
70
+ });
71
+ });
72
+
73
+ describe('publishStatusUpdate fan-out', () => {
74
+ beforeEach(() => {
75
+ SetPushStatusPublishHook(undefined);
76
+ });
77
+
78
+ it('stamps the publishing instance on every payload', () => {
79
+ const { engine, published } = fakePubSub();
80
+
81
+ publishStatusUpdate(engine, { sessionId: SESSION, ownerUserId: OWNER, message: envelope('ExecutionProgress') });
82
+
83
+ expect(published).toHaveLength(1);
84
+ expect(published[0].payload.SourceServerId).toBe(MJGlobal.Instance.ProcessUUID);
85
+ });
86
+
87
+ it('still publishes locally when no hook is registered', () => {
88
+ const { engine, published } = fakePubSub();
89
+
90
+ publishStatusUpdate(engine, { sessionId: SESSION, ownerUserId: OWNER, message: envelope('ExecutionProgress') });
91
+
92
+ expect(published[0].payload.ownerUserId).toBe(OWNER);
93
+ });
94
+
95
+ it('forwards a replicable update to the hook', () => {
96
+ const hook = vi.fn();
97
+ SetPushStatusPublishHook(hook);
98
+ const { engine } = fakePubSub();
99
+
100
+ publishStatusUpdate(engine, { sessionId: SESSION, ownerUserId: OWNER, message: envelope('ExecutionProgress') });
101
+
102
+ expect(hook).toHaveBeenCalledTimes(1);
103
+ const forwarded = hook.mock.calls[0][0] as PushStatusNotificationPayload;
104
+ expect(forwarded.sessionId).toBe(SESSION);
105
+ expect(forwarded.ownerUserId).toBe(OWNER);
106
+ expect(forwarded.SourceServerId).toBe(MJGlobal.Instance.ProcessUUID);
107
+ });
108
+
109
+ it('does not forward streaming content, but still delivers it locally', () => {
110
+ const hook = vi.fn();
111
+ SetPushStatusPublishHook(hook);
112
+ const { engine, published } = fakePubSub();
113
+
114
+ publishStatusUpdate(engine, { sessionId: SESSION, ownerUserId: OWNER, message: envelope('StreamingContent') });
115
+
116
+ expect(hook).not.toHaveBeenCalled();
117
+ expect(published).toHaveLength(1);
118
+ });
119
+
120
+ it('delivers locally even when the hook throws', () => {
121
+ SetPushStatusPublishHook(() => {
122
+ throw new Error('redis is down');
123
+ });
124
+ const { engine, published } = fakePubSub();
125
+
126
+ expect(() =>
127
+ publishStatusUpdate(engine, { sessionId: SESSION, ownerUserId: OWNER, message: envelope('ExecutionProgress') })
128
+ ).not.toThrow();
129
+ expect(published).toHaveLength(1);
130
+ });
131
+
132
+ it('publishes locally before attempting fan-out', () => {
133
+ const order: string[] = [];
134
+ SetPushStatusPublishHook(() => order.push('hook'));
135
+ const engine = {
136
+ publish: () => {
137
+ order.push('local');
138
+ return Promise.resolve();
139
+ },
140
+ } as unknown as PubSubEngine;
141
+
142
+ publishStatusUpdate(engine, { sessionId: SESSION, ownerUserId: OWNER, message: envelope('ExecutionProgress') });
143
+
144
+ expect(order).toEqual(['local', 'hook']);
145
+ });
146
+
147
+ it('clears the hook when set with no argument', () => {
148
+ const hook = vi.fn();
149
+ SetPushStatusPublishHook(hook);
150
+ SetPushStatusPublishHook(undefined);
151
+ const { engine } = fakePubSub();
152
+
153
+ publishStatusUpdate(engine, { sessionId: SESSION, ownerUserId: OWNER, message: envelope('ExecutionProgress') });
154
+
155
+ expect(hook).not.toHaveBeenCalled();
156
+ });
157
+ });
158
+
159
+ describe('ParseReplicatedStatusUpdate', () => {
160
+ /**
161
+ * Messages on the shared channel come from other processes, so every field is checked before
162
+ * the update is republished onto the local topic, where the subscription filter compares
163
+ * `ownerUserId` against the connection's user.
164
+ */
165
+ const LOCAL = 'LOCAL-PROCESS';
166
+ const raw = (over: Record<string, unknown> = {}) =>
167
+ JSON.stringify({ sessionId: SESSION, ownerUserId: OWNER, message: 'hello', SourceServerId: 'OTHER', ...over });
168
+
169
+ it('returns the update from another instance', () => {
170
+ expect(ParseReplicatedStatusUpdate(raw(), LOCAL)).toEqual({
171
+ sessionId: SESSION,
172
+ ownerUserId: OWNER,
173
+ message: 'hello',
174
+ SourceServerId: 'OTHER',
175
+ });
176
+ });
177
+
178
+ it('drops our own message echoed back by the bus', () => {
179
+ expect(ParseReplicatedStatusUpdate(raw({ SourceServerId: LOCAL }), LOCAL)).toBeNull();
180
+ });
181
+
182
+ it('drops an update with no identity', () => {
183
+ expect(ParseReplicatedStatusUpdate(raw({ ownerUserId: '' }), LOCAL)).toBeNull();
184
+ expect(ParseReplicatedStatusUpdate(raw({ sessionId: undefined }), LOCAL)).toBeNull();
185
+ });
186
+
187
+ it('drops identity fields that are not strings', () => {
188
+ // A truthy object would pass a presence check and reach the filter as the wrong type.
189
+ expect(ParseReplicatedStatusUpdate(raw({ ownerUserId: { ID: OWNER } }), LOCAL)).toBeNull();
190
+ expect(ParseReplicatedStatusUpdate(raw({ sessionId: 42 }), LOCAL)).toBeNull();
191
+ });
192
+
193
+ it('drops a message body that is not a string', () => {
194
+ expect(ParseReplicatedStatusUpdate(raw({ message: { type: 'x' } }), LOCAL)).toBeNull();
195
+ });
196
+
197
+ it('accepts an update with no message body', () => {
198
+ expect(ParseReplicatedStatusUpdate(raw({ message: undefined }), LOCAL)?.message).toBeUndefined();
199
+ });
200
+
201
+ it('drops malformed JSON and values that are not objects', () => {
202
+ expect(ParseReplicatedStatusUpdate('{not json', LOCAL)).toBeNull();
203
+ expect(ParseReplicatedStatusUpdate('null', LOCAL)).toBeNull();
204
+ expect(ParseReplicatedStatusUpdate('42', LOCAL)).toBeNull();
205
+ });
206
+ });
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import 'reflect-metadata';
12
12
  import { describe, it, expect } from 'vitest';
13
- import { statusUpdatesFilter, type PushStatusNotificationPayload, type StatusUpdatesFilterContext } from '../generic/PushStatusResolver';
13
+ import { StatusUpdatesFilter, type PushStatusNotificationPayload, type StatusUpdatesFilterContext } from '../generic/PushStatusResolver';
14
14
  import type { UserPayload } from '../types';
15
15
 
16
16
  const OWNER = 'AA11BB22-0000-4000-8000-000000000001';
@@ -28,29 +28,29 @@ function push(overrides: Partial<PushStatusNotificationPayload> = {}): PushStatu
28
28
 
29
29
  describe('statusUpdatesFilter (B49 session-hijack gate)', () => {
30
30
  it('delivers when sessionId matches AND the connection identity owns the push', () => {
31
- expect(statusUpdatesFilter({ payload: push(), args: { sessionId: SESSION }, context: ctxFor(OWNER) })).toBe(true);
31
+ expect(StatusUpdatesFilter({ payload: push(), args: { sessionId: SESSION }, context: ctxFor(OWNER) })).toBe(true);
32
32
  });
33
33
 
34
34
  it('THE FIX: rejects a matching sessionId when the connection identity is a DIFFERENT user (hijack)', () => {
35
35
  // Attacker lifted the victim's sessionId and subscribes with it — but their authenticated
36
36
  // connection identity is their own, so delivery must be denied.
37
- expect(statusUpdatesFilter({ payload: push({ ownerUserId: OWNER }), args: { sessionId: SESSION }, context: ctxFor(ATTACKER) })).toBe(false);
37
+ expect(StatusUpdatesFilter({ payload: push({ ownerUserId: OWNER }), args: { sessionId: SESSION }, context: ctxFor(ATTACKER) })).toBe(false);
38
38
  });
39
39
 
40
40
  it('rejects when the requested sessionId does not match the push', () => {
41
- expect(statusUpdatesFilter({ payload: push(), args: { sessionId: 'some-other-session' }, context: ctxFor(OWNER) })).toBe(false);
41
+ expect(StatusUpdatesFilter({ payload: push(), args: { sessionId: 'some-other-session' }, context: ctxFor(OWNER) })).toBe(false);
42
42
  });
43
43
 
44
44
  it('fails closed when the push carries no ownerUserId', () => {
45
- expect(statusUpdatesFilter({ payload: push({ ownerUserId: '' }), args: { sessionId: SESSION }, context: ctxFor(OWNER) })).toBe(false);
45
+ expect(StatusUpdatesFilter({ payload: push({ ownerUserId: '' }), args: { sessionId: SESSION }, context: ctxFor(OWNER) })).toBe(false);
46
46
  });
47
47
 
48
48
  it('fails closed when the connection has no authenticated identity', () => {
49
- expect(statusUpdatesFilter({ payload: push(), args: { sessionId: SESSION }, context: ctxFor(undefined) })).toBe(false);
50
- expect(statusUpdatesFilter({ payload: push(), args: { sessionId: SESSION }, context: undefined })).toBe(false);
49
+ expect(StatusUpdatesFilter({ payload: push(), args: { sessionId: SESSION }, context: ctxFor(undefined) })).toBe(false);
50
+ expect(StatusUpdatesFilter({ payload: push(), args: { sessionId: SESSION }, context: undefined })).toBe(false);
51
51
  });
52
52
 
53
53
  it('matches identity case-insensitively (SQL Server upper vs PostgreSQL lower UUIDs)', () => {
54
- expect(statusUpdatesFilter({ payload: push({ ownerUserId: OWNER.toUpperCase() }), args: { sessionId: SESSION }, context: ctxFor(OWNER.toLowerCase()) })).toBe(true);
54
+ expect(StatusUpdatesFilter({ payload: push({ ownerUserId: OWNER.toUpperCase() }), args: { sessionId: SESSION }, context: ctxFor(OWNER.toLowerCase()) })).toBe(true);
55
55
  });
56
56
  });
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
2
  import type { IMetadataProvider } from '@memberjunction/core';
3
- import { redactArg, ResetUnboundCrudInputWarnings } from '../logging/secretRedactor.js';
3
+ import { RedactArg, ResetUnboundCrudInputWarnings } from '../logging/secretRedactor.js';
4
4
 
5
5
  /**
6
6
  * `redactArg` binds a GraphQL input type to an entity by NAME:
@@ -42,7 +42,7 @@ afterEach(() => {
42
42
 
43
43
  describe('redactArg — entity-bound inputs (the codegen case)', () => {
44
44
  it('redacts an encrypted column, keeping the rest', () => {
45
- const out = redactArg({
45
+ const out = RedactArg({
46
46
  inputTypeName: 'CreateMJCredentialInput',
47
47
  rawValue: { Name: 'Stripe', Values: SECRET },
48
48
  provider: CREDENTIAL_ENTITY,
@@ -55,7 +55,7 @@ describe('redactArg — entity-bound inputs (the codegen case)', () => {
55
55
  });
56
56
 
57
57
  it('emits no warning, because the binding resolved', () => {
58
- redactArg({
58
+ RedactArg({
59
59
  inputTypeName: 'CreateMJCredentialInput',
60
60
  rawValue: { Values: SECRET },
61
61
  provider: CREDENTIAL_ENTITY,
@@ -76,14 +76,14 @@ describe('redactArg — name matches the convention but no entity exists', () =>
76
76
  };
77
77
 
78
78
  it('falls open — values are logged, which is the defect being surfaced', () => {
79
- const out = redactArg({ ...unbound });
79
+ const out = RedactArg({ ...unbound });
80
80
  // Documents current behaviour: no entity binding and no @NoLog means no
81
81
  // redaction source, so the value survives into the log.
82
82
  expect(JSON.stringify(out)).toContain(SECRET);
83
83
  });
84
84
 
85
85
  it('now warns, naming the input type and what to do about it', () => {
86
- redactArg({ ...unbound });
86
+ RedactArg({ ...unbound });
87
87
 
88
88
  expect(console.warn).toHaveBeenCalledTimes(1);
89
89
  const message = vi.mocked(console.warn).mock.calls[0][0] as string;
@@ -94,22 +94,22 @@ describe('redactArg — name matches the convention but no entity exists', () =>
94
94
  });
95
95
 
96
96
  it('warns only once per input type, however hot the mutation is', () => {
97
- redactArg({ ...unbound });
98
- redactArg({ ...unbound });
99
- redactArg({ ...unbound });
97
+ RedactArg({ ...unbound });
98
+ RedactArg({ ...unbound });
99
+ RedactArg({ ...unbound });
100
100
  expect(console.warn).toHaveBeenCalledTimes(1);
101
101
  });
102
102
 
103
103
  it('warns separately for a different unbound input type', () => {
104
- redactArg({ ...unbound });
105
- redactArg({ ...unbound, inputTypeName: 'CreateScheduleInput' });
104
+ RedactArg({ ...unbound });
105
+ RedactArg({ ...unbound, inputTypeName: 'CreateScheduleInput' });
106
106
  expect(console.warn).toHaveBeenCalledTimes(2);
107
107
  });
108
108
  });
109
109
 
110
110
  describe('redactArg — @NoLog closes the gap the metadata cannot', () => {
111
111
  it('redacts a marked field on an input with no entity binding', () => {
112
- const out = redactArg({
112
+ const out = RedactArg({
113
113
  inputTypeName: 'CreateConnectionInput',
114
114
  rawValue: { CredentialName: 'acme', CredentialValues: SECRET },
115
115
  provider: CREDENTIAL_ENTITY,
@@ -123,7 +123,7 @@ describe('redactArg — @NoLog closes the gap the metadata cannot', () => {
123
123
  });
124
124
 
125
125
  it('a parameter-level mark redacts the whole arg regardless of binding', () => {
126
- const out = redactArg({
126
+ const out = RedactArg({
127
127
  inputTypeName: 'CreateConnectionInput',
128
128
  rawValue: { CredentialValues: SECRET },
129
129
  provider: CREDENTIAL_ENTITY,
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect } from 'vitest';
2
2
  import type { IMetadataProvider } from '@memberjunction/core';
3
- import { redactArg } from '../logging/secretRedactor.js';
3
+ import { RedactArg } from '../logging/secretRedactor.js';
4
4
 
5
5
  type EncryptedField = { Name: string };
6
6
  type FakeEntity = { ClassName: string; EncryptedFields: EncryptedField[] };
@@ -22,7 +22,7 @@ describe('redactArg', () => {
22
22
  };
23
23
 
24
24
  it('returns "<redacted>" when noLogParameter is set, regardless of other inputs', () => {
25
- const result = redactArg({
25
+ const result = RedactArg({
26
26
  inputTypeName: 'CreateMJCredentialInput',
27
27
  rawValue: { Values: 'FAKE_SECRET_VALUE_DO_NOT_USE' },
28
28
  provider: makeProvider([credentialEntity]),
@@ -33,7 +33,7 @@ describe('redactArg', () => {
33
33
  });
34
34
 
35
35
  it('returns "<metadata-not-ready>" when the provider has no entities (bootstrap window)', () => {
36
- const result = redactArg({
36
+ const result = RedactArg({
37
37
  inputTypeName: 'CreateMJCredentialInput',
38
38
  rawValue: { Values: 'FAKE_SECRET_VALUE_DO_NOT_USE' },
39
39
  provider: makeProvider([]),
@@ -44,7 +44,7 @@ describe('redactArg', () => {
44
44
  });
45
45
 
46
46
  it('fails open (passes through) when input type does not match Create/Update<X>Input regex', () => {
47
- const result = redactArg({
47
+ const result = RedactArg({
48
48
  inputTypeName: 'SomeCustomArgs',
49
49
  rawValue: { accessToken: 'FAKE_TOKEN' },
50
50
  provider: makeProvider([credentialEntity]),
@@ -55,7 +55,7 @@ describe('redactArg', () => {
55
55
  });
56
56
 
57
57
  it('fails open when input type matches regex but no entity is found', () => {
58
- const result = redactArg({
58
+ const result = RedactArg({
59
59
  inputTypeName: 'CreateUnknownEntityInput',
60
60
  rawValue: { Foo: 'bar' },
61
61
  provider: makeProvider([credentialEntity]),
@@ -66,7 +66,7 @@ describe('redactArg', () => {
66
66
  });
67
67
 
68
68
  it('redacts top-level keys matching EntityFieldInfo.Encrypt=true on entity-bound CRUD inputs', () => {
69
- const result = redactArg({
69
+ const result = RedactArg({
70
70
  inputTypeName: 'CreateMJCredentialInput',
71
71
  rawValue: { ID: 'abc-123', Name: 'HubSpot', Values: 'FAKE_SECRET_VALUE_DO_NOT_USE' },
72
72
  provider: makeProvider([credentialEntity]),
@@ -81,7 +81,7 @@ describe('redactArg', () => {
81
81
  });
82
82
 
83
83
  it('redacts top-level keys in noLogFields even when EncryptedFields does not include them', () => {
84
- const result = redactArg({
84
+ const result = RedactArg({
85
85
  inputTypeName: 'CreateUserInput',
86
86
  rawValue: { Name: 'Alice', SecretToken: 'oops' },
87
87
  provider: makeProvider([userEntity]),
@@ -95,7 +95,7 @@ describe('redactArg', () => {
95
95
  });
96
96
 
97
97
  it('Update<X>Input is also handled (not just Create<X>Input)', () => {
98
- const result = redactArg({
98
+ const result = RedactArg({
99
99
  inputTypeName: 'UpdateMJCredentialInput',
100
100
  rawValue: { ID: 'abc-123', Values: 'NEW_FAKE_SECRET' },
101
101
  provider: makeProvider([credentialEntity]),
@@ -113,7 +113,7 @@ describe('redactArg', () => {
113
113
  // resolvers as metadata-bound instead of flooding with false positives. Security is identical:
114
114
  // delete inputs carry PK + Options only — no encrypted field, so nothing is redacted, the keys
115
115
  // just pass through. See docs/adr/0001-graphql-variables-logging-tiered-by-verbose.md.
116
- const result = redactArg({
116
+ const result = RedactArg({
117
117
  inputTypeName: 'DeleteMJCredentialInput',
118
118
  rawValue: { ID: 'abc-123' },
119
119
  provider: makeProvider([credentialEntity]),
@@ -125,7 +125,7 @@ describe('redactArg', () => {
125
125
 
126
126
  it('Delete<X>Input never exposes an encrypted value even if one were somehow present', () => {
127
127
  // Defense-in-depth: even if a delete input carried an encrypted field name, it must still mask.
128
- const result = redactArg({
128
+ const result = RedactArg({
129
129
  inputTypeName: 'DeleteMJCredentialInput',
130
130
  rawValue: { ID: 'abc-123', Values: 'FAKE_SECRET_VALUE_DO_NOT_USE' },
131
131
  provider: makeProvider([credentialEntity]),
@@ -136,7 +136,7 @@ describe('redactArg', () => {
136
136
  });
137
137
 
138
138
  it('only walks TOP-level keys — nested objects with encrypted-field names are not recursed', () => {
139
- const result = redactArg({
139
+ const result = RedactArg({
140
140
  inputTypeName: 'CreateMJCredentialInput',
141
141
  rawValue: {
142
142
  Name: 'HubSpot',
@@ -151,7 +151,7 @@ describe('redactArg', () => {
151
151
  });
152
152
 
153
153
  it('passes non-object raw values through to shortenForLog', () => {
154
- const result = redactArg({
154
+ const result = RedactArg({
155
155
  inputTypeName: 'CreateMJCredentialInput',
156
156
  rawValue: 'plain-string',
157
157
  provider: makeProvider([credentialEntity]),
@@ -11,7 +11,7 @@ import { fileURLToPath } from 'node:url';
11
11
  import {
12
12
  CORE_CONSTANT_RESERVED_SERVER_EXTENSION_ROOTS,
13
13
  CORE_STATIC_RESERVED_SERVER_EXTENSION_ROOTS,
14
- coreReservedServerExtensionRoots,
14
+ CoreReservedServerExtensionRoots,
15
15
  } from '../serverExtensionReservedRoots.js';
16
16
  import { validateServerExtensionRootPath } from '@memberjunction/server-extensions-core';
17
17
 
@@ -58,12 +58,12 @@ describe('coreReservedServerExtensionRoots', () => {
58
58
 
59
59
  it('structurally guarantees every pre-auth app.use / app.get / app.post mount in index.ts is reserved', () => {
60
60
  const indexSrc = readFileSync(join(SRC, 'index.ts'), 'utf8');
61
- const authMiddlewareIndex = indexSrc.indexOf('app.use(createUnifiedAuthMiddleware');
61
+ const authMiddlewareIndex = indexSrc.indexOf('app.use(CreateUnifiedAuthMiddleware');
62
62
  expect(authMiddlewareIndex).toBeGreaterThan(0);
63
63
  const preAuthSrc = indexSrc.substring(0, authMiddlewareIndex);
64
64
 
65
65
  const mountRegex = /app\.(?:use|get|post)\s*\(\s*([^,\s)]+)/g;
66
- const reservedRoots = coreReservedServerExtensionRoots('/');
66
+ const reservedRoots = CoreReservedServerExtensionRoots('/');
67
67
 
68
68
  // Explicit allowlist of known non-path middleware mounts (e.g. app.use(mw), app.use(cors()), app.use(compression(...)))
69
69
  const knownNonPathTokens = [
@@ -71,7 +71,7 @@ describe('coreReservedServerExtensionRoots', () => {
71
71
  'express.',
72
72
  'compression',
73
73
  'cookieParser',
74
- 'createUnifiedAuthMiddleware',
74
+ 'CreateUnifiedAuthMiddleware',
75
75
  'mw',
76
76
  ];
77
77
  const isKnownNonPath = (t: string): boolean =>
@@ -120,7 +120,7 @@ describe('coreReservedServerExtensionRoots', () => {
120
120
  });
121
121
 
122
122
  it('includes graphqlRootPath and every core mount', () => {
123
- const roots = coreReservedServerExtensionRoots('/api');
123
+ const roots = CoreReservedServerExtensionRoots('/api');
124
124
  expect(roots).toEqual(
125
125
  expect.arrayContaining([
126
126
  '/api',
@@ -139,7 +139,7 @@ describe('coreReservedServerExtensionRoots', () => {
139
139
  });
140
140
 
141
141
  it('closes the F-M2 bypasses: cased /auth and sibling /healthcheck', () => {
142
- const extra = coreReservedServerExtensionRoots('/');
142
+ const extra = CoreReservedServerExtensionRoots('/');
143
143
  expect(validateServerExtensionRootPath('/Auth', extra)).toMatch(/reserved prefix/);
144
144
  expect(validateServerExtensionRootPath('/healthcheck', extra)).toMatch(/reserved prefix/);
145
145
  expect(validateServerExtensionRootPath('/Healthcheck', extra)).toMatch(/reserved prefix/);
@@ -156,7 +156,7 @@ describe('coreReservedServerExtensionRoots', () => {
156
156
  });
157
157
 
158
158
  it('reserves a non-default graphqlRootPath and its nested paths', () => {
159
- const extra = coreReservedServerExtensionRoots('/api');
159
+ const extra = CoreReservedServerExtensionRoots('/api');
160
160
  expect(validateServerExtensionRootPath('/api', extra)).toMatch(/reserved prefix/);
161
161
  expect(validateServerExtensionRootPath('/api/graphql', extra)).toMatch(/reserved prefix/);
162
162
  expect(validateServerExtensionRootPath('/apiv2', extra)).toBeNull();
@@ -45,7 +45,7 @@ vi.mock('../config.js', () => ({
45
45
  },
46
46
  }));
47
47
 
48
- import { variablesLoggingMiddleware } from '../logging/variablesLoggingMiddleware.js';
48
+ import { VariablesLoggingMiddleware } from '../logging/variablesLoggingMiddleware.js';
49
49
 
50
50
  /**
51
51
  * Build a synthetic GraphQLResolveInfo-shaped object that matches what type-graphql passes
@@ -99,7 +99,7 @@ describe('variablesLoggingMiddleware', () => {
99
99
 
100
100
  it('skips field resolvers (info.path.prev !== undefined) without logging', async () => {
101
101
  const next = vi.fn(async () => 'next-result');
102
- const result = await variablesLoggingMiddleware(
102
+ const result = await VariablesLoggingMiddleware(
103
103
  {
104
104
  root: undefined,
105
105
  args: { x: 1 },
@@ -126,7 +126,7 @@ describe('variablesLoggingMiddleware', () => {
126
126
  ],
127
127
  };
128
128
 
129
- await variablesLoggingMiddleware(
129
+ await VariablesLoggingMiddleware(
130
130
  {
131
131
  root: undefined,
132
132
  args: { input: { ID: 'abc', Name: 'HubSpot', Values: 'FAKE_SECRET' } },
@@ -165,7 +165,7 @@ describe('variablesLoggingMiddleware', () => {
165
165
  Entities: [{ ClassName: 'SomeUnrelatedEntity', EncryptedFields: [] }],
166
166
  };
167
167
 
168
- await variablesLoggingMiddleware(
168
+ await VariablesLoggingMiddleware(
169
169
  {
170
170
  root: undefined,
171
171
  args: { token: 'plaintext-leak' },
@@ -196,7 +196,7 @@ describe('variablesLoggingMiddleware', () => {
196
196
  const next = vi.fn(async () => undefined);
197
197
  const fakeProvider = { Entities: [] };
198
198
 
199
- await variablesLoggingMiddleware(
199
+ await VariablesLoggingMiddleware(
200
200
  {
201
201
  root: undefined,
202
202
  args: { input: { Values: 'FAKE_SECRET' } },
@@ -59,16 +59,22 @@ vi.mock('jsonwebtoken', () => ({
59
59
  }));
60
60
 
61
61
  vi.mock('../auth/index.js', () => ({
62
- getSigningKeys: mockGetSigningKeys,
63
- getSystemUser: vi.fn(),
64
- getValidationOptions: mockGetValidationOptions,
65
- verifyUserRecord: mockVerifyUserRecord,
66
- extractUserInfoFromPayload: mockExtractUserInfo,
62
+ GetSigningKeys: mockGetSigningKeys,
63
+ get getSigningKeys() { return this.GetSigningKeys; },
64
+ GetSystemUser: vi.fn(),
65
+ get getSystemUser() { return this.GetSystemUser; },
66
+ GetValidationOptions: mockGetValidationOptions,
67
+ get getValidationOptions() { return this.GetValidationOptions; },
68
+ VerifyUserRecord: mockVerifyUserRecord,
69
+ get verifyUserRecord() { return this.VerifyUserRecord; },
70
+ ExtractUserInfoFromPayload: mockExtractUserInfo,
71
+ get extractUserInfoFromPayload() { return this.ExtractUserInfoFromPayload; },
67
72
  }));
68
73
 
69
74
  vi.mock('../cache.js', () => {
70
75
  const map = new Map<string, boolean>();
71
- return { authCache: map };
76
+ return { AuthCache: map,
77
+ get authCache() { return this.AuthCache; } };
72
78
  });
73
79
 
74
80
  vi.mock('../config.js', () => ({
@@ -95,7 +101,7 @@ vi.mock('@memberjunction/api-keys', () => ({
95
101
  GetAPIKeyEngine: vi.fn(),
96
102
  }));
97
103
 
98
- import { createUnifiedAuthMiddleware } from '../context.js';
104
+ import { CreateUnifiedAuthMiddleware } from '../context.js';
99
105
  import type { Request, Response, NextFunction } from 'express';
100
106
  import type { DataSourceInfo } from '../types.js';
101
107
 
@@ -178,11 +184,11 @@ function setupSuccessfulAuth() {
178
184
  // ─── Tests ──────────────────────────────────────────────────────────────────
179
185
 
180
186
  describe('createUnifiedAuthMiddleware', () => {
181
- let middleware: ReturnType<typeof createUnifiedAuthMiddleware>;
187
+ let middleware: ReturnType<typeof CreateUnifiedAuthMiddleware>;
182
188
 
183
189
  beforeEach(() => {
184
190
  vi.clearAllMocks();
185
- middleware = createUnifiedAuthMiddleware(mockDataSources);
191
+ middleware = CreateUnifiedAuthMiddleware(mockDataSources);
186
192
  });
187
193
 
188
194
  describe('OPTIONS passthrough', () => {
@@ -13,7 +13,7 @@ vi.mock('@memberjunction/core', async (importOriginal) => {
13
13
  };
14
14
  });
15
15
 
16
- import { resolveIdentityByEmail } from '../realtimeWidget/visitorIdentity.js';
16
+ import { ResolveIdentityByEmail } from '../realtimeWidget/visitorIdentity.js';
17
17
  import type { EntityInfo, IMetadataProvider, UserInfo } from '@memberjunction/core';
18
18
 
19
19
  type LookupParams = { EntityName: string; ExtraFilter: string; Fields: string[] };
@@ -32,7 +32,7 @@ describe('resolveIdentityByEmail — the configured identity entity can have ANY
32
32
  it('selects the real key column and returns its bare value for a single non-ID key', async () => {
33
33
  runViewMock.mockResolvedValue({ Success: true, Results: [{ individual_id: 4711 }] });
34
34
  const provider = makeProvider({ ID: 'ent-persons', PrimaryKeys: [{ Name: 'individual_id' }] });
35
- const out = await resolveIdentityByEmail('ada@example.com', user, provider, { entityName: 'Persons', emailField: 'EmailAddress' });
35
+ const out = await ResolveIdentityByEmail('ada@example.com', user, provider, { entityName: 'Persons', EmailField: 'EmailAddress' });
36
36
  expect(lastParams().Fields).toEqual(['individual_id']);
37
37
  expect(lastParams().ExtraFilter).toBe("EmailAddress = 'ada@example.com'");
38
38
  expect(out).toEqual({ entityId: 'ent-persons', recordId: '4711' });
@@ -41,7 +41,7 @@ describe('resolveIdentityByEmail — the configured identity entity can have ANY
41
41
  it('selects EVERY key column and carries a composite key as a full segment, not its first column', async () => {
42
42
  runViewMock.mockResolvedValue({ Success: true, Results: [{ OrderID: '11055', LineNo: 3 }] });
43
43
  const provider = makeProvider({ ID: 'ent-lines', PrimaryKeys: [{ Name: 'OrderID' }, { Name: 'LineNo' }] });
44
- const out = await resolveIdentityByEmail('x@y.com', user, provider, { entityName: 'Order Lines' });
44
+ const out = await ResolveIdentityByEmail('x@y.com', user, provider, { entityName: 'Order Lines' });
45
45
  expect(lastParams().Fields).toEqual(['OrderID', 'LineNo']);
46
46
  expect(out).toEqual({ entityId: 'ent-lines', recordId: 'OrderID|11055||LineNo|3' });
47
47
  });
@@ -49,13 +49,13 @@ describe('resolveIdentityByEmail — the configured identity entity can have ANY
49
49
  it('stays anonymous when no row matches or a key column is null', async () => {
50
50
  const provider = makeProvider({ ID: 'ent-users', PrimaryKeys: [{ Name: 'ID' }] });
51
51
  runViewMock.mockResolvedValue({ Success: true, Results: [] });
52
- expect(await resolveIdentityByEmail('none@y.com', user, provider)).toBeUndefined();
52
+ expect(await ResolveIdentityByEmail('none@y.com', user, provider)).toBeUndefined();
53
53
  runViewMock.mockResolvedValue({ Success: true, Results: [{ ID: null }] });
54
- expect(await resolveIdentityByEmail('null@y.com', user, provider)).toBeUndefined();
54
+ expect(await ResolveIdentityByEmail('null@y.com', user, provider)).toBeUndefined();
55
55
  });
56
56
 
57
57
  it('stays anonymous when the configured entity is not in metadata', async () => {
58
- expect(await resolveIdentityByEmail('a@b.com', user, makeProvider(undefined), { entityName: 'Nope' })).toBeUndefined();
58
+ expect(await ResolveIdentityByEmail('a@b.com', user, makeProvider(undefined), { entityName: 'Nope' })).toBeUndefined();
59
59
  expect(runViewMock).not.toHaveBeenCalled();
60
60
  });
61
61
  });