@memberjunction/server 6.2.0-edge.5 → 6.2.0-edge.7
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.
- package/README.md +96 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/BridgeHostInstance.d.ts +8 -3
- package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -1
- package/dist/agentSessions/BridgeHostInstance.js +14 -4
- package/dist/agentSessions/BridgeHostInstance.js.map +1 -1
- package/dist/agentSessions/HandoffOfferExpiry.d.ts +10 -0
- package/dist/agentSessions/HandoffOfferExpiry.d.ts.map +1 -0
- package/dist/agentSessions/HandoffOfferExpiry.js +18 -0
- package/dist/agentSessions/HandoffOfferExpiry.js.map +1 -0
- package/dist/agentSessions/ReturningVisitorRecap.js +1 -0
- package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
- package/dist/agentSessions/SessionJanitor.d.ts +34 -11
- package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
- package/dist/agentSessions/SessionJanitor.js +88 -44
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/agentSessions/SessionManager.d.ts +29 -9
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +62 -16
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/agentSessions/conversationBrowsers.d.ts +61 -0
- package/dist/agentSessions/conversationBrowsers.d.ts.map +1 -0
- package/dist/agentSessions/conversationBrowsers.js +118 -0
- package/dist/agentSessions/conversationBrowsers.js.map +1 -0
- package/dist/agentSessions/sessionDeadline.d.ts +43 -0
- package/dist/agentSessions/sessionDeadline.d.ts.map +1 -0
- package/dist/agentSessions/sessionDeadline.js +68 -0
- package/dist/agentSessions/sessionDeadline.js.map +1 -0
- package/dist/auth/APIKeyScopeAuth.d.ts.map +1 -1
- package/dist/auth/APIKeyScopeAuth.js +5 -4
- package/dist/auth/APIKeyScopeAuth.js.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.js +2 -0
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +51 -10
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +10 -0
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +37 -1
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/localDevAuth.d.ts +79 -0
- package/dist/auth/localDevAuth.d.ts.map +1 -0
- package/dist/auth/localDevAuth.js +439 -0
- package/dist/auth/localDevAuth.js.map +1 -0
- package/dist/auth/loginEmailResolution.d.ts +41 -0
- package/dist/auth/loginEmailResolution.d.ts.map +1 -0
- package/dist/auth/loginEmailResolution.js +47 -0
- package/dist/auth/loginEmailResolution.js.map +1 -0
- package/dist/auth/magicLink/MagicLinkKeys.d.ts +51 -3
- package/dist/auth/magicLink/MagicLinkKeys.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkKeys.js +130 -13
- package/dist/auth/magicLink/MagicLinkKeys.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.d.ts +3 -0
- package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +23 -5
- package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.d.ts +39 -5
- package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +221 -9
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/magicLink/index.d.ts +1 -1
- package/dist/auth/magicLink/index.d.ts.map +1 -1
- package/dist/auth/magicLink/index.js +1 -1
- package/dist/auth/magicLink/index.js.map +1 -1
- package/dist/auth/magicLink/redeemLanding.d.ts +2 -2
- package/dist/auth/magicLink/redeemLanding.d.ts.map +1 -1
- package/dist/auth/magicLink/redeemLanding.js +7 -4
- package/dist/auth/magicLink/redeemLanding.js.map +1 -1
- package/dist/auth/magicLink/types.d.ts +39 -3
- package/dist/auth/magicLink/types.d.ts.map +1 -1
- package/dist/auth/magicLink/types.js +0 -4
- package/dist/auth/magicLink/types.js.map +1 -1
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +1 -0
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/auth/sessionUserClone.d.ts +1 -1
- package/dist/auth/sessionUserClone.d.ts.map +1 -1
- package/dist/auth/sessionUserClone.js +3 -2
- package/dist/auth/sessionUserClone.js.map +1 -1
- package/dist/backgroundSweepConfigUnits.d.ts +231 -0
- package/dist/backgroundSweepConfigUnits.d.ts.map +1 -0
- package/dist/backgroundSweepConfigUnits.js +180 -0
- package/dist/backgroundSweepConfigUnits.js.map +1 -0
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts +292 -0
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js +442 -0
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js.map +1 -0
- package/dist/broadcast/index.d.ts +6 -0
- package/dist/broadcast/index.d.ts.map +1 -0
- package/dist/broadcast/index.js +6 -0
- package/dist/broadcast/index.js.map +1 -0
- package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.d.ts +43 -0
- package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.js +144 -0
- package/dist/broadcast/providers/AWSIoTCoreBroadcastProvider.js.map +1 -0
- package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.d.ts +46 -0
- package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.js +149 -0
- package/dist/broadcast/providers/AzureWebPubSubBroadcastProvider.js.map +1 -0
- package/dist/broadcast/providers/GCPPubSubBroadcastProvider.d.ts +49 -0
- package/dist/broadcast/providers/GCPPubSubBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/providers/GCPPubSubBroadcastProvider.js +131 -0
- package/dist/broadcast/providers/GCPPubSubBroadcastProvider.js.map +1 -0
- package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.d.ts +24 -0
- package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.d.ts.map +1 -0
- package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.js +51 -0
- package/dist/broadcast/providers/SequencedRoleBucketBroadcastProvider.js.map +1 -0
- package/dist/cache.d.ts +3 -2
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js.map +1 -1
- package/dist/config.d.ts +1402 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +120 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +5 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +64 -12
- package/dist/context.js.map +1 -1
- package/dist/coreRoutes.d.ts +3 -1
- package/dist/coreRoutes.d.ts.map +1 -1
- package/dist/coreRoutes.js +20 -4
- package/dist/coreRoutes.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts +863 -14
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +4167 -62
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +50 -30
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +154 -79
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts +11 -0
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js +29 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
- package/dist/generic/PubSubManager.d.ts +10 -0
- package/dist/generic/PubSubManager.d.ts.map +1 -1
- package/dist/generic/PubSubManager.js +44 -1
- package/dist/generic/PubSubManager.js.map +1 -1
- package/dist/generic/PushStatusResolver.d.ts +39 -6
- package/dist/generic/PushStatusResolver.d.ts.map +1 -1
- package/dist/generic/PushStatusResolver.js +93 -11
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +114 -29
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +509 -220
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +15 -3
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +126 -20
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/generic/actionOutputFieldSecurity.d.ts +26 -0
- package/dist/generic/actionOutputFieldSecurity.d.ts.map +1 -0
- package/dist/generic/actionOutputFieldSecurity.js +47 -0
- package/dist/generic/actionOutputFieldSecurity.js.map +1 -0
- package/dist/generic/fieldSecurityTransport.d.ts +30 -0
- package/dist/generic/fieldSecurityTransport.d.ts.map +1 -0
- package/dist/generic/fieldSecurityTransport.js +30 -0
- package/dist/generic/fieldSecurityTransport.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +262 -84
- package/dist/index.js.map +1 -1
- package/dist/integration/ConnectionPause.d.ts +121 -0
- package/dist/integration/ConnectionPause.d.ts.map +1 -0
- package/dist/integration/ConnectionPause.js +183 -0
- package/dist/integration/ConnectionPause.js.map +1 -0
- package/dist/integration/CustomColumnPromoter.d.ts +72 -6
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +93 -47
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/integration/EntityMapLifecycle.d.ts +78 -4
- package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
- package/dist/integration/EntityMapLifecycle.js +199 -5
- package/dist/integration/EntityMapLifecycle.js.map +1 -1
- package/dist/integration/InactiveRowWarnings.d.ts +31 -0
- package/dist/integration/InactiveRowWarnings.d.ts.map +1 -1
- package/dist/integration/InactiveRowWarnings.js +29 -0
- package/dist/integration/InactiveRowWarnings.js.map +1 -1
- package/dist/integration/ObjectNamesByID.d.ts +28 -0
- package/dist/integration/ObjectNamesByID.d.ts.map +1 -0
- package/dist/integration/ObjectNamesByID.js +87 -0
- package/dist/integration/ObjectNamesByID.js.map +1 -0
- package/dist/integration/PostRestartIntrospect.d.ts +26 -0
- package/dist/integration/PostRestartIntrospect.d.ts.map +1 -0
- package/dist/integration/PostRestartIntrospect.js +27 -0
- package/dist/integration/PostRestartIntrospect.js.map +1 -0
- package/dist/integration/RSUPostRestartProgress.d.ts +176 -0
- package/dist/integration/RSUPostRestartProgress.d.ts.map +1 -0
- package/dist/integration/RSUPostRestartProgress.js +323 -0
- package/dist/integration/RSUPostRestartProgress.js.map +1 -0
- package/dist/integration/RSUProgressBridge.d.ts +41 -2
- package/dist/integration/RSUProgressBridge.d.ts.map +1 -1
- package/dist/integration/RSUProgressBridge.js +84 -1
- package/dist/integration/RSUProgressBridge.js.map +1 -1
- package/dist/integration/RunArtifactAuthorization.d.ts +39 -0
- package/dist/integration/RunArtifactAuthorization.d.ts.map +1 -0
- package/dist/integration/RunArtifactAuthorization.js +45 -0
- package/dist/integration/RunArtifactAuthorization.js.map +1 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts +9 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts.map +1 -1
- package/dist/integration/SchemaRefreshLaunch.js +3 -2
- package/dist/integration/SchemaRefreshLaunch.js.map +1 -1
- package/dist/integration/ScopedFieldsForBuild.d.ts +46 -0
- package/dist/integration/ScopedFieldsForBuild.d.ts.map +1 -0
- package/dist/integration/ScopedFieldsForBuild.js +91 -0
- package/dist/integration/ScopedFieldsForBuild.js.map +1 -0
- package/dist/integration/TargetConfigGuard.d.ts +40 -0
- package/dist/integration/TargetConfigGuard.d.ts.map +1 -0
- package/dist/integration/TargetConfigGuard.js +40 -0
- package/dist/integration/TargetConfigGuard.js.map +1 -0
- package/dist/logging/variablesLoggingMiddleware.d.ts +12 -0
- package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.js +50 -1
- package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
- package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -1
- package/dist/realtimeSessions/SessionVerificationPortsBase.js +1 -0
- package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -1
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts +8 -6
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -1
- package/dist/realtimeSessions/ownedRealtimeSession.js +14 -6
- package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -1
- package/dist/realtimeSessions/sessionAccess.d.ts +103 -11
- package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
- package/dist/realtimeSessions/sessionAccess.js +147 -22
- package/dist/realtimeSessions/sessionAccess.js.map +1 -1
- package/dist/realtimeSessions/sessionConfigStamps.js +1 -1
- package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -1
- package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -1
- package/dist/realtimeSessions/subscriptionAuthorization.js +5 -2
- package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -1
- package/dist/realtimeSessions/verificationWorkflow.d.ts +2 -0
- package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -1
- package/dist/realtimeSessions/verificationWorkflow.js +1 -1
- package/dist/realtimeSessions/verificationWorkflow.js.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.js +19 -3
- package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts +67 -7
- package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.js +203 -19
- package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
- package/dist/realtimeWidget/host-identity.d.ts +1 -1
- package/dist/realtimeWidget/host-identity.js +1 -1
- package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.js +1 -0
- package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
- package/dist/realtimeWidget/widgetCore.d.ts +20 -1
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetCore.js +21 -8
- package/dist/realtimeWidget/widgetCore.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.d.ts +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +3 -1
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/requestOrigin.d.ts +22 -0
- package/dist/requestOrigin.d.ts.map +1 -0
- package/dist/requestOrigin.js +60 -0
- package/dist/requestOrigin.js.map +1 -0
- package/dist/resolvers/ActionResolver.d.ts +19 -1
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +63 -12
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.js +1 -0
- package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
- package/dist/resolvers/AgentRunStatusPublisher.d.ts +18 -4
- package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -1
- package/dist/resolvers/AgentRunStatusPublisher.js +32 -8
- package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -1
- package/dist/resolvers/AgentSessionResolver.d.ts +10 -4
- package/dist/resolvers/AgentSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/AgentSessionResolver.js +44 -17
- package/dist/resolvers/AgentSessionResolver.js.map +1 -1
- package/dist/resolvers/AutotagPipelineResolver.d.ts.map +1 -1
- package/dist/resolvers/AutotagPipelineResolver.js +2 -1
- package/dist/resolvers/AutotagPipelineResolver.js.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.js +2 -0
- package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts +13 -1
- package/dist/resolvers/EntityCommunicationsResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityCommunicationsResolver.js +50 -14
- package/dist/resolvers/EntityCommunicationsResolver.js.map +1 -1
- package/dist/resolvers/ExecuteRemoteOperationResolver.d.ts +6 -0
- package/dist/resolvers/ExecuteRemoteOperationResolver.d.ts.map +1 -1
- package/dist/resolvers/ExecuteRemoteOperationResolver.js +30 -7
- package/dist/resolvers/ExecuteRemoteOperationResolver.js.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts +28 -0
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js +117 -21
- package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +1 -0
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +5 -0
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +13 -4
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +34 -13
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +401 -11
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +2713 -1290
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts.map +1 -1
- package/dist/resolvers/MCPResolver.js +13 -2
- package/dist/resolvers/MCPResolver.js.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts +8 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +31 -3
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/PipelineProgressResolver.d.ts +6 -0
- package/dist/resolvers/PipelineProgressResolver.d.ts.map +1 -1
- package/dist/resolvers/PipelineProgressResolver.js +5 -3
- package/dist/resolvers/PipelineProgressResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +20 -6
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +38 -0
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +184 -88
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RSUResolver.d.ts.map +1 -1
- package/dist/resolvers/RSUResolver.js +12 -0
- package/dist/resolvers/RSUResolver.js.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +1 -0
- package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +22 -2
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +118 -33
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts +62 -10
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +224 -39
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +80 -16
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +388 -125
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts +5 -3
- package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +19 -18
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +7 -5
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/RunTestResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTestResolver.js +3 -1
- package/dist/resolvers/RunTestResolver.js.map +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +4 -0
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.js +1 -0
- package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts +17 -2
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +60 -15
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.d.ts +1 -1
- package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
- package/dist/resolvers/UserViewResolver.js +2 -1
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.js +2 -0
- package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts +6 -0
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +19 -5
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/MediaAccessKeys.d.ts.map +1 -1
- package/dist/rest/MediaAccessKeys.js +6 -2
- package/dist/rest/MediaAccessKeys.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
- package/dist/rest/OAuthCallbackHandler.js +11 -5
- package/dist/rest/OAuthCallbackHandler.js.map +1 -1
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +8 -5
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/RealtimeRecordingHandler.d.ts +3 -3
- package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -1
- package/dist/rest/RealtimeRecordingHandler.js +6 -8
- package/dist/rest/RealtimeRecordingHandler.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +6 -0
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +24 -6
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +3 -1
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +11 -2
- package/dist/rest/setupRESTEndpoints.js.map +1 -1
- package/dist/serverRoleConfigUnits.d.ts +29 -0
- package/dist/serverRoleConfigUnits.d.ts.map +1 -0
- package/dist/serverRoleConfigUnits.js +33 -0
- package/dist/serverRoleConfigUnits.js.map +1 -0
- package/dist/services/DurableEntityActionTaskSubmitter.d.ts.map +1 -1
- package/dist/services/DurableEntityActionTaskSubmitter.js +6 -1
- package/dist/services/DurableEntityActionTaskSubmitter.js.map +1 -1
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphActionRunner.js +2 -26
- package/dist/services/TaskGraphActionRunner.js.map +1 -1
- package/dist/services/TaskGraphAgentRunner.d.ts +6 -0
- package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphAgentRunner.js +38 -0
- package/dist/services/TaskGraphAgentRunner.js.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.d.ts +5 -0
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +43 -15
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/services/WorkQueueHostService.d.ts +2 -1
- package/dist/services/WorkQueueHostService.d.ts.map +1 -1
- package/dist/services/WorkQueueHostService.js +19 -4
- package/dist/services/WorkQueueHostService.js.map +1 -1
- package/dist/services/workQueueConfig.d.ts +2 -2
- package/dist/services/workQueueConfig.js +5 -5
- package/dist/services/workQueueConfig.js.map +1 -1
- package/dist/sharedCache.js +1 -1
- package/dist/sharedCache.js.map +1 -1
- package/dist/types.d.ts +40 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +98 -98
- package/src/__tests__/APIKeyScopeAuth.test.ts +4 -8
- package/src/__tests__/ActionResolver.fieldSecurity.test.ts +237 -0
- package/src/__tests__/ActiveOperations.test.ts +68 -0
- package/src/__tests__/AdhocQueryResolver.dialect.test.ts +137 -0
- package/src/__tests__/AgentRunStatusPublisher.test.ts +49 -0
- package/src/__tests__/AgentSessionResolver.ownership.test.ts +150 -0
- package/src/__tests__/AssertTargetConfigs.test.ts +75 -0
- package/src/__tests__/BatchApplyParity.test.ts +109 -0
- package/src/__tests__/BridgeHostInstance.test.ts +42 -0
- package/src/__tests__/CollectInactiveRowWarnings.test.ts +115 -0
- package/src/__tests__/ConnectionPause.test.ts +192 -0
- package/src/__tests__/ConnectionPauseResolver.test.ts +166 -0
- package/src/__tests__/ConnectionPauseSave.test.ts +143 -0
- package/src/__tests__/CustomColumnPromoterCompletion.test.ts +142 -0
- package/src/__tests__/CustomColumnPromoterOnePass.test.ts +15 -1
- package/src/__tests__/DeleteConnectionRemovesPerConnectionCatalog.test.ts +51 -0
- package/src/__tests__/DetachedDiscoveryStart.test.ts +65 -0
- package/src/__tests__/DurableEntityActionTaskSubmitter.test.ts +73 -0
- package/src/__tests__/EntityCommunicationsResolver.actingUser.test.ts +151 -0
- package/src/__tests__/EntityMapLifecycle.rekey.test.ts +252 -0
- package/src/__tests__/EvolutionActsOnWhatItDetects.test.ts +113 -0
- package/src/__tests__/ExecuteRemoteOperationResolver.test.ts +213 -0
- package/src/__tests__/FetchEntityVectorsResolver.test.ts +206 -3
- package/src/__tests__/FileResolver.fieldSecurity.test.ts +82 -0
- package/src/__tests__/HandoffOfferExpiry.test.ts +40 -0
- package/src/__tests__/IntegrationRunArtifactAuthorization.test.ts +126 -0
- package/src/__tests__/MagicLinkKeys.test.ts +102 -0
- package/src/__tests__/MediaAccessKeys.test.ts +57 -10
- package/src/__tests__/NewArrivalsDefaultDisabled.test.ts +50 -0
- package/src/__tests__/ObjectNamesByID.test.ts +176 -0
- package/src/__tests__/PipelineProgressResolver.filter.test.ts +58 -0
- package/src/__tests__/PostRestartMapsInCatalogScope.test.ts +146 -0
- package/src/__tests__/QuerySystemUserResolver.childRows.test.ts +80 -0
- package/src/__tests__/QuerySystemUserResolver.collision.test.ts +200 -0
- package/src/__tests__/QuerySystemUserResolver.fieldSecurity.test.ts +49 -0
- package/src/__tests__/QuerySystemUserResolver.permissions.test.ts +132 -0
- package/src/__tests__/RESTEndpointHandler.test.ts +25 -0
- package/src/__tests__/RSUPostRestartProgress.test.ts +343 -0
- package/src/__tests__/RSUProgressBridge.test.ts +188 -5
- package/src/__tests__/RSUStartupSweepWiring.test.ts +30 -0
- package/src/__tests__/ReactivateRefreshMessage.test.ts +10 -3
- package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +23 -3
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +346 -46
- package/src/__tests__/{RefreshAdoptsNewColumns.test.ts → RefreshReportsNewColumns.test.ts} +25 -16
- package/src/__tests__/RemoteBrowserActionRecovery.test.ts +287 -0
- package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +3 -0
- package/src/__tests__/RemoteBrowserActionResolver.ownership.test.ts +100 -0
- package/src/__tests__/RemoteBrowserAudioStream.test.ts +3 -0
- package/src/__tests__/RemoteBrowserSnapshot.test.ts +3 -0
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +344 -14
- package/src/__tests__/ResolverBase.deleteReturnProjection.test.ts +52 -0
- package/src/__tests__/ResolverBase.encryptedApiZeroReencrypt.test.ts +307 -0
- package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +227 -0
- package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +83 -1
- package/src/__tests__/ResolverBase.publishStatusUpdate.test.ts +68 -0
- package/src/__tests__/ResolverBase.userViewCacheAndDedup.test.ts +130 -0
- package/src/__tests__/RunAIAgentResolver.branch.test.ts +72 -13
- package/src/__tests__/RunAIAgentResolver.consultPredecessor.test.ts +289 -0
- package/src/__tests__/RunAIAgentResolver.conversationWriter.test.ts +210 -0
- package/src/__tests__/RunAIAgentResolver.fireAndForgetCompletion.test.ts +209 -0
- package/src/__tests__/RunAIAgentResolver.handoff.test.ts +649 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +19 -27
- package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +10 -2
- package/src/__tests__/RunAIAgentResolver.serverReply.test.ts +358 -0
- package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +91 -13
- package/src/__tests__/RunTemplateResolver.test.ts +35 -2
- package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +11 -0
- package/src/__tests__/SchemaEvolutionCustomColumns.test.ts +119 -0
- package/src/__tests__/SchemaRefreshLaunch.test.ts +24 -2
- package/src/__tests__/ScopedFieldsForBuild.test.ts +192 -0
- package/src/__tests__/SessionJanitor.test.ts +195 -4
- package/src/__tests__/SessionManager.test.ts +164 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +2 -2
- package/src/__tests__/TaskGraphAgentRunner.test.ts +272 -16
- package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +114 -3
- package/src/__tests__/TransactionGroupResolver.fieldSecurity.test.ts +199 -0
- package/src/__tests__/UserViewResolver.updateWhereClause.test.ts +15 -0
- package/src/__tests__/ViewOperationsHandler.test.ts +9 -7
- package/src/__tests__/WidgetSessionService.test.ts +583 -4
- package/src/__tests__/WorkQueueHostService.test.ts +25 -7
- package/src/__tests__/apiRootBoot.test.ts +1 -1
- package/src/__tests__/backgroundSweepConfigUnits.test.ts +153 -0
- package/src/__tests__/buildMagicLinkSessionUser.test.ts +96 -0
- package/src/__tests__/cacheBroadcastProviders.test.ts +403 -0
- package/src/__tests__/cacheInvalidationRecordData.test.ts +45 -0
- package/src/__tests__/contextRequestOrigin.test.ts +105 -0
- package/src/__tests__/conversationBrowsers.test.ts +62 -0
- package/src/__tests__/fieldSecurityFixtures.ts +91 -0
- package/src/__tests__/globalCors.test.ts +3 -3
- package/src/__tests__/localDevAuth.test.ts +196 -0
- package/src/__tests__/magicLinkExtensionCapabilities.test.ts +413 -0
- package/src/__tests__/orphanedConversationDetailReconciler.start.test.ts +82 -0
- package/src/__tests__/orphanedConversationDetailReconciler.test.ts +10 -0
- package/src/__tests__/ownedRealtimeSession.test.ts +14 -0
- package/src/__tests__/pushStatusResolver.filter.test.ts +57 -1
- package/src/__tests__/realtimeRecordingHandler.test.ts +24 -2
- package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +29 -1
- package/src/__tests__/realtimeSessions/ownedRealtimeSession.anonymous.test.ts +31 -0
- package/src/__tests__/realtimeSessions/ownedRealtimeSession.namedScoped.test.ts +37 -0
- package/src/__tests__/realtimeSessions/sessionAccess.test.ts +224 -7
- package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +1 -1
- package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +25 -4
- package/src/__tests__/requestOrigin.test.ts +104 -0
- package/src/__tests__/resolverBase.cloudEventChangedFields.test.ts +157 -0
- package/src/__tests__/resolverBase.fieldSecurityTransport.test.ts +222 -0
- package/src/__tests__/resolverBase.fls.test.ts +146 -97
- package/src/__tests__/restTransport.fieldSecurity.test.ts +148 -0
- package/src/__tests__/runParamsTimeZone.test.ts +179 -0
- package/src/__tests__/runStreams.fieldSecurity.test.ts +100 -0
- package/src/__tests__/runViewProperties.test.ts +114 -0
- package/src/__tests__/scalabilityBenchmarks.test.ts +765 -0
- package/src/__tests__/scalabilityDatabaseIntegration.test.ts +207 -0
- package/src/__tests__/securityHardeningPr6034.test.ts +120 -0
- package/src/__tests__/sessionDeadline.test.ts +51 -0
- package/src/__tests__/sessionUserClone.test.ts +5 -1
- package/src/__tests__/sharedCache.test.ts +11 -0
- package/src/__tests__/startupSweepOrder.test.ts +40 -0
- package/src/__tests__/unifiedAuth.test.ts +101 -1
- package/src/__tests__/widgetGuestElevation.test.ts +2 -0
- package/src/agentSessions/BridgeHostInstance.ts +20 -5
- package/src/agentSessions/HandoffOfferExpiry.ts +18 -0
- package/src/agentSessions/ReturningVisitorRecap.ts +1 -0
- package/src/agentSessions/SessionJanitor.ts +95 -45
- package/src/agentSessions/SessionManager.ts +73 -20
- package/src/agentSessions/conversationBrowsers.ts +143 -0
- package/src/agentSessions/sessionDeadline.ts +81 -0
- package/src/auth/APIKeyScopeAuth.ts +5 -4
- package/src/auth/AuthProviderCatalogRouter.ts +3 -0
- package/src/auth/__tests__/loginEmailResolution.test.ts +67 -0
- package/src/auth/index.ts +56 -12
- package/src/auth/initializeProviders.ts +43 -1
- package/src/auth/localDevAuth.ts +528 -0
- package/src/auth/loginEmailResolution.ts +67 -0
- package/src/auth/magicLink/MagicLinkKeys.ts +147 -15
- package/src/auth/magicLink/MagicLinkRouter.ts +33 -6
- package/src/auth/magicLink/MagicLinkService.ts +250 -10
- package/src/auth/magicLink/index.ts +1 -1
- package/src/auth/magicLink/redeemLanding.ts +7 -4
- package/src/auth/magicLink/types.ts +38 -3
- package/src/auth/newUsers.ts +1 -0
- package/src/auth/sessionUserClone.ts +3 -2
- package/src/backgroundSweepConfigUnits.ts +213 -0
- package/src/broadcast/BaseCacheInvalidationBroadcastProvider.ts +674 -0
- package/src/broadcast/index.ts +5 -0
- package/src/broadcast/providers/AWSIoTCoreBroadcastProvider.ts +180 -0
- package/src/broadcast/providers/AzureWebPubSubBroadcastProvider.ts +182 -0
- package/src/broadcast/providers/GCPPubSubBroadcastProvider.ts +169 -0
- package/src/broadcast/providers/SequencedRoleBucketBroadcastProvider.ts +57 -0
- package/src/cache.ts +2 -1
- package/src/config.ts +138 -0
- package/src/context.ts +71 -14
- package/src/coreRoutes.ts +29 -7
- package/src/generated/graphql-schemas/__mj.ts +4145 -1193
- package/src/generic/CacheInvalidationResolver.ts +135 -78
- package/src/generic/OrphanedConversationDetailReconciler.ts +36 -3
- package/src/generic/PubSubManager.ts +54 -1
- package/src/generic/PushStatusResolver.ts +108 -11
- package/src/generic/ResolverBase.ts +635 -234
- package/src/generic/RunViewResolver.ts +176 -64
- package/src/generic/actionOutputFieldSecurity.ts +75 -0
- package/src/generic/fieldSecurityTransport.ts +62 -0
- package/src/index.ts +310 -85
- package/src/integration/ConnectionPause.ts +222 -0
- package/src/integration/CustomColumnPromoter.ts +129 -54
- package/src/integration/EntityMapLifecycle.ts +229 -6
- package/src/integration/InactiveRowWarnings.ts +50 -0
- package/src/integration/ObjectNamesByID.ts +97 -0
- package/src/integration/PostRestartIntrospect.ts +49 -0
- package/src/integration/RSUPostRestartProgress.ts +359 -0
- package/src/integration/RSUProgressBridge.ts +85 -2
- package/src/integration/RunArtifactAuthorization.ts +65 -0
- package/src/integration/SchemaRefreshLaunch.ts +12 -2
- package/src/integration/ScopedFieldsForBuild.ts +113 -0
- package/src/integration/TargetConfigGuard.ts +71 -0
- package/src/logging/variablesLoggingMiddleware.ts +59 -3
- package/src/realtimeSessions/README.md +7 -3
- package/src/realtimeSessions/SessionVerificationPortsBase.ts +1 -0
- package/src/realtimeSessions/ownedRealtimeSession.ts +16 -6
- package/src/realtimeSessions/sessionAccess.ts +211 -25
- package/src/realtimeSessions/sessionConfigStamps.ts +1 -1
- package/src/realtimeSessions/subscriptionAuthorization.ts +4 -2
- package/src/realtimeSessions/verificationWorkflow.ts +3 -1
- package/src/realtimeWidget/WidgetRouter.ts +22 -4
- package/src/realtimeWidget/WidgetSessionService.ts +254 -17
- package/src/realtimeWidget/host-identity.ts +1 -1
- package/src/realtimeWidget/visitorIdentity.ts +1 -0
- package/src/realtimeWidget/widgetCore.ts +34 -9
- package/src/realtimeWidget/widgetGuestElevation.ts +3 -1
- package/src/requestOrigin.ts +64 -0
- package/src/resolvers/ActionResolver.ts +78 -15
- package/src/resolvers/AdhocQueryResolver.ts +1 -0
- package/src/resolvers/AgentRunStatusPublisher.ts +36 -8
- package/src/resolvers/AgentSessionResolver.ts +50 -18
- package/src/resolvers/AutotagPipelineResolver.ts +2 -1
- package/src/resolvers/ConversationRunEventsResolver.ts +2 -0
- package/src/resolvers/EntityCommunicationsResolver.ts +56 -15
- package/src/resolvers/ExecuteRemoteOperationResolver.ts +41 -9
- package/src/resolvers/FetchEntityVectorsResolver.ts +132 -21
- package/src/resolvers/FileCategoryResolver.ts +1 -0
- package/src/resolvers/FileResolver.ts +14 -4
- package/src/resolvers/GetDataResolver.ts +35 -13
- package/src/resolvers/IntegrationDiscoveryResolver.ts +1570 -209
- package/src/resolvers/MCPResolver.ts +15 -2
- package/src/resolvers/MergeRecordsResolver.ts +23 -2
- package/src/resolvers/PipelineProgressResolver.ts +12 -3
- package/src/resolvers/QueryResolver.ts +20 -6
- package/src/resolvers/QuerySystemUserResolver.ts +207 -99
- package/src/resolvers/RSUResolver.ts +12 -0
- package/src/resolvers/RealtimeBridgeResolver.ts +1 -0
- package/src/resolvers/RealtimeClientSessionResolver.ts +144 -40
- package/src/resolvers/RemoteBrowserActionResolver.ts +252 -37
- package/src/resolvers/RunAIAgentResolver.ts +518 -163
- package/src/resolvers/RunAIPromptResolver.ts +18 -18
- package/src/resolvers/RunTemplateResolver.ts +9 -5
- package/src/resolvers/RunTestResolver.ts +3 -1
- package/src/resolvers/SyncDataResolver.ts +4 -0
- package/src/resolvers/TestQuerySQLResolver.ts +1 -0
- package/src/resolvers/TransactionGroupResolver.ts +66 -15
- package/src/resolvers/UserViewResolver.ts +2 -1
- package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +52 -0
- package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +43 -0
- package/src/resolvers/meetingRecordingRegistration.ts +2 -0
- package/src/rest/EntityCRUDHandler.ts +22 -5
- package/src/rest/MediaAccessKeys.ts +6 -2
- package/src/rest/OAuthCallbackHandler.ts +13 -5
- package/src/rest/RESTEndpointHandler.ts +8 -5
- package/src/rest/RealtimeRecordingHandler.ts +9 -10
- package/src/rest/ViewOperationsHandler.ts +26 -7
- package/src/rest/setupRESTEndpoints.ts +11 -2
- package/src/serverRoleConfigUnits.ts +48 -0
- package/src/services/DurableEntityActionTaskSubmitter.ts +10 -2
- package/src/services/TaskGraphActionRunner.ts +2 -23
- package/src/services/TaskGraphAgentRunner.ts +43 -0
- package/src/services/TaskGraphContinuationDeliverer.ts +53 -20
- package/src/services/WorkQueueHostService.ts +26 -4
- package/src/services/workQueueConfig.ts +5 -5
- package/src/sharedCache.ts +1 -1
- package/src/types.ts +41 -1
- package/src/services/TaskOrchestration-Integration.md +0 -188
|
@@ -90,7 +90,7 @@ function bootCoreRoutes(): { app: Application; paths: string[] } {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
async function statusOf(app: Application, path: string): Promise<number> {
|
|
93
|
-
const server = app.listen(0);
|
|
93
|
+
const server = app.listen(0, '127.0.0.1');
|
|
94
94
|
try {
|
|
95
95
|
await new Promise<void>((resolve) => server.once('listening', () => resolve()));
|
|
96
96
|
const { port } = server.address() as AddressInfo;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config contract for the two background sweeps an idle MJAPI runs against its database: the AI
|
|
3
|
+
* Agent Session janitor (`agentSessions.janitor`) and the agent-run watchdog (`agentRunWatchdog`).
|
|
4
|
+
*
|
|
5
|
+
* Pins three things: the shipped defaults are exactly the values MJAPI always ran with (so existing
|
|
6
|
+
* deployments see no change), each sweep can be turned off the documented way, and the env-var
|
|
7
|
+
* readers that feed `DEFAULT_SERVER_CONFIG` reject typos instead of silently running a default or
|
|
8
|
+
* a zero-delay timer.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect } from 'vitest';
|
|
11
|
+
import {
|
|
12
|
+
AgentRunWatchdogDefaultsFromEnv,
|
|
13
|
+
AgentRunWatchdogSchema,
|
|
14
|
+
AgentSessionsDefaultsFromEnv,
|
|
15
|
+
AgentSessionsSchema,
|
|
16
|
+
ConversationDetailReconcilerDefaultsFromEnv,
|
|
17
|
+
ConversationDetailReconcilerSchema,
|
|
18
|
+
EnabledFromEnv,
|
|
19
|
+
IntervalMsFromEnv,
|
|
20
|
+
} from '../backgroundSweepConfigUnits.js';
|
|
21
|
+
|
|
22
|
+
describe('agentSessions.janitor schema', () => {
|
|
23
|
+
it('defaults to what MJAPI has always run: janitor on every 60s (15-minute idle close), bridge reconcile on every 10 min', () => {
|
|
24
|
+
expect(AgentSessionsSchema.parse({})).toEqual({
|
|
25
|
+
janitor: { enabled: true, sweepIntervalMs: 60_000, closeThresholdMinutes: 15 },
|
|
26
|
+
bridgeReconciler: { enabled: true, sweepIntervalMs: 600_000 },
|
|
27
|
+
handoffOfferExpiry: { enabled: true, sweepIntervalMs: 15_000 },
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('accepts enabled: false and a longer interval', () => {
|
|
32
|
+
const parsed = AgentSessionsSchema.parse({ janitor: { enabled: false, sweepIntervalMs: 3_600_000 }, bridgeReconciler: { enabled: false } });
|
|
33
|
+
expect(parsed.janitor).toEqual({ enabled: false, sweepIntervalMs: 3_600_000, closeThresholdMinutes: 15 });
|
|
34
|
+
expect(parsed.bridgeReconciler).toEqual({ enabled: false, sweepIntervalMs: 600_000 });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('rejects a zero or negative interval (turn the tick off with enabled: false instead)', () => {
|
|
38
|
+
expect(AgentSessionsSchema.safeParse({ janitor: { sweepIntervalMs: 0 } }).success).toBe(false);
|
|
39
|
+
expect(AgentSessionsSchema.safeParse({ janitor: { closeThresholdMinutes: -1 } }).success).toBe(false);
|
|
40
|
+
expect(AgentSessionsSchema.safeParse({ bridgeReconciler: { sweepIntervalMs: 0 } }).success).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('conversationDetailReconciler schema', () => {
|
|
45
|
+
it('defaults to what MJAPI has always run: on, every 5 minutes', () => {
|
|
46
|
+
expect(ConversationDetailReconcilerSchema.parse({})).toEqual({ enabled: true, sweepIntervalMs: 300_000 });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('accepts enabled: false and rejects a zero interval', () => {
|
|
50
|
+
expect(ConversationDetailReconcilerSchema.parse({ enabled: false }).enabled).toBe(false);
|
|
51
|
+
expect(ConversationDetailReconcilerSchema.safeParse({ sweepIntervalMs: 0 }).success).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe('DEFAULT_SERVER_CONFIG blocks from the environment', () => {
|
|
56
|
+
it('an empty environment gives exactly the shipped defaults', () => {
|
|
57
|
+
expect(AgentSessionsDefaultsFromEnv({})).toEqual(AgentSessionsSchema.parse({}));
|
|
58
|
+
expect(ConversationDetailReconcilerDefaultsFromEnv({})).toEqual(ConversationDetailReconcilerSchema.parse({}));
|
|
59
|
+
expect(AgentRunWatchdogDefaultsFromEnv({})).toEqual(AgentRunWatchdogSchema.parse({}));
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('reads every documented variable', () => {
|
|
63
|
+
const env = {
|
|
64
|
+
MJ_SESSION_JANITOR_ENABLED: 'false',
|
|
65
|
+
MJ_SESSION_JANITOR_SWEEP_INTERVAL_MS: '120000',
|
|
66
|
+
MJ_BRIDGE_RECONCILER_ENABLED: 'off',
|
|
67
|
+
MJ_BRIDGE_RECONCILER_SWEEP_INTERVAL_MS: '1200000',
|
|
68
|
+
MJ_CONVERSATION_DETAIL_RECONCILER_ENABLED: '0',
|
|
69
|
+
MJ_CONVERSATION_DETAIL_RECONCILER_SWEEP_INTERVAL_MS: '900000',
|
|
70
|
+
MJ_HANDOFF_OFFER_EXPIRY_ENABLED: 'no',
|
|
71
|
+
MJ_HANDOFF_OFFER_EXPIRY_SWEEP_INTERVAL_MS: '60000',
|
|
72
|
+
MJ_AGENT_RUN_WATCHDOG_SWEEP_INTERVAL_MS: '0',
|
|
73
|
+
};
|
|
74
|
+
expect(AgentSessionsDefaultsFromEnv(env)).toEqual({
|
|
75
|
+
janitor: { enabled: false, sweepIntervalMs: 120_000, closeThresholdMinutes: 15 },
|
|
76
|
+
bridgeReconciler: { enabled: false, sweepIntervalMs: 1_200_000 },
|
|
77
|
+
handoffOfferExpiry: { enabled: false, sweepIntervalMs: 60_000 },
|
|
78
|
+
});
|
|
79
|
+
expect(ConversationDetailReconcilerDefaultsFromEnv(env)).toEqual({ enabled: false, sweepIntervalMs: 900_000 });
|
|
80
|
+
expect(AgentRunWatchdogDefaultsFromEnv(env).sweepIntervalMs).toBe(0);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('a bad value fails, naming the variable', () => {
|
|
84
|
+
expect(() => AgentSessionsDefaultsFromEnv({ MJ_BRIDGE_RECONCILER_ENABLED: 'nope' }))
|
|
85
|
+
.toThrow('Invalid MJ_BRIDGE_RECONCILER_ENABLED "nope". Expected true or false.');
|
|
86
|
+
expect(() => ConversationDetailReconcilerDefaultsFromEnv({ MJ_CONVERSATION_DETAIL_RECONCILER_SWEEP_INTERVAL_MS: '0' }))
|
|
87
|
+
.toThrow(/Invalid MJ_CONVERSATION_DETAIL_RECONCILER_SWEEP_INTERVAL_MS "0"/);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('agentRunWatchdog schema', () => {
|
|
92
|
+
it('defaults to the watchdog MJAPI has always run: 5-min sweep, 30s heartbeat, 5-min stale threshold', () => {
|
|
93
|
+
expect(AgentRunWatchdogSchema.parse({})).toEqual({
|
|
94
|
+
sweepIntervalMs: 300_000,
|
|
95
|
+
heartbeatIntervalMs: 30_000,
|
|
96
|
+
staleThresholdMinutes: 5,
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('accepts sweepIntervalMs: 0 (startup sweep only)', () => {
|
|
101
|
+
expect(AgentRunWatchdogSchema.parse({ sweepIntervalMs: 0 }).sweepIntervalMs).toBe(0);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('rejects a zero heartbeat (other instances would force-fail this one\'s runs) and negative values', () => {
|
|
105
|
+
expect(AgentRunWatchdogSchema.safeParse({ heartbeatIntervalMs: 0 }).success).toBe(false);
|
|
106
|
+
expect(AgentRunWatchdogSchema.safeParse({ staleThresholdMinutes: 0 }).success).toBe(false);
|
|
107
|
+
expect(AgentRunWatchdogSchema.safeParse({ sweepIntervalMs: -1 }).success).toBe(false);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('EnabledFromEnv', () => {
|
|
112
|
+
it('returns the fallback when the variable is unset or blank', () => {
|
|
113
|
+
expect(EnabledFromEnv('X', undefined, true)).toBe(true);
|
|
114
|
+
expect(EnabledFromEnv('X', null, false)).toBe(false);
|
|
115
|
+
expect(EnabledFromEnv('X', ' ', true)).toBe(true);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it.each(['false', 'FALSE', '0', 'no', 'off', 'n', 'f'])('%j turns the switch off', value => {
|
|
119
|
+
expect(EnabledFromEnv('X', value, true)).toBe(false);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it.each(['true', '1', 'yes', 'on', 'Y', 't'])('%j turns it on', value => {
|
|
123
|
+
expect(EnabledFromEnv('X', value, false)).toBe(true);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('fails fast on anything else, naming the variable (a typo must not silently turn a sweep off)', () => {
|
|
127
|
+
expect(() => EnabledFromEnv('MJ_SESSION_JANITOR_ENABLED', 'flase', true))
|
|
128
|
+
.toThrow('Invalid MJ_SESSION_JANITOR_ENABLED "flase". Expected true or false.');
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
describe('IntervalMsFromEnv', () => {
|
|
133
|
+
it('returns the fallback when the variable is unset or blank', () => {
|
|
134
|
+
expect(IntervalMsFromEnv('X', undefined, 60_000, false)).toBe(60_000);
|
|
135
|
+
expect(IntervalMsFromEnv('X', '', 60_000, false)).toBe(60_000);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('reads a number of milliseconds', () => {
|
|
139
|
+
expect(IntervalMsFromEnv('X', ' 3600000 ', 60_000, false)).toBe(3_600_000);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('accepts 0 only where 0 means off', () => {
|
|
143
|
+
expect(IntervalMsFromEnv('MJ_AGENT_RUN_WATCHDOG_SWEEP_INTERVAL_MS', '0', 300_000, true)).toBe(0);
|
|
144
|
+
expect(() => IntervalMsFromEnv('MJ_SESSION_JANITOR_SWEEP_INTERVAL_MS', '0', 60_000, false))
|
|
145
|
+
.toThrow('Invalid MJ_SESSION_JANITOR_SWEEP_INTERVAL_MS "0". Expected a number of milliseconds greater than 0.');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('fails fast on a typo, naming the variable', () => {
|
|
149
|
+
expect(() => IntervalMsFromEnv('MJ_AGENT_RUN_WATCHDOG_SWEEP_INTERVAL_MS', '5m', 300_000, true))
|
|
150
|
+
.toThrow('Invalid MJ_AGENT_RUN_WATCHDOG_SWEEP_INTERVAL_MS "5m". Expected a number of milliseconds, 0 or greater.');
|
|
151
|
+
expect(() => IntervalMsFromEnv('X', '-5', 60_000, true)).toThrow(/Invalid X/);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { UserInfo } from '@memberjunction/core';
|
|
3
|
+
import type jwt from 'jsonwebtoken';
|
|
4
|
+
|
|
5
|
+
vi.mock('../config.js', () => ({
|
|
6
|
+
userEmailMap: {},
|
|
7
|
+
apiKey: 'test-api-key',
|
|
8
|
+
mj_core_schema: '__mj',
|
|
9
|
+
configInfo: {},
|
|
10
|
+
}));
|
|
11
|
+
vi.mock('../auth/index.js', () => ({
|
|
12
|
+
GetSigningKeys: vi.fn(),
|
|
13
|
+
GetSystemUser: vi.fn(),
|
|
14
|
+
GetValidationOptions: vi.fn(),
|
|
15
|
+
VerifyUserRecord: vi.fn(),
|
|
16
|
+
ExtractUserInfoFromPayload: vi.fn(),
|
|
17
|
+
}));
|
|
18
|
+
vi.mock('../util.js', () => ({
|
|
19
|
+
GetReadOnlyDataSource: vi.fn(),
|
|
20
|
+
GetReadWriteDataSource: vi.fn(),
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
import { BuildMagicLinkSessionUser } from '../context.js';
|
|
24
|
+
|
|
25
|
+
const uuid = (a: string, b: string) =>
|
|
26
|
+
[a.repeat(8), b.repeat(4), '4' + b.repeat(3), '8' + b.repeat(3), b.repeat(12)].join('-');
|
|
27
|
+
const ANON_USER_ID = uuid('A', '0');
|
|
28
|
+
const NAMED_USER_ID = uuid('B', '1');
|
|
29
|
+
|
|
30
|
+
function makeUserRecord(id: string, email: string): UserInfo {
|
|
31
|
+
return new UserInfo(null, {
|
|
32
|
+
ID: id,
|
|
33
|
+
Name: 'Session Test User',
|
|
34
|
+
Email: email,
|
|
35
|
+
IsActive: true,
|
|
36
|
+
Type: 'User',
|
|
37
|
+
UserRoles: [],
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('BuildMagicLinkSessionUser', () => {
|
|
42
|
+
it('sets AnonymousVisitorID from mj_sid for an anonymous magic-link token', () => {
|
|
43
|
+
const baseUser = makeUserRecord(ANON_USER_ID, 'anonymous@magic-link.local');
|
|
44
|
+
const payload: jwt.JwtPayload = {
|
|
45
|
+
mj_magic_link: true,
|
|
46
|
+
mj_anon: true,
|
|
47
|
+
mj_sid: 'sid-visitor-123',
|
|
48
|
+
mj_scopes: [{ inviteId: 'inv-1', appId: 'app-1', role: 'Widget Guest', resourceId: 'res-shared' }],
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const result = BuildMagicLinkSessionUser(baseUser, payload);
|
|
52
|
+
|
|
53
|
+
expect(result).not.toBe(baseUser);
|
|
54
|
+
expect(result.IsMagicLinkAnonymous).toBe(true);
|
|
55
|
+
expect(result.AnonymousVisitorID).toBe('sid-visitor-123');
|
|
56
|
+
expect(result.MagicLinkScope?.ResourceID).toBe('res-shared');
|
|
57
|
+
expect(baseUser.AnonymousVisitorID).toBeUndefined();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('rejects an anonymous magic-link token without mj_sid', () => {
|
|
61
|
+
const baseUser = makeUserRecord(ANON_USER_ID, 'anonymous@magic-link.local');
|
|
62
|
+
const missingSid: jwt.JwtPayload = {
|
|
63
|
+
mj_magic_link: true,
|
|
64
|
+
mj_anon: true,
|
|
65
|
+
mj_scopes: [{ inviteId: 'inv-1', appId: 'app-1', role: 'Widget Guest', resourceId: 'res-shared' }],
|
|
66
|
+
};
|
|
67
|
+
const blankSid: jwt.JwtPayload = {
|
|
68
|
+
mj_magic_link: true,
|
|
69
|
+
mj_anon: true,
|
|
70
|
+
mj_sid: ' ',
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
expect(() => BuildMagicLinkSessionUser(baseUser, missingSid)).toThrow(/mj_sid/);
|
|
74
|
+
expect(() => BuildMagicLinkSessionUser(baseUser, blankSid)).toThrow(/mj_sid/);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('leaves AnonymousVisitorID undefined for a named magic-link token (with or without resource scope)', () => {
|
|
78
|
+
const baseUser = makeUserRecord(NAMED_USER_ID, 'named@example.com');
|
|
79
|
+
const unscopedNamed: jwt.JwtPayload = {
|
|
80
|
+
mj_magic_link: true,
|
|
81
|
+
mj_scopes: [{ inviteId: 'inv-named', appId: 'app-1', role: 'UI' }],
|
|
82
|
+
};
|
|
83
|
+
const scopedNamed: jwt.JwtPayload = {
|
|
84
|
+
mj_magic_link: true,
|
|
85
|
+
mj_scopes: [{ inviteId: 'inv-named-2', appId: 'app-1', role: 'UI', resourceId: 'res-named-1', resourceType: 'Report' }],
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const unscopedResult = BuildMagicLinkSessionUser(baseUser, unscopedNamed);
|
|
89
|
+
expect(unscopedResult.AnonymousVisitorID).toBeUndefined();
|
|
90
|
+
|
|
91
|
+
const scopedResult = BuildMagicLinkSessionUser(baseUser, scopedNamed);
|
|
92
|
+
expect(scopedResult.IsMagicLinkAnonymous).toBe(false);
|
|
93
|
+
expect(scopedResult.MagicLinkScope?.ResourceID).toBe('res-named-1');
|
|
94
|
+
expect(scopedResult.AnonymousVisitorID).toBeUndefined();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
3
|
+
import type { EntityInfo, UserInfo } from '@memberjunction/core';
|
|
4
|
+
import type { PubSubEngine } from 'type-graphql';
|
|
5
|
+
import {
|
|
6
|
+
AzureWebPubSubBroadcastProvider,
|
|
7
|
+
AWSIoTCoreBroadcastProvider,
|
|
8
|
+
CacheInvalidationBroadcastManager,
|
|
9
|
+
GCPPubSubBroadcastProvider,
|
|
10
|
+
SequencedRoleBucketBroadcastProvider,
|
|
11
|
+
type AzureWebPubSubGroupMessage,
|
|
12
|
+
type AWSIoTCoreTopicMessage,
|
|
13
|
+
type GCPPubSubTopicMessage,
|
|
14
|
+
} from '../broadcast/index.js';
|
|
15
|
+
import type { CacheInvalidationPayload } from '../generic/CacheInvalidationResolver.js';
|
|
16
|
+
import {
|
|
17
|
+
GetSessionStatusTopic,
|
|
18
|
+
PUSH_STATUS_UPDATES_TOPIC,
|
|
19
|
+
ParseStatusUpdateMessage,
|
|
20
|
+
PublishStatusUpdate,
|
|
21
|
+
ShouldReplicateStatusUpdate,
|
|
22
|
+
type PushStatusNotificationPayload,
|
|
23
|
+
} from '../generic/PushStatusResolver.js';
|
|
24
|
+
import { CreateSessionRoutingPubSub, PubSubManager } from '../generic/PubSubManager.js';
|
|
25
|
+
import {
|
|
26
|
+
ResolveServerRole,
|
|
27
|
+
ShouldRunBackgroundWorkers,
|
|
28
|
+
ShouldServeInteractiveTraffic,
|
|
29
|
+
} from '../serverRoleConfigUnits.js';
|
|
30
|
+
|
|
31
|
+
function makeUser(id: string, roleIds: string[]): UserInfo {
|
|
32
|
+
return {
|
|
33
|
+
ID: id,
|
|
34
|
+
Name: `User ${id}`,
|
|
35
|
+
Email: `${id}@example.com`,
|
|
36
|
+
UserRoles: roleIds.map((r) => ({ UserID: id, RoleID: r, RoleName: r })),
|
|
37
|
+
} as unknown as UserInfo;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function makePayload(overrides: Partial<CacheInvalidationPayload> = {}): CacheInvalidationPayload {
|
|
41
|
+
return {
|
|
42
|
+
entityName: 'Invoices',
|
|
43
|
+
primaryKeyValues: '[{"FieldName":"ID","Value":"inv-1"}]',
|
|
44
|
+
action: 'save',
|
|
45
|
+
sourceServerId: 'srv-1',
|
|
46
|
+
timestamp: new Date('2026-10-20T12:00:00Z'),
|
|
47
|
+
recordData: '{"ID":"inv-1","Total":500}',
|
|
48
|
+
...overrides,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
describe('CacheInvalidationBroadcastManager & SequencedRoleBucketBroadcastProvider (Topologies 1 & 2)', () => {
|
|
53
|
+
let provider: SequencedRoleBucketBroadcastProvider;
|
|
54
|
+
|
|
55
|
+
beforeEach(() => {
|
|
56
|
+
provider = CacheInvalidationBroadcastManager.Instance.Configure({
|
|
57
|
+
provider: 'SequencedRoleBucket',
|
|
58
|
+
ringBufferSize: 5,
|
|
59
|
+
excludedEntities: ['MJ: Audit Logs'],
|
|
60
|
+
}) as SequencedRoleBucketBroadcastProvider;
|
|
61
|
+
provider.ResetStateForTesting();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('defaults to SequencedRoleBucket and stamps monotonically increasing sequences', () => {
|
|
65
|
+
expect(provider.Topology).toBe('SequencedRoleBucket');
|
|
66
|
+
expect(provider.CurrentSequence).toBe(0);
|
|
67
|
+
|
|
68
|
+
const p1 = provider.RecordInvalidation(makePayload({ primaryKeyValues: 'pk-1' }));
|
|
69
|
+
const p2 = provider.RecordInvalidation(makePayload({ primaryKeyValues: 'pk-2' }));
|
|
70
|
+
|
|
71
|
+
expect(p1.sequence).toBe(1);
|
|
72
|
+
expect(p2.sequence).toBe(2);
|
|
73
|
+
expect(provider.CurrentSequence).toBe(2);
|
|
74
|
+
expect(provider.BufferedEventCount).toBe(2);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('suppresses excluded high-churn entities from sequencing and broadcast', () => {
|
|
78
|
+
expect(provider.ShouldBroadcastEntity('MJ: Audit Logs')).toBe(false);
|
|
79
|
+
expect(provider.ShouldBroadcastEntity('Invoices')).toBe(true);
|
|
80
|
+
|
|
81
|
+
const ignored = provider.RecordInvalidation(makePayload({ entityName: 'MJ: Audit Logs' }));
|
|
82
|
+
expect(ignored.sequence).toBeUndefined();
|
|
83
|
+
expect(provider.CurrentSequence).toBe(0);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('computes canonical, order-independent role fingerprints and memoizes per user object', () => {
|
|
87
|
+
const u1 = makeUser('u1', ['Role-B', 'role-a']);
|
|
88
|
+
const u2 = makeUser('u2', ['ROLE-A', ' role-b ']);
|
|
89
|
+
|
|
90
|
+
const fp1 = provider.GetRoleFingerprint(u1);
|
|
91
|
+
const fp2 = provider.GetRoleFingerprint(u2);
|
|
92
|
+
|
|
93
|
+
expect(fp1).toBe('roles:role-a|role-b');
|
|
94
|
+
expect(fp2).toBe('roles:role-a|role-b');
|
|
95
|
+
// Second call hits WeakMap cache
|
|
96
|
+
expect(provider.GetRoleFingerprint(u1)).toBe(fp1);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('coalesces permission & RLS evaluation to O(Roles) instead of O(Subscribers)', () => {
|
|
100
|
+
const getUserPermisionsSpy = vi.fn((user: UserInfo) => {
|
|
101
|
+
const hasDeniedOnly = user.UserRoles.every((r) => r.RoleID === 'role-none');
|
|
102
|
+
return { CanRead: !hasDeniedOnly };
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const fakeEntity = {
|
|
106
|
+
Name: 'Invoices',
|
|
107
|
+
GetUserPermisions: getUserPermisionsSpy,
|
|
108
|
+
Permissions: [
|
|
109
|
+
{ RoleID: 'role-open', CanRead: true, Type: 'Allow', ReadRLSFilterID: null },
|
|
110
|
+
{ RoleID: 'role-rls', CanRead: true, Type: 'Allow', ReadRLSFilterID: 'rls-filter-1' },
|
|
111
|
+
{ RoleID: 'role-none', CanRead: false, Type: 'Allow', ReadRLSFilterID: null },
|
|
112
|
+
],
|
|
113
|
+
} as unknown as EntityInfo;
|
|
114
|
+
|
|
115
|
+
vi.spyOn(provider, 'ResolveEntityForPayload').mockReturnValue(fakeEntity);
|
|
116
|
+
const rlsSpy = vi.spyOn(provider, 'ReadIsRowFiltered');
|
|
117
|
+
|
|
118
|
+
const payload = makePayload();
|
|
119
|
+
|
|
120
|
+
// Create 300 subscribers across only 3 distinct role buckets (100 per bucket)
|
|
121
|
+
const openUsers = Array.from({ length: 100 }, (_, i) => makeUser(`open-${i}`, ['role-open']));
|
|
122
|
+
const rlsUsers = Array.from({ length: 100 }, (_, i) => makeUser(`rls-${i}`, ['role-rls']));
|
|
123
|
+
const deniedUsers = Array.from({ length: 100 }, (_, i) => makeUser(`denied-${i}`, ['role-none']));
|
|
124
|
+
|
|
125
|
+
for (const u of openUsers) {
|
|
126
|
+
expect(provider.EvaluateEntityReadAccess(payload, u)).toBe(true);
|
|
127
|
+
const shaped = provider.ShapeEventForSubscriber(payload, u, fakeEntity);
|
|
128
|
+
expect(shaped.PrimaryKeyValues).toBe(payload.primaryKeyValues);
|
|
129
|
+
expect(shaped.RecordData).toBe(payload.recordData);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
for (const u of rlsUsers) {
|
|
133
|
+
expect(provider.EvaluateEntityReadAccess(payload, u)).toBe(true);
|
|
134
|
+
const shaped = provider.ShapeEventForSubscriber(payload, u, fakeEntity);
|
|
135
|
+
expect(shaped.PrimaryKeyValues).toBeUndefined();
|
|
136
|
+
expect(shaped.RecordData).toBeUndefined();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
for (const u of deniedUsers) {
|
|
140
|
+
expect(provider.EvaluateEntityReadAccess(payload, u)).toBe(false);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Despite 300 subscribers, GetUserPermisions ran only 3 times (once per unique role bucket)
|
|
144
|
+
// and ReadIsRowFiltered ran only 2 times (for the 2 allowed role buckets)!
|
|
145
|
+
expect(getUserPermisionsSpy).toHaveBeenCalledTimes(3);
|
|
146
|
+
expect(rlsSpy).toHaveBeenCalledTimes(2);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('serves delta catch-up from the circular ring buffer and coalesces duplicate PK updates', () => {
|
|
150
|
+
const fakeEntity = {
|
|
151
|
+
Name: 'Invoices',
|
|
152
|
+
GetUserPermisions: () => ({ CanRead: true }),
|
|
153
|
+
Permissions: [{ RoleID: 'role-open', CanRead: true, Type: 'Allow', ReadRLSFilterID: null }],
|
|
154
|
+
} as unknown as EntityInfo;
|
|
155
|
+
vi.spyOn(provider, 'ResolveEntityForPayload').mockReturnValue(fakeEntity);
|
|
156
|
+
|
|
157
|
+
const user = makeUser('u1', ['role-open']);
|
|
158
|
+
|
|
159
|
+
// Record 4 events (two on inv-1, one on inv-2, one on inv-1 again)
|
|
160
|
+
provider.RecordInvalidation(makePayload({ primaryKeyValues: 'inv-1', recordData: '{"v":1}' })); // seq 1
|
|
161
|
+
provider.RecordInvalidation(makePayload({ primaryKeyValues: 'inv-2', recordData: '{"v":2}' })); // seq 2
|
|
162
|
+
provider.RecordInvalidation(makePayload({ primaryKeyValues: 'inv-1', recordData: '{"v":3}' })); // seq 3
|
|
163
|
+
|
|
164
|
+
const catchUp = provider.GetChangesSince(0, user);
|
|
165
|
+
expect(catchUp.RequiresFullRefresh).toBe(false);
|
|
166
|
+
expect(catchUp.CurrentSequence).toBe(3);
|
|
167
|
+
// inv-1 (seq 1 and seq 3) coalesced to latest (seq 3), so 2 events total
|
|
168
|
+
expect(catchUp.Events).toHaveLength(2);
|
|
169
|
+
const inv1Event = catchUp.Events.find((e) => e.PrimaryKeyValues === 'inv-1');
|
|
170
|
+
expect(inv1Event?.RecordData).toBe('{"v":3}');
|
|
171
|
+
expect(inv1Event?.Sequence).toBe(3);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('signals RequiresFullRefresh when sinceSequence has been evicted from the circular ring buffer', () => {
|
|
175
|
+
const fakeEntity = {
|
|
176
|
+
Name: 'Invoices',
|
|
177
|
+
GetUserPermisions: () => ({ CanRead: true }),
|
|
178
|
+
Permissions: [{ RoleID: 'role-open', CanRead: true, Type: 'Allow', ReadRLSFilterID: null }],
|
|
179
|
+
} as unknown as EntityInfo;
|
|
180
|
+
vi.spyOn(provider, 'ResolveEntityForPayload').mockReturnValue(fakeEntity);
|
|
181
|
+
|
|
182
|
+
const user = makeUser('u1', ['role-open']);
|
|
183
|
+
|
|
184
|
+
// Ring buffer size is 5; push 7 events so sequences 1 and 2 are overwritten (oldest in buffer is 3)
|
|
185
|
+
for (let i = 1; i <= 7; i++) {
|
|
186
|
+
provider.RecordInvalidation(makePayload({ primaryKeyValues: `inv-${i}` }));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Requesting sinceSequence = 1 (missed seq 2, which was evicted) -> RequiresFullRefresh: true
|
|
190
|
+
const evictedCatchUp = provider.GetChangesSince(1, user);
|
|
191
|
+
expect(evictedCatchUp.RequiresFullRefresh).toBe(true);
|
|
192
|
+
expect(evictedCatchUp.Events).toHaveLength(0);
|
|
193
|
+
|
|
194
|
+
// Requesting sinceSequence = 2 (oldest needed is seq 3, still in buffer) -> RequiresFullRefresh: false
|
|
195
|
+
const validCatchUp = provider.GetChangesSince(2, user);
|
|
196
|
+
expect(validCatchUp.RequiresFullRefresh).toBe(false);
|
|
197
|
+
expect(validCatchUp.Events).toHaveLength(5);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
describe('Topology 3 Cloud Multiplexer Providers (AzureWebPubSub, AWSIoTCore, GCPPubSub)', () => {
|
|
202
|
+
afterEach(() => {
|
|
203
|
+
CacheInvalidationBroadcastManager.Instance.Configure({ provider: 'SequencedRoleBucket' });
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('AzureWebPubSubBroadcastProvider negotiates signed JWT URLs and publishes role-shaped group messages', async () => {
|
|
207
|
+
const azureProvider = CacheInvalidationBroadcastManager.Instance.Configure({
|
|
208
|
+
provider: 'AzureWebPubSub',
|
|
209
|
+
azureWebPubSub: {
|
|
210
|
+
endpoint: 'https://mj-test.webpubsub.azure.com',
|
|
211
|
+
hubName: 'mj_hub',
|
|
212
|
+
accessKey: 'test-secret-access-key-123456',
|
|
213
|
+
tokenTtlMinutes: 30,
|
|
214
|
+
},
|
|
215
|
+
}) as AzureWebPubSubBroadcastProvider;
|
|
216
|
+
|
|
217
|
+
expect(azureProvider).toBeInstanceOf(AzureWebPubSubBroadcastProvider);
|
|
218
|
+
expect(azureProvider.Topology).toBe('AzureWebPubSub');
|
|
219
|
+
|
|
220
|
+
const user = makeUser('u-azure', ['Role-Admin', 'Role-Finance']);
|
|
221
|
+
const negotiated = await azureProvider.NegotiateClientConnection(user);
|
|
222
|
+
expect(negotiated.Provider).toBe('AzureWebPubSub');
|
|
223
|
+
expect(negotiated.Url).toContain('wss://mj-test.webpubsub.azure.com/client/hubs/mj_hub?access_token=');
|
|
224
|
+
expect(negotiated.Token).toBeDefined();
|
|
225
|
+
expect(negotiated.Groups).toEqual(['mj-role-role-admin', 'mj-role-role-finance']);
|
|
226
|
+
|
|
227
|
+
const published: AzureWebPubSubGroupMessage[] = [];
|
|
228
|
+
azureProvider.SetGroupPublisher(async (msg) => {
|
|
229
|
+
published.push(msg);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const fakeEntity = {
|
|
233
|
+
Name: 'Invoices',
|
|
234
|
+
GetUserPermisions: () => ({ CanRead: true }),
|
|
235
|
+
Permissions: [
|
|
236
|
+
{ RoleID: 'role-admin', CanRead: true, Type: 'Allow', ReadRLSFilterID: null },
|
|
237
|
+
{ RoleID: 'role-rls', CanRead: true, Type: 'Allow', ReadRLSFilterID: 'rls-1' },
|
|
238
|
+
],
|
|
239
|
+
} as unknown as EntityInfo;
|
|
240
|
+
vi.spyOn(azureProvider, 'ResolveEntityForPayload').mockReturnValue(fakeEntity);
|
|
241
|
+
|
|
242
|
+
azureProvider.RecordInvalidation(makePayload());
|
|
243
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
244
|
+
|
|
245
|
+
expect(published).toHaveLength(2);
|
|
246
|
+
const adminMsg = published.find((m) => m.GroupName === 'mj-role-role-admin');
|
|
247
|
+
const rlsMsg = published.find((m) => m.GroupName === 'mj-role-role-rls');
|
|
248
|
+
expect(adminMsg?.Event.PrimaryKeyValues).toBeDefined();
|
|
249
|
+
expect(rlsMsg?.Event.PrimaryKeyValues).toBeUndefined();
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('AWSIoTCoreBroadcastProvider negotiates SigV4 presigned MQTT URLs and publishes role topics', async () => {
|
|
253
|
+
const awsProvider = CacheInvalidationBroadcastManager.Instance.Configure({
|
|
254
|
+
provider: 'AWSIoTCore',
|
|
255
|
+
awsIoTCore: {
|
|
256
|
+
endpoint: 'a1b2c3-ats.iot.us-east-1.amazonaws.com',
|
|
257
|
+
region: 'us-east-1',
|
|
258
|
+
topicPrefix: 'mj/prod/cache',
|
|
259
|
+
accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
|
|
260
|
+
secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
|
|
261
|
+
},
|
|
262
|
+
}) as AWSIoTCoreBroadcastProvider;
|
|
263
|
+
|
|
264
|
+
expect(awsProvider).toBeInstanceOf(AWSIoTCoreBroadcastProvider);
|
|
265
|
+
const user = makeUser('u-aws', ['role-ops']);
|
|
266
|
+
const negotiated = await awsProvider.NegotiateClientConnection(user);
|
|
267
|
+
expect(negotiated.Provider).toBe('AWSIoTCore');
|
|
268
|
+
expect(negotiated.Url).toContain('wss://a1b2c3-ats.iot.us-east-1.amazonaws.com/mqtt?X-Amz-Algorithm=AWS4-HMAC-SHA256');
|
|
269
|
+
expect(negotiated.Groups).toEqual(['mj/prod/cache/roles/role-ops']);
|
|
270
|
+
|
|
271
|
+
const published: AWSIoTCoreTopicMessage[] = [];
|
|
272
|
+
awsProvider.SetTopicPublisher(async (msg) => {
|
|
273
|
+
published.push(msg);
|
|
274
|
+
});
|
|
275
|
+
const fakeEntity = {
|
|
276
|
+
Name: 'Invoices',
|
|
277
|
+
GetUserPermisions: () => ({ CanRead: true }),
|
|
278
|
+
Permissions: [{ RoleID: 'role-ops', CanRead: true, Type: 'Allow', ReadRLSFilterID: null }],
|
|
279
|
+
} as unknown as EntityInfo;
|
|
280
|
+
vi.spyOn(awsProvider, 'ResolveEntityForPayload').mockReturnValue(fakeEntity);
|
|
281
|
+
|
|
282
|
+
awsProvider.RecordInvalidation(makePayload());
|
|
283
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
284
|
+
expect(published).toHaveLength(1);
|
|
285
|
+
expect(published[0].Topic).toBe('mj/prod/cache/roles/role-ops');
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('GCPPubSubBroadcastProvider negotiates gateway tokens and publishes Pub/Sub topic messages', async () => {
|
|
289
|
+
const gcpProvider = CacheInvalidationBroadcastManager.Instance.Configure({
|
|
290
|
+
provider: 'GCPPubSub',
|
|
291
|
+
gcpPubSub: {
|
|
292
|
+
projectId: 'mj-cloud-prod',
|
|
293
|
+
topicPrefix: 'mj-invalidation',
|
|
294
|
+
gatewayUrl: 'https://cache-gw.run.app/ws',
|
|
295
|
+
signingSecret: 'gcp-gateway-secret-key',
|
|
296
|
+
},
|
|
297
|
+
}) as GCPPubSubBroadcastProvider;
|
|
298
|
+
|
|
299
|
+
expect(gcpProvider).toBeInstanceOf(GCPPubSubBroadcastProvider);
|
|
300
|
+
const user = makeUser('u-gcp', ['role-analyst']);
|
|
301
|
+
const negotiated = await gcpProvider.NegotiateClientConnection(user);
|
|
302
|
+
expect(negotiated.Provider).toBe('GCPPubSub');
|
|
303
|
+
expect(negotiated.Url).toContain('wss://cache-gw.run.app/ws?token=');
|
|
304
|
+
expect(negotiated.Groups).toEqual(['projects/mj-cloud-prod/topics/mj-invalidation-role-role-analyst']);
|
|
305
|
+
|
|
306
|
+
const published: GCPPubSubTopicMessage[] = [];
|
|
307
|
+
gcpProvider.SetTopicPublisher(async (msg) => {
|
|
308
|
+
published.push(msg);
|
|
309
|
+
});
|
|
310
|
+
const fakeEntity = {
|
|
311
|
+
Name: 'Invoices',
|
|
312
|
+
GetUserPermisions: () => ({ CanRead: true }),
|
|
313
|
+
Permissions: [{ RoleID: 'role-analyst', CanRead: true, Type: 'Allow', ReadRLSFilterID: null }],
|
|
314
|
+
} as unknown as EntityInfo;
|
|
315
|
+
vi.spyOn(gcpProvider, 'ResolveEntityForPayload').mockReturnValue(fakeEntity);
|
|
316
|
+
|
|
317
|
+
gcpProvider.RecordInvalidation(makePayload());
|
|
318
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
319
|
+
expect(published).toHaveLength(1);
|
|
320
|
+
expect(published[0].TopicName).toBe('projects/mj-cloud-prod/topics/mj-invalidation-role-role-analyst');
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
describe('PushStatusResolver O(1) session routing and WeakMap JSON memoization', () => {
|
|
325
|
+
it('routes session-specific updates to PUSH_STATUS_UPDATES:session:<id> and wildcard updates to PUSH_STATUS_UPDATES', async () => {
|
|
326
|
+
const rawPublish = vi.fn(async () => undefined);
|
|
327
|
+
const rawPubSub: PubSubEngine = {
|
|
328
|
+
publish: rawPublish,
|
|
329
|
+
subscribe: vi.fn(),
|
|
330
|
+
unsubscribe: vi.fn(),
|
|
331
|
+
asyncIterator: vi.fn(),
|
|
332
|
+
} as unknown as PubSubEngine;
|
|
333
|
+
|
|
334
|
+
PubSubManager.Instance.SetPubSubEngine(rawPubSub);
|
|
335
|
+
const routedPubSub = PubSubManager.Instance.PubSubEngine!;
|
|
336
|
+
|
|
337
|
+
PublishStatusUpdate(routedPubSub, {
|
|
338
|
+
sessionId: 'tab-abc',
|
|
339
|
+
ownerUserId: 'user-1',
|
|
340
|
+
message: '{"type":"Progress"}',
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
PublishStatusUpdate(routedPubSub, {
|
|
344
|
+
sessionId: '*',
|
|
345
|
+
ownerUserId: 'user-1',
|
|
346
|
+
message: '{"type":"Broadcast"}',
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
expect(rawPublish).toHaveBeenCalledTimes(2);
|
|
350
|
+
expect(rawPublish).toHaveBeenNthCalledWith(
|
|
351
|
+
1,
|
|
352
|
+
GetSessionStatusTopic('tab-abc'),
|
|
353
|
+
expect.objectContaining({ sessionId: 'tab-abc' })
|
|
354
|
+
);
|
|
355
|
+
expect(rawPublish).toHaveBeenNthCalledWith(
|
|
356
|
+
2,
|
|
357
|
+
PUSH_STATUS_UPDATES_TOPIC,
|
|
358
|
+
expect.objectContaining({ sessionId: '*' })
|
|
359
|
+
);
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
it('memoizes JSON.parse per PushStatusNotificationPayload object via WeakMap', () => {
|
|
363
|
+
const payload: PushStatusNotificationPayload = {
|
|
364
|
+
sessionId: 'tab-1',
|
|
365
|
+
ownerUserId: 'u-1',
|
|
366
|
+
message: JSON.stringify({ type: 'StreamingContent', step: 1 }),
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
const parseSpy = vi.spyOn(JSON, 'parse');
|
|
370
|
+
try {
|
|
371
|
+
const first = ParseStatusUpdateMessage(payload);
|
|
372
|
+
const second = ParseStatusUpdateMessage(payload);
|
|
373
|
+
const shouldReplicate = ShouldReplicateStatusUpdate(payload.message, payload);
|
|
374
|
+
|
|
375
|
+
expect(first).toBe(second);
|
|
376
|
+
expect(shouldReplicate).toBe(false);
|
|
377
|
+
expect(parseSpy).toHaveBeenCalledTimes(1);
|
|
378
|
+
} finally {
|
|
379
|
+
parseSpy.mockRestore();
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
describe('ServerRole configuration units (Pillar 4)', () => {
|
|
385
|
+
it('resolves all, api, and worker roles case-insensitively and defaults to all', () => {
|
|
386
|
+
expect(ResolveServerRole(undefined)).toBe('all');
|
|
387
|
+
expect(ResolveServerRole('')).toBe('all');
|
|
388
|
+
expect(ResolveServerRole(' API ')).toBe('api');
|
|
389
|
+
expect(ResolveServerRole('WORKER')).toBe('worker');
|
|
390
|
+
expect(ResolveServerRole('all')).toBe('all');
|
|
391
|
+
expect(() => ResolveServerRole('invalid-role')).toThrow(/Invalid MJ_SERVER_ROLE/);
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it('correctly gates background workers and interactive traffic by role', () => {
|
|
395
|
+
expect(ShouldRunBackgroundWorkers('all')).toBe(true);
|
|
396
|
+
expect(ShouldRunBackgroundWorkers('worker')).toBe(true);
|
|
397
|
+
expect(ShouldRunBackgroundWorkers('api')).toBe(false);
|
|
398
|
+
|
|
399
|
+
expect(ShouldServeInteractiveTraffic('all')).toBe(true);
|
|
400
|
+
expect(ShouldServeInteractiveTraffic('api')).toBe(true);
|
|
401
|
+
expect(ShouldServeInteractiveTraffic('worker')).toBe(false);
|
|
402
|
+
});
|
|
403
|
+
});
|