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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) 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 +11 -0
  69. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  70. package/dist/generated/graphql-schemas/__mj.js +48 -0
  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 +3 -1
  81. package/dist/generic/FireAndForgetHeartbeat.d.ts.map +1 -1
  82. package/dist/generic/FireAndForgetHeartbeat.js +8 -4
  83. package/dist/generic/FireAndForgetHeartbeat.js.map +1 -1
  84. package/dist/generic/PushStatusResolver.d.ts +10 -1
  85. package/dist/generic/PushStatusResolver.d.ts.map +1 -1
  86. package/dist/generic/PushStatusResolver.js +11 -3
  87. package/dist/generic/PushStatusResolver.js.map +1 -1
  88. package/dist/generic/ResolverBase.d.ts +5 -1
  89. package/dist/generic/ResolverBase.d.ts.map +1 -1
  90. package/dist/generic/ResolverBase.js +15 -8
  91. package/dist/generic/ResolverBase.js.map +1 -1
  92. package/dist/index.d.ts +6 -0
  93. package/dist/index.d.ts.map +1 -1
  94. package/dist/index.js +30 -9
  95. package/dist/index.js.map +1 -1
  96. package/dist/integration/CustomColumnPromoter.d.ts +2 -0
  97. package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
  98. package/dist/integration/CustomColumnPromoter.js +5 -1
  99. package/dist/integration/CustomColumnPromoter.js.map +1 -1
  100. package/dist/integration/EntityMapLifecycle.d.ts +4 -0
  101. package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
  102. package/dist/integration/EntityMapLifecycle.js +10 -2
  103. package/dist/integration/EntityMapLifecycle.js.map +1 -1
  104. package/dist/logging/NoLog.d.ts +4 -0
  105. package/dist/logging/NoLog.d.ts.map +1 -1
  106. package/dist/logging/NoLog.js +10 -2
  107. package/dist/logging/NoLog.js.map +1 -1
  108. package/dist/logging/StartupLogger.d.ts +2 -0
  109. package/dist/logging/StartupLogger.d.ts.map +1 -1
  110. package/dist/logging/StartupLogger.js +5 -1
  111. package/dist/logging/StartupLogger.js.map +1 -1
  112. package/dist/logging/bootAudit.d.ts +11 -7
  113. package/dist/logging/bootAudit.d.ts.map +1 -1
  114. package/dist/logging/bootAudit.js +15 -7
  115. package/dist/logging/bootAudit.js.map +1 -1
  116. package/dist/logging/boundaryLogPayload.d.ts +4 -0
  117. package/dist/logging/boundaryLogPayload.d.ts.map +1 -1
  118. package/dist/logging/boundaryLogPayload.js +5 -1
  119. package/dist/logging/boundaryLogPayload.js.map +1 -1
  120. package/dist/logging/secretRedactor.d.ts +2 -0
  121. package/dist/logging/secretRedactor.d.ts.map +1 -1
  122. package/dist/logging/secretRedactor.js +8 -4
  123. package/dist/logging/secretRedactor.js.map +1 -1
  124. package/dist/logging/shortenForLog.d.ts +2 -0
  125. package/dist/logging/shortenForLog.d.ts.map +1 -1
  126. package/dist/logging/shortenForLog.js +7 -3
  127. package/dist/logging/shortenForLog.js.map +1 -1
  128. package/dist/logging/variablesLoggingMiddleware.d.ts +2 -0
  129. package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
  130. package/dist/logging/variablesLoggingMiddleware.js +8 -6
  131. package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
  132. package/dist/metadataRefreshSignal.d.ts +19 -0
  133. package/dist/metadataRefreshSignal.d.ts.map +1 -0
  134. package/dist/metadataRefreshSignal.js +45 -0
  135. package/dist/metadataRefreshSignal.js.map +1 -0
  136. package/dist/middleware/MJTenantFilterMiddleware.js +4 -4
  137. package/dist/multiTenancy/index.d.ts +8 -0
  138. package/dist/multiTenancy/index.d.ts.map +1 -1
  139. package/dist/multiTenancy/index.js +21 -5
  140. package/dist/multiTenancy/index.js.map +1 -1
  141. package/dist/realtimeWidget/WidgetRouter.d.ts +5 -0
  142. package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
  143. package/dist/realtimeWidget/WidgetRouter.js +14 -10
  144. package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
  145. package/dist/realtimeWidget/WidgetSessionService.d.ts +6 -6
  146. package/dist/realtimeWidget/WidgetSessionService.js +27 -27
  147. package/dist/realtimeWidget/host-identity.d.ts +5 -1
  148. package/dist/realtimeWidget/host-identity.d.ts.map +1 -1
  149. package/dist/realtimeWidget/host-identity.js +11 -3
  150. package/dist/realtimeWidget/host-identity.js.map +1 -1
  151. package/dist/realtimeWidget/index.d.ts +2 -2
  152. package/dist/realtimeWidget/index.d.ts.map +1 -1
  153. package/dist/realtimeWidget/index.js +2 -2
  154. package/dist/realtimeWidget/index.js.map +1 -1
  155. package/dist/realtimeWidget/visitorIdentity.d.ts +21 -1
  156. package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
  157. package/dist/realtimeWidget/visitorIdentity.js +16 -4
  158. package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
  159. package/dist/realtimeWidget/widgetCore.d.ts +48 -0
  160. package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
  161. package/dist/realtimeWidget/widgetCore.js +38 -10
  162. package/dist/realtimeWidget/widgetCore.js.map +1 -1
  163. package/dist/realtimeWidget/widgetGuestElevation.d.ts +10 -6
  164. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  165. package/dist/realtimeWidget/widgetGuestElevation.js +14 -6
  166. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  167. package/dist/resolvers/AdhocQueryResolver.js +3 -3
  168. package/dist/resolvers/FileResolver.js +3 -3
  169. package/dist/resolvers/GeoResolver.d.ts +2 -2
  170. package/dist/resolvers/GeoResolver.js +4 -4
  171. package/dist/resolvers/GetDataResolver.d.ts +14 -0
  172. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  173. package/dist/resolvers/GetDataResolver.js +43 -15
  174. package/dist/resolvers/GetDataResolver.js.map +1 -1
  175. package/dist/resolvers/IntegrationDiscoveryResolver.js +2 -2
  176. package/dist/resolvers/ListOperationsResolver.d.ts +20 -0
  177. package/dist/resolvers/ListOperationsResolver.d.ts.map +1 -1
  178. package/dist/resolvers/ListOperationsResolver.js +68 -28
  179. package/dist/resolvers/ListOperationsResolver.js.map +1 -1
  180. package/dist/resolvers/MCPResolver.d.ts +11 -1
  181. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  182. package/dist/resolvers/MCPResolver.js +7 -3
  183. package/dist/resolvers/MCPResolver.js.map +1 -1
  184. package/dist/resolvers/RealtimeBridgeResolver.js +3 -3
  185. package/dist/resolvers/RealtimeClientSessionResolver.js +3 -3
  186. package/dist/resolvers/RemoteBrowserActionResolver.js +5 -5
  187. package/dist/resolvers/RunAIAgentResolver.d.ts +10 -4
  188. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  189. package/dist/resolvers/RunAIAgentResolver.js +69 -38
  190. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  191. package/dist/resolvers/RunAIPromptResolver.d.ts +1 -1
  192. package/dist/resolvers/RunAIPromptResolver.js +2 -2
  193. package/dist/resolvers/RunTestResolver.js +5 -5
  194. package/dist/resolvers/SqlLoggingConfigResolver.d.ts +8 -4
  195. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  196. package/dist/resolvers/SqlLoggingConfigResolver.js +5 -5
  197. package/dist/resolvers/TaskGraphFrameResolver.d.ts +8 -1
  198. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
  199. package/dist/resolvers/TaskGraphFrameResolver.js +6 -2
  200. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
  201. package/dist/resolvers/adhoc-query-helpers.d.ts +6 -0
  202. package/dist/resolvers/adhoc-query-helpers.d.ts.map +1 -1
  203. package/dist/resolvers/adhoc-query-helpers.js +10 -2
  204. package/dist/resolvers/adhoc-query-helpers.js.map +1 -1
  205. package/dist/resolvers/artifact-routing.d.ts +8 -8
  206. package/dist/resolvers/artifact-routing.js +2 -2
  207. package/dist/resolvers/artifact-routing.js.map +1 -1
  208. package/dist/resolvers/meetingRecordingRegistration.d.ts +10 -2
  209. package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
  210. package/dist/resolvers/meetingRecordingRegistration.js +24 -8
  211. package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
  212. package/dist/resolvers/peaksSidecar.d.ts +4 -0
  213. package/dist/resolvers/peaksSidecar.d.ts.map +1 -1
  214. package/dist/resolvers/peaksSidecar.js +10 -2
  215. package/dist/resolvers/peaksSidecar.js.map +1 -1
  216. package/dist/rest/EntityCRUDHandler.d.ts +28 -0
  217. package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
  218. package/dist/rest/EntityCRUDHandler.js +20 -4
  219. package/dist/rest/EntityCRUDHandler.js.map +1 -1
  220. package/dist/rest/MediaStreamHandler.d.ts +2 -0
  221. package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
  222. package/dist/rest/MediaStreamHandler.js +10 -6
  223. package/dist/rest/MediaStreamHandler.js.map +1 -1
  224. package/dist/rest/OAuthCallbackHandler.d.ts +9 -0
  225. package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
  226. package/dist/rest/OAuthCallbackHandler.js +15 -3
  227. package/dist/rest/OAuthCallbackHandler.js.map +1 -1
  228. package/dist/rest/RESTEndpointHandler.d.ts +6 -4
  229. package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
  230. package/dist/rest/RESTEndpointHandler.js +15 -11
  231. package/dist/rest/RESTEndpointHandler.js.map +1 -1
  232. package/dist/rest/RealtimeSdpBrokerHandler.d.ts +5 -1
  233. package/dist/rest/RealtimeSdpBrokerHandler.d.ts.map +1 -1
  234. package/dist/rest/RealtimeSdpBrokerHandler.js +12 -4
  235. package/dist/rest/RealtimeSdpBrokerHandler.js.map +1 -1
  236. package/dist/rest/SignatureWebhookHandler.d.ts +2 -0
  237. package/dist/rest/SignatureWebhookHandler.d.ts.map +1 -1
  238. package/dist/rest/SignatureWebhookHandler.js +5 -1
  239. package/dist/rest/SignatureWebhookHandler.js.map +1 -1
  240. package/dist/rest/UploadTokenManager.d.ts +24 -8
  241. package/dist/rest/UploadTokenManager.d.ts.map +1 -1
  242. package/dist/rest/UploadTokenManager.js +53 -21
  243. package/dist/rest/UploadTokenManager.js.map +1 -1
  244. package/dist/rest/ViewOperationsHandler.d.ts +20 -0
  245. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  246. package/dist/rest/ViewOperationsHandler.js +20 -4
  247. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  248. package/dist/rest/mediaRange.d.ts +4 -0
  249. package/dist/rest/mediaRange.d.ts.map +1 -1
  250. package/dist/rest/mediaRange.js +10 -2
  251. package/dist/rest/mediaRange.js.map +1 -1
  252. package/dist/rest/setupRESTEndpoints.d.ts +4 -0
  253. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  254. package/dist/rest/setupRESTEndpoints.js +13 -7
  255. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  256. package/dist/serverExtensionReservedRoots.d.ts +2 -0
  257. package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
  258. package/dist/serverExtensionReservedRoots.js +5 -1
  259. package/dist/serverExtensionReservedRoots.js.map +1 -1
  260. package/dist/services/TaskGraphActionRunner.d.ts +13 -8
  261. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  262. package/dist/services/TaskGraphActionRunner.js +16 -15
  263. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  264. package/dist/types.d.ts +2 -0
  265. package/dist/types.d.ts.map +1 -1
  266. package/dist/types.js +7 -3
  267. package/dist/types.js.map +1 -1
  268. package/dist/util.d.ts +6 -0
  269. package/dist/util.d.ts.map +1 -1
  270. package/dist/util.js +13 -5
  271. package/dist/util.js.map +1 -1
  272. package/package.json +92 -92
  273. package/src/__tests__/DeleteOptionsInput.wireShape.test.ts +62 -0
  274. package/src/__tests__/FileResolverPeaks.test.ts +13 -13
  275. package/src/__tests__/ListOperationsResolver.test.ts +17 -17
  276. package/src/__tests__/MediaStreamHandler.test.ts +28 -28
  277. package/src/__tests__/NoLog.test.ts +11 -11
  278. package/src/__tests__/PrimaryKeyAlwaysMapped.test.ts +10 -10
  279. package/src/__tests__/RESTEndpointHandler.test.ts +14 -14
  280. package/src/__tests__/RealtimeBridgeResolver.test.ts +4 -2
  281. package/src/__tests__/RealtimeSdpBrokerHandler.test.ts +6 -6
  282. package/src/__tests__/RefreshAdoptsNewColumns.test.ts +8 -8
  283. package/src/__tests__/RemoteBrowserGoalEngine.test.ts +18 -18
  284. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +228 -0
  285. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +129 -0
  286. package/src/__tests__/TaskGraphFrameResolver.test.ts +2 -2
  287. package/src/__tests__/WidgetSessionService.test.ts +8 -4
  288. package/src/__tests__/adhoc-query-helpers.test.ts +21 -21
  289. package/src/__tests__/bootAudit.test.ts +11 -11
  290. package/src/__tests__/boundaryLogPayload.test.ts +6 -6
  291. package/src/__tests__/cacheInvalidationRecordData.test.ts +177 -0
  292. package/src/__tests__/databaseAbstraction.test.ts +12 -6
  293. package/src/__tests__/getDataTokenRedaction.test.ts +7 -7
  294. package/src/__tests__/initializeProviders.refresh.test.ts +4 -4
  295. package/src/__tests__/magicLink.test.ts +73 -134
  296. package/src/__tests__/magicLinkService.consume.test.ts +224 -0
  297. package/src/__tests__/meetingRecordingRegistration.test.ts +12 -12
  298. package/src/__tests__/metadataRefreshSignal.test.ts +78 -0
  299. package/src/__tests__/multiTenancy.security.test.ts +40 -40
  300. package/src/__tests__/multiTenancy.test.ts +18 -18
  301. package/src/__tests__/newUsers.test.ts +24 -23
  302. package/src/__tests__/principals.test.ts +22 -22
  303. package/src/__tests__/pushStatusResolver.filter.test.ts +8 -8
  304. package/src/__tests__/secretRedactor.failOpen.test.ts +12 -12
  305. package/src/__tests__/secretRedactor.test.ts +12 -12
  306. package/src/__tests__/serverExtensionReservedRoots.test.ts +7 -7
  307. package/src/__tests__/subscriptionRedaction.test.ts +5 -5
  308. package/src/__tests__/unifiedAuth.test.ts +15 -9
  309. package/src/__tests__/visitorIdentity.resolve.test.ts +6 -6
  310. package/src/__tests__/widget.test.ts +45 -45
  311. package/src/__tests__/widgetGuestElevation.test.ts +7 -7
  312. package/src/__tests__/widgetHostIdentity.test.ts +14 -14
  313. package/src/agentSessions/ReturningVisitorRecap.ts +12 -1
  314. package/src/agentSessions/SessionManager.ts +2 -2
  315. package/src/agentSessions/remoteBrowserGoalEngine.ts +30 -5
  316. package/src/auth/AuthProviderCatalogRouter.ts +6 -1
  317. package/src/auth/__tests__/backward-compatibility.test.ts +3 -3
  318. package/src/auth/index.ts +43 -28
  319. package/src/auth/initializeProviders.ts +25 -5
  320. package/src/auth/magicLink/MagicLinkRouter.ts +28 -10
  321. package/src/auth/magicLink/MagicLinkService.ts +71 -52
  322. package/src/auth/magicLink/index.ts +7 -7
  323. package/src/auth/magicLink/magicLinkCore.ts +96 -64
  324. package/src/auth/magicLink/redeemLanding.ts +14 -4
  325. package/src/auth/magicLink/types.ts +54 -54
  326. package/src/auth/newUsers.ts +1 -1
  327. package/src/auth/principals.ts +11 -2
  328. package/src/cache.ts +4 -1
  329. package/src/config.ts +37 -4
  330. package/src/context.ts +37 -24
  331. package/src/directives/Public.ts +4 -1
  332. package/src/directives/RequireSystemUser.ts +4 -1
  333. package/src/generated/graphql-schemas/__mj.ts +37 -0
  334. package/src/generic/CacheInvalidationResolver.ts +148 -4
  335. package/src/generic/DeleteOptionsInput.ts +9 -2
  336. package/src/generic/FireAndForgetHeartbeat.ts +19 -14
  337. package/src/generic/PushStatusResolver.ts +21 -7
  338. package/src/generic/ResolverBase.ts +16 -8
  339. package/src/generic/RunViewResolver.ts +22 -22
  340. package/src/generic/__tests__/FireAndForgetHeartbeat.test.ts +7 -7
  341. package/src/index.ts +35 -9
  342. package/src/integration/CustomColumnPromoter.ts +6 -1
  343. package/src/integration/EntityMapLifecycle.ts +20 -2
  344. package/src/logging/NoLog.ts +16 -2
  345. package/src/logging/StartupLogger.ts +6 -1
  346. package/src/logging/bootAudit.ts +26 -16
  347. package/src/logging/boundaryLogPayload.ts +8 -1
  348. package/src/logging/secretRedactor.ts +14 -9
  349. package/src/logging/shortenForLog.ts +8 -3
  350. package/src/logging/variablesLoggingMiddleware.ts +9 -6
  351. package/src/metadataRefreshSignal.ts +45 -0
  352. package/src/middleware/MJTenantFilterMiddleware.ts +4 -4
  353. package/src/multiTenancy/index.ts +29 -5
  354. package/src/realtimeWidget/WidgetRouter.ts +15 -10
  355. package/src/realtimeWidget/WidgetSessionService.ts +76 -76
  356. package/src/realtimeWidget/host-identity.ts +24 -10
  357. package/src/realtimeWidget/index.ts +3 -3
  358. package/src/realtimeWidget/visitorIdentity.ts +39 -8
  359. package/src/realtimeWidget/widgetCore.ts +75 -10
  360. package/src/realtimeWidget/widgetGuestElevation.ts +25 -12
  361. package/src/resolvers/AdhocQueryResolver.ts +3 -3
  362. package/src/resolvers/AgentSessionResolver.ts +3 -3
  363. package/src/resolvers/ColorResolver.ts +6 -6
  364. package/src/resolvers/ComponentRegistryResolver.ts +36 -36
  365. package/src/resolvers/EntityCommunicationsResolver.ts +4 -4
  366. package/src/resolvers/ExecuteRemoteOperationResolver.ts +9 -9
  367. package/src/resolvers/FileResolver.ts +42 -42
  368. package/src/resolvers/GeoResolver.ts +4 -4
  369. package/src/resolvers/GetDataResolver.ts +50 -15
  370. package/src/resolvers/IntegrationDiscoveryResolver.ts +2 -2
  371. package/src/resolvers/ListOperationsResolver.ts +78 -28
  372. package/src/resolvers/MCPResolver.ts +30 -15
  373. package/src/resolvers/QueryResolver.ts +13 -13
  374. package/src/resolvers/RealtimeBridgeResolver.ts +3 -3
  375. package/src/resolvers/RealtimeClientSessionResolver.ts +3 -3
  376. package/src/resolvers/RemoteBrowserActionResolver.ts +5 -5
  377. package/src/resolvers/RunAIAgentResolver.ts +113 -72
  378. package/src/resolvers/RunAIPromptResolver.ts +22 -22
  379. package/src/resolvers/RunTemplateResolver.ts +4 -4
  380. package/src/resolvers/RunTestResolver.ts +25 -25
  381. package/src/resolvers/SqlLoggingConfigResolver.ts +56 -56
  382. package/src/resolvers/TaskGraphFrameResolver.ts +37 -28
  383. package/src/resolvers/TelemetryResolver.ts +79 -79
  384. package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +40 -38
  385. package/src/resolvers/__tests__/artifact-routing.test.ts +23 -23
  386. package/src/resolvers/adhoc-query-helpers.ts +19 -2
  387. package/src/resolvers/artifact-routing.ts +19 -19
  388. package/src/resolvers/meetingRecordingRegistration.ts +44 -10
  389. package/src/resolvers/peaksSidecar.ts +12 -2
  390. package/src/rest/EntityCRUDHandler.ts +24 -4
  391. package/src/rest/MediaStreamHandler.ts +11 -6
  392. package/src/rest/OAuthCallbackHandler.ts +25 -7
  393. package/src/rest/RESTEndpointHandler.ts +20 -15
  394. package/src/rest/RealtimeSdpBrokerHandler.ts +14 -4
  395. package/src/rest/SignatureWebhookHandler.ts +6 -1
  396. package/src/rest/UploadTokenManager.ts +66 -30
  397. package/src/rest/ViewOperationsHandler.ts +24 -4
  398. package/src/rest/mediaRange.ts +16 -6
  399. package/src/rest/setupRESTEndpoints.ts +24 -12
  400. package/src/serverExtensionReservedRoots.ts +6 -1
  401. package/src/services/TaskGraphActionRunner.ts +16 -15
  402. package/src/types.ts +21 -16
  403. package/src/util.ts +16 -6
