@memberjunction/server 6.2.0-edge.4 → 6.2.0-edge.6

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 (560) hide show
  1. package/README.md +47 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentSessions/SessionJanitor.d.ts +91 -30
  4. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  5. package/dist/agentSessions/SessionJanitor.js +311 -81
  6. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  7. package/dist/agentSessions/SessionManager.d.ts +17 -3
  8. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  9. package/dist/agentSessions/SessionManager.js +44 -10
  10. package/dist/agentSessions/SessionManager.js.map +1 -1
  11. package/dist/apiRoot.d.ts +32 -0
  12. package/dist/apiRoot.d.ts.map +1 -0
  13. package/dist/apiRoot.js +67 -0
  14. package/dist/apiRoot.js.map +1 -0
  15. package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
  16. package/dist/auth/AuthProviderCatalogRouter.js +27 -0
  17. package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
  18. package/dist/auth/LoginScreenEngine.d.ts +22 -0
  19. package/dist/auth/LoginScreenEngine.d.ts.map +1 -0
  20. package/dist/auth/LoginScreenEngine.js +57 -0
  21. package/dist/auth/LoginScreenEngine.js.map +1 -0
  22. package/dist/auth/index.d.ts +1 -0
  23. package/dist/auth/index.d.ts.map +1 -1
  24. package/dist/auth/index.js +52 -10
  25. package/dist/auth/index.js.map +1 -1
  26. package/dist/auth/initializeProviders.d.ts +10 -0
  27. package/dist/auth/initializeProviders.d.ts.map +1 -1
  28. package/dist/auth/initializeProviders.js +37 -1
  29. package/dist/auth/initializeProviders.js.map +1 -1
  30. package/dist/auth/localDevAuth.d.ts +79 -0
  31. package/dist/auth/localDevAuth.d.ts.map +1 -0
  32. package/dist/auth/localDevAuth.js +439 -0
  33. package/dist/auth/localDevAuth.js.map +1 -0
  34. package/dist/auth/magicLink/MagicLinkKeys.d.ts +2 -2
  35. package/dist/auth/magicLink/MagicLinkKeys.d.ts.map +1 -1
  36. package/dist/auth/magicLink/MagicLinkKeys.js +1 -1
  37. package/dist/auth/magicLink/MagicLinkKeys.js.map +1 -1
  38. package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
  39. package/dist/auth/magicLink/MagicLinkRouter.js +3 -2
  40. package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
  41. package/dist/auth/magicLink/types.d.ts +12 -0
  42. package/dist/auth/magicLink/types.d.ts.map +1 -1
  43. package/dist/auth/sessionUserClone.d.ts +1 -1
  44. package/dist/auth/sessionUserClone.d.ts.map +1 -1
  45. package/dist/auth/sessionUserClone.js +3 -2
  46. package/dist/auth/sessionUserClone.js.map +1 -1
  47. package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts +292 -0
  48. package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts.map +1 -0
  49. package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js +442 -0
  50. package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js.map +1 -0
  51. package/dist/broadcast/index.d.ts +6 -0
  52. package/dist/broadcast/index.d.ts.map +1 -0
  53. package/dist/broadcast/index.js +6 -0
  54. package/dist/broadcast/index.js.map +1 -0
  55. package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.d.ts +43 -0
  56. package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.d.ts.map +1 -0
  57. package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.js +144 -0
  58. package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.js.map +1 -0
  59. package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.d.ts +46 -0
  60. package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.d.ts.map +1 -0
  61. package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.js +149 -0
  62. package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.js.map +1 -0
  63. package/dist/broadcast/providers/GCPPubSubBroadcastProvider.d.ts +49 -0
  64. package/dist/broadcast/providers/GCPPubSubBroadcastProvider.d.ts.map +1 -0
  65. package/dist/broadcast/providers/GCPPubSubBroadcastProvider.js +131 -0
  66. package/dist/broadcast/providers/GCPPubSubBroadcastProvider.js.map +1 -0
  67. package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.d.ts +24 -0
  68. package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.d.ts.map +1 -0
  69. package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.js +51 -0
  70. package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.js.map +1 -0
  71. package/dist/cache.d.ts +3 -2
  72. package/dist/cache.d.ts.map +1 -1
  73. package/dist/cache.js.map +1 -1
  74. package/dist/config.d.ts +632 -22
  75. package/dist/config.d.ts.map +1 -1
  76. package/dist/config.js +104 -4
  77. package/dist/config.js.map +1 -1
  78. package/dist/context.d.ts +3 -1
  79. package/dist/context.d.ts.map +1 -1
  80. package/dist/context.js +29 -8
  81. package/dist/context.js.map +1 -1
  82. package/dist/coreRoutes.d.ts +29 -0
  83. package/dist/coreRoutes.d.ts.map +1 -0
  84. package/dist/coreRoutes.js +156 -0
  85. package/dist/coreRoutes.js.map +1 -0
  86. package/dist/generated/graphql-schemas/__mj.d.ts +1016 -29
  87. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  88. package/dist/generated/graphql-schemas/__mj.js +5125 -434
  89. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  90. package/dist/generic/CacheInvalidationResolver.d.ts +85 -30
  91. package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
  92. package/dist/generic/CacheInvalidationResolver.js +175 -60
  93. package/dist/generic/CacheInvalidationResolver.js.map +1 -1
  94. package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -1
  95. package/dist/generic/OrphanedConversationDetailReconciler.js +2 -0
  96. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
  97. package/dist/generic/PubSubManager.d.ts +10 -0
  98. package/dist/generic/PubSubManager.d.ts.map +1 -1
  99. package/dist/generic/PubSubManager.js +44 -1
  100. package/dist/generic/PubSubManager.js.map +1 -1
  101. package/dist/generic/PushStatusResolver.d.ts +39 -6
  102. package/dist/generic/PushStatusResolver.d.ts.map +1 -1
  103. package/dist/generic/PushStatusResolver.js +94 -12
  104. package/dist/generic/PushStatusResolver.js.map +1 -1
  105. package/dist/generic/ResolverBase.d.ts +168 -69
  106. package/dist/generic/ResolverBase.d.ts.map +1 -1
  107. package/dist/generic/ResolverBase.js +464 -405
  108. package/dist/generic/ResolverBase.js.map +1 -1
  109. package/dist/generic/RunViewResolver.d.ts +11 -3
  110. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  111. package/dist/generic/RunViewResolver.js +91 -13
  112. package/dist/generic/RunViewResolver.js.map +1 -1
  113. package/dist/generic/actionOutputFieldSecurity.d.ts +26 -0
  114. package/dist/generic/actionOutputFieldSecurity.d.ts.map +1 -0
  115. package/dist/generic/actionOutputFieldSecurity.js +47 -0
  116. package/dist/generic/actionOutputFieldSecurity.js.map +1 -0
  117. package/dist/generic/fieldSecurityTransport.d.ts +30 -0
  118. package/dist/generic/fieldSecurityTransport.d.ts.map +1 -0
  119. package/dist/generic/fieldSecurityTransport.js +30 -0
  120. package/dist/generic/fieldSecurityTransport.js.map +1 -0
  121. package/dist/globalCors.d.ts +33 -0
  122. package/dist/globalCors.d.ts.map +1 -0
  123. package/dist/globalCors.js +58 -0
  124. package/dist/globalCors.js.map +1 -0
  125. package/dist/index.d.ts +14 -0
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +230 -222
  128. package/dist/index.js.map +1 -1
  129. package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
  130. package/dist/integration/CustomColumnPromoter.js +6 -1
  131. package/dist/integration/CustomColumnPromoter.js.map +1 -1
  132. package/dist/logging/variablesLoggingMiddleware.d.ts +12 -0
  133. package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
  134. package/dist/logging/variablesLoggingMiddleware.js +50 -1
  135. package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
  136. package/dist/multiTenancy/index.d.ts.map +1 -1
  137. package/dist/multiTenancy/index.js +22 -2
  138. package/dist/multiTenancy/index.js.map +1 -1
  139. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -1
  140. package/dist/realtimeSessions/RealtimeSessionVerificationService.js +2 -1
  141. package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -1
  142. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -1
  143. package/dist/realtimeSessions/RealtimeVerifyRouter.js +2 -1
  144. package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -1
  145. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts +100 -0
  146. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts.map +1 -0
  147. package/dist/realtimeSessions/RecordingAssemblyScheduler.js +173 -0
  148. package/dist/realtimeSessions/RecordingAssemblyScheduler.js.map +1 -0
  149. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -1
  150. package/dist/realtimeSessions/SessionVerificationPortsBase.js +1 -0
  151. package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -1
  152. package/dist/realtimeSessions/index.d.ts +2 -0
  153. package/dist/realtimeSessions/index.d.ts.map +1 -1
  154. package/dist/realtimeSessions/index.js +2 -0
  155. package/dist/realtimeSessions/index.js.map +1 -1
  156. package/dist/realtimeSessions/ownedRealtimeSession.d.ts +32 -0
  157. package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -0
  158. package/dist/realtimeSessions/ownedRealtimeSession.js +56 -0
  159. package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -0
  160. package/dist/realtimeSessions/sessionAccess.d.ts +91 -8
  161. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
  162. package/dist/realtimeSessions/sessionAccess.js +127 -20
  163. package/dist/realtimeSessions/sessionAccess.js.map +1 -1
  164. package/dist/realtimeSessions/sessionConfigStamps.js +1 -1
  165. package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -1
  166. package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -1
  167. package/dist/realtimeSessions/subscriptionAuthorization.js +5 -2
  168. package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -1
  169. package/dist/realtimeSessions/verificationWorkflow.d.ts +2 -0
  170. package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -1
  171. package/dist/realtimeSessions/verificationWorkflow.js +1 -1
  172. package/dist/realtimeSessions/verificationWorkflow.js.map +1 -1
  173. package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
  174. package/dist/realtimeWidget/WidgetRouter.js +19 -3
  175. package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
  176. package/dist/realtimeWidget/WidgetSessionService.d.ts +67 -7
  177. package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -1
  178. package/dist/realtimeWidget/WidgetSessionService.js +201 -19
  179. package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
  180. package/dist/realtimeWidget/host-identity.d.ts +1 -1
  181. package/dist/realtimeWidget/host-identity.js +1 -1
  182. package/dist/realtimeWidget/widgetCore.d.ts +20 -1
  183. package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
  184. package/dist/realtimeWidget/widgetCore.js +17 -1
  185. package/dist/realtimeWidget/widgetCore.js.map +1 -1
  186. package/dist/realtimeWidget/widgetGuestElevation.d.ts +1 -1
  187. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  188. package/dist/realtimeWidget/widgetGuestElevation.js +2 -1
  189. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  190. package/dist/resolvers/ActionResolver.d.ts +19 -1
  191. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  192. package/dist/resolvers/ActionResolver.js +63 -12
  193. package/dist/resolvers/ActionResolver.js.map +1 -1
  194. package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
  195. package/dist/resolvers/AdhocQueryResolver.js +1 -0
  196. package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
  197. package/dist/resolvers/AgentRunStatusPublisher.d.ts +18 -4
  198. package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -1
  199. package/dist/resolvers/AgentRunStatusPublisher.js +32 -8
  200. package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -1
  201. package/dist/resolvers/AgentSessionResolver.d.ts +10 -4
  202. package/dist/resolvers/AgentSessionResolver.d.ts.map +1 -1
  203. package/dist/resolvers/AgentSessionResolver.js +40 -17
  204. package/dist/resolvers/AgentSessionResolver.js.map +1 -1
  205. package/dist/resolvers/ArtifactFileResolver.d.ts +5 -1
  206. package/dist/resolvers/ArtifactFileResolver.d.ts.map +1 -1
  207. package/dist/resolvers/ArtifactFileResolver.js +9 -7
  208. package/dist/resolvers/ArtifactFileResolver.js.map +1 -1
  209. package/dist/resolvers/ConversationRunEventsResolver.d.ts +8 -4
  210. package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
  211. package/dist/resolvers/ConversationRunEventsResolver.js +6 -6
  212. package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
  213. package/dist/resolvers/DatasetResolver.d.ts +24 -3
  214. package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
  215. package/dist/resolvers/DatasetResolver.js +57 -8
  216. package/dist/resolvers/DatasetResolver.js.map +1 -1
  217. package/dist/resolvers/EntityCommunicationsResolver.d.ts +13 -1
  218. package/dist/resolvers/EntityCommunicationsResolver.d.ts.map +1 -1
  219. package/dist/resolvers/EntityCommunicationsResolver.js +50 -14
  220. package/dist/resolvers/EntityCommunicationsResolver.js.map +1 -1
  221. package/dist/resolvers/EntityRecordNameResolver.d.ts +2 -1
  222. package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
  223. package/dist/resolvers/EntityRecordNameResolver.js +3 -2
  224. package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
  225. package/dist/resolvers/FetchEntityVectorsResolver.d.ts +46 -3
  226. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  227. package/dist/resolvers/FetchEntityVectorsResolver.js +211 -50
  228. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  229. package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
  230. package/dist/resolvers/FileCategoryResolver.js +1 -0
  231. package/dist/resolvers/FileCategoryResolver.js.map +1 -1
  232. package/dist/resolvers/FileResolver.d.ts +87 -11
  233. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  234. package/dist/resolvers/FileResolver.js +292 -105
  235. package/dist/resolvers/FileResolver.js.map +1 -1
  236. package/dist/resolvers/GetDataContextDataResolver.d.ts +33 -7
  237. package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
  238. package/dist/resolvers/GetDataContextDataResolver.js +117 -38
  239. package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
  240. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  241. package/dist/resolvers/GetDataResolver.js +6 -3
  242. package/dist/resolvers/GetDataResolver.js.map +1 -1
  243. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  244. package/dist/resolvers/IntegrationDiscoveryResolver.js +49 -9
  245. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  246. package/dist/resolvers/MergeRecordsResolver.d.ts +8 -1
  247. package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
  248. package/dist/resolvers/MergeRecordsResolver.js +31 -3
  249. package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
  250. package/dist/resolvers/PipelineProgressResolver.d.ts +6 -0
  251. package/dist/resolvers/PipelineProgressResolver.d.ts.map +1 -1
  252. package/dist/resolvers/PipelineProgressResolver.js +5 -3
  253. package/dist/resolvers/PipelineProgressResolver.js.map +1 -1
  254. package/dist/resolvers/QueryResolver.d.ts +2 -0
  255. package/dist/resolvers/QueryResolver.d.ts.map +1 -1
  256. package/dist/resolvers/QueryResolver.js +33 -6
  257. package/dist/resolvers/QueryResolver.js.map +1 -1
  258. package/dist/resolvers/QuerySystemUserResolver.d.ts +2 -0
  259. package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
  260. package/dist/resolvers/QuerySystemUserResolver.js +15 -6
  261. package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
  262. package/dist/resolvers/RSUResolver.d.ts.map +1 -1
  263. package/dist/resolvers/RSUResolver.js +12 -0
  264. package/dist/resolvers/RSUResolver.js.map +1 -1
  265. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +18 -10
  266. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  267. package/dist/resolvers/RealtimeClientSessionResolver.js +92 -54
  268. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  269. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  270. package/dist/resolvers/RemoteBrowserActionResolver.js +11 -9
  271. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  272. package/dist/resolvers/RunAIAgentResolver.d.ts +56 -8
  273. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  274. package/dist/resolvers/RunAIAgentResolver.js +241 -67
  275. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  276. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  277. package/dist/resolvers/RunTemplateResolver.js +4 -4
  278. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  279. package/dist/resolvers/RunTestResolver.d.ts.map +1 -1
  280. package/dist/resolvers/RunTestResolver.js +3 -1
  281. package/dist/resolvers/RunTestResolver.js.map +1 -1
  282. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts +12 -1
  283. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts.map +1 -1
  284. package/dist/resolvers/SearchKnowledgeStreamResolver.js +15 -2
  285. package/dist/resolvers/SearchKnowledgeStreamResolver.js.map +1 -1
  286. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  287. package/dist/resolvers/SqlLoggingConfigResolver.js +2 -3
  288. package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
  289. package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
  290. package/dist/resolvers/SyncDataResolver.js +4 -0
  291. package/dist/resolvers/SyncDataResolver.js.map +1 -1
  292. package/dist/resolvers/TaskGraphFrameResolver.d.ts +2 -1
  293. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
  294. package/dist/resolvers/TaskGraphFrameResolver.js +28 -1
  295. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
  296. package/dist/resolvers/TestQuerySQLResolver.d.ts +24 -0
  297. package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
  298. package/dist/resolvers/TestQuerySQLResolver.js +66 -13
  299. package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
  300. package/dist/resolvers/TransactionGroupResolver.d.ts +34 -2
  301. package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
  302. package/dist/resolvers/TransactionGroupResolver.js +150 -27
  303. package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
  304. package/dist/resolvers/UserViewResolver.d.ts +1 -1
  305. package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
  306. package/dist/resolvers/UserViewResolver.js +2 -1
  307. package/dist/resolvers/UserViewResolver.js.map +1 -1
  308. package/dist/resolvers/agent-run-data-guard.d.ts +31 -0
  309. package/dist/resolvers/agent-run-data-guard.d.ts.map +1 -0
  310. package/dist/resolvers/agent-run-data-guard.js +72 -0
  311. package/dist/resolvers/agent-run-data-guard.js.map +1 -0
  312. package/dist/rest/EntityCRUDHandler.d.ts +6 -0
  313. package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
  314. package/dist/rest/EntityCRUDHandler.js +19 -5
  315. package/dist/rest/EntityCRUDHandler.js.map +1 -1
  316. package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
  317. package/dist/rest/RESTEndpointHandler.js +8 -5
  318. package/dist/rest/RESTEndpointHandler.js.map +1 -1
  319. package/dist/rest/RealtimeRecordingHandler.d.ts +49 -0
  320. package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -0
  321. package/dist/rest/RealtimeRecordingHandler.js +383 -0
  322. package/dist/rest/RealtimeRecordingHandler.js.map +1 -0
  323. package/dist/rest/ViewOperationsHandler.d.ts +9 -1
  324. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  325. package/dist/rest/ViewOperationsHandler.js +43 -17
  326. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  327. package/dist/rest/setupRESTEndpoints.d.ts +6 -0
  328. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  329. package/dist/rest/setupRESTEndpoints.js +6 -0
  330. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  331. package/dist/serverExtensionReservedRoots.d.ts +12 -10
  332. package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
  333. package/dist/serverExtensionReservedRoots.js +14 -17
  334. package/dist/serverExtensionReservedRoots.js.map +1 -1
  335. package/dist/serverRoleConfigUnits.d.ts +29 -0
  336. package/dist/serverRoleConfigUnits.d.ts.map +1 -0
  337. package/dist/serverRoleConfigUnits.js +33 -0
  338. package/dist/serverRoleConfigUnits.js.map +1 -0
  339. package/dist/services/MJStorageBlobStore.d.ts +8 -1
  340. package/dist/services/MJStorageBlobStore.d.ts.map +1 -1
  341. package/dist/services/MJStorageBlobStore.js +25 -19
  342. package/dist/services/MJStorageBlobStore.js.map +1 -1
  343. package/dist/services/StartTaskGraphDispatcher.js +2 -2
  344. package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
  345. package/dist/services/TaskGraphActionRunner.d.ts +5 -3
  346. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  347. package/dist/services/TaskGraphActionRunner.js +27 -5
  348. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  349. package/dist/services/TaskGraphAgentRunner.d.ts +14 -2
  350. package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
  351. package/dist/services/TaskGraphAgentRunner.js +157 -9
  352. package/dist/services/TaskGraphAgentRunner.js.map +1 -1
  353. package/dist/services/TaskGraphContinuationDeliverer.d.ts +59 -2
  354. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  355. package/dist/services/TaskGraphContinuationDeliverer.js +626 -16
  356. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  357. package/dist/sharedCache.d.ts.map +1 -1
  358. package/dist/sharedCache.js +3 -0
  359. package/dist/sharedCache.js.map +1 -1
  360. package/dist/types.d.ts +23 -1
  361. package/dist/types.d.ts.map +1 -1
  362. package/dist/types.js.map +1 -1
  363. package/package.json +99 -98
  364. package/src/__tests__/ActionResolver.fieldSecurity.test.ts +237 -0
  365. package/src/__tests__/AdhocQueryResolver.dialect.test.ts +137 -0
  366. package/src/__tests__/AgentRunStatusPublisher.test.ts +49 -0
  367. package/src/__tests__/AgentSessionResolver.ownership.test.ts +137 -0
  368. package/src/__tests__/CustomColumnPromoterOnePass.test.ts +15 -1
  369. package/src/__tests__/DatasetResolver.itemFilters.test.ts +201 -0
  370. package/src/__tests__/EntityCommunicationsResolver.actingUser.test.ts +151 -0
  371. package/src/__tests__/EntityRecordNameResolver.rowSecurity.test.ts +152 -0
  372. package/src/__tests__/EvolutionActsOnWhatItDetects.test.ts +113 -0
  373. package/src/__tests__/FetchEntityVectorsResolver.test.ts +369 -18
  374. package/src/__tests__/FileResolver.fieldSecurity.test.ts +82 -0
  375. package/src/__tests__/FileResolver.storageAccess.test.ts +562 -0
  376. package/src/__tests__/GetDataContextDataResolver.sqlItems.test.ts +416 -0
  377. package/src/__tests__/ListOperationsResolver.adhocScreen.test.ts +137 -0
  378. package/src/__tests__/LoginScreenEngine.test.ts +86 -0
  379. package/src/__tests__/MJStorageBlobStore.storageGate.test.ts +63 -0
  380. package/src/__tests__/PipelineProgressResolver.filter.test.ts +58 -0
  381. package/src/__tests__/QuerySystemUserResolver.fieldSecurity.test.ts +49 -0
  382. package/src/__tests__/RESTEndpointHandler.test.ts +25 -0
  383. package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +23 -3
  384. package/src/__tests__/RealtimeClientSessionResolver.test.ts +324 -46
  385. package/src/__tests__/RecordingAssemblyScheduler.test.ts +178 -0
  386. package/src/__tests__/RemoteBrowserActionResolver.ownership.test.ts +98 -0
  387. package/src/__tests__/ResolverBase.adhocReadScope.test.ts +133 -2
  388. package/src/__tests__/ResolverBase.balancedClause.test.ts +155 -0
  389. package/src/__tests__/ResolverBase.clauseUnscopedRead.test.ts +127 -0
  390. package/src/__tests__/ResolverBase.clientOldValues.test.ts +243 -7
  391. package/src/__tests__/ResolverBase.deleteReturnProjection.test.ts +52 -0
  392. package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +176 -0
  393. package/src/__tests__/ResolverBase.filterEscaping.test.ts +5 -2
  394. package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +23 -1
  395. package/src/__tests__/ResolverBase.publishStatusUpdate.test.ts +68 -0
  396. package/src/__tests__/ResolverBase.userViewCacheAndDedup.test.ts +130 -0
  397. package/src/__tests__/RunAIAgentResolver.branch.test.ts +69 -13
  398. package/src/__tests__/RunAIAgentResolver.conversationWriter.test.ts +210 -0
  399. package/src/__tests__/RunAIAgentResolver.fireAndForgetCompletion.test.ts +209 -0
  400. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +20 -28
  401. package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +264 -0
  402. package/src/__tests__/RunAIAgentResolver.serverReply.test.ts +358 -0
  403. package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +4 -1
  404. package/src/__tests__/RunTemplateResolver.test.ts +35 -2
  405. package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +11 -0
  406. package/src/__tests__/RunViewResolver.cacheCheckScreen.test.ts +165 -0
  407. package/src/__tests__/SearchKnowledgeStreamResolver.test.ts +161 -0
  408. package/src/__tests__/SessionJanitor.test.ts +365 -10
  409. package/src/__tests__/SessionManager.test.ts +122 -0
  410. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +25 -0
  411. package/src/__tests__/TaskGraphAgentRunner.test.ts +266 -0
  412. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +468 -23
  413. package/src/__tests__/TaskGraphFrameResolver.test.ts +22 -0
  414. package/src/__tests__/TestQuerySQLResolver.test.ts +274 -0
  415. package/src/__tests__/TransactionGroupResolver.fieldSecurity.test.ts +199 -0
  416. package/src/__tests__/TransactionGroupResolver.refusals.test.ts +98 -1
  417. package/src/__tests__/UpdateMJDataContextItem.oldValues.test.ts +220 -0
  418. package/src/__tests__/UserViewResolver.updateWhereClause.test.ts +15 -0
  419. package/src/__tests__/ViewOperationsHandler.clauseScreen.test.ts +157 -0
  420. package/src/__tests__/ViewOperationsHandler.test.ts +7 -2
  421. package/src/__tests__/WidgetSessionService.test.ts +583 -4
  422. package/src/__tests__/agent-run-data-guard.test.ts +130 -0
  423. package/src/__tests__/apiRootBoot.test.ts +202 -0
  424. package/src/__tests__/buildMagicLinkSessionUser.test.ts +96 -0
  425. package/src/__tests__/cacheBroadcastProviders.test.ts +403 -0
  426. package/src/__tests__/cacheInvalidationRecordData.test.ts +109 -0
  427. package/src/__tests__/conversationRunEvents.test.ts +56 -14
  428. package/src/__tests__/fieldSecurityFixtures.ts +91 -0
  429. package/src/__tests__/globalCors.test.ts +217 -0
  430. package/src/__tests__/localDevAuth.test.ts +196 -0
  431. package/src/__tests__/multiTenancy.postgresRewrite.test.ts +181 -0
  432. package/src/__tests__/multiTenancy.security.test.ts +51 -0
  433. package/src/__tests__/multiTenancy.test.ts +1 -1
  434. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +10 -0
  435. package/src/__tests__/ownedRealtimeSession.test.ts +39 -0
  436. package/src/__tests__/pushStatusResolver.filter.test.ts +64 -1
  437. package/src/__tests__/realtimeRecordingHandler.test.ts +669 -0
  438. package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +29 -1
  439. package/src/__tests__/realtimeSessions/ownedRealtimeSession.anonymous.test.ts +31 -0
  440. package/src/__tests__/realtimeSessions/ownedRealtimeSession.namedScoped.test.ts +37 -0
  441. package/src/__tests__/realtimeSessions/sessionAccess.test.ts +146 -7
  442. package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +1 -1
  443. package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +25 -4
  444. package/src/__tests__/resolverBase.cloudEventChangedFields.test.ts +157 -0
  445. package/src/__tests__/resolverBase.fieldSecurityTransport.test.ts +222 -0
  446. package/src/__tests__/resolverBase.fls.test.ts +146 -97
  447. package/src/__tests__/restTransport.fieldSecurity.test.ts +148 -0
  448. package/src/__tests__/runParamsTimeZone.test.ts +179 -0
  449. package/src/__tests__/runStreams.fieldSecurity.test.ts +100 -0
  450. package/src/__tests__/runViewProperties.test.ts +114 -0
  451. package/src/__tests__/scalabilityBenchmarks.test.ts +765 -0
  452. package/src/__tests__/scalabilityDatabaseIntegration.test.ts +207 -0
  453. package/src/__tests__/serverExtensionHostOverlay.test.ts +66 -0
  454. package/src/__tests__/serverExtensionReservedRoots.test.ts +11 -98
  455. package/src/__tests__/sessionUserClone.test.ts +5 -1
  456. package/src/__tests__/sharedCache.test.ts +5 -3
  457. package/src/__tests__/startupSweepOrder.test.ts +40 -0
  458. package/src/__tests__/unifiedAuth.test.ts +28 -0
  459. package/src/__tests__/widgetGuestElevation.test.ts +2 -0
  460. package/src/agentSessions/SessionJanitor.ts +369 -93
  461. package/src/agentSessions/SessionManager.ts +45 -10
  462. package/src/apiRoot.ts +78 -0
  463. package/src/auth/AuthProviderCatalogRouter.ts +29 -0
  464. package/src/auth/LoginScreenEngine.ts +50 -0
  465. package/src/auth/index.ts +57 -12
  466. package/src/auth/initializeProviders.ts +43 -1
  467. package/src/auth/localDevAuth.ts +528 -0
  468. package/src/auth/magicLink/MagicLinkKeys.ts +2 -2
  469. package/src/auth/magicLink/MagicLinkRouter.ts +3 -2
  470. package/src/auth/magicLink/types.ts +10 -0
  471. package/src/auth/sessionUserClone.ts +3 -2
  472. package/src/broadcast/BaseCacheInvalidationBroadcastProvider.ts +674 -0
  473. package/src/broadcast/index.ts +5 -0
  474. package/src/broadcast/providers/AWSIoTCoreBroadcastProvider.ts +180 -0
  475. package/src/broadcast/providers/AzureWebPubSubBroadcastProvider.ts +182 -0
  476. package/src/broadcast/providers/GCPPubSubBroadcastProvider.ts +169 -0
  477. package/src/broadcast/providers/SequencedRoleBucketBroadcastProvider.ts +57 -0
  478. package/src/cache.ts +2 -1
  479. package/src/config.ts +115 -5
  480. package/src/context.ts +32 -8
  481. package/src/coreRoutes.ts +181 -0
  482. package/src/generated/graphql-schemas/__mj.ts +3684 -284
  483. package/src/generic/CacheInvalidationResolver.ts +172 -60
  484. package/src/generic/OrphanedConversationDetailReconciler.ts +4 -2
  485. package/src/generic/PubSubManager.ts +54 -1
  486. package/src/generic/PushStatusResolver.ts +109 -12
  487. package/src/generic/ResolverBase.ts +540 -431
  488. package/src/generic/RunViewResolver.ts +97 -15
  489. package/src/generic/actionOutputFieldSecurity.ts +75 -0
  490. package/src/generic/fieldSecurityTransport.ts +62 -0
  491. package/src/globalCors.ts +71 -0
  492. package/src/index.ts +239 -238
  493. package/src/integration/CustomColumnPromoter.ts +6 -1
  494. package/src/logging/variablesLoggingMiddleware.ts +59 -3
  495. package/src/multiTenancy/index.ts +24 -2
  496. package/src/realtimeSessions/README.md +7 -3
  497. package/src/realtimeSessions/RealtimeSessionVerificationService.ts +2 -1
  498. package/src/realtimeSessions/RealtimeVerifyRouter.ts +2 -1
  499. package/src/realtimeSessions/RecordingAssemblyScheduler.ts +234 -0
  500. package/src/realtimeSessions/SessionVerificationPortsBase.ts +1 -0
  501. package/src/realtimeSessions/index.ts +2 -0
  502. package/src/realtimeSessions/ownedRealtimeSession.ts +69 -0
  503. package/src/realtimeSessions/sessionAccess.ts +183 -23
  504. package/src/realtimeSessions/sessionConfigStamps.ts +1 -1
  505. package/src/realtimeSessions/subscriptionAuthorization.ts +4 -2
  506. package/src/realtimeSessions/verificationWorkflow.ts +3 -1
  507. package/src/realtimeWidget/WidgetRouter.ts +22 -4
  508. package/src/realtimeWidget/WidgetSessionService.ts +252 -17
  509. package/src/realtimeWidget/host-identity.ts +1 -1
  510. package/src/realtimeWidget/widgetCore.ts +30 -1
  511. package/src/realtimeWidget/widgetGuestElevation.ts +2 -1
  512. package/src/resolvers/ActionResolver.ts +78 -15
  513. package/src/resolvers/AdhocQueryResolver.ts +1 -0
  514. package/src/resolvers/AgentRunStatusPublisher.ts +36 -8
  515. package/src/resolvers/AgentSessionResolver.ts +46 -18
  516. package/src/resolvers/ArtifactFileResolver.ts +9 -8
  517. package/src/resolvers/ConversationRunEventsResolver.ts +15 -11
  518. package/src/resolvers/DatasetResolver.ts +70 -10
  519. package/src/resolvers/EntityCommunicationsResolver.ts +56 -15
  520. package/src/resolvers/EntityRecordNameResolver.ts +3 -2
  521. package/src/resolvers/FetchEntityVectorsResolver.ts +248 -55
  522. package/src/resolvers/FileCategoryResolver.ts +1 -0
  523. package/src/resolvers/FileResolver.ts +334 -109
  524. package/src/resolvers/GetDataContextDataResolver.ts +139 -41
  525. package/src/resolvers/GetDataResolver.ts +6 -3
  526. package/src/resolvers/IntegrationDiscoveryResolver.ts +53 -9
  527. package/src/resolvers/MergeRecordsResolver.ts +23 -2
  528. package/src/resolvers/PipelineProgressResolver.ts +12 -3
  529. package/src/resolvers/QueryResolver.ts +31 -6
  530. package/src/resolvers/QuerySystemUserResolver.ts +15 -6
  531. package/src/resolvers/RSUResolver.ts +12 -0
  532. package/src/resolvers/RealtimeClientSessionResolver.ts +114 -66
  533. package/src/resolvers/RemoteBrowserActionResolver.ts +15 -10
  534. package/src/resolvers/RunAIAgentResolver.ts +296 -85
  535. package/src/resolvers/RunTemplateResolver.ts +6 -4
  536. package/src/resolvers/RunTestResolver.ts +3 -1
  537. package/src/resolvers/SearchKnowledgeStreamResolver.ts +19 -3
  538. package/src/resolvers/SqlLoggingConfigResolver.ts +2 -4
  539. package/src/resolvers/SyncDataResolver.ts +4 -0
  540. package/src/resolvers/TaskGraphFrameResolver.ts +33 -1
  541. package/src/resolvers/TestQuerySQLResolver.ts +69 -13
  542. package/src/resolvers/TransactionGroupResolver.ts +185 -30
  543. package/src/resolvers/UserViewResolver.ts +2 -1
  544. package/src/resolvers/__tests__/GetDataResolver.validation.test.ts +95 -0
  545. package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +43 -0
  546. package/src/resolvers/agent-run-data-guard.ts +89 -0
  547. package/src/rest/EntityCRUDHandler.ts +22 -5
  548. package/src/rest/RESTEndpointHandler.ts +8 -5
  549. package/src/rest/RealtimeRecordingHandler.ts +467 -0
  550. package/src/rest/ViewOperationsHandler.ts +52 -18
  551. package/src/rest/setupRESTEndpoints.ts +6 -0
  552. package/src/serverExtensionReservedRoots.ts +14 -17
  553. package/src/serverRoleConfigUnits.ts +48 -0
  554. package/src/services/MJStorageBlobStore.ts +31 -30
  555. package/src/services/StartTaskGraphDispatcher.ts +2 -2
  556. package/src/services/TaskGraphActionRunner.ts +25 -5
  557. package/src/services/TaskGraphAgentRunner.ts +188 -11
  558. package/src/services/TaskGraphContinuationDeliverer.ts +738 -16
  559. package/src/sharedCache.ts +3 -0
  560. package/src/types.ts +23 -1
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Field-level security on the REST transport (rest/EntityCRUDHandler.ts, rest/ViewOperationsHandler.ts).
3
+ *
4
+ * Output: every record and every view row is projected for the caller. The entity objects and
5
+ * view results here are deliberately FULL WIDTH, standing in for any value not narrowed at its
6
+ * source; the response must still omit what the caller may not read.
7
+ *
8
+ * Input: a restricted caller's create or update body is refused when it names a field the caller
9
+ * may not read, or a key that names no field, with the same message for both.
10
+ *
11
+ * Views: callers may not ask for `entity_object` results, whose serialization would send an
12
+ * entity object's internal state rather than its projected fields.
13
+ */
14
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
15
+
16
+ const { mockGetEntityObject, mockRunViewFn, mockRunViewsFn, mockEntityList } = vi.hoisted(() => ({
17
+ mockGetEntityObject: vi.fn(),
18
+ mockRunViewFn: vi.fn(),
19
+ mockRunViewsFn: vi.fn(),
20
+ mockEntityList: [] as unknown[],
21
+ }));
22
+
23
+ vi.mock('@memberjunction/core', async (importOriginal) => {
24
+ const actual = await importOriginal<typeof import('@memberjunction/core')>();
25
+ class MockMetadata {
26
+ public get Entities() { return mockEntityList; }
27
+ public EntityByID() { return undefined; }
28
+ public GetEntityObject(entityName: string, contextUser?: unknown): Promise<unknown> {
29
+ return mockGetEntityObject(entityName, contextUser);
30
+ }
31
+ }
32
+ class MockRunView {
33
+ public RunView(params: unknown, contextUser?: unknown): Promise<unknown> { return mockRunViewFn(params, contextUser); }
34
+ public RunViews(params: unknown[], contextUser?: unknown): Promise<unknown> { return mockRunViewsFn(params, contextUser); }
35
+ }
36
+ return { ...actual, Metadata: MockMetadata, RunView: MockRunView, LogError: vi.fn() };
37
+ });
38
+
39
+ vi.mock('@memberjunction/generic-database-provider', () => ({
40
+ ClientClauseScreen: { ScreenViewClauses: vi.fn(), DialectFor: vi.fn() },
41
+ }));
42
+
43
+ import { EntityInfo, RunViewParams } from '@memberjunction/core';
44
+ import { EntityCRUDHandler } from '../rest/EntityCRUDHandler.js';
45
+ import { ViewOperationsHandler } from '../rest/ViewOperationsHandler.js';
46
+ import { EmployeeEntity, FullWidthEmployeeRow, HRUser, Intern, RefusalFor, SECRET_SALARY } from './fieldSecurityFixtures.js';
47
+
48
+ function fullWidthEntity(entityInfo: EntityInfo) {
49
+ return {
50
+ EntityInfo: entityInfo,
51
+ Dirty: true,
52
+ LatestResult: null,
53
+ CheckPermissions: vi.fn(() => true),
54
+ NewRecord: vi.fn(),
55
+ Set: vi.fn(),
56
+ Validate: vi.fn(() => ({ Success: true, Errors: [] })),
57
+ Save: vi.fn(async () => true),
58
+ InnerLoad: vi.fn(async () => true),
59
+ GetDataObject: vi.fn(async () => FullWidthEmployeeRow()),
60
+ };
61
+ }
62
+
63
+ let entity: ReturnType<typeof fullWidthEntity>;
64
+
65
+ beforeEach(() => {
66
+ vi.clearAllMocks();
67
+ entity = fullWidthEntity(EmployeeEntity());
68
+ mockGetEntityObject.mockImplementation(async () => entity);
69
+ mockEntityList.length = 0;
70
+ mockEntityList.push(EmployeeEntity());
71
+ mockRunViewFn.mockResolvedValue({ Success: true, Results: [FullWidthEmployeeRow()] });
72
+ mockRunViewsFn.mockResolvedValue([{ Success: true, Results: [FullWidthEmployeeRow()] }]);
73
+ });
74
+
75
+ describe('REST entity CRUD: responses are projected for the caller', () => {
76
+ it('REGRESSION: GetEntity omits a denied field from a full-width record', async () => {
77
+ const result = await EntityCRUDHandler.GetEntity('Employees', 'emp-1', null, Intern());
78
+ expect(result.entity).toEqual({ ID: 'emp-1', Name: 'Ada', Notes: 'n' });
79
+ });
80
+
81
+ it('REGRESSION: CreateEntity and UpdateEntity omit a denied field from the saved record', async () => {
82
+ const created = await EntityCRUDHandler.CreateEntity('Employees', { Name: 'Ada' }, Intern());
83
+ const updated = await EntityCRUDHandler.UpdateEntity('Employees', 'emp-1', { Notes: 'x' }, Intern());
84
+ expect(JSON.stringify([created, updated])).not.toContain(String(SECRET_SALARY));
85
+ expect(created.entity).toMatchObject({ ID: 'emp-1', Name: 'Ada' });
86
+ });
87
+
88
+ it('a caller who may read the field still receives it', async () => {
89
+ const result = await EntityCRUDHandler.GetEntity('Employees', 'emp-1', null, HRUser());
90
+ expect(result.entity).toMatchObject({ Salary: SECRET_SALARY });
91
+ });
92
+ });
93
+
94
+ describe('REST entity CRUD: client input is gated for a restricted caller', () => {
95
+ it.each([
96
+ ['a denied field', 'Salary'],
97
+ ['a key that names no field', 'Bogus'],
98
+ ])('REGRESSION: CreateEntity refuses %s with the same message, before anything is set', async (_label, key) => {
99
+ const result = await EntityCRUDHandler.CreateEntity('Employees', { Name: 'Ada', [key]: 1 }, Intern());
100
+ expect(result).toMatchObject({ success: false, error: RefusalFor(key) });
101
+ expect(entity.Set).not.toHaveBeenCalled();
102
+ expect(entity.Save).not.toHaveBeenCalled();
103
+ });
104
+
105
+ it.each([
106
+ ['a denied field', 'Salary'],
107
+ ['a key that names no field', 'Bogus'],
108
+ ])('REGRESSION: UpdateEntity refuses %s with the same message, before anything is set', async (_label, key) => {
109
+ const result = await EntityCRUDHandler.UpdateEntity('Employees', 'emp-1', { Notes: 'x', [key]: 1 }, Intern());
110
+ expect(result).toMatchObject({ success: false, error: RefusalFor(key) });
111
+ expect(entity.Set).not.toHaveBeenCalled();
112
+ });
113
+
114
+ it('accepts the save-options key and readable fields', async () => {
115
+ const result = await EntityCRUDHandler.UpdateEntity('Employees', 'emp-1', { Notes: 'x', options: { SkipEntityActions: true } }, Intern());
116
+ expect(result.success).toBe(true);
117
+ expect(entity.Set).toHaveBeenCalledWith('Notes', 'x');
118
+ });
119
+ });
120
+
121
+ describe('REST views: rows are projected and entity objects never cross the wire', () => {
122
+ it('REGRESSION: RunView omits a denied field from full-width rows', async () => {
123
+ const outcome = await ViewOperationsHandler.RunView({ EntityName: 'Employees' }, Intern());
124
+ expect(outcome.result?.Results).toEqual([{ ID: 'emp-1', Name: 'Ada', Notes: 'n' }]);
125
+ });
126
+
127
+ it('REGRESSION: RunViews omits a denied field from every result set', async () => {
128
+ const outcome = await ViewOperationsHandler.RunViews([{ EntityName: 'Employees' }], Intern());
129
+ expect(JSON.stringify(outcome.results)).not.toContain(String(SECRET_SALARY));
130
+ });
131
+
132
+ it('REGRESSION: ListEntities omits a denied field from full-width rows', async () => {
133
+ const result = await ViewOperationsHandler.ListEntities({ EntityName: 'Employees' }, Intern());
134
+ expect(JSON.stringify(result)).not.toContain(String(SECRET_SALARY));
135
+ });
136
+
137
+ it('REGRESSION: a caller-chosen entity_object ResultType is forced to simple, singly and in a batch', async () => {
138
+ await ViewOperationsHandler.RunView({ EntityName: 'Employees', ResultType: 'entity_object' }, Intern());
139
+ await ViewOperationsHandler.RunViews([{ EntityName: 'Employees', ResultType: 'entity_object' }], Intern());
140
+ expect((mockRunViewFn.mock.calls[0][0] as RunViewParams).ResultType).toBe('simple');
141
+ expect((mockRunViewsFn.mock.calls[0][0] as RunViewParams[])[0].ResultType).toBe('simple');
142
+ });
143
+
144
+ it('a caller who may read the field still receives it', async () => {
145
+ const outcome = await ViewOperationsHandler.RunView({ EntityName: 'Employees' }, HRUser());
146
+ expect(outcome.result?.Results[0]).toMatchObject({ Salary: SECRET_SALARY });
147
+ });
148
+ });
@@ -0,0 +1,179 @@
1
+ // ResolverBase / RunViewResolver / RunQueryResolver pull in type-graphql decorators, which need the
2
+ // Reflect.metadata polyfill at import time.
3
+ import 'reflect-metadata';
4
+ import { describe, it, expect, vi } from 'vitest';
5
+
6
+ // QueryResolver's GraphQL types lean on emitted decorator metadata, which vitest's transform does not
7
+ // produce. The decorators are irrelevant to what the resolvers pass on, so they become no-ops.
8
+ vi.mock('type-graphql', async (importOriginal) => {
9
+ const actual = await importOriginal<Record<string, unknown>>();
10
+ const noopDecorator = () => () => undefined;
11
+ return {
12
+ ...actual,
13
+ Resolver: noopDecorator, Query: noopDecorator, Mutation: noopDecorator, Subscription: noopDecorator,
14
+ ObjectType: noopDecorator, InputType: noopDecorator, Field: noopDecorator, Arg: noopDecorator,
15
+ Args: noopDecorator, Ctx: noopDecorator, Root: noopDecorator, PubSub: noopDecorator,
16
+ };
17
+ });
18
+ import type {
19
+ DatabaseProviderBase,
20
+ RunQueryParams,
21
+ RunQueryResult,
22
+ RunQueryWithCacheCheckParams,
23
+ RunQueriesWithCacheCheckResponse,
24
+ RunViewParams,
25
+ RunViewResult,
26
+ RunViewWithCacheCheckParams,
27
+ RunViewsWithCacheCheckResponse,
28
+ UserInfo,
29
+ } from '@memberjunction/core';
30
+ import { ResolverBase } from '../generic/ResolverBase.js';
31
+ import {
32
+ RunViewResolver,
33
+ type RunDynamicViewInput,
34
+ type RunViewByIDInput,
35
+ type RunViewByNameInput,
36
+ type RunViewWithCacheCheckInput,
37
+ } from '../generic/RunViewResolver.js';
38
+ import { RunQueryResolver, type RunQueryInput, type RunQueryWithCacheCheckInput } from '../resolvers/QueryResolver.js';
39
+ import type { AppContext, UserPayload } from '../types.js';
40
+
41
+ /**
42
+ * The view and query resolvers pass the caller's time zone (UserPayload.TimeZone, read from the
43
+ * x-mj-timezone header) on to the provider as RunViewParams.TimeZone / RunQueryParams.TimeZone,
44
+ * and leave it unset when the request carried none.
45
+ */
46
+
47
+ const ENTITY_NAME = 'MJ: Things';
48
+
49
+ function payload(timeZone?: string): UserPayload {
50
+ const p = { email: 'tester@example.com', userRecord: { Email: 'tester@example.com' } as UserInfo } as UserPayload;
51
+ if (timeZone) p.TimeZone = timeZone;
52
+ return p;
53
+ }
54
+
55
+ function entityStub() {
56
+ return { ID: 'ent-1', Name: ENTITY_NAME, BaseView: 'vwThings', PrimaryKeys: [{ Name: 'ID' }], Fields: [{ Name: 'ID', CodeName: 'ID' }], EncryptedFields: [] };
57
+ }
58
+
59
+ const okView = (): RunViewResult => ({ Success: true, Results: [], RowCount: 0, TotalRowCount: 0, ErrorMessage: '' } as RunViewResult);
60
+ const okQuery = (): RunQueryResult => ({ Success: true, Results: [], RowCount: 0, TotalRowCount: 0, ExecutionTime: 0, ErrorMessage: '' } as RunQueryResult);
61
+
62
+ /** Provider that records the run params every resolver path hands it. */
63
+ function recordingProvider() {
64
+ const views: RunViewParams[] = [];
65
+ const queries: RunQueryParams[] = [];
66
+ const provider = {
67
+ Entities: [entityStub()],
68
+ EntityByName: (name: string) => (name === ENTITY_NAME ? entityStub() : undefined),
69
+ RunView: async (params: RunViewParams) => { views.push(params); return okView(); },
70
+ RunViews: async (params: RunViewParams[]) => { views.push(...params); return params.map(okView); },
71
+ RunViewsWithCacheCheck: async (params: RunViewWithCacheCheckParams[]) => {
72
+ views.push(...params.map((p) => p.params));
73
+ return { success: true, results: [] } as RunViewsWithCacheCheckResponse;
74
+ },
75
+ RunQuery: async (params: RunQueryParams) => { queries.push(params); return okQuery(); },
76
+ RunQueries: async (params: RunQueryParams[]) => { queries.push(...params); return params.map(okQuery); },
77
+ RunQueriesWithCacheCheck: async (params: RunQueryWithCacheCheckParams[]) => {
78
+ queries.push(...params.map((p) => p.params));
79
+ return { success: true, results: [] } as RunQueriesWithCacheCheckResponse;
80
+ },
81
+ } as unknown as DatabaseProviderBase;
82
+ return { provider, views, queries };
83
+ }
84
+
85
+ function appContext(provider: DatabaseProviderBase, userPayload: UserPayload): AppContext {
86
+ return { providers: [{ provider, type: 'Read-Write' }], userPayload } as unknown as AppContext;
87
+ }
88
+
89
+ /** Skips the encrypted-field filter (it needs live Metadata) — irrelevant here. */
90
+ class Probe extends ResolverBase {
91
+ protected override async ArrayFilterEncryptedFieldsForAPI(_entityName: string, rows: Record<string, unknown>[]): Promise<Record<string, unknown>[]> {
92
+ return rows;
93
+ }
94
+ }
95
+
96
+ describe('RunViewParams.TimeZone from the request', () => {
97
+ const dynamic = { EntityName: ENTITY_NAME, ExtraFilter: '', OrderBy: '' } as RunDynamicViewInput;
98
+
99
+ it('a single view run carries the caller zone', async () => {
100
+ const { provider, views } = recordingProvider();
101
+ await new Probe().RunDynamicViewGeneric(dynamic, provider, payload('Europe/Paris'), undefined as never);
102
+ expect(views[0].TimeZone).toBe('Europe/Paris');
103
+ });
104
+
105
+ it('a single view run without the header leaves it unset (UTC)', async () => {
106
+ const { provider, views } = recordingProvider();
107
+ await new Probe().RunDynamicViewGeneric(dynamic, provider, payload(), undefined as never);
108
+ expect(views[0].TimeZone).toBeUndefined();
109
+ });
110
+
111
+ it('a batch carries it on every view', async () => {
112
+ const { provider, views } = recordingProvider();
113
+ const inputs = [dynamic, dynamic] as (RunViewByNameInput & RunViewByIDInput & RunDynamicViewInput)[];
114
+ await new Probe().RunViewsGeneric(inputs, provider, payload('Asia/Tokyo'));
115
+ expect(views.map((v) => v.TimeZone)).toEqual(['Asia/Tokyo', 'Asia/Tokyo']);
116
+ });
117
+
118
+ it('the cache-check batch carries it', async () => {
119
+ const { provider, views } = recordingProvider();
120
+ const input = [{ params: { EntityName: ENTITY_NAME } }] as unknown as RunViewWithCacheCheckInput[];
121
+ await new RunViewResolver().RunViewsWithCacheCheck(input, appContext(provider, payload('America/Chicago')));
122
+ expect(views[0].TimeZone).toBe('America/Chicago');
123
+ });
124
+ });
125
+
126
+ describe('RunQueryParams.TimeZone from the request', () => {
127
+ it('a single query run carries the caller zone, or none', async () => {
128
+ const withZone = recordingProvider();
129
+ await new RunQueryResolver().GetQueryDataByName('Active Members', appContext(withZone.provider, payload('Europe/Paris')));
130
+ expect(withZone.queries[0].TimeZone).toBe('Europe/Paris');
131
+
132
+ const without = recordingProvider();
133
+ await new RunQueryResolver().GetQueryDataByName('Active Members', appContext(without.provider, payload()));
134
+ expect(without.queries[0].TimeZone).toBeUndefined();
135
+ });
136
+
137
+ it('a batch carries it on every query', async () => {
138
+ const { provider, queries } = recordingProvider();
139
+ const input = [{ QueryName: 'A' }, { QueryName: 'B' }] as RunQueryInput[];
140
+ await new RunQueryResolver().RunQueries(input, appContext(provider, payload('Asia/Tokyo')));
141
+ expect(queries.map((q) => q.TimeZone)).toEqual(['Asia/Tokyo', 'Asia/Tokyo']);
142
+ });
143
+
144
+ it('the cache-check batch carries it', async () => {
145
+ const { provider, queries } = recordingProvider();
146
+ const input = [{ params: { QueryName: 'A' } }] as unknown as RunQueryWithCacheCheckInput[];
147
+ await new RunQueryResolver().RunQueriesWithCacheCheck(input, appContext(provider, payload('America/Chicago')));
148
+ expect(queries[0].TimeZone).toBe('America/Chicago');
149
+ });
150
+ });
151
+
152
+ /**
153
+ * #4789 A17: ServerParameters (values for server-set query parameters) and RequireApproved are
154
+ * server-only. No GraphQL run input declares them, and the RunQuery* resolvers build the run params
155
+ * field by field, so a value a client smuggles into an input object never reaches the provider. A
156
+ * client's only channel for a value is `Parameters`, where a server-set parameter is refused.
157
+ */
158
+ describe('RunQueryParams.ServerParameters and RequireApproved never come from a request', () => {
159
+ const smuggled = { ServerParameters: { ChapterID: 'someone-elses-chapter' }, RequireApproved: false, TimeZone: 'Pacific/Fiji' };
160
+
161
+ it('a batch drops them from each input', async () => {
162
+ const { provider, queries } = recordingProvider();
163
+ const input = [{ QueryName: 'A', Parameters: { Region: 'West' }, ...smuggled }] as unknown as RunQueryInput[];
164
+ await new RunQueryResolver().RunQueries(input, appContext(provider, payload('Asia/Tokyo')));
165
+ expect(queries[0].ServerParameters).toBeUndefined();
166
+ expect(queries[0].RequireApproved).toBeUndefined();
167
+ expect(queries[0].TimeZone).toBe('Asia/Tokyo'); // from the header, not the input
168
+ expect(queries[0].Parameters).toEqual({ Region: 'West' });
169
+ });
170
+
171
+ it('the cache-check batch drops them too', async () => {
172
+ const { provider, queries } = recordingProvider();
173
+ const input = [{ params: { QueryName: 'A', ...smuggled } }] as unknown as RunQueryWithCacheCheckInput[];
174
+ await new RunQueryResolver().RunQueriesWithCacheCheck(input, appContext(provider, payload()));
175
+ expect(queries[0].ServerParameters).toBeUndefined();
176
+ expect(queries[0].RequireApproved).toBeUndefined();
177
+ expect(queries[0].TimeZone).toBeUndefined();
178
+ });
179
+ });
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Field-level security on the agent-run and test-run streams.
3
+ *
4
+ * Each of these publishes an entity object's `GetAll()` to the caller's session: the agent run on
5
+ * every progress and streaming message and in the final result, the test run on every progress
6
+ * message. The objects come from long-running engines and can have been built for another
7
+ * identity, so the transport projects them for the recipient. The objects here are FULL WIDTH,
8
+ * and the recipient may not read `Salary`.
9
+ */
10
+ import 'reflect-metadata';
11
+ import { describe, it, expect, vi } from 'vitest';
12
+ import type { PubSubEngine } from 'type-graphql';
13
+
14
+ vi.mock('type-graphql', () => {
15
+ const decoratorFactory = (..._args: unknown[]) => (..._decorated: unknown[]) => undefined;
16
+ const exportNames = [
17
+ 'Resolver', 'Query', 'Mutation', 'Subscription', 'Arg', 'Args', 'ArgsType', 'Ctx', 'Root',
18
+ 'Info', 'Field', 'FieldResolver', 'ObjectType', 'InputType', 'InterfaceType', 'Authorized',
19
+ 'UseMiddleware', 'Extensions', 'Directive', 'ID', 'Int', 'Float', 'GraphQLISODateTime',
20
+ 'GraphQLTimestamp', 'registerEnumType', 'createMethodDecorator', 'createParamDecorator',
21
+ 'buildSchema', 'buildSchemaSync', 'PubSub',
22
+ ];
23
+ return Object.fromEntries(exportNames.map((name) => [name, decoratorFactory]));
24
+ });
25
+
26
+ vi.mock('@memberjunction/ai-agents', async (importOriginal) => ({
27
+ ...(await importOriginal<typeof import('@memberjunction/ai-agents')>()),
28
+ AgentRunner: class {},
29
+ }));
30
+
31
+ import type { ExecuteAgentResult } from '@memberjunction/ai-core-plus';
32
+ import { AgentRunStatusPublisher } from '../resolvers/AgentRunStatusPublisher.js';
33
+ import { RunAIAgentResolver } from '../resolvers/RunAIAgentResolver.js';
34
+ import { RunTestResolver } from '../resolvers/RunTestResolver.js';
35
+ import type { UserPayload } from '../types.js';
36
+ import { EmployeeEntity, FullWidthEmployeeRow, Intern, SECRET_SALARY } from './fieldSecurityFixtures.js';
37
+
38
+ /** A run object holding every column, as one built for another identity would. */
39
+ function fullWidthRun() {
40
+ return {
41
+ ID: 'emp-1',
42
+ ConversationDetailID: 'detail-1',
43
+ Steps: [{ StepName: 'Answer' }],
44
+ EntityInfo: EmployeeEntity(),
45
+ GetAll: () => FullWidthEmployeeRow(),
46
+ };
47
+ }
48
+
49
+ function capture() {
50
+ const publish = vi.fn().mockResolvedValue(undefined);
51
+ const pubSub = { publish } as unknown as PubSubEngine;
52
+ const userPayload = { sessionId: 'session-1', userRecord: Intern() } as unknown as UserPayload;
53
+ const messages = () => publish.mock.calls.map((call) => String((call[1] as { message: string }).message));
54
+ return { pubSub, userPayload, messages };
55
+ }
56
+
57
+ describe('AgentRunStatusPublisher: the run is projected for the recipient', () => {
58
+ it('REGRESSION: progress and streaming messages never carry a denied value', () => {
59
+ const { pubSub, userPayload, messages } = capture();
60
+ const publisher = new AgentRunStatusPublisher(pubSub, userPayload);
61
+ publisher.OnProgress({ step: 'prompt_execution', percentage: 10, message: 'm', metadata: { agentRun: fullWidthRun() } } as never);
62
+ publisher.OnStreaming({ content: 'hi', isComplete: false } as never);
63
+
64
+ expect(messages()).toHaveLength(2);
65
+ for (const message of messages()) {
66
+ expect(message).not.toContain(String(SECRET_SALARY));
67
+ expect(message).toContain('"Name":"Ada"');
68
+ }
69
+ });
70
+ });
71
+
72
+ describe('RunAIAgentResolver: the final result is projected for the recipient', () => {
73
+ it('REGRESSION: the sanitized result never carries a denied value of the run', () => {
74
+ const sanitize = (RunAIAgentResolver.prototype as unknown as {
75
+ sanitizeAgentResult(result: ExecuteAgentResult, user?: unknown): Record<string, unknown>;
76
+ }).sanitizeAgentResult;
77
+ const result = { success: true, agentRun: fullWidthRun() } as unknown as ExecuteAgentResult;
78
+
79
+ const sanitized = sanitize.call(new RunAIAgentResolver(), result, Intern());
80
+
81
+ expect(JSON.stringify(sanitized)).not.toContain(String(SECRET_SALARY));
82
+ expect(sanitized.agentRun).toMatchObject({ ID: 'emp-1', Name: 'Ada' });
83
+ });
84
+ });
85
+
86
+ describe('RunTestResolver: progress is projected for the recipient', () => {
87
+ it('REGRESSION: a progress message never carries a denied value of the test run', () => {
88
+ const { pubSub, userPayload, messages } = capture();
89
+ const create = (RunTestResolver.prototype as unknown as {
90
+ createProgressCallback(pubSub: PubSubEngine, userPayload: UserPayload, testId: string): (progress: unknown) => void;
91
+ }).createProgressCallback;
92
+ const onProgress = create.call(new RunTestResolver(), pubSub, userPayload, 'test-1');
93
+
94
+ onProgress({ step: 'running', percentage: 50, message: 'm', metadata: { testRun: fullWidthRun() } });
95
+
96
+ expect(messages()).toHaveLength(1);
97
+ expect(messages()[0]).not.toContain(String(SECRET_SALARY));
98
+ expect(messages()[0]).toContain('Ada');
99
+ });
100
+ });
@@ -0,0 +1,114 @@
1
+ // ResolverBase / RunViewResolver pull in type-graphql decorators, which need the Reflect.metadata
2
+ // polyfill at import time.
3
+ import 'reflect-metadata';
4
+ import { describe, it, expect, vi } from 'vitest';
5
+
6
+ // The decorators are irrelevant to what the resolvers pass on, so they become no-ops.
7
+ vi.mock('type-graphql', async (importOriginal) => {
8
+ const actual = await importOriginal<Record<string, unknown>>();
9
+ const noopDecorator = () => () => undefined;
10
+ return {
11
+ ...actual,
12
+ Resolver: noopDecorator, Query: noopDecorator, Mutation: noopDecorator, Subscription: noopDecorator,
13
+ ObjectType: noopDecorator, InputType: noopDecorator, Field: noopDecorator, Arg: noopDecorator,
14
+ Args: noopDecorator, Ctx: noopDecorator, Root: noopDecorator, PubSub: noopDecorator,
15
+ };
16
+ });
17
+ import type { DatabaseProviderBase, RunViewParams, RunViewResult, UserInfo } from '@memberjunction/core';
18
+ import { ResolverBase } from '../generic/ResolverBase.js';
19
+ import { RunViewResolver, type RunDynamicViewInput, type RunViewByIDInput, type RunViewByNameInput } from '../generic/RunViewResolver.js';
20
+ import type { AppContext, UserPayload } from '../types.js';
21
+
22
+ /**
23
+ * The GraphQL view resolvers pass a client's `Properties` on to the provider and never
24
+ * `ServerProperties`, whatever the input object carries; and a refusal the provider returns
25
+ * reaches the client with its message.
26
+ */
27
+
28
+ const ENTITY_NAME = 'MJ: Things';
29
+ const VIEW_ID = '33333333-3333-4333-8333-333333333333';
30
+ const CHAPTER = '11111111-1111-4111-8111-111111111111';
31
+ const REFUSAL = 'View property "Chapter" is set by the server; a client value for it is refused.';
32
+
33
+ function payload(): UserPayload {
34
+ return { email: 'tester@example.com', userRecord: { Email: 'tester@example.com' } as UserInfo } as UserPayload;
35
+ }
36
+
37
+ function entityStub() {
38
+ return { ID: 'ent-1', Name: ENTITY_NAME, BaseView: 'vwThings', PrimaryKeys: [{ Name: 'ID' }], Fields: [{ Name: 'ID', CodeName: 'ID', NeedsQuotes: true }], EncryptedFields: [] };
39
+ }
40
+
41
+ function userViewsEntityStub() {
42
+ return { ...entityStub(), ID: 'ent-views', Name: 'MJ: User Views' };
43
+ }
44
+
45
+ const viewRow = { ID: VIEW_ID, Name: 'Chapter Things', Entity: ENTITY_NAME, EntityID: 'ent-1' };
46
+
47
+ /** Records the run params each resolver hands the provider; a run carrying Properties is refused like the provider would. */
48
+ function recordingProvider() {
49
+ const views: RunViewParams[] = [];
50
+ const answer = (p: RunViewParams): RunViewResult => {
51
+ if (p.EntityName === 'MJ: User Views') {
52
+ return { Success: true, Results: [viewRow], RowCount: 1, TotalRowCount: 1, ErrorMessage: '' } as RunViewResult;
53
+ }
54
+ views.push(p);
55
+ return p.Properties
56
+ ? ({ Success: false, Results: [], RowCount: 0, TotalRowCount: 0, ErrorMessage: REFUSAL } as RunViewResult)
57
+ : ({ Success: true, Results: [], RowCount: 0, TotalRowCount: 0, ErrorMessage: '' } as RunViewResult);
58
+ };
59
+ const provider = {
60
+ Entities: [entityStub(), userViewsEntityStub()],
61
+ EntityByName: (name: string) => (name === ENTITY_NAME ? entityStub() : undefined),
62
+ EntityByID: () => entityStub(),
63
+ GetEntityObject: async () => ({ ...viewRow, Load: async () => true }),
64
+ RunView: async (params: RunViewParams) => answer(params),
65
+ RunViews: async (params: RunViewParams[]) => params.map(answer),
66
+ } as unknown as DatabaseProviderBase;
67
+ return { provider, views };
68
+ }
69
+
70
+ function appContext(provider: DatabaseProviderBase): AppContext {
71
+ return { providers: [{ provider, type: 'Read-Write' }], userPayload: payload() } as unknown as AppContext;
72
+ }
73
+
74
+ class Probe extends ResolverBase {
75
+ protected override async ArrayFilterEncryptedFieldsForAPI(_entityName: string, rows: Record<string, unknown>[]): Promise<Record<string, unknown>[]> {
76
+ return rows;
77
+ }
78
+ }
79
+
80
+ /** An input as a client might shape it, with a ServerProperties field smuggled in. */
81
+ function smuggled<T>(input: T): T {
82
+ return { ...input, Properties: { Chapter: CHAPTER }, ServerProperties: { Chapter: 'forged' } } as T;
83
+ }
84
+
85
+ describe('GraphQL view resolvers and view properties', () => {
86
+ it('RunViewByID and RunViewByName pass Properties on, never ServerProperties', async () => {
87
+ const { provider, views } = recordingProvider();
88
+ await new Probe().RunViewByIDGeneric(smuggled({ ViewID: VIEW_ID } as RunViewByIDInput), provider, payload(), undefined as never);
89
+ await new Probe().RunViewByNameGeneric(smuggled({ ViewName: viewRow.Name } as RunViewByNameInput), provider, payload(), undefined as never);
90
+ expect(views.map((v) => v.Properties)).toEqual([{ Chapter: CHAPTER }, { Chapter: CHAPTER }]);
91
+ expect(views.map((v) => v.ServerProperties)).toEqual([undefined, undefined]);
92
+ expect(views[0].ViewID).toBe(VIEW_ID);
93
+ });
94
+
95
+ it('RunViews passes Properties on for each view, never ServerProperties', async () => {
96
+ const { provider, views } = recordingProvider();
97
+ const inputs = [smuggled({ ViewID: VIEW_ID }), { EntityName: ENTITY_NAME }] as (RunViewByNameInput & RunViewByIDInput & RunDynamicViewInput)[];
98
+ await new Probe().RunViewsGeneric(inputs, provider, payload());
99
+ expect(views.map((v) => v.Properties)).toEqual([{ Chapter: CHAPTER }, undefined]);
100
+ expect(views.every((v) => v.ServerProperties === undefined)).toBe(true);
101
+ });
102
+
103
+ it('a run without Properties carries none', async () => {
104
+ const { provider, views } = recordingProvider();
105
+ await new Probe().RunViewByIDGeneric({ ViewID: VIEW_ID } as RunViewByIDInput, provider, payload(), undefined as never);
106
+ expect(views[0].Properties).toBeUndefined();
107
+ });
108
+
109
+ it('RunViewByID returns the provider refusal, naming the property', async () => {
110
+ const { provider } = recordingProvider();
111
+ const result = await new RunViewResolver().RunViewByID(smuggled({ ViewID: VIEW_ID } as RunViewByIDInput), appContext(provider), undefined as never);
112
+ expect(result).toMatchObject({ Success: false, ErrorMessage: REFUSAL });
113
+ });
114
+ });