@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
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The FIELD rows a schema build materializes, for a connection with its own catalog.
|
|
3
|
+
*
|
|
4
|
+
* A schema build (ApplySchema, ApplyAll, ApplyAllBatch, the connector build, schema evolution)
|
|
5
|
+
* reconstructs the source schema from persisted catalog rows and hands it to SchemaBuilder. It used
|
|
6
|
+
* to read each object's fields from the engine's in-memory catalog. Once a connection's field rows
|
|
7
|
+
* are no longer held resident — they are warmed per object on demand, and the only site that warms
|
|
8
|
+
* them is the sync loop — that read answers `[]` for every object of the connection, and an object
|
|
9
|
+
* with no fields materializes nothing. Observed on a per-connection catalog (364 objects, 7,230
|
|
10
|
+
* active fields): the apply logged "Reusing 364 persisted IOs", then ran a migration with an empty
|
|
11
|
+
* table list in 4 ms — no CREATE, no ALTER, no error.
|
|
12
|
+
*
|
|
13
|
+
* So the build reads the connection's field rows itself: one read per {@link SCOPED_FIELDS_CHUNK}
|
|
14
|
+
* objects, plain rows, bypassing the query cache (an answer cached before discovery's persist is the
|
|
15
|
+
* empty set), and without the row cap (one object can carry thousands of fields). A failed read
|
|
16
|
+
* THROWS: an empty answer here is exactly what produced the zero-table apply.
|
|
17
|
+
*
|
|
18
|
+
* Outside a per-connection scope — or for a connection without its own catalog — this returns
|
|
19
|
+
* `null`, and the build reads the shared catalog from memory exactly as before.
|
|
20
|
+
*/
|
|
21
|
+
import { RunView, type UserInfo } from '@memberjunction/core';
|
|
22
|
+
import type { MJIntegrationObjectFieldEntity } from '@memberjunction/core-entities';
|
|
23
|
+
import {
|
|
24
|
+
IntegrationEngineBase,
|
|
25
|
+
ENTITY_COMPANY_INTEGRATION_OBJECT_FIELDS,
|
|
26
|
+
type CompanyIntegrationObjectFieldRow,
|
|
27
|
+
} from '@memberjunction/integration-engine-base';
|
|
28
|
+
import { CurrentCatalogCI } from '@memberjunction/integration-engine';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* What a schema build — and a refresh's re-key check — reads off a field row. The shared entity and
|
|
32
|
+
* the per-connection row both satisfy it.
|
|
33
|
+
*/
|
|
34
|
+
export type BuildFieldRow = Pick<
|
|
35
|
+
MJIntegrationObjectFieldEntity,
|
|
36
|
+
'Name' | 'DisplayName' | 'Description' | 'Type' | 'IsRequired' | 'AllowsNull' | 'Length' | 'Precision'
|
|
37
|
+
| 'Scale' | 'DefaultValue' | 'IsPrimaryKey' | 'IsUniqueKey' | 'IsReadOnly' | 'RelatedIntegrationObjectID' | 'Status'
|
|
38
|
+
| 'Sequence'
|
|
39
|
+
>;
|
|
40
|
+
|
|
41
|
+
/** A connection's field rows, keyed by lower-cased per-connection object id. */
|
|
42
|
+
export type ScopedBuildFields = Map<string, CompanyIntegrationObjectFieldRow[]>;
|
|
43
|
+
|
|
44
|
+
/** Objects per read. Each read is one `IN (…)` list, so this bounds the filter's length. */
|
|
45
|
+
export const SCOPED_FIELDS_CHUNK = 200;
|
|
46
|
+
|
|
47
|
+
/** A per-connection field row as the database returns it — before the legacy read names are derived. */
|
|
48
|
+
type StoredFieldRow = Omit<CompanyIntegrationObjectFieldRow, 'IntegrationObjectID' | 'RelatedIntegrationObjectID'>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Loads the field rows of the connection in catalog scope for a schema build, or returns `null`
|
|
52
|
+
* when the build should read the shared catalog (no scope, or no per-connection catalog).
|
|
53
|
+
*
|
|
54
|
+
* @throws PER_CONNECTION_FIELDS_UNREADABLE when a read fails — never an empty answer.
|
|
55
|
+
*/
|
|
56
|
+
export async function LoadScopedFieldsForBuild(integrationID: string, user: UserInfo): Promise<ScopedBuildFields | null> {
|
|
57
|
+
const ciID = CurrentCatalogCI();
|
|
58
|
+
if (!ciID) return null;
|
|
59
|
+
const engine = IntegrationEngineBase.Instance;
|
|
60
|
+
if (!engine.HasCompanyIntegrationCatalog(ciID)) return null;
|
|
61
|
+
|
|
62
|
+
const objects = engine.GetActiveIntegrationObjects(integrationID);
|
|
63
|
+
const byObject: ScopedBuildFields = new Map();
|
|
64
|
+
const rv = new RunView();
|
|
65
|
+
for (let i = 0; i < objects.length; i += SCOPED_FIELDS_CHUNK) {
|
|
66
|
+
const chunk = objects.slice(i, i + SCOPED_FIELDS_CHUNK);
|
|
67
|
+
const ids = chunk.map(o => `'${String(o.ID).replace(/'/g, "''")}'`).join(',');
|
|
68
|
+
const res = await rv.RunView<StoredFieldRow>({
|
|
69
|
+
EntityName: ENTITY_COMPANY_INTEGRATION_OBJECT_FIELDS,
|
|
70
|
+
ExtraFilter: `CompanyIntegrationObjectID IN (${ids})`,
|
|
71
|
+
ResultType: 'simple',
|
|
72
|
+
BypassCache: true,
|
|
73
|
+
IgnoreMaxRows: true,
|
|
74
|
+
}, user);
|
|
75
|
+
if (!res?.Success) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
`PER_CONNECTION_FIELDS_UNREADABLE: could not read the field rows of connection ${ciID} ` +
|
|
78
|
+
`(objects ${i + 1}-${i + chunk.length} of ${objects.length}): ${res?.ErrorMessage ?? 'unknown error'}. ` +
|
|
79
|
+
`Refusing to build a schema from an empty field list.`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
for (const row of res.Results ?? []) addRow(byObject, row);
|
|
83
|
+
}
|
|
84
|
+
const rowCount = [...byObject.values()].reduce((n, rows) => n + rows.length, 0);
|
|
85
|
+
console.log(`[LoadScopedFieldsForBuild] connection ${ciID}: ${rowCount} field rows for ${byObject.size} of ${objects.length} active objects`);
|
|
86
|
+
return byObject;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The fields a build reads for one object: the connection's rows when they were loaded, the
|
|
91
|
+
* engine's catalog otherwise. With loaded rows the engine is not consulted at all, so a cold
|
|
92
|
+
* per-connection field cache cannot empty the build.
|
|
93
|
+
*/
|
|
94
|
+
export function FieldsForBuild(objectID: string, scoped: ScopedBuildFields | null | undefined, engine: IntegrationEngineBase): BuildFieldRow[] {
|
|
95
|
+
if (scoped) return scoped.get(String(objectID).trim().toLowerCase()) ?? [];
|
|
96
|
+
return engine.GetIntegrationObjectFields(objectID);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Files one stored row under its object, deriving the two legacy names the build reads
|
|
101
|
+
* (`IntegrationObjectID`, `RelatedIntegrationObjectID`) exactly as the engine's projection does.
|
|
102
|
+
*/
|
|
103
|
+
function addRow(byObject: ScopedBuildFields, row: StoredFieldRow): void {
|
|
104
|
+
const key = String(row.CompanyIntegrationObjectID).trim().toLowerCase();
|
|
105
|
+
const projected: CompanyIntegrationObjectFieldRow = {
|
|
106
|
+
...row,
|
|
107
|
+
IntegrationObjectID: row.CompanyIntegrationObjectID,
|
|
108
|
+
RelatedIntegrationObjectID: row.RelatedCompanyIntegrationObjectID ?? null,
|
|
109
|
+
};
|
|
110
|
+
const bucket = byObject.get(key);
|
|
111
|
+
if (bucket) bucket.push(projected);
|
|
112
|
+
else byObject.set(key, [projected]);
|
|
113
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refuses a schema build whose selected objects produced no target table.
|
|
3
|
+
*
|
|
4
|
+
* `buildTargetConfigs` drops a selected object that is not in the source schema, has no fields or
|
|
5
|
+
* has no primary key, and logs each drop — but every execution caller then built and ran a migration
|
|
6
|
+
* anyway. With nothing accepted that migration is a header-only file: RSU wrote it, opened and merged
|
|
7
|
+
* a PR, ran CodeGen, redeployed Explorer, and the sync "completed" over zero entity maps, every signal
|
|
8
|
+
* green. Seen 2026-10-29 on a PropFuel connection: three selections requested, three dropped as
|
|
9
|
+
* notInSchema, three empty migrations committed.
|
|
10
|
+
*
|
|
11
|
+
* A caller that asked for tables and gets none has failed, and should hear so with the names it asked
|
|
12
|
+
* for and why each was dropped — in the error itself, because an API or UI caller cannot read the
|
|
13
|
+
* server log line that used to be the only place the reasons appeared. Preview is deliberately not
|
|
14
|
+
* gated: an empty preview is an honest answer.
|
|
15
|
+
*/
|
|
16
|
+
import type { TargetTableConfig } from '@memberjunction/integration-schema-builder';
|
|
17
|
+
|
|
18
|
+
/** Why `buildTargetConfigs` left each selected object out. */
|
|
19
|
+
export interface TargetConfigDrops {
|
|
20
|
+
NotInSchema: string[];
|
|
21
|
+
NoFields: string[];
|
|
22
|
+
NoPrimaryKey: string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** How many names one list in the error shows before summarising the rest — the summary log's cap. */
|
|
26
|
+
export const TARGET_CONFIG_NAME_SAMPLE = 5;
|
|
27
|
+
|
|
28
|
+
/** An empty set of drop lists, for `buildTargetConfigs` to fill. */
|
|
29
|
+
export function NewTargetConfigDrops(): TargetConfigDrops {
|
|
30
|
+
return { NotInSchema: [], NoFields: [], NoPrimaryKey: [] };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** `a, b, c, d, e and 163 more` — so a large selection cannot make a multi-KB error. */
|
|
34
|
+
export function SampleNames(names: ReadonlyArray<string>): string {
|
|
35
|
+
const head = names.slice(0, TARGET_CONFIG_NAME_SAMPLE).join(', ');
|
|
36
|
+
const rest = names.length - TARGET_CONFIG_NAME_SAMPLE;
|
|
37
|
+
return rest > 0 ? `${head} and ${rest} more` : head;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Throws `NO_TARGET_TABLES` when objects were selected and none produced a target table.
|
|
42
|
+
*
|
|
43
|
+
* @param drops why each object was dropped; without it the error lists the three possible reasons.
|
|
44
|
+
* @param alreadyCommitted what the caller had already written before the build, for a caller that
|
|
45
|
+
* cannot honestly say "Nothing was applied" (schema evolution persists the catalog and disables the
|
|
46
|
+
* removed objects' maps first).
|
|
47
|
+
*/
|
|
48
|
+
export function AssertTargetConfigs(
|
|
49
|
+
objects: ReadonlyArray<{ SourceObjectName: string }>,
|
|
50
|
+
targetConfigs: ReadonlyArray<TargetTableConfig>,
|
|
51
|
+
sourceType: string,
|
|
52
|
+
drops?: TargetConfigDrops,
|
|
53
|
+
alreadyCommitted?: string,
|
|
54
|
+
): void {
|
|
55
|
+
if (objects.length === 0 || targetConfigs.length > 0) return;
|
|
56
|
+
const reasons = drops ? describeDrops(drops) : '';
|
|
57
|
+
throw new Error(
|
|
58
|
+
`NO_TARGET_TABLES: none of the ${objects.length} selected object(s) for ${sourceType} produced a target table ` +
|
|
59
|
+
`(${SampleNames(objects.map(o => o.SourceObjectName))}). ` +
|
|
60
|
+
(reasons || 'Each was dropped as not in the source schema, without fields, or without a primary key.') +
|
|
61
|
+
` ${alreadyCommitted ?? 'Nothing was applied.'} Re-run discovery for this connection and apply again.`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function describeDrops(drops: TargetConfigDrops): string {
|
|
66
|
+
const parts: string[] = [];
|
|
67
|
+
if (drops.NotInSchema.length > 0) parts.push(`not in the source schema: ${SampleNames(drops.NotInSchema)}`);
|
|
68
|
+
if (drops.NoFields.length > 0) parts.push(`no fields: ${SampleNames(drops.NoFields)}`);
|
|
69
|
+
if (drops.NoPrimaryKey.length > 0) parts.push(`no primary key: ${SampleNames(drops.NoPrimaryKey)}`);
|
|
70
|
+
return parts.length > 0 ? `Dropped as ${parts.join('; ')}.` : '';
|
|
71
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { MiddlewareFn } from 'type-graphql';
|
|
1
|
+
import type { MiddlewareFn, ResolverData } from 'type-graphql';
|
|
2
2
|
import { getMetadataStorage } from 'type-graphql';
|
|
3
|
-
import { getNamedType } from 'graphql';
|
|
4
|
-
import type { GraphQLArgument } from 'graphql';
|
|
3
|
+
import { defaultFieldResolver, getNamedType } from 'graphql';
|
|
4
|
+
import type { GraphQLArgument, GraphQLField, GraphQLObjectType, GraphQLSchema } from 'graphql';
|
|
5
5
|
import { configInfo } from '../config.js';
|
|
6
6
|
import type { AppContext } from '../types.js';
|
|
7
7
|
import { RedactArg } from './secretRedactor.js';
|
|
@@ -191,6 +191,62 @@ export const VariablesLoggingMiddleware: MiddlewareFn<AppContext> = async (actio
|
|
|
191
191
|
/** @deprecated Use {@link VariablesLoggingMiddleware}. */
|
|
192
192
|
export const variablesLoggingMiddleware: MiddlewareFn<AppContext> = VariablesLoggingMiddleware;
|
|
193
193
|
|
|
194
|
+
/**
|
|
195
|
+
* Attaches {@link VariablesLoggingMiddleware} ONLY to root `Query`, `Mutation`, and `Subscription`
|
|
196
|
+
* fields on the compiled GraphQLSchema instead of registering it via TypeGraphQL `globalMiddlewares`.
|
|
197
|
+
*
|
|
198
|
+
* Registering a global middleware in TypeGraphQL wraps every scalar and child field resolver across
|
|
199
|
+
* all 300+ `@ObjectType` entities in an async middleware chain, allocating $O(\text{Rows} \times \text{Fields})$
|
|
200
|
+
* Promises per query even when `logVariables` is false or `info.path.prev !== undefined`.
|
|
201
|
+
* Wrapping only the root operation fields reduces middleware invocations from ~15,000 per 500-row
|
|
202
|
+
* `RunView` response down to 1.
|
|
203
|
+
*/
|
|
204
|
+
export function ApplyRootVariablesLoggingMiddleware(
|
|
205
|
+
schema: GraphQLSchema,
|
|
206
|
+
middleware: MiddlewareFn<AppContext> = VariablesLoggingMiddleware
|
|
207
|
+
): GraphQLSchema {
|
|
208
|
+
const rootTypes: Array<GraphQLObjectType | null | undefined> = [
|
|
209
|
+
schema.getQueryType(),
|
|
210
|
+
schema.getMutationType(),
|
|
211
|
+
schema.getSubscriptionType(),
|
|
212
|
+
];
|
|
213
|
+
|
|
214
|
+
for (const rootType of rootTypes) {
|
|
215
|
+
if (!rootType) continue;
|
|
216
|
+
const fields = rootType.getFields();
|
|
217
|
+
for (const field of Object.values(fields) as Array<GraphQLField<unknown, AppContext>>) {
|
|
218
|
+
if (field.resolve) {
|
|
219
|
+
const originalResolve = field.resolve;
|
|
220
|
+
field.resolve = (root, args, context, info) => {
|
|
221
|
+
const action: ResolverData<AppContext> = {
|
|
222
|
+
root,
|
|
223
|
+
args: args as Record<string, unknown>,
|
|
224
|
+
context,
|
|
225
|
+
info,
|
|
226
|
+
};
|
|
227
|
+
return middleware(action, async () => originalResolve(root, args, context, info));
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
if (field.subscribe) {
|
|
231
|
+
const originalSubscribe = field.subscribe;
|
|
232
|
+
field.subscribe = (root, args, context, info) => {
|
|
233
|
+
const action: ResolverData<AppContext> = {
|
|
234
|
+
root,
|
|
235
|
+
args: args as Record<string, unknown>,
|
|
236
|
+
context,
|
|
237
|
+
info,
|
|
238
|
+
};
|
|
239
|
+
return middleware(action, async () =>
|
|
240
|
+
originalSubscribe ? originalSubscribe(root, args, context, info) : defaultFieldResolver(root, args, context, info)
|
|
241
|
+
);
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return schema;
|
|
248
|
+
}
|
|
249
|
+
|
|
194
250
|
/**
|
|
195
251
|
* Heuristic: an arg is "custom" (i.e. needs `@NoLog` discipline because metadata can't redact it)
|
|
196
252
|
* when its GraphQL input type is not a known `Create<X>Input` / `Update<X>Input` for an entity
|
|
@@ -64,9 +64,13 @@ The principal comes from the **server-authenticated** context (`userPayload.user
|
|
|
64
64
|
argument. An id argument only selects *which of the caller's own sessions*.
|
|
65
65
|
|
|
66
66
|
A caller may use a session when `AIAgentSession.UserID` equals their user (`UUIDsEqual`). Widget guests all
|
|
67
|
-
share one Anonymous user, so for an anonymous/magic-link principal that is **not enough**: the
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
share one Anonymous user, so for an anonymous/magic-link principal that is **not enough**: the session's
|
|
68
|
+
conversation `ExternalID` must equal the principal's scope identity (`ResolveSessionScopeIdentity`): the
|
|
69
|
+
signed `MagicLinkScope.ResourceID` when the token carries one, else the anonymous visitor's `mj_sid`.
|
|
70
|
+
`SessionManager` stamps that same value when it creates the conversation. An anonymous principal with
|
|
71
|
+
neither is refused outright. A *named* user with a resource scope must match too, which keeps one person's
|
|
72
|
+
different links apart; but it may also use its own session on a conversation that carries no stamp (one
|
|
73
|
+
started from the Conversations app) when its own row-level security let it read that conversation.
|
|
70
74
|
|
|
71
75
|
- Refusals are uniform ("session not found") whether the session is missing or simply not yours, so ids
|
|
72
76
|
cannot be probed.
|
|
@@ -54,6 +54,7 @@ function toSnapshot(loaded: LoadedSessionForAccess): SessionSnapshot {
|
|
|
54
54
|
AgentSessionID: Session.ID,
|
|
55
55
|
OwnerUserID: Session.UserID,
|
|
56
56
|
ConversationExternalID: loaded.ConversationExternalID,
|
|
57
|
+
ConversationReadable: loaded.ConversationReadable,
|
|
57
58
|
Status: Session.Status,
|
|
58
59
|
ConfigRaw: Session.Config_,
|
|
59
60
|
// `__mj_CreatedAt` is the row's creation instant — i.e. the session start. It is read-only and
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { IMetadataProvider, LogError, UserInfo } from '@memberjunction/core';
|
|
9
9
|
import { UUIDsEqual } from '@memberjunction/global';
|
|
10
10
|
import type { MJAIAgentSessionEntity } from '@memberjunction/core-entities';
|
|
11
|
+
import { AuthorizeLoadedSession } from './sessionAccess.js';
|
|
11
12
|
|
|
12
13
|
const SESSION_ENTITY = 'MJ: AI Agent Sessions';
|
|
13
14
|
|
|
@@ -19,7 +20,7 @@ export class RealtimeSessionNotFoundError extends Error {
|
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
/** The session exists but
|
|
23
|
+
/** The session exists but the caller may not use it: another user owns it, or (for a scoped or anonymous caller) its conversation carries another scope identity. */
|
|
23
24
|
export class RealtimeSessionOwnershipError extends Error {
|
|
24
25
|
constructor(public readonly AgentSessionID: string) {
|
|
25
26
|
super('Not authorized: you do not own this realtime session');
|
|
@@ -28,13 +29,15 @@ export class RealtimeSessionOwnershipError extends Error {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
|
-
* Loads a session under the caller's identity and enforces ownership
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
32
|
+
* Loads a session under the caller's identity and enforces ownership: `UserID === contextUser.ID`, then the
|
|
33
|
+
* scope rule of {@link AuthorizeSessionAccess} (every anonymous visitor shares one Anonymous user, so the
|
|
34
|
+
* session's conversation `ExternalID` must equal the caller's scope identity). It deliberately does NOT
|
|
35
|
+
* reject `Closed` sessions: the final channel-state flush and the recording terminal signal legitimately
|
|
36
|
+
* arrive after the session closed. Loading as the caller also applies the entity's row-level security.
|
|
35
37
|
*
|
|
36
38
|
* @throws RealtimeSessionNotFoundError when the row does not load
|
|
37
|
-
* @throws RealtimeSessionOwnershipError when
|
|
39
|
+
* @throws RealtimeSessionOwnershipError when another user owns the session (logged with both user ids) or
|
|
40
|
+
* the scope rule refuses the caller (logged with the refusal reason)
|
|
38
41
|
*/
|
|
39
42
|
export async function LoadOwnedRealtimeSession(
|
|
40
43
|
agentSessionId: string,
|
|
@@ -51,5 +54,12 @@ export async function LoadOwnedRealtimeSession(
|
|
|
51
54
|
);
|
|
52
55
|
throw new RealtimeSessionOwnershipError(agentSessionId);
|
|
53
56
|
}
|
|
57
|
+
const access = await AuthorizeLoadedSession(session, contextUser, provider);
|
|
58
|
+
if (!access.Allowed) {
|
|
59
|
+
LogError(
|
|
60
|
+
`LoadOwnedRealtimeSession: session access refused (${access.Reason}) — user ${contextUser.ID} attempted to operate on session ${agentSessionId}`,
|
|
61
|
+
);
|
|
62
|
+
throw new RealtimeSessionOwnershipError(agentSessionId);
|
|
63
|
+
}
|
|
54
64
|
return session;
|
|
55
65
|
}
|
|
@@ -9,13 +9,17 @@
|
|
|
9
9
|
* ## The two ownership rules
|
|
10
10
|
*
|
|
11
11
|
* 1. **Owner.** The session's `UserID` must be the caller's user.
|
|
12
|
-
* 2. **Scope.** A *named* user is fully identified by (1). An **anonymous widget guest
|
|
13
|
-
* every
|
|
14
|
-
* address any other
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
12
|
+
* 2. **Scope.** A *named* user is fully identified by (1). An **anonymous visitor** (widget guest or
|
|
13
|
+
* anonymous magic-link invitee) is not: every one authenticates as the one shared Anonymous user, so
|
|
14
|
+
* (1) alone would let any visitor address any other visitor's session. What separates them is the
|
|
15
|
+
* scope identity {@link ResolveSessionScopeIdentity} reads off the signed token — the resource scope
|
|
16
|
+
* (`MagicLinkScope.ResourceID`) when the token carries one, else the per-token `mj_sid`
|
|
17
|
+
* (`AnonymousVisitorID`). `SessionManager` stamps that same value onto the session's Conversation as
|
|
18
|
+
* `ExternalID`, so a principal with a scope identity must match it, and an anonymous principal with
|
|
19
|
+
* none is refused outright — it cannot be told apart from every other anonymous principal.
|
|
20
|
+
* One allowance: a NAMED principal with a resource scope may also use its own session whose
|
|
21
|
+
* conversation carries no stamp at all, when it could read that conversation (see the comment in
|
|
22
|
+
* {@link AuthorizeSessionAccess}).
|
|
19
23
|
*
|
|
20
24
|
* The decision is deliberately pure (no I/O) so it can be applied identically to a freshly loaded
|
|
21
25
|
* row at subscribe time and to the owner/scope snapshot carried inside each published event.
|
|
@@ -41,14 +45,22 @@ export interface SessionAccessSubject {
|
|
|
41
45
|
* could not be loaded.
|
|
42
46
|
*/
|
|
43
47
|
ConversationExternalID: string | null | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* True when the conversation was loaded under the CALLER's identity (so its row-level security allowed
|
|
50
|
+
* the read). Only consulted for a named principal with a resource scope on a conversation that carries
|
|
51
|
+
* no `ExternalID`; omitted means unknown and is treated as unreadable (fail closed).
|
|
52
|
+
*/
|
|
53
|
+
ConversationReadable?: boolean;
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
/** What the decision needs to know about the caller (a subset of `UserInfo`). */
|
|
47
57
|
export interface SessionAccessPrincipal {
|
|
48
58
|
/** The caller's user id. */
|
|
49
59
|
ID: string;
|
|
50
|
-
/** True for the shared-Anonymous-user principal of a public-widget guest. */
|
|
60
|
+
/** True for the shared-Anonymous-user principal of a public-widget guest or anonymous magic-link invitee. */
|
|
51
61
|
IsMagicLinkAnonymous?: boolean;
|
|
62
|
+
/** Per-visitor session identity (`mj_sid`) for an anonymous principal. */
|
|
63
|
+
AnonymousVisitorID?: string;
|
|
52
64
|
/** The signed per-session scope carried by the caller's token, when any. */
|
|
53
65
|
MagicLinkScope?: { ResourceID?: string } | undefined;
|
|
54
66
|
}
|
|
@@ -57,7 +69,29 @@ export interface SessionAccessPrincipal {
|
|
|
57
69
|
export type SessionAccessRefusal = 'not_owner' | 'scope_missing' | 'scope_mismatch';
|
|
58
70
|
|
|
59
71
|
/** Outcome of {@link AuthorizeSessionAccess}. */
|
|
60
|
-
export type SessionAccessDecision =
|
|
72
|
+
export type SessionAccessDecision =
|
|
73
|
+
| { Allowed: true; Reason?: undefined }
|
|
74
|
+
| { Allowed: false; Reason: SessionAccessRefusal };
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The scope identity a session is keyed on for `principal` — the one value `SessionManager` stamps as
|
|
78
|
+
* the session conversation's `ExternalID` and {@link AuthorizeSessionAccess} compares against it.
|
|
79
|
+
*
|
|
80
|
+
* - The token's resource scope (`MagicLinkScope.ResourceID`) when it carries one. A widget guest's
|
|
81
|
+
* resource scope IS its `mj_sid`; an anonymous magic-link invite with a `ResourceID` (e.g. a Caliber
|
|
82
|
+
* Invite Scope, one per subject) shares that scope across its redemptions by design, and the
|
|
83
|
+
* `{{ScopeResourceID}}` RLS filters key on the same value, so the visitor can read its own rows.
|
|
84
|
+
* - Otherwise, for an anonymous principal, the per-token `mj_sid` (`AnonymousVisitorID`), which tells two
|
|
85
|
+
* redemptions of an unscoped multi-use invite apart.
|
|
86
|
+
* - Otherwise `undefined` (a named user without a resource scope).
|
|
87
|
+
*/
|
|
88
|
+
export function ResolveSessionScopeIdentity(principal: SessionAccessPrincipal): string | undefined {
|
|
89
|
+
const resourceId = principal.MagicLinkScope?.ResourceID;
|
|
90
|
+
if (resourceId) {
|
|
91
|
+
return resourceId;
|
|
92
|
+
}
|
|
93
|
+
return principal.IsMagicLinkAnonymous ? principal.AnonymousVisitorID || undefined : undefined;
|
|
94
|
+
}
|
|
61
95
|
|
|
62
96
|
/**
|
|
63
97
|
* Decides whether `principal` may address the session described by `subject`.
|
|
@@ -74,14 +108,26 @@ export function AuthorizeSessionAccess(
|
|
|
74
108
|
if (!principal?.ID || !subject.SessionUserID || !UUIDsEqual(subject.SessionUserID, principal.ID)) {
|
|
75
109
|
return { Allowed: false, Reason: 'not_owner' };
|
|
76
110
|
}
|
|
77
|
-
const scopeId = principal
|
|
111
|
+
const scopeId = ResolveSessionScopeIdentity(principal);
|
|
78
112
|
if (!scopeId) {
|
|
79
|
-
//
|
|
80
|
-
//
|
|
113
|
+
// A named user without a scope is identified by the owner check alone; an anonymous principal
|
|
114
|
+
// without one cannot be told apart from any other anonymous principal.
|
|
81
115
|
return principal.IsMagicLinkAnonymous ? { Allowed: false, Reason: 'scope_missing' } : { Allowed: true };
|
|
82
116
|
}
|
|
83
117
|
// Scope ids are opaque base64url strings (case-significant), so compare exactly — not UUIDsEqual.
|
|
84
|
-
|
|
118
|
+
if (subject.ConversationExternalID === scopeId) {
|
|
119
|
+
return { Allowed: true };
|
|
120
|
+
}
|
|
121
|
+
// A named user is identified by the owner check; its scope only keeps one link's sessions apart from
|
|
122
|
+
// the same person's other links (magic links resolve the user by email, so one person can hold several).
|
|
123
|
+
// A conversation with no stamp belongs to no link (one started from the Conversations app), so the owner
|
|
124
|
+
// may use it when its own row-level security let it read the conversation. `ExternalID` is not stamped
|
|
125
|
+
// here because other features own that column on their conversations (meeting room names, for example).
|
|
126
|
+
// An anonymous visitor gets no such allowance: the stamp is the only thing that identifies it.
|
|
127
|
+
if (!principal.IsMagicLinkAnonymous && subject.ConversationExternalID === null && subject.ConversationReadable === true) {
|
|
128
|
+
return { Allowed: true };
|
|
129
|
+
}
|
|
130
|
+
return { Allowed: false, Reason: 'scope_mismatch' };
|
|
85
131
|
}
|
|
86
132
|
|
|
87
133
|
/** A session row together with the one fact about its conversation the decision needs. */
|
|
@@ -90,6 +136,8 @@ export interface LoadedSessionForAccess {
|
|
|
90
136
|
Session: MJAIAgentSessionEntity;
|
|
91
137
|
/** The session's conversation `ExternalID` (anonymous scope id), or null. */
|
|
92
138
|
ConversationExternalID: string | null;
|
|
139
|
+
/** Whether the caller could read the session's conversation (false when there is none). */
|
|
140
|
+
ConversationReadable: boolean;
|
|
93
141
|
}
|
|
94
142
|
|
|
95
143
|
/**
|
|
@@ -115,31 +163,169 @@ export async function LoadSessionForAccess(
|
|
|
115
163
|
if (!(await session.Load(agentSessionId))) {
|
|
116
164
|
return null;
|
|
117
165
|
}
|
|
118
|
-
|
|
166
|
+
const conversation = await LoadSessionConversationScope(session, contextUser, provider);
|
|
167
|
+
return { Session: session, ConversationExternalID: conversation.ExternalID, ConversationReadable: conversation.Readable };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** What the caller could learn about a session's conversation: the scope half of {@link SessionAccessSubject}. */
|
|
171
|
+
export interface SessionConversationScope {
|
|
172
|
+
/** The conversation's `ExternalID` (the anonymous scope id), or null when it has none or was not read. */
|
|
173
|
+
ExternalID: string | null;
|
|
174
|
+
/** Whether the caller could read the conversation (false when the session has none). */
|
|
175
|
+
Readable: boolean;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** {@link SessionConversationScope} plus the conversation's owner, for a conversation addressed without a session. */
|
|
179
|
+
export interface ConversationScope extends SessionConversationScope {
|
|
180
|
+
/** `Conversation.UserID`, or null when the conversation was not read. */
|
|
181
|
+
UserID: string | null;
|
|
119
182
|
}
|
|
120
183
|
|
|
121
184
|
/**
|
|
122
|
-
* Reads an already-loaded session's conversation `
|
|
123
|
-
*
|
|
124
|
-
* through another gate and only need the scope half of
|
|
185
|
+
* Reads an already-loaded session's conversation under `contextUser` (so its row-level security applies).
|
|
186
|
+
* A missing conversation, a refused read and a failed read (logged) all report `Readable: false`. For
|
|
187
|
+
* callers that loaded the session through another gate and only need the scope half of
|
|
188
|
+
* {@link AuthorizeSessionAccess}'s subject.
|
|
125
189
|
*/
|
|
126
|
-
export async function
|
|
190
|
+
export async function LoadSessionConversationScope(
|
|
127
191
|
session: MJAIAgentSessionEntity,
|
|
128
192
|
contextUser: UserInfo,
|
|
129
193
|
provider: IMetadataProvider,
|
|
130
|
-
): Promise<
|
|
194
|
+
): Promise<SessionConversationScope> {
|
|
131
195
|
if (!session.ConversationID) {
|
|
132
|
-
return null;
|
|
196
|
+
return { ExternalID: null, Readable: false };
|
|
197
|
+
}
|
|
198
|
+
const { ExternalID, Readable } = await LoadConversationScope(session.ConversationID, contextUser, provider);
|
|
199
|
+
return { ExternalID, Readable };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Decides whether `contextUser` may address an already-loaded `session`: the {@link AuthorizeSessionAccess}
|
|
204
|
+
* decision, reading the session's conversation only when that decision needs it.
|
|
205
|
+
*
|
|
206
|
+
* {@link AuthorizeSessionAccess} decides a principal without a scope identity — a named user with no magic-link
|
|
207
|
+
* scope, the usual signed-in caller — from the owner check alone, and refuses a non-owner before it looks at
|
|
208
|
+
* anything else, so neither needs the conversation read. This function and that one encode the same rule on
|
|
209
|
+
* purpose and live together for that reason: change the rule there, change the read here. The
|
|
210
|
+
* `AuthorizeLoadedSession` table test in `sessionAccess.test.ts` fails if the two ever disagree.
|
|
211
|
+
*
|
|
212
|
+
* @param session - the session, loaded through the caller's own gate
|
|
213
|
+
* @param contextUser - the authenticated caller; the conversation, when read, is read as this user (RLS applies)
|
|
214
|
+
* @param provider - the request-scoped provider
|
|
215
|
+
*/
|
|
216
|
+
export async function AuthorizeLoadedSession(
|
|
217
|
+
session: MJAIAgentSessionEntity,
|
|
218
|
+
contextUser: UserInfo,
|
|
219
|
+
provider: IMetadataProvider,
|
|
220
|
+
): Promise<SessionAccessDecision> {
|
|
221
|
+
const ownsSession = !!contextUser?.ID && !!session.UserID && UUIDsEqual(session.UserID, contextUser.ID);
|
|
222
|
+
if (!ownsSession || !ResolveSessionScopeIdentity(contextUser)) {
|
|
223
|
+
return AuthorizeSessionAccess({ SessionUserID: session.UserID, ConversationExternalID: null, ConversationReadable: false }, contextUser);
|
|
224
|
+
}
|
|
225
|
+
const conversation = await LoadSessionConversationScope(session, contextUser, provider);
|
|
226
|
+
return AuthorizeSessionAccess(
|
|
227
|
+
{ SessionUserID: session.UserID, ConversationExternalID: conversation.ExternalID, ConversationReadable: conversation.Readable },
|
|
228
|
+
contextUser,
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Reads a conversation's owner and scope id under `contextUser` (so its row-level security applies), for a
|
|
234
|
+
* caller that addresses the conversation directly rather than through a session — a text agent turn, for
|
|
235
|
+
* example, whose only handle is a message in it. Together with the caller's principal this is exactly the
|
|
236
|
+
* subject {@link AuthorizeSessionAccess} decides on: `SessionUserID` is the conversation's owner, since the
|
|
237
|
+
* session a conversation belongs to is owned by the same user.
|
|
238
|
+
*
|
|
239
|
+
* An empty id, a missing conversation, a refused read and a failed read (logged) all report
|
|
240
|
+
* `Readable: false` with no owner, which {@link AuthorizeSessionAccess} then refuses for any scoped caller.
|
|
241
|
+
*/
|
|
242
|
+
export async function LoadConversationScope(
|
|
243
|
+
conversationId: string | null | undefined,
|
|
244
|
+
contextUser: UserInfo,
|
|
245
|
+
provider: IMetadataProvider,
|
|
246
|
+
): Promise<ConversationScope> {
|
|
247
|
+
const unreadable: ConversationScope = { UserID: null, ExternalID: null, Readable: false };
|
|
248
|
+
if (!conversationId) {
|
|
249
|
+
return unreadable;
|
|
133
250
|
}
|
|
134
251
|
try {
|
|
135
252
|
const conversation = await provider.GetEntityObject<MJConversationEntity>(CONVERSATION_ENTITY, contextUser);
|
|
136
|
-
if (!(await conversation.Load(
|
|
137
|
-
return
|
|
253
|
+
if (!(await conversation.Load(conversationId))) {
|
|
254
|
+
return unreadable;
|
|
138
255
|
}
|
|
139
|
-
return conversation.ExternalID ?? null;
|
|
256
|
+
return { UserID: conversation.UserID ?? null, ExternalID: conversation.ExternalID ?? null, Readable: true };
|
|
140
257
|
} catch (error) {
|
|
141
258
|
const message = error instanceof Error ? error.message : String(error);
|
|
142
|
-
LogError(`
|
|
143
|
-
return
|
|
259
|
+
LogError(`LoadConversationScope: could not read conversation ${conversationId} for user ${contextUser?.ID}: ${message}`);
|
|
260
|
+
return unreadable;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Who may run a conversation turn (a text agent turn, addressed by a message in the conversation) in
|
|
266
|
+
* `conversationId`, decided the same way as session access.
|
|
267
|
+
*
|
|
268
|
+
* A NAMED principal is allowed without a read: its entity permissions and row filters already decided
|
|
269
|
+
* whether it could load the message, and a named user is fully identified by its `UserID`. An ANONYMOUS
|
|
270
|
+
* principal is not (see the module doc), so the conversation is read as the caller and
|
|
271
|
+
* {@link AuthorizeSessionAccess} compares its scope id with the conversation's stamp — the same
|
|
272
|
+
* decision #5997 applies to the realtime gates, so the text and voice paths agree on ownership.
|
|
273
|
+
* An unreadable conversation refuses (`not_owner`, there is no owner to match).
|
|
274
|
+
*/
|
|
275
|
+
export async function AuthorizeConversationTurn(
|
|
276
|
+
conversationId: string,
|
|
277
|
+
principal: UserInfo,
|
|
278
|
+
provider: IMetadataProvider,
|
|
279
|
+
): Promise<SessionAccessDecision> {
|
|
280
|
+
if (!principal?.IsMagicLinkAnonymous) {
|
|
281
|
+
return { Allowed: true };
|
|
282
|
+
}
|
|
283
|
+
const scope = await LoadConversationScope(conversationId, principal, provider);
|
|
284
|
+
return AuthorizeSessionAccess(
|
|
285
|
+
{ SessionUserID: scope.UserID ?? '', ConversationExternalID: scope.ExternalID, ConversationReadable: scope.Readable },
|
|
286
|
+
principal,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Whether an anonymous caller owns any of a LiveKit room's agent sessions — the check MJServer registers with
|
|
292
|
+
* `RoomAuthorizationService.SetAnonymousSessionOwnerCheck` (`@memberjunction/livekit-room-server` cannot import
|
|
293
|
+
* this package). Each session is loaded as the caller (its row-level security applies) and decided by
|
|
294
|
+
* {@link AuthorizeSessionAccess}, the same decision every realtime gate makes, so a room admits exactly the visitor
|
|
295
|
+
* whose scope id its session's conversation carries (MJ#6044). Nothing to read, or no provider: refused.
|
|
296
|
+
*/
|
|
297
|
+
export async function AuthorizeAnonymousRoomSessions(
|
|
298
|
+
agentSessionIds: string[],
|
|
299
|
+
user: UserInfo,
|
|
300
|
+
provider: IMetadataProvider | undefined,
|
|
301
|
+
): Promise<boolean> {
|
|
302
|
+
if (agentSessionIds.length === 0 || !provider) {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
for (const agentSessionId of agentSessionIds) {
|
|
306
|
+
const loaded = await LoadSessionForAccess(agentSessionId, user, provider);
|
|
307
|
+
if (!loaded) {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
const decision = AuthorizeSessionAccess(
|
|
311
|
+
{ SessionUserID: loaded.Session.UserID, ConversationExternalID: loaded.ConversationExternalID, ConversationReadable: loaded.ConversationReadable },
|
|
312
|
+
user,
|
|
313
|
+
);
|
|
314
|
+
if (decision.Allowed) {
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
144
317
|
}
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* The session conversation's `ExternalID` alone; null when there is none or it cannot be read.
|
|
323
|
+
* Prefer {@link LoadSessionConversationScope}, which also says whether the read succeeded.
|
|
324
|
+
*/
|
|
325
|
+
export async function LoadSessionConversationExternalID(
|
|
326
|
+
session: MJAIAgentSessionEntity,
|
|
327
|
+
contextUser: UserInfo,
|
|
328
|
+
provider: IMetadataProvider,
|
|
329
|
+
): Promise<string | null> {
|
|
330
|
+
return (await LoadSessionConversationScope(session, contextUser, provider)).ExternalID;
|
|
145
331
|
}
|
|
@@ -113,7 +113,7 @@ export async function LoadInheritedVerifiedIdentity(
|
|
|
113
113
|
return undefined;
|
|
114
114
|
}
|
|
115
115
|
const decision = AuthorizeSessionAccess(
|
|
116
|
-
{ SessionUserID: prior.Session.UserID, ConversationExternalID: prior.ConversationExternalID },
|
|
116
|
+
{ SessionUserID: prior.Session.UserID, ConversationExternalID: prior.ConversationExternalID, ConversationReadable: prior.ConversationReadable },
|
|
117
117
|
contextUser,
|
|
118
118
|
);
|
|
119
119
|
if (decision.Allowed === false) {
|