@@ -15685,6 +15685,10 @@ export class MJAIPromptRun_ {
15685
15685
  @MaxLength(25)
15686
15686
  ToolCallingMode?: string;
15687
15687
 
15688
+ @Field({nullable: true, description: `The user on whose behalf this prompt was executed, written when the run is created. NULL for automated/unauthenticated runs and for runs that pre-date this column. For an agent-driven run the agent run's user is also reachable through AIAgentRunStep.TargetLogID, which vwAIUsageFacts falls back to.`})
15689
+ @MaxLength(36)
15690
+ UserID?: string;
15691
+
15688
15692
  @Field({nullable: true})
15689
15693
  @MaxLength(255)
15690
15694
  Prompt?: string;
@@ -15733,6 +15737,10 @@ export class MJAIPromptRun_ {
15733
15737
  @MaxLength(50)
15734
15738
  UsageType?: string;
15735
15739
 
15740
+ @Field({nullable: true})
15741
+ @MaxLength(100)
15742
+ User?: string;
15743
+
15736
15744
  @Field({nullable: true})
15737
15745
  @MaxLength(36)
15738
15746
  RootParentID?: string;
@@ -16029,6 +16037,9 @@ export class CreateMJAIPromptRunInput {
16029
16037
  @Field({ nullable: true })
16030
16038
  ToolCallingMode: string | null;
16031
16039
 
16040
+ @Field({ nullable: true })
16041
+ UserID: string | null;
16042
+
16032
16043
  @Field(() => RestoreContextInput, { nullable: true })
16033
16044
  RestoreContext___?: RestoreContextInput;
16034
16045
  }
@@ -16309,6 +16320,9 @@ export class UpdateMJAIPromptRunInput {
16309
16320
  @Field({ nullable: true })
16310
16321
  ToolCallingMode?: string | null;
16311
16322
 
16323
+ @Field({ nullable: true })
16324
+ UserID?: string | null;
16325
+
16312
16326
  @Field(() => [KeyValuePairInput], { nullable: true })
16313
16327
  OldValues___?: KeyValuePairInput[];
16314
16328
 
@@ -19215,6 +19229,9 @@ export class MJAIVendor_ {
19215
19229
  @MaxLength(36)
19216
19230
  CredentialTypeID?: string;
19217
19231
 
19232
+ @Field({nullable: true, description: `Vendor configuration bag (JSON, IAIVendorConfiguration shape). Its ModelDefaults key is an IAIModelConfiguration bag (LLM / Realtime / Vision / Audio sections) that forms the default model configuration for every model this vendor serves: the vendor layer of the ModelConfiguration cascade, above AIModelType and AIModel and below AIModelVendor, which may override it per key. NULL = contributes nothing.`})
19233
+ Configuration?: string;
19234
+
19218
19235
  @Field({nullable: true})
19219
19236
  @MaxLength(100)
19220
19237
  CredentialType?: string;
@@ -19241,6 +19258,9 @@ export class CreateMJAIVendorInput {
19241
19258
  @Field({ nullable: true })
19242
19259
  CredentialTypeID: string | null;
19243
19260
 
19261
+ @Field({ nullable: true })
19262
+ Configuration: string | null;
19263
+
19244
19264
  @Field(() => RestoreContextInput, { nullable: true })
19245
19265
  RestoreContext___?: RestoreContextInput;
19246
19266
  }
@@ -19263,6 +19283,9 @@ export class UpdateMJAIVendorInput {
19263
19283
  @Field({ nullable: true })
19264
19284
  CredentialTypeID?: string | null;
19265
19285
 
19286
+ @Field({ nullable: true })
19287
+ Configuration?: string | null;
19288
+
19266
19289
  @Field(() => [KeyValuePairInput], { nullable: true })
19267
19290
  OldValues___?: KeyValuePairInput[];
19268
19291
 
@@ -66952,6 +66975,10 @@ export class MJProject_ {
66952
66975
  @Field()
66953
66976
  _mj__UpdatedAt: Date;
66954
66977
 
66978
+ @Field({nullable: true, description: `The user who owns this folder, or NULL when the folder is shared with the whole environment. NULL (the value every pre-existing folder carries) means SHARED: visible to anyone who can read projects in the environment, which was the only possible behaviour before this column existed. A set value means PERSONAL: the folder belongs to that user and consumers filter it to them, so it stays out of other people's sidebars. Personal is opt-in at create time; nothing is migrated.`})
66979
+ @MaxLength(36)
66980
+ OwnerUserID?: string;
66981
+
66955
66982
  @Field({nullable: true})
66956
66983
  @MaxLength(255)
66957
66984
  Environment?: string;
@@ -66960,6 +66987,10 @@ export class MJProject_ {
66960
66987
  @MaxLength(255)
66961
66988
  Parent?: string;
66962
66989
 
66990
+ @Field({nullable: true})
66991
+ @MaxLength(100)
66992
+ OwnerUser?: string;
66993
+
66963
66994
  @Field({nullable: true})
66964
66995
  @MaxLength(36)
66965
66996
  RootParentID?: string;
@@ -67010,6 +67041,9 @@ export class CreateMJProjectInput {
67010
67041
  @Field(() => Boolean, { nullable: true })
67011
67042
  IsArchived?: boolean;
67012
67043
 
67044
+ @Field({ nullable: true })
67045
+ OwnerUserID: string | null;
67046
+
67013
67047
  @Field(() => RestoreContextInput, { nullable: true })
67014
67048
  RestoreContext___?: RestoreContextInput;
67015
67049
  }
@@ -67044,6 +67078,9 @@ export class UpdateMJProjectInput {
67044
67078
  @Field(() => Boolean, { nullable: true })
67045
67079
  IsArchived?: boolean;
67046
67080
 
67081
+ @Field({ nullable: true })
67082
+ OwnerUserID?: string | null;
67083
+
67047
67084
  @Field(() => [KeyValuePairInput], { nullable: true })
67048
67085
  OldValues___?: KeyValuePairInput[];
67049
67086
 
@@ -1,7 +1,57 @@
1
1
  import { Field, ObjectType, Resolver, Root, Subscription } from 'type-graphql';
2
+ import { Metadata, UserInfo } from '@memberjunction/core';
2
3
 
3
4
  export const CACHE_INVALIDATION_TOPIC = 'CACHE_INVALIDATION';
4
5
 
6
+ /**
7
+ * Entities whose rows may ride along with an invalidation event. Empty until the server entry point
8
+ * supplies the configured list, so the default — including in any process that never configures it
9
+ * — is to broadcast nothing.
10
+ */
11
+ let allowedRecordDataEntities: readonly string[] = [];
12
+
13
+ /**
14
+ * Supply the configured allowlist. Called once from the server entry point during bootstrap.
15
+ *
16
+ * INJECTED rather than read from `configInfo` here, deliberately. `config.ts` runs `loadConfig()` at
17
+ * module scope, so importing it from this module would drag full config validation into every
18
+ * import chain that touches the resolver — including unit tests, which have no server config and
19
+ * would fail at import with "Configuration validation failed". This module deliberately imports
20
+ * nothing from MJServer itself — only type-graphql and `@memberjunction/core` (for the entity
21
+ * permission check in the subscription filter), neither of which loads config.
22
+ */
23
+ export function ConfigureRecordDataBroadcast(entities: readonly string[] | undefined | null): void {
24
+ // Normalised HERE, once, rather than at each comparison. The wildcard used to be matched raw
25
+ // (`includes('*')`) while entity names were trimmed and lowercased two lines below, so a
26
+ // hand-edited `[' * ']` matched neither branch and silently opted nothing in — a config that
27
+ // looks like it disables the gate while leaving it fully on. Empty entries are dropped so a
28
+ // stray `''` cannot match an entity whose name is somehow blank.
29
+ allowedRecordDataEntities = (entities ?? [])
30
+ .map((e) => e.trim().toLowerCase())
31
+ .filter((e) => e.length > 0);
32
+ }
33
+
34
+ /**
35
+ * May the full row of `entityName` be broadcast alongside its cache-invalidation event?
36
+ *
37
+ * The subscription below is filtered only by ENTITY-level read permission, so anything included
38
+ * here is disclosed to every signed-in session that may read the entity at all — regardless of
39
+ * row-level security or any tenant scoping a consumer applies on the read path, neither of which
40
+ * this push traverses. The answer is therefore NO unless a deployment has explicitly opted the
41
+ * entity in via `cacheSettings.recordDataBroadcastEntities`.
42
+ *
43
+ * Callers that get `false` simply omit `recordData`; the event still carries the entity name and
44
+ * primary key, so clients evict and re-fetch through the normal access-controlled read path.
45
+ *
46
+ * Matching is exact (trimmed, case-insensitive) rather than substring: a loose match would let an
47
+ * allowlisted name drag in every entity whose name contains it.
48
+ */
49
+ export function MayBroadcastRecordData(entityName: string): boolean {
50
+ if (allowedRecordDataEntities.length === 0) return false;
51
+ if (allowedRecordDataEntities.includes('*')) return true;
52
+ return allowedRecordDataEntities.includes(entityName.trim().toLowerCase());
53
+ }
54
+
5
55
  @ObjectType()
6
56
  export class CacheInvalidationNotification {
7
57
  @Field(() => String)
@@ -40,17 +90,111 @@ export interface CacheInvalidationPayload {
40
90
  recordData?: string;
41
91
  }
42
92
 
93
+ /**
94
+ * What the subscription filter needs off the WS connection.
95
+ *
96
+ * Declared structurally rather than importing MJServer's `UserPayload`, which reaches `types.ts`
97
+ * and through it `auth/index.js` and config. Keeping this module's imports minimal is not fussiness
98
+ * — importing `configInfo` here is what previously broke every unit test that touched the resolver,
99
+ * and the import-surface test in this package exists to keep it that way.
100
+ */
101
+ export interface CacheInvalidationFilterContext {
102
+ userPayload?: { userRecord?: unknown };
103
+ }
104
+
105
+ /**
106
+ * Should this subscriber hear about this event at all?
107
+ *
108
+ * Entity-level narrowing, raised in review: an event for an entity a session has no read
109
+ * permission on tells that session the record exists, its stable key, and when it changed — and
110
+ * the session could never have read it anyway, so nothing is lost by withholding it. This is a
111
+ * monotonic reduction in disclosure that needs no tenancy model, which is why it is here and the
112
+ * row-level question is not.
113
+ *
114
+ * What it does NOT close: two sessions that both hold read permission on an entity still see each
115
+ * other's keys, because what separates them is row-level. That predicate is tracked separately —
116
+ * see the class docblock below.
117
+ *
118
+ * `GetUserPermisions` is an in-memory match of the entity's permission rows against the user's
119
+ * roles, so this stays cheap enough to run per subscriber per event. It is not free: it runs for
120
+ * every connected socket on every save, so keep it free of I/O.
121
+ */
122
+ export function CacheInvalidationFilter(data: {
123
+ payload: CacheInvalidationPayload;
124
+ context: CacheInvalidationFilterContext | undefined;
125
+ }): boolean {
126
+ const user = data.context?.userPayload?.userRecord as UserInfo | undefined;
127
+ // FAIL CLOSED on identity, matching `statusUpdatesFilter`. `onConnect` rejects a socket whose
128
+ // token does not validate, so a subscriber with no user record should not exist; if one does,
129
+ // it is the case least deserving of an unfiltered firehose.
130
+ if (!user) {
131
+ return false;
132
+ }
133
+
134
+ const entityName = data.payload?.entityName;
135
+ if (!entityName) {
136
+ return false;
137
+ }
138
+
139
+ // A pub/sub subscription filter has no per-request provider to thread: it runs on the server's
140
+ // own metadata, which is the one place the entity's permission rows can be answered from.
141
+ const entity = new Metadata().EntityByName(entityName); // global-provider-ok: subscription filter — server-wide metadata, no request-scoped provider exists here
142
+ // DELIVER when the entity is unknown here, deliberately — the opposite of the choice above.
143
+ // A name absent from metadata cannot be permission-checked, and withholding would silently
144
+ // stop invalidating a legitimately cacheable entity, which is a correctness bug rather than a
145
+ // disclosure one. All it discloses is the name and key of something this server cannot
146
+ // describe.
147
+ if (!entity) {
148
+ return true;
149
+ }
150
+
151
+ return entity.GetUserPermisions(user).CanRead;
152
+ }
153
+
154
+ /** @deprecated Use {@link CacheInvalidationFilter}. */
155
+ export function cacheInvalidationFilter(data: {
156
+ payload: CacheInvalidationPayload;
157
+ context: CacheInvalidationFilterContext | undefined;
158
+ }): boolean {
159
+ return CacheInvalidationFilter(data);
160
+ }
161
+
43
162
  @Resolver()
44
163
  export class CacheInvalidationResolver {
45
164
  /**
46
- * Subscription that broadcasts cache invalidation events to ALL connected clients.
47
- * No session filter — every browser connected via WebSocket receives every event.
48
- * This enables cross-server cache invalidation to propagate to browser clients.
165
+ * Subscription that broadcasts cache invalidation events to connected clients, so cross-server
166
+ * cache invalidation reaches browsers.
167
+ *
168
+ * Delivery is filtered only by ENTITY-level read permission (see {@link CacheInvalidationFilter}).
169
+ * Every session that may read an entity at all still receives every event for it, from every
170
+ * other session and tenant.
171
+ *
172
+ * Because that narrowing stops well short of row level, `RecordData` is only populated for entities a
173
+ * deployment has opted in through `cacheSettings.recordDataBroadcastEntities` — see
174
+ * {@link MayBroadcastRecordData}, applied at both publish sites.
175
+ *
176
+ * `EntityName`, `PrimaryKeyValues`, `Action` and `Timestamp` ARE still broadcast to every
177
+ * session, and that is a disclosure, not a safe residue. An earlier version of this comment
178
+ * called them "safe to broadcast" on the grounds that reading the record still goes through
179
+ * the access-controlled path — true of the row's CONTENTS, and beside the point for the
180
+ * metadata itself. A session with no relationship to a record still learns that it exists,
181
+ * its stable key, and every time it changes; across entities it learns the cadence and volume
182
+ * of another tenant's activity.
183
+ *
184
+ * The key is kept deliberately, because consumers need it to re-read the record they were
185
+ * told about (see `ResolveEntityEventKey` in @memberjunction/core) and because the alternative
186
+ * — a coarse "something in this entity changed" — forces whole-entity invalidation on the
187
+ * hottest write paths. That is a trade, not an absence of cost. Narrowing it means filtering
188
+ * delivery per subscriber, which needs an authorization predicate cheap enough to run per
189
+ * subscriber per event; entity-level permissions (`EntityInfo.GetUserPermisions`, an in-memory
190
+ * role match) would cover part of it, row-level tenancy would not.
49
191
  */
50
192
  @Subscription(() => CacheInvalidationNotification, {
51
193
  topics: CACHE_INVALIDATION_TOPIC,
194
+ filter: (data: { payload: CacheInvalidationPayload; context: CacheInvalidationFilterContext | undefined }) =>
195
+ CacheInvalidationFilter(data),
52
196
  })
53
- cacheInvalidation(
197
+ cacheInvalidation( // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
54
198
  @Root() payload: CacheInvalidationPayload
55
199
  ): CacheInvalidationNotification {
56
200
  return {
@@ -50,9 +50,16 @@ export class DeleteOptionsInput {
50
50
  * schema-sync gate requires `DeleteOptionsInput` to carry every `EntityDeleteOptions` field;
51
51
  * {@link DeleteOptionsInput.SanitizeFromWire} forces it back to false on every request. See
52
52
  * that method for why.
53
+ *
54
+ * **Optional on the wire, on purpose.** This field did not exist in 5.51.x, and every other
55
+ * field here is required, so making it required too turned a 6.1 upgrade into a hard failure
56
+ * for every client that spells out `options___` on a delete (`Field
57
+ * "DeleteOptionsInput.SkipRecordChanges" of required type "Boolean!" was not provided`). A
58
+ * 5.51 client that omits it and a 6.1 client that sends `false` mean the same thing, and the
59
+ * server forces it to `false` regardless, so `null`/absent defaults to `false` here.
53
60
  */
54
- @Field(() => Boolean)
55
- SkipRecordChanges: boolean;
61
+ @Field(() => Boolean, { nullable: true, defaultValue: false })
62
+ SkipRecordChanges?: boolean;
56
63
 
57
64
  /**
58
65
  * Strips wire-unreachable capabilities from client-supplied delete options.
@@ -1,6 +1,6 @@
1
1
  import { PubSubEngine } from 'type-graphql';
2
2
  import { LogError } from '@memberjunction/core';
3
- import { publishStatusUpdate } from './PushStatusResolver.js';
3
+ import { PublishStatusUpdate } from './PushStatusResolver.js';
4
4
 
5
5
  /** Default cadence for fire-and-forget liveness pulses (5 minutes). */
6
6
  export const DEFAULT_PULSE_INTERVAL_MS = 5 * 60 * 1000;
@@ -15,38 +15,38 @@ export const HEARTBEAT_MESSAGE_TYPE = 'Heartbeat';
15
15
  */
16
16
  export interface PulseStatus {
17
17
  /** Primary key of the persisted run record (AIAgentRun, TestRun, TestSuiteRun). */
18
- runId?: string;
18
+ runId?: 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
19
19
  /** Current run status, e.g. 'Running'. */
20
- status?: string;
20
+ status?: 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
  /** Optional human-readable current step for UI display. */
22
- currentStep?: string;
22
+ currentStep?: 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
23
23
  }
24
24
 
25
25
  /** Handle returned by {@link startLivenessPulse}; call `stop()` when the work settles. */
26
26
  export interface LivenessPulseHandle {
27
- stop(): void;
27
+ Stop(): void;
28
28
  }
29
29
 
30
30
  export interface LivenessPulseOptions {
31
31
  /** PubSub engine used to publish on the shared push-status topic. */
32
- pubSub: PubSubEngine;
32
+ pubSub: PubSubEngine; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
33
33
  /** Session the client is subscribed on (used by the subscription filter). */
34
- sessionId: string;
34
+ sessionId: 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
35
35
  /**
36
36
  * Authenticated user the operation belongs to (B49). Stamped on every pulse so the
37
37
  * subscription filter binds delivery to identity, not just the client-chosen sessionId.
38
38
  */
39
- ownerUserId: string;
39
+ ownerUserId: string; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
40
40
  /** Resolver label echoed in the message envelope (e.g. 'RunAIAgentResolver'). */
41
- resolver: string;
41
+ resolver: 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
42
42
  /** Pulse cadence in ms. Defaults to {@link DEFAULT_PULSE_INTERVAL_MS}. */
43
- intervalMs?: number;
43
+ intervalMs?: number; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
44
44
  /**
45
45
  * Optional cheap status reader invoked on each tick. Should read from an
46
46
  * in-memory ref, not the database. Errors are swallowed so a transient read
47
47
  * never kills the pulse loop.
48
48
  */
49
- readStatus?: () => PulseStatus | undefined;
49
+ readStatus?: () => PulseStatus | undefined; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
50
50
  }
51
51
 
52
52
  /**
@@ -60,7 +60,7 @@ export interface LivenessPulseOptions {
60
60
  * (`{ message: JSON.stringify({ resolver, type, status, data }), sessionId }`),
61
61
  * so the client receives it through the same subscription with no special parsing.
62
62
  */
63
- export function startLivenessPulse(options: LivenessPulseOptions): LivenessPulseHandle {
63
+ export function StartLivenessPulse(options: LivenessPulseOptions): LivenessPulseHandle {
64
64
  const { pubSub, sessionId, ownerUserId, resolver, readStatus } = options;
65
65
  const intervalMs = options.intervalMs ?? DEFAULT_PULSE_INTERVAL_MS;
66
66
 
@@ -73,7 +73,7 @@ export function startLivenessPulse(options: LivenessPulseOptions): LivenessPulse
73
73
  LogError(`[LivenessPulse:${resolver}] readStatus failed: ${(e as Error).message}`);
74
74
  }
75
75
 
76
- publishStatusUpdate(pubSub, {
76
+ PublishStatusUpdate(pubSub, {
77
77
  sessionId,
78
78
  ownerUserId,
79
79
  message: JSON.stringify({
@@ -86,6 +86,11 @@ export function startLivenessPulse(options: LivenessPulseOptions): LivenessPulse
86
86
  }, intervalMs);
87
87
 
88
88
  return {
89
- stop: () => clearInterval(timer),
89
+ Stop: () => clearInterval(timer),
90
90
  };
91
91
  }
92
+
93
+ /** @deprecated Use {@link StartLivenessPulse}. */
94
+ export function startLivenessPulse(options: LivenessPulseOptions): LivenessPulseHandle {
95
+ return StartLivenessPulse(options);
96
+ }
@@ -7,13 +7,13 @@ export const PUSH_STATUS_UPDATES_TOPIC = 'PUSH_STATUS_UPDATES';
7
7
  @ObjectType()
8
8
  export class PushStatusNotification {
9
9
  @Field(() => String, { nullable: true })
10
- message?: string;
10
+ message?: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
11
11
 
12
12
  @Field((_type) => Date)
13
- date!: Date;
13
+ date!: Date; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
14
14
 
15
15
  @Field((_type) => ID)
16
- sessionId!: string;
16
+ sessionId!: string; // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
17
17
  }
18
18
 
19
19
  /**
@@ -55,7 +55,7 @@ export interface StatusUpdateParams {
55
55
  * payload shape and the required-identity guarantee live in exactly one place. Adding a field to
56
56
  * the push is a one-line change here; a new publisher physically cannot omit `ownerUserId`.
57
57
  */
58
- export function publishStatusUpdate(pubSub: PubSubEngine, params: StatusUpdateParams): void {
58
+ export function PublishStatusUpdate(pubSub: PubSubEngine, params: StatusUpdateParams): void {
59
59
  const payload: PushStatusNotificationPayload = {
60
60
  sessionId: params.sessionId,
61
61
  ownerUserId: params.ownerUserId,
@@ -64,6 +64,11 @@ export function publishStatusUpdate(pubSub: PubSubEngine, params: StatusUpdatePa
64
64
  pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, payload);
65
65
  }
66
66
 
67
+ /** @deprecated Use {@link PublishStatusUpdate}. */
68
+ export function publishStatusUpdate(pubSub: PubSubEngine, params: StatusUpdateParams): void {
69
+ return PublishStatusUpdate(pubSub, params);
70
+ }
71
+
67
72
  /** Minimal shape of the subscription's connection context needed by the filter. */
68
73
  export interface StatusUpdatesFilterContext {
69
74
  userPayload?: UserPayload;
@@ -82,7 +87,7 @@ export interface StatusUpdatesFilterContext {
82
87
  * `sessionId` is no longer sufficient. Fails CLOSED — a missing owner or connection identity never
83
88
  * matches.
84
89
  */
85
- export function statusUpdatesFilter(data: {
90
+ export function StatusUpdatesFilter(data: {
86
91
  payload: PushStatusNotificationPayload;
87
92
  args: PushStatusNotificationArgs;
88
93
  context: StatusUpdatesFilterContext | undefined;
@@ -98,14 +103,23 @@ export function statusUpdatesFilter(data: {
98
103
  return UUIDsEqual(payload.ownerUserId, connectionUserId);
99
104
  }
100
105
 
106
+ /** @deprecated Use {@link StatusUpdatesFilter}. */
107
+ export function statusUpdatesFilter(data: {
108
+ payload: PushStatusNotificationPayload;
109
+ args: PushStatusNotificationArgs;
110
+ context: StatusUpdatesFilterContext | undefined;
111
+ }): boolean {
112
+ return StatusUpdatesFilter(data);
113
+ }
114
+
101
115
  @Resolver()
102
116
  export class PushStatusResolver {
103
117
  @Subscription(() => PushStatusNotification, {
104
118
  topics: PUSH_STATUS_UPDATES_TOPIC,
105
119
  filter: (data: ResolverFilterData<PushStatusNotificationPayload, PushStatusNotificationArgs, StatusUpdatesFilterContext>) =>
106
- statusUpdatesFilter(data),
120
+ StatusUpdatesFilter(data),
107
121
  })
108
- statusUpdates(
122
+ statusUpdates( // case-violation-ok-legacy-back-compat: the property name is the GraphQL schema field name — renaming it breaks every client query
109
123
  @Root() { message }: PushStatusNotificationPayload,
110
124
  @Arg('sessionId', () => String) sessionId: string
111
125
  ): PushStatusNotification {
@@ -40,8 +40,8 @@ import { MJEvent, MJEventType, MJGlobal, ENCRYPTED_SENTINEL, EscapeSQLString, Is
40
40
  import { SQLParser } from '@memberjunction/sql-parser';
41
41
  import { PostgreSQLDialect, SQLServerDialect, type SQLParserDialect } from '@memberjunction/sql-dialect';
42
42
  import { EncryptionEngine } from '@memberjunction/encryption';
43
- import { PUSH_STATUS_UPDATES_TOPIC, publishStatusUpdate } from './PushStatusResolver.js';
44
- import { CACHE_INVALIDATION_TOPIC } from './CacheInvalidationResolver.js';
43
+ import { PUSH_STATUS_UPDATES_TOPIC, PublishStatusUpdate } from './PushStatusResolver.js';
44
+ import { CACHE_INVALIDATION_TOPIC, MayBroadcastRecordData } from './CacheInvalidationResolver.js';
45
45
  import { PubSubManager } from './PubSubManager.js';
46
46
  import { FieldMapper } from '@memberjunction/graphql-dataprovider';
47
47
  import { Subscription } from 'rxjs';
@@ -51,7 +51,7 @@ export class ResolverBase {
51
51
  private static _cloudeventsHeaders = process.env.CLOUDEVENTS_HTTP_HEADERS ? JSON.parse(process.env.CLOUDEVENTS_HTTP_HEADERS) : {};
52
52
 
53
53
  private static _eventSubscriptionKey: string = '___MJServer___ResolverBase___EventSubscriptions';
54
- private get EventSubscriptions(): Map<string, Subscription> {
54
+ private get eventSubscriptions(): Map<string, Subscription> {
55
55
  // here we use the global object store instead of a static member becuase in some cases based on import code paths/bundling/etc, the static member
56
56
  // could actually be duplicated and we'd end up with multiple instances of the same map, which would be bad.
57
57
  const g = MJGlobal.Instance.GetGlobalObjectStore();
@@ -1450,16 +1450,24 @@ export class ResolverBase {
1450
1450
  * Publishes a CACHE_INVALIDATION event to connected browser clients after a successful
1451
1451
  * entity save or delete. Includes the originSessionId so the originating browser can
1452
1452
  * skip redundant re-fetches (it already handled the event locally).
1453
+ *
1454
+ * The row itself rides along ONLY for entities opted in via
1455
+ * `cacheSettings.recordDataBroadcastEntities` — this event reaches every connected client
1456
+ * unfiltered, so the row would otherwise be readable by sessions that could not read the record.
1453
1457
  */
1454
1458
  protected PublishCacheInvalidation(entityObject: BaseEntity, action: 'save' | 'delete', userPayload: UserPayload): void {
1459
+ const entityName = entityObject.EntityInfo.Name;
1455
1460
  PubSubManager.Instance.Publish(CACHE_INVALIDATION_TOPIC, {
1456
- entityName: entityObject.EntityInfo.Name,
1461
+ entityName,
1457
1462
  primaryKeyValues: JSON.stringify(entityObject.PrimaryKey.KeyValuePairs),
1458
1463
  action,
1459
1464
  sourceServerId: MJGlobal.Instance.ProcessUUID,
1460
1465
  timestamp: new Date(),
1461
1466
  originSessionId: userPayload?.sessionId || null,
1462
- recordData: action === 'save' ? JSON.stringify(entityObject.GetAll()) : undefined,
1467
+ recordData:
1468
+ action === 'save' && MayBroadcastRecordData(entityName)
1469
+ ? JSON.stringify(entityObject.GetAll())
1470
+ : undefined,
1463
1471
  });
1464
1472
  }
1465
1473
 
@@ -1472,7 +1480,7 @@ export class ResolverBase {
1472
1480
  * `publishStatusUpdate()` function directly with an explicit `ownerUserId`.
1473
1481
  */
1474
1482
  protected PublishStatusUpdate(pubSub: PubSubEngine, sessionId: string, message: string | undefined, userPayload: UserPayload): void {
1475
- publishStatusUpdate(pubSub, {
1483
+ PublishStatusUpdate(pubSub, {
1476
1484
  sessionId,
1477
1485
  ownerUserId: userPayload?.userRecord?.ID ?? '',
1478
1486
  message,
@@ -1485,7 +1493,7 @@ export class ResolverBase {
1485
1493
  // cause issues with multiple messages for the same event.
1486
1494
  const uniqueKey = entityObject.EntityInfo.Name;
1487
1495
 
1488
- if (!this.EventSubscriptions.has(uniqueKey)) {
1496
+ if (!this.eventSubscriptions.has(uniqueKey)) {
1489
1497
  // listen for events from the entityObject in case it is a long running task and we can push messages back to the client via pubSub
1490
1498
  LogDebug(`ResolverBase.ListenForEntityMessages: About to call MJGlobal.Instance.GetEventListener() to get the event listener subscription for ${uniqueKey}`);
1491
1499
  const theSub = MJGlobal.Instance.GetEventListener(false).subscribe(async (event: MJEvent) => {
@@ -1518,7 +1526,7 @@ export class ResolverBase {
1518
1526
  }
1519
1527
  }
1520
1528
  });
1521
- this.EventSubscriptions.set(uniqueKey, theSub);
1529
+ this.eventSubscriptions.set(uniqueKey, theSub);
1522
1530
  }
1523
1531
  }
1524
1532