@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
@@ -13,25 +13,40 @@ import type { MagicLinkJWTClaims, MagicLinkScopeEntry, RedeemErrorCode } from '.
13
13
  export const MAGIC_LINK_TOKEN_PREFIX = 'mj_ml_';
14
14
 
15
15
  /** Generates a cryptographically random raw magic-link token. */
16
- export function generateRawToken(): string {
16
+ export function GenerateRawToken(): string {
17
17
  return MAGIC_LINK_TOKEN_PREFIX + randomBytes(32).toString('hex');
18
18
  }
19
19
 
20
+ /** @deprecated Use {@link GenerateRawToken}. */
21
+ export function generateRawToken(): string {
22
+ return GenerateRawToken();
23
+ }
24
+
20
25
  /** Generates an opaque per-session id (anonymous-session forensics correlation). */
21
- export function generateSessionId(): string {
26
+ export function GenerateSessionId(): string {
22
27
  return randomBytes(16).toString('base64url');
23
28
  }
24
29
 
30
+ /** @deprecated Use {@link GenerateSessionId}. */
31
+ export function generateSessionId(): string {
32
+ return GenerateSessionId();
33
+ }
34
+
25
35
  /**
26
36
  * SHA-256 hash of a raw token, base64url-encoded — only the hash is ever
27
37
  * persisted. base64url (43 chars) is shorter than hex (64 chars), URL-safe, and
28
38
  * carries the full 256 bits. Both write (CreateInvite) and read (RedeemInvite)
29
39
  * paths call this, so the encoding stays internally consistent.
30
40
  */
31
- export function hashToken(rawToken: string): string {
41
+ export function HashToken(rawToken: string): string {
32
42
  return createHash('sha256').update(rawToken).digest('base64url');
33
43
  }
34
44
 
45
+ /** @deprecated Use {@link HashToken}. */
46
+ export function hashToken(rawToken: string): string {
47
+ return HashToken(rawToken);
48
+ }
49
+
35
50
  /** Minimal shape of an invite needed for redemption eligibility. */
36
51
  export interface InviteEvaluationInput {
37
52
  Status: string;
@@ -54,7 +69,7 @@ function normalizeName(name: string): string {
54
69
  * (including an external user already holding a restricted magic-link session)
55
70
  * from minting invites.
56
71
  */
57
- export function canIssueInvites(
72
+ export function CanIssueInvites(
58
73
  userType: string | null | undefined,
59
74
  userRoleNames: readonly string[],
60
75
  issuerRoleNames: readonly string[],
@@ -69,13 +84,22 @@ export function canIssueInvites(
69
84
  return userRoleNames.some((r) => allowed.has(normalizeName(r)));
70
85
  }
71
86
 
87
+ /** @deprecated Use {@link CanIssueInvites}. */
88
+ export function canIssueInvites(
89
+ userType: string | null | undefined,
90
+ userRoleNames: readonly string[],
91
+ issuerRoleNames: readonly string[],
92
+ ): boolean {
93
+ return CanIssueInvites(userType, userRoleNames, issuerRoleNames);
94
+ }
95
+
72
96
  /**
73
97
  * Pure check for WHAT role an invite may grant. The restricted role is always
74
98
  * grantable; any other role must be explicitly listed in `grantableRoleNames`.
75
99
  * Applied to every caller (Owners included) so a privileged role can never be
76
100
  * attached to an external magic-link user unless the deployment opts in.
77
101
  */
78
- export function isRoleGrantable(
102
+ export function IsRoleGrantable(
79
103
  roleName: string | null | undefined,
80
104
  restrictedRoleName: string,
81
105
  grantableRoleNames: readonly string[],
@@ -88,8 +112,17 @@ export function isRoleGrantable(
88
112
  return allowed.has(target);
89
113
  }
90
114
 
115
+ /** @deprecated Use {@link IsRoleGrantable}. */
116
+ export function isRoleGrantable(
117
+ roleName: string | null | undefined,
118
+ restrictedRoleName: string,
119
+ grantableRoleNames: readonly string[],
120
+ ): boolean {
121
+ return IsRoleGrantable(roleName, restrictedRoleName, grantableRoleNames);
122
+ }
123
+
91
124
  /** Pure redemption-eligibility check. Returns ok + an error code when not. */
92
- export function evaluateInvite(invite: InviteEvaluationInput, nowMs: number): { ok: boolean; errorCode?: RedeemErrorCode } {
125
+ export function EvaluateInvite(invite: InviteEvaluationInput, nowMs: number): { ok: boolean; errorCode?: RedeemErrorCode } {
93
126
  if (invite.Status === 'Revoked') {
94
127
  return { ok: false, errorCode: 'revoked' };
95
128
  }
@@ -106,75 +139,43 @@ export function evaluateInvite(invite: InviteEvaluationInput, nowMs: number): {
106
139
  return { ok: true };
107
140
  }
108
141
 
109
- /** SQL dialect for {@link buildConsumeInviteSQL}. */
110
- export type ConsumeInviteDialect = 'sqlserver' | 'postgresql';
142
+ /** @deprecated Use {@link EvaluateInvite}. */
143
+ export function evaluateInvite(invite: InviteEvaluationInput, nowMs: number): { ok: boolean; errorCode?: RedeemErrorCode } {
144
+ return EvaluateInvite(invite, nowMs);
145
+ }
111
146
 
112
- /** SQL Server table identifier — bracket-quoted `[schema].[table]` (word chars only). */
113
- const QUALIFIED_TABLE_PATTERN = /^\[\w+\]\.\[\w+\]$/;
114
147
  /** PostgreSQL table identifier — `schema.table` (word chars only); auto-quoted downstream. */
115
148
  const QUALIFIED_TABLE_PATTERN_PG = /^\w+\.\w+$/;
116
149
 
117
150
  /**
118
- * Builds the atomic compare-and-swap UPDATE that consumes one use of an invite,
119
- * in the given SQL dialect.
120
- *
121
- * The WHERE clause re-checks every eligibility condition at the DB level, so the
122
- * increment and the guard are a single atomic operation: concurrent redemptions
123
- * of a single-use link race on the row and exactly one matches. This is what
124
- * actually enforces single-use — the JS-side `evaluateInvite` is only a friendly
125
- * pre-check. The matched row's ID is returned to the caller (via `OUTPUT` on SQL
126
- * Server, `RETURNING` on PostgreSQL) so it can detect a win (exactly one row).
151
+ * Builds the PostgreSQL atomic compare-and-swap UPDATE that consumes one use of an invite.
127
152
  *
128
- * The invite ID MUST be bound as a parameter by the caller (`@p0` on SQL Server,
129
- * `$1` on PostgreSQL) — it is never interpolated into the string, so this builder
130
- * is injection-safe regardless of the ID's contents.
153
+ * PostgreSQL only. SQL Server consumes through the granted `spConsumeMagicLinkInvite` procedure,
154
+ * because its runtime roles are never granted table DML (#4753). PostgreSQL needs neither: its
155
+ * runtime roles hold INSERT/UPDATE/DELETE on every `__mj` table
156
+ * (V202605040300__v5.33.x__Unblock_PostgreSQL_End_To_End.pg-only.sql), and no PG counterpart of
157
+ * the procedure exists — the release-time converter leaves `CREATE PROCEDURE` unhandled.
131
158
  *
132
- * **SQL Server** — `OUTPUT` goes `INTO` a table variable (not a bare OUTPUT):
133
- * SQL Server forbids a bare OUTPUT clause on a table that has enabled triggers,
134
- * and CodeGen adds an `__mj_UpdatedAt` trigger to every MJ table. The trailing
135
- * SELECT returns the matched row(s) regardless of trigger behavior.
159
+ * The WHERE re-checks every eligibility condition (the same predicate as the procedure), so the
160
+ * increment and the guard are one atomic statement: concurrent redemptions of a single-use link
161
+ * serialize on the row lock and exactly one matches. `RETURNING ID` yields the row iff the guard
162
+ * matched. The invite ID MUST be bound by the caller as `$1` — it is never interpolated.
136
163
  *
137
- * **PostgreSQL** — the `UPDATE … WHERE` guard IS itself the atomic single-use
138
- * gate: the row is locked for the UPDATE's duration, so concurrent redemptions
139
- * serialize and only the first matching `Status='Active' AND UseCount < MaxUses`
140
- * wins; `RETURNING` yields the row iff the guard matched (equivalent to the SS
141
- * `OUTPUT`-into-table win-detect). PascalCase identifiers are auto-quoted by
142
- * `PostgreSQLDataProvider.ExecuteSQL`, so the table is passed unquoted (`schema.table`).
143
- *
144
- * `qualifiedTable` is asserted to match the dialect's whitelist pattern before
145
- * interpolation. The caller derives it from `EntityInfo` (never user input), so
146
- * this is defense-in-depth: even a future careless caller cannot turn this into
147
- * an injection vector — a non-conforming table throws.
148
- *
149
- * @param qualifiedTable `[schema].[table]` (sqlserver) or `schema.table` (postgresql) for MagicLinkInvite
150
- * @param dialect target SQL dialect (defaults to `'sqlserver'`)
164
+ * `qualifiedTable` is `schema.table` unquoted (PostgreSQLDataProvider.ExecuteSQL auto-quotes the
165
+ * PascalCase identifiers) and is asserted against a whitelist before interpolation — the caller
166
+ * never passes user input, so this is defense-in-depth.
151
167
  */
152
- export function buildConsumeInviteSQL(qualifiedTable: string, dialect: ConsumeInviteDialect = 'sqlserver'): string {
153
- if (dialect === 'postgresql') {
154
- if (!QUALIFIED_TABLE_PATTERN_PG.test(qualifiedTable)) {
155
- throw new Error(`buildConsumeInviteSQL: refusing to build SQL for non-whitelisted table identifier '${qualifiedTable}'.`);
156
- }
157
- return (
158
- `UPDATE ${qualifiedTable} ` +
159
- `SET UseCount = UseCount + 1, ` +
160
- `ConsumedAt = COALESCE(ConsumedAt, (now() AT TIME ZONE 'utc')), ` +
161
- `Status = CASE WHEN UseCount + 1 >= MaxUses THEN 'Consumed' ELSE Status END ` +
162
- `WHERE ID = $1 AND Status = 'Active' AND UseCount < MaxUses AND ExpiresAt > (now() AT TIME ZONE 'utc') ` +
163
- `RETURNING ID;`
164
- );
165
- }
166
- if (!QUALIFIED_TABLE_PATTERN.test(qualifiedTable)) {
167
- throw new Error(`buildConsumeInviteSQL: refusing to build SQL for non-whitelisted table identifier '${qualifiedTable}'.`);
168
+ export function BuildConsumeInvitePostgresSQL(qualifiedTable: string): string {
169
+ if (!QUALIFIED_TABLE_PATTERN_PG.test(qualifiedTable)) {
170
+ throw new Error(`BuildConsumeInvitePostgresSQL: refusing to build SQL for non-whitelisted table identifier '${qualifiedTable}'.`);
168
171
  }
169
172
  return (
170
- `DECLARE @consumed TABLE (ID UNIQUEIDENTIFIER); ` +
171
173
  `UPDATE ${qualifiedTable} ` +
172
174
  `SET UseCount = UseCount + 1, ` +
173
- `ConsumedAt = COALESCE(ConsumedAt, SYSUTCDATETIME()), ` +
175
+ `ConsumedAt = COALESCE(ConsumedAt, (now() AT TIME ZONE 'utc')), ` +
174
176
  `Status = CASE WHEN UseCount + 1 >= MaxUses THEN 'Consumed' ELSE Status END ` +
175
- `OUTPUT INSERTED.ID INTO @consumed ` +
176
- `WHERE ID = @p0 AND Status = 'Active' AND UseCount < MaxUses AND ExpiresAt > SYSUTCDATETIME(); ` +
177
- `SELECT ID FROM @consumed;`
177
+ `WHERE ID = $1 AND Status = 'Active' AND UseCount < MaxUses AND ExpiresAt > (now() AT TIME ZONE 'utc') ` +
178
+ `RETURNING ID;`
178
179
  );
179
180
  }
180
181
 
@@ -184,7 +185,7 @@ export function buildConsumeInviteSQL(qualifiedTable: string, dialect: ConsumeIn
184
185
  * of scopes across multiple redeemed links — carried in the re-minted JWT, never as
185
186
  * roles on a shared user, so anonymous sessions can't accrete into a superuser.
186
187
  */
187
- export function unionScopes(prior: readonly MagicLinkScopeEntry[] | undefined, next: MagicLinkScopeEntry): MagicLinkScopeEntry[] {
188
+ export function UnionScopes(prior: readonly MagicLinkScopeEntry[] | undefined, next: MagicLinkScopeEntry): MagicLinkScopeEntry[] {
188
189
  const result = [...(prior ?? [])];
189
190
  if (!result.some((s) => s.inviteId === next.inviteId)) {
190
191
  result.push(next);
@@ -192,8 +193,13 @@ export function unionScopes(prior: readonly MagicLinkScopeEntry[] | undefined, n
192
193
  return result;
193
194
  }
194
195
 
196
+ /** @deprecated Use {@link UnionScopes}. */
197
+ export function unionScopes(prior: readonly MagicLinkScopeEntry[] | undefined, next: MagicLinkScopeEntry): MagicLinkScopeEntry[] {
198
+ return UnionScopes(prior, next);
199
+ }
200
+
195
201
  /** Builds the session-token claims (pure). */
196
- export function buildSessionClaims(args: {
202
+ export function BuildSessionClaims(args: {
197
203
  issuer: string;
198
204
  audience: string;
199
205
  inviteId: string;
@@ -236,9 +242,35 @@ export function buildSessionClaims(args: {
236
242
  mj_app_id: args.applicationId,
237
243
  mj_role: args.roleName,
238
244
  mj_invited_by: args.invitedByUserId,
239
- mj_scopes: unionScopes(args.priorScopes, scopeEntry),
245
+ mj_scopes: UnionScopes(args.priorScopes, scopeEntry),
240
246
  mj_anon: args.anonymous ? true : undefined,
241
247
  mj_sid: args.sessionId,
242
248
  mj_magic_link: true,
243
249
  };
244
250
  }
251
+
252
+ /** @deprecated Use {@link BuildSessionClaims}. */
253
+ export function buildSessionClaims(args: {
254
+ issuer: string;
255
+ audience: string;
256
+ inviteId: string;
257
+ email: string;
258
+ firstName?: string;
259
+ lastName?: string;
260
+ applicationId: string;
261
+ roleName: string;
262
+ invitedByUserId?: string;
263
+ /** True for anonymous sessions — the server enforces scope from mj_scopes, not roles. */
264
+ anonymous?: boolean;
265
+ /** Opaque per-session id (anonymous forensics correlation). */
266
+ sessionId?: string;
267
+ /** Prior session's scope union to carry forward (multi-link anonymous sessions). */
268
+ priorScopes?: readonly MagicLinkScopeEntry[];
269
+ /** Resource-share/embed scope for this link's entry. */
270
+ resourceType?: string;
271
+ resourceId?: string;
272
+ nowSeconds: number;
273
+ ttlSeconds: number;
274
+ }): MagicLinkJWTClaims {
275
+ return BuildSessionClaims(args);
276
+ }
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  /** Minimal HTML-escape for safe interpolation into attribute/text content. */
8
- export function escapeHtml(s: string): string {
8
+ export function EscapeHtml(s: string): string {
9
9
  return s
10
10
  .replace(/&/g, '&amp;')
11
11
  .replace(/</g, '&lt;')
@@ -14,6 +14,11 @@ export function escapeHtml(s: string): string {
14
14
  .replace(/'/g, '&#39;');
15
15
  }
16
16
 
17
+ /** @deprecated Use {@link EscapeHtml}. */
18
+ export function escapeHtml(s: string): string {
19
+ return EscapeHtml(s);
20
+ }
21
+
17
22
  /**
18
23
  * Builds the redemption landing page served by `GET /magic-link/redeem`.
19
24
  *
@@ -27,9 +32,9 @@ export function escapeHtml(s: string): string {
27
32
  * @param token the raw magic-link token (embedded in a hidden field)
28
33
  * @param actionPath the same-origin path the form POSTs to (e.g. `/magic-link/redeem`)
29
34
  */
30
- export function buildRedeemLandingHtml(token: string, actionPath: string): string {
31
- const t = escapeHtml(token);
32
- const action = escapeHtml(actionPath);
35
+ export function BuildRedeemLandingHtml(token: string, actionPath: string): string {
36
+ const t = EscapeHtml(token);
37
+ const action = EscapeHtml(actionPath);
33
38
  // Hardcoded colors are intentional here — this is a standalone server-rendered
34
39
  // HTML response, not Angular component CSS, so the design-token rule doesn't apply.
35
40
  return `<!doctype html>
@@ -60,3 +65,8 @@ export function buildRedeemLandingHtml(token: string, actionPath: string): strin
60
65
  </body>
61
66
  </html>`;
62
67
  }
68
+
69
+ /** @deprecated Use {@link BuildRedeemLandingHtml}. */
70
+ export function buildRedeemLandingHtml(token: string, actionPath: string): string {
71
+ return BuildRedeemLandingHtml(token, actionPath);
72
+ }
@@ -10,14 +10,14 @@
10
10
  */
11
11
  export interface MagicLinkScopeEntry {
12
12
  /** The invite that granted this scope entry. */
13
- inviteId: string;
13
+ inviteId: string; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined
14
14
  /** The Application this entry grants access to. */
15
- appId: string;
15
+ appId: string; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined
16
16
  /** The role name this entry carries (email/app-session links). */
17
- role?: string;
17
+ role?: string; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
18
18
  /** For resource-share/embed links: the shared resource's type + id. */
19
- resourceType?: string;
20
- resourceId?: string;
19
+ resourceType?: string; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
20
+ resourceId?: string; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
21
21
  }
22
22
 
23
23
  /**
@@ -27,25 +27,25 @@ export interface MagicLinkScopeEntry {
27
27
  */
28
28
  export interface MagicLinkJWTClaims {
29
29
  /** Issuer — MJ's public URL; resolves to the registered `magic-link` auth provider. */
30
- iss: string;
30
+ iss: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
31
31
  /** Audience — the configured magic-link audience (default `mj-magic-link`). */
32
- aud: string;
32
+ aud: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
33
33
  /** Subject — `magic-link|<inviteId>`. */
34
- sub: string;
34
+ sub: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
35
35
  /** Issued-at (epoch seconds). */
36
- iat: number;
36
+ iat: number; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
37
37
  /** Expiry (epoch seconds). */
38
- exp: number;
39
- email: string;
40
- given_name?: string;
41
- family_name?: string;
42
- name?: string;
38
+ exp: number; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
39
+ email: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
40
+ given_name?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
41
+ family_name?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
42
+ name?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
43
43
  /** The single Application this session is scoped to. */
44
- mj_app_id: string;
44
+ mj_app_id: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
45
45
  /** The restricted role name assigned to this user (informational; enforcement is server-side via the role's entity permissions). */
46
- mj_role: string;
46
+ mj_role: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
47
47
  /** UserID of the internal user who issued the invite (attribution/audit). Absent on links whose inviter could not be resolved. */
48
- mj_invited_by?: string;
48
+ mj_invited_by?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
49
49
  /**
50
50
  * Per-session scope UNION (Phase 4+). Each entry is one redeemed link's grant.
51
51
  * The server enforces anonymous sessions against THIS set (not the user's role
@@ -53,81 +53,81 @@ export interface MagicLinkJWTClaims {
53
53
  * different scopes without accretion. For email sessions the singular mj_app_id/
54
54
  * mj_role remain authoritative; this carries the union when links are stacked.
55
55
  */
56
- mj_scopes?: MagicLinkScopeEntry[];
56
+ mj_scopes?: MagicLinkScopeEntry[]; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
57
57
  /** True when this session resolves to the shared Anonymous principal (claims-based enforcement). */
58
- mj_anon?: boolean;
58
+ mj_anon?: boolean; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
59
59
  /** Opaque per-session id — correlates one anonymous session's activity across audit rows without a real user. */
60
- mj_sid?: string;
60
+ mj_sid?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
61
61
  /**
62
62
  * Public web widget instance id (additive — set only for widget guest sessions
63
63
  * minted by WidgetSessionService). Binds the synthesized guest principal to one
64
64
  * widget instance so its pinned agent / guest role can be locked down. Absent on
65
65
  * ordinary magic-link sessions.
66
66
  */
67
- mj_widget_id?: string;
67
+ mj_widget_id?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
68
68
  /**
69
69
  * Host-asserted visitor email for a widget `host-identity` session (additive). The
70
70
  * authoritative `email`/`sub` still resolve the constrained shared Anonymous principal;
71
71
  * this carries WHO the host says the visitor is, for the agent to look up their account —
72
72
  * without granting that account's permissions. Absent on anonymous/ordinary sessions.
73
73
  */
74
- mj_host_email?: string;
74
+ mj_host_email?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
75
75
  /**
76
76
  * Returning-visitor anchor for a widget guest session (additive, RV1). Carried so the VOICE path —
77
77
  * whose conversation is created server-side — can stamp the same Conversation.VisitorKey the text
78
78
  * path stamps client-side. Present only when the widget remembers returning visitors.
79
79
  */
80
- mj_visitor_key?: string;
80
+ mj_visitor_key?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
81
81
  /** The prior conversation this visit chains from (RV2), for the voice path to stamp Conversation.LastConversationID. */
82
- mj_last_conversation_id?: string;
82
+ mj_last_conversation_id?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
83
83
  /** Resolved polymorphic identity entity id (RV4), for the voice path to stamp the existing Conversation.LinkedEntityID / AIAgentSession.LinkedEntityID. */
84
- mj_linked_entity_id?: string;
84
+ mj_linked_entity_id?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
85
85
  /** Resolved polymorphic identity record id (RV4), for the voice path to stamp the existing Conversation.LinkedRecordID / AIAgentSession.LinkedRecordID. */
86
- mj_linked_record_id?: string;
86
+ mj_linked_record_id?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
87
87
  /** Marks the session as magic-link so the Explorer can confine the UI. */
88
- mj_magic_link: true;
88
+ mj_magic_link: true; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
89
89
  }
90
90
 
91
91
  /** Parameters for creating a magic-link invite (POST /magic-link/create). */
92
92
  export interface CreateMagicLinkInviteParams {
93
93
  /** Recipient email — becomes the provisioned user's email. */
94
- email: string;
94
+ email: string; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined
95
95
  /** The Application the invite grants access to. */
96
- applicationId: string;
96
+ ApplicationId: string;
97
97
  /** Restricted role to assign. Defaults to the configured `restrictedRoleName`. */
98
- roleId?: string;
98
+ RoleId?: string;
99
99
  /** Hours until the link expires. Defaults to config `defaultExpiresInHours`. */
100
- expiresInHours?: number;
100
+ ExpiresInHours?: number;
101
101
  /** Maximum redemptions. Defaults to 1 (single-use). */
102
- maxUses?: number;
102
+ MaxUses?: number;
103
103
  /** Optional given/family name to seed the provisioned user. */
104
- firstName?: string;
105
- lastName?: string;
104
+ firstName?: string; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
105
+ lastName?: string; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
106
106
  }
107
107
 
108
108
  /** Result of creating an invite. */
109
109
  export interface CreateMagicLinkInviteResult {
110
- success: boolean;
111
- inviteId?: string;
110
+ success: boolean; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
111
+ inviteId?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
112
112
  /** Full redemption URL to share. */
113
- redemptionUrl?: string;
113
+ redemptionUrl?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
114
114
  /**
115
115
  * The raw token, returned ONLY when no email provider is configured (so the
116
116
  * caller can deliver the link out of band). Never returned once email send
117
117
  * succeeds, and never persisted.
118
118
  */
119
- rawToken?: string;
119
+ rawToken?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
120
120
  /** Whether the invite email was dispatched. */
121
- emailSent?: boolean;
121
+ emailSent?: boolean; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
122
122
  /** ISO expiry timestamp. */
123
- expiresAt?: string;
124
- error?: string;
123
+ expiresAt?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
124
+ error?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
125
125
  /**
126
126
  * Set when the request was rejected for authorization reasons:
127
127
  * `forbidden` — caller may not issue invites; `invalid_role` — the requested
128
128
  * role is not grantable via magic-link. Drives the HTTP status in the router.
129
129
  */
130
- errorCode?: 'forbidden' | 'invalid_role';
130
+ errorCode?: 'forbidden' | 'invalid_role'; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
131
131
  }
132
132
 
133
133
  /** Why a redemption failed. */
@@ -139,25 +139,25 @@ export type RedeemErrorCode = 'not_found' | 'expired' | 'consumed' | 'revoked' |
139
139
  * all fields optional because the API/JSON flow may omit them.
140
140
  */
141
141
  export interface RedeemAuditContext {
142
- ipAddress?: string;
143
- userAgent?: string;
144
- origin?: string;
142
+ ipAddress?: string; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
143
+ userAgent?: string; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
144
+ origin?: string; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
145
145
  }
146
146
 
147
147
  /** Result of redeeming an invite. */
148
148
  export interface RedeemMagicLinkResult {
149
- success: boolean;
149
+ success: boolean; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
150
150
  /** The minted session JWT (RS256). */
151
- token?: string;
151
+ token?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
152
152
  /** ISO expiry of the session token. */
153
- expiresAt?: string;
153
+ expiresAt?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
154
154
  /** The Application the session is scoped to. */
155
- applicationId?: string;
155
+ applicationId?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
156
156
  /** The Application's display name (used to deep-link the browser into that app). */
157
- applicationName?: string;
157
+ applicationName?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
158
158
  /** The Application's URL path slug (preferred for deep-linking; falls back to name). */
159
- applicationPath?: string;
160
- email?: string;
161
- error?: string;
162
- errorCode?: RedeemErrorCode;
159
+ applicationPath?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
160
+ email?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
161
+ error?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
162
+ errorCode?: RedeemErrorCode; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
163
163
  }
@@ -5,7 +5,7 @@ import { configInfo } from "../config.js";
5
5
  import { MJUserEntity, MJUserRoleEntity, MJUserApplicationEntity, MJUserApplicationEntityEntity, MJApplicationEntityType, MJApplicationEntityEntityType, UserInfoEngine } from "@memberjunction/core-entities";
6
6
 
7
7
  export class NewUserBase {
8
- public async createNewUser(firstName: string, lastName: string, email: string, linkedRecordType: string = 'None', linkedEntityId?: string, linkedEntityRecordId?: string): Promise<MJUserEntity | null> {
8
+ public async createNewUser(firstName: string, lastName: string, email: string, linkedRecordType: string = 'None', linkedEntityId?: string, linkedEntityRecordId?: string): Promise<MJUserEntity | null> { // case-violation-ok-legacy-back-compat: a subclass overrides this; a stub preserves CALLING the old name but not OVERRIDING it
9
9
  try {
10
10
  const contextUser: UserInfo | null = ResolveConfiguredPrincipal(
11
11
  configInfo?.userHandling?.contextUserForNewUserCreation,
@@ -116,7 +116,7 @@ function lowestActiveById<T extends ResolvablePrincipal>(matches: readonly T[]):
116
116
  * @param users the candidate pool, normally `UserCache.Users`
117
117
  * @param systemUserId the deployment's system user ID (`UserCache.Instance.SYSTEM_USER_ID`)
118
118
  */
119
- export function resolvePrincipalFrom<T extends ResolvablePrincipal>(
119
+ export function ResolvePrincipalFrom<T extends ResolvablePrincipal>(
120
120
  candidate: string | undefined,
121
121
  users: readonly T[],
122
122
  systemUserId: string,
@@ -156,6 +156,15 @@ export function resolvePrincipalFrom<T extends ResolvablePrincipal>(
156
156
  };
157
157
  }
158
158
 
159
+ /** @deprecated Use {@link ResolvePrincipalFrom}. */
160
+ export function resolvePrincipalFrom<T extends ResolvablePrincipal>(
161
+ candidate: string | undefined,
162
+ users: readonly T[],
163
+ systemUserId: string,
164
+ ): PrincipalResolution<T> {
165
+ return ResolvePrincipalFrom(candidate, users, systemUserId);
166
+ }
167
+
159
168
  /**
160
169
  * Why a configured candidate yielded nothing. The two causes need opposite fixes, so the message
161
170
  * has to tell them apart: "no such user" is a typo or the wrong column, while "matched, but
@@ -230,7 +239,7 @@ export function ReportedMisconfigurationCount(): number {
230
239
  * handle null rather than assume a principal is always available
231
240
  */
232
241
  export function ResolveConfiguredPrincipal(candidate: string | undefined, purpose: string): UserInfo | null {
233
- const resolution = resolvePrincipalFrom(candidate, UserCache.Instance.Users, UserCache.Instance.SYSTEM_USER_ID);
242
+ const resolution = ResolvePrincipalFrom(candidate, UserCache.Instance.Users, UserCache.Instance.SYSTEM_USER_ID);
234
243
 
235
244
  if (resolution.warning) {
236
245
  const key = `${purpose} :: ${candidate ?? ''}`;
package/src/cache.ts CHANGED
@@ -2,9 +2,12 @@ import { LRUCache } from 'lru-cache';
2
2
 
3
3
  const oneHourMs = 60 * 60 * 1000;
4
4
 
5
- export const authCache = new LRUCache({
5
+ export const AuthCache = new LRUCache({
6
6
  max: 50000,
7
7
  ttl: oneHourMs,
8
8
  ttlAutopurge: false,
9
9
  });
10
10
 
11
+ /** @deprecated Use {@link AuthCache}. */
12
+ export const authCache = AuthCache;
13
+
package/src/config.ts CHANGED
@@ -230,6 +230,29 @@ const cacheSettingsSchema = z.object({
230
230
  evictionSweepIntervalSeconds: z.number().optional().default(300),
231
231
  /** Enable verbose cache logging (hits, misses, evictions). Default: false. */
232
232
  verboseLogging: z.boolean().optional().default(false),
233
+ /**
234
+ * Entity names whose FULL ROW may ride along with a cache-invalidation broadcast.
235
+ *
236
+ * The cache-invalidation subscription is delivered to EVERY connected client with no per-user
237
+ * filter (see CacheInvalidationResolver), so any row named here is disclosed to every signed-in
238
+ * session, whatever row-level security or tenant scoping would otherwise apply to reading it.
239
+ *
240
+ * Defaults to `[]`: invalidation still carries the entity name and primary key, which is all a
241
+ * client needs to evict, and the client re-fetches through the normal read path where access
242
+ * control applies. Listing an entity re-enables the apply-in-place optimisation for it — correct
243
+ * only for reference data every signed-in user is allowed to read.
244
+ *
245
+ * What the re-fetch costs depends on the consumer. `ConversationEngine` re-reads the ONE record
246
+ * by primary key. `BaseEngine` (every engine subclass with `AutoRefresh`, the default) applies a
247
+ * remote save in place only when the row is present, so without it a remote save falls through to
248
+ * a full reload of each matching config — a `RunView` of that entity, not a keyed read. Remote
249
+ * deletes still apply in place from the primary key. Engine-cached reference entities that every
250
+ * signed-in user may read are the ones worth listing here.
251
+ *
252
+ * `['*']` opts every entity in, restoring the previous behaviour. Only safe on a deployment where
253
+ * every signed-in user may read every row of every entity.
254
+ */
255
+ recordDataBroadcastEntities: z.array(z.string()).optional().default([]),
233
256
  });
234
257
 
235
258
  const loggingSettingsSchema = z.object({
@@ -812,9 +835,14 @@ export const DEFAULT_SERVER_CONFIG: Partial<ConfigInfo> = {
812
835
  * startup summary `Config` line. Declared before `configInfo` so the assignment
813
836
  * inside `loadConfig()` (invoked below) is not in its temporal dead zone.
814
837
  */
815
- export let configFilePath: string | undefined;
838
+ export let ConfigFilePath: string | undefined;
816
839
 
817
- export const configInfo: ConfigInfo = loadConfig();
840
+ export {
841
+ /** @deprecated Use {@link ConfigFilePath} instead. */
842
+ ConfigFilePath as configFilePath,
843
+ };
844
+
845
+ export const configInfo: ConfigInfo = LoadConfig(); // case-violation-ok-legacy-back-compat: the PascalCase name is already taken in this scope
818
846
 
819
847
  export const {
820
848
  dbUsername,
@@ -841,7 +869,7 @@ export const {
841
869
  restApiOptions: RESTApiOptions,
842
870
  } = configInfo;
843
871
 
844
- export function loadConfig() {
872
+ export function LoadConfig() {
845
873
  const configSearchResult = explorer.search(process.cwd());
846
874
 
847
875
  // Start with DEFAULT_SERVER_CONFIG as base
@@ -851,7 +879,7 @@ export function loadConfig() {
851
879
  if (configSearchResult && !configSearchResult.isEmpty) {
852
880
  // Resolved config-file path. Surfaced in the startup summary `Config` line at standard
853
881
  // level (see StartupLogger). Demoted to verbose-only here to avoid a duplicate inline line.
854
- configFilePath = configSearchResult.filepath;
882
+ ConfigFilePath = configSearchResult.filepath;
855
883
  LogStatusEx({ message: `Config file found at ${configSearchResult.filepath}`, verboseOnly: true });
856
884
 
857
885
  // Merge user config with defaults (user config takes precedence)
@@ -868,3 +896,8 @@ export function loadConfig() {
868
896
  }
869
897
  return configParsing.data;
870
898
  }
899
+
900
+ /** @deprecated Use {@link LoadConfig}. */
901
+ export function loadConfig() {
902
+ return LoadConfig();
903
+ }