@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
|
@@ -61,7 +61,9 @@ export function RealtimeSessionEventsFilter(data: {
|
|
|
61
61
|
return false;
|
|
62
62
|
}
|
|
63
63
|
const decision = AuthorizeSessionAccess(
|
|
64
|
-
|
|
64
|
+
// Readability is per caller and was proven when this subscription opened (it only receives events for
|
|
65
|
+
// that one session); the snapshot carries just the stamp, so a null ScopeKey stays usable by that owner.
|
|
66
|
+
{ SessionUserID: payload.OwnerUserID, ConversationExternalID: payload.ScopeKey, ConversationReadable: true },
|
|
65
67
|
connectionPrincipal(context),
|
|
66
68
|
);
|
|
67
69
|
return decision.Allowed;
|
|
@@ -105,7 +107,7 @@ export async function AuthorizeRealtimeSessionSubscription(
|
|
|
105
107
|
throw new Error(REFUSAL_MESSAGE);
|
|
106
108
|
}
|
|
107
109
|
const decision = AuthorizeSessionAccess(
|
|
108
|
-
{ SessionUserID: loaded.Session.UserID, ConversationExternalID: loaded.ConversationExternalID },
|
|
110
|
+
{ SessionUserID: loaded.Session.UserID, ConversationExternalID: loaded.ConversationExternalID, ConversationReadable: loaded.ConversationReadable },
|
|
109
111
|
principal,
|
|
110
112
|
);
|
|
111
113
|
if (decision.Allowed === false) {
|
|
@@ -90,6 +90,8 @@ export interface SessionSnapshot {
|
|
|
90
90
|
OwnerUserID: string;
|
|
91
91
|
/** `Conversation.ExternalID` (anonymous scope id), or null. */
|
|
92
92
|
ConversationExternalID: string | null;
|
|
93
|
+
/** Whether the caller could read the session's conversation. */
|
|
94
|
+
ConversationReadable: boolean;
|
|
93
95
|
Status: 'Active' | 'Idle' | 'Closed';
|
|
94
96
|
/** `AIAgentSession.Config` as stored. */
|
|
95
97
|
ConfigRaw: string | null;
|
|
@@ -660,7 +662,7 @@ export class RealtimeSessionVerificationWorkflow {
|
|
|
660
662
|
return notFound;
|
|
661
663
|
}
|
|
662
664
|
const decision = AuthorizeSessionAccess(
|
|
663
|
-
{ SessionUserID: session.OwnerUserID, ConversationExternalID: session.ConversationExternalID },
|
|
665
|
+
{ SessionUserID: session.OwnerUserID, ConversationExternalID: session.ConversationExternalID, ConversationReadable: session.ConversationReadable },
|
|
664
666
|
caller.ContextUser,
|
|
665
667
|
);
|
|
666
668
|
if (decision.Allowed === false) {
|
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
import { Router, json, type Request, type Response } from 'express';
|
|
14
14
|
import { rateLimit, ipKeyGenerator } from 'express-rate-limit';
|
|
15
15
|
import { LogStatus } from '@memberjunction/core';
|
|
16
|
+
import type { ProofPublicJwk } from '@memberjunction/global';
|
|
16
17
|
import { configInfo, type WidgetConfig } from '../config.js';
|
|
17
18
|
import { MagicLinkKeyManager } from '../auth/magicLink/MagicLinkKeys.js';
|
|
18
19
|
import { RegisterMagicLinkAuthProvider } from '../auth/magicLink/MagicLinkRouter.js';
|
|
19
|
-
import { WidgetSessionService, type MintGuestSessionResult } from './WidgetSessionService.js';
|
|
20
|
+
import { WidgetSessionService, WIDGET_REFRESH_PATH, type MintGuestSessionResult } from './WidgetSessionService.js';
|
|
20
21
|
import { LooksLikeBot } from './widgetCore.js';
|
|
21
22
|
|
|
22
23
|
/** The mount path for the widget public router (`/widget`). */
|
|
@@ -54,7 +55,9 @@ function ensureWidgetSigning(publicUrl: string, widgetConfig: WidgetConfig): voi
|
|
|
54
55
|
export function CreateWidgetHandler(publicUrl: string, config: WidgetConfig): { publicRouter: Router; authenticatedRouter: Router } {
|
|
55
56
|
ensureWidgetSigning(publicUrl, config);
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
// A widget may hand an anonymous guest only a scope-isolated role (MJ#6043); the opt-in list is the one
|
|
59
|
+
// magic-link invites already use, so an admin declares "safe for anonymous visitors" in one place.
|
|
60
|
+
const service = new WidgetSessionService(publicUrl, config, { GrantableRoleNames: configInfo.magicLink?.grantableRoleNames ?? [] });
|
|
58
61
|
|
|
59
62
|
// Per-instance DYNAMIC mint limiter (W6 hardening): keyed by (widgetKey + IP) so each widget
|
|
60
63
|
// deployment gets its own bucket and one abusive IP can't exhaust a shared instance's budget for
|
|
@@ -80,7 +83,7 @@ export function CreateWidgetHandler(publicUrl: string, config: WidgetConfig): {
|
|
|
80
83
|
await handleMint(service, req, res, false);
|
|
81
84
|
});
|
|
82
85
|
|
|
83
|
-
publicRouter.post(
|
|
86
|
+
publicRouter.post(WIDGET_REFRESH_PATH, json(), mintLimiter, async (req: Request, res: Response) => {
|
|
84
87
|
await handleMint(service, req, res, true);
|
|
85
88
|
});
|
|
86
89
|
|
|
@@ -171,14 +174,26 @@ async function handleUpgrade(service: WidgetSessionService, req: Request, res: R
|
|
|
171
174
|
res.status(status).json(result);
|
|
172
175
|
}
|
|
173
176
|
|
|
177
|
+
/** Extracts a raw JWT from an `Authorization: Bearer <token>` header, or undefined when absent/malformed. */
|
|
178
|
+
function extractBearerToken(authHeader: string | undefined): string | undefined {
|
|
179
|
+
if (!authHeader) {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
const match = /^Bearer\s+(\S+)$/i.exec(authHeader.trim());
|
|
183
|
+
const token = match?.[1]?.trim();
|
|
184
|
+
return token && token.length > 0 ? token : undefined;
|
|
185
|
+
}
|
|
186
|
+
|
|
174
187
|
/** Shared mint/refresh handler — parses the request, calls the service, maps the status. */
|
|
175
188
|
async function handleMint(service: WidgetSessionService, req: Request, res: Response, refresh: boolean): Promise<void> {
|
|
176
|
-
const body = (req.body ?? {}) as { widgetKey?: string; hostAssertion?: string; visitorKey?: string };
|
|
189
|
+
const body = (req.body ?? {}) as { widgetKey?: string; hostAssertion?: string; visitorKey?: string; proofKey?: unknown };
|
|
177
190
|
const widgetKey = typeof body.widgetKey === 'string' ? body.widgetKey : '';
|
|
178
191
|
if (!widgetKey) {
|
|
179
192
|
res.status(400).json({ success: false, errorCode: 'not_found', error: 'widgetKey is required.' });
|
|
180
193
|
return;
|
|
181
194
|
}
|
|
195
|
+
// The service validates the key's shape (ToProofPublicJwk) and refuses anything that is not a public P-256 JWK.
|
|
196
|
+
const proofKey = body.proofKey === undefined ? undefined : (body.proofKey as ProofPublicJwk);
|
|
182
197
|
|
|
183
198
|
// W6 hardening: coarse bot/automation rejection before any DB lookup or token mint. Returns the same
|
|
184
199
|
// 403 as a policy rejection so a probe can't distinguish "bot-blocked" from "bad key/origin".
|
|
@@ -193,6 +208,9 @@ async function handleMint(service: WidgetSessionService, req: Request, res: Resp
|
|
|
193
208
|
origin,
|
|
194
209
|
hostAssertion: typeof body.hostAssertion === 'string' ? body.hostAssertion : undefined,
|
|
195
210
|
visitorKey: typeof body.visitorKey === 'string' ? body.visitorKey : undefined,
|
|
211
|
+
BearerToken: refresh ? extractBearerToken(req.get('authorization')) : undefined,
|
|
212
|
+
Proof: refresh ? req.get('dpop') : undefined,
|
|
213
|
+
ProofKey: refresh ? undefined : proofKey,
|
|
196
214
|
audit: { ipAddress: req.ip, userAgent: req.get('user-agent') ?? undefined, origin },
|
|
197
215
|
};
|
|
198
216
|
const result = refresh ? await service.RefreshGuestSession(input) : await service.MintGuestSession(input);
|
|
@@ -9,20 +9,22 @@
|
|
|
9
9
|
* widget guest is ephemeral). Forensics ride the opaque per-session id (`mj_sid`)
|
|
10
10
|
* carried in the token, plus best-effort structured audit logging. The minted
|
|
11
11
|
* token is validated by the SAME `magic-link` auth provider (same issuer/audience/
|
|
12
|
-
* JWKS) and synthesized into a constrained guest principal by `
|
|
12
|
+
* JWKS) and synthesized into a constrained guest principal by `BuildMagicLinkSessionUser`.
|
|
13
13
|
*
|
|
14
14
|
* @module @memberjunction/server/widget
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { createPublicKey } from 'node:crypto';
|
|
18
|
+
import jwt from 'jsonwebtoken';
|
|
17
19
|
import { Metadata, RunView, UserInfo, LogError, LogStatus } from '@memberjunction/core';
|
|
18
|
-
import { MJLruCache, UUIDsEqual } from '@memberjunction/global';
|
|
20
|
+
import { ComputeJwkThumbprint, MJLruCache, ToProofPublicJwk, UUIDsEqual, VerifyProofOfPossessionJwt, type ProofPublicJwk } from '@memberjunction/global';
|
|
19
21
|
import type { MJConversationWidgetInstanceEntity, MJConversationEntity } from '@memberjunction/core-entities';
|
|
20
22
|
import { ResolveConfiguredPrincipal } from '../auth/principals.js';
|
|
21
23
|
import { MagicLinkKeyManager } from '../auth/magicLink/MagicLinkKeys.js';
|
|
22
24
|
import { GenerateSessionId } from '../auth/magicLink/magicLinkCore.js';
|
|
23
25
|
import { MagicLinkService } from '../auth/magicLink/MagicLinkService.js';
|
|
24
26
|
import { configInfo, type WidgetConfig } from '../config.js';
|
|
25
|
-
import { BuildWidgetGuestClaims, EvaluateWidgetMint, ParseEnabledChannels, type WidgetMintErrorCode } from './widgetCore.js';
|
|
27
|
+
import { BuildWidgetGuestClaims, EvaluateWidgetMint, IsIsolatedGuestRole, ParseEnabledChannels, type GuestRolePolicy, type WidgetMintErrorCode } from './widgetCore.js';
|
|
26
28
|
import { VerifyHostAssertion, type HostAssertedIdentity } from './host-identity.js';
|
|
27
29
|
import { WriteReturningVisitorRecap } from '../agentSessions/ReturningVisitorRecap.js';
|
|
28
30
|
import { ResolveIdentityByEmail, MergeVisitorIdentity, ForgetVisitor, type ResolvedVisitorIdentity } from './visitorIdentity.js';
|
|
@@ -33,6 +35,43 @@ const CONVERSATIONS_ENTITY = 'MJ: Conversations';
|
|
|
33
35
|
/** Shape of the durable visitor anchor key (opaque base64url, same alphabet as generateSessionId). */
|
|
34
36
|
const VISITOR_KEY_PATTERN = /^[A-Za-z0-9_-]{16,128}$/;
|
|
35
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Maximum clock-skew / late-timer grace window (seconds) after `exp` during which
|
|
40
|
+
* `RefreshGuestSession` still accepts a widget guest Bearer token and preserves its `mj_sid`.
|
|
41
|
+
*/
|
|
42
|
+
export const REFRESH_GRACE_SECONDS = 300;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Hard end of a widget guest session (seconds after its first mint, `mj_sid_iat`). Refresh keeps the
|
|
46
|
+
* visitor's `mj_sid`, so without an end a token captured once could be renewed forever and keep reading
|
|
47
|
+
* that visitor's conversations; past this point refresh is refused and no token outlives it.
|
|
48
|
+
*/
|
|
49
|
+
export const MAX_GUEST_SESSION_SECONDS = 12 * 3600;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The least lifetime a refreshed token may have. Refresh is refused once less than this remains before the hard end,
|
|
53
|
+
* so the last refresh gets the 403 that makes the widget start a new session. It must exceed the widget's refresh
|
|
54
|
+
* lead (60 s before `exp`): a token issued with less would be due for refresh at once, every time, until the rate
|
|
55
|
+
* limiter answered 429 instead. It also keeps a re-minted token's `exp` after its `iat`.
|
|
56
|
+
*/
|
|
57
|
+
export const MIN_REFRESHED_TOKEN_SECONDS = 120;
|
|
58
|
+
|
|
59
|
+
/** The refresh route's path under the widget mount; the refresh proof must name it (`htu`). */
|
|
60
|
+
export const WIDGET_REFRESH_PATH = '/session/refresh';
|
|
61
|
+
|
|
62
|
+
/** How far a refresh proof's signing time (`iat`) may be from the server clock, either way. */
|
|
63
|
+
export const REFRESH_PROOF_MAX_SKEW_SECONDS = 60;
|
|
64
|
+
|
|
65
|
+
/** The session a valid refresh token belongs to, carried into the re-minted token unchanged. */
|
|
66
|
+
interface RefreshableGuestSession {
|
|
67
|
+
/** `mj_sid`. */
|
|
68
|
+
SessionId: string;
|
|
69
|
+
/** `mj_sid_iat`: when the session was first minted, epoch seconds. */
|
|
70
|
+
StartedAtSeconds: number;
|
|
71
|
+
/** `cnf.jkt`: the thumbprint of the key the session is bound to. */
|
|
72
|
+
KeyThumbprint: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
36
75
|
/** Resolved returning-visitor anchor for a mint: the durable key + the prior conversation to chain from. */
|
|
37
76
|
interface ReturningVisitorResolution {
|
|
38
77
|
/** The durable VisitorKey to persist as a cookie (validated-presented or freshly minted). */
|
|
@@ -67,6 +106,19 @@ export interface MintGuestSessionInput {
|
|
|
67
106
|
* server mints a fresh one. Ignored entirely when remembering is off.
|
|
68
107
|
*/
|
|
69
108
|
visitorKey?: string; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
|
|
109
|
+
/**
|
|
110
|
+
* The caller's current guest session JWT (`Authorization: Bearer <token>`), required by
|
|
111
|
+
* `RefreshGuestSession` so a refresh proves possession of the session being renewed and
|
|
112
|
+
* preserves its `mj_sid` (`sessionId`).
|
|
113
|
+
*/
|
|
114
|
+
BearerToken?: string;
|
|
115
|
+
/**
|
|
116
|
+
* The widget's proof key (public P-256 JWK, from the mint body's `proofKey`). Its thumbprint is signed into
|
|
117
|
+
* the token as `cnf.jkt`; a token minted without one cannot be refreshed.
|
|
118
|
+
*/
|
|
119
|
+
ProofKey?: ProofPublicJwk;
|
|
120
|
+
/** The refresh proof (`DPoP` header), signed by the key registered at mint. Required by `RefreshGuestSession`. */
|
|
121
|
+
Proof?: string;
|
|
70
122
|
audit?: WidgetMintAuditContext; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
|
|
71
123
|
}
|
|
72
124
|
|
|
@@ -210,6 +262,8 @@ export class WidgetSessionService {
|
|
|
210
262
|
constructor(
|
|
211
263
|
private readonly publicUrl: string,
|
|
212
264
|
private readonly config: WidgetConfig,
|
|
265
|
+
/** Which roles a widget may hand to an anonymous guest; by default only the scope-isolated `Widget Guest`. */
|
|
266
|
+
private readonly guestRolePolicy: GuestRolePolicy = { GrantableRoleNames: [] },
|
|
213
267
|
) {}
|
|
214
268
|
|
|
215
269
|
/**
|
|
@@ -237,11 +291,11 @@ export class WidgetSessionService {
|
|
|
237
291
|
return this.audited({ success: false, errorCode: eligibility.errorCode, error: 'Widget mint rejected.' }, input, widget);
|
|
238
292
|
}
|
|
239
293
|
|
|
240
|
-
const
|
|
241
|
-
if (
|
|
242
|
-
|
|
243
|
-
return this.audited({ success: false, errorCode: 'server_error', error: 'Guest role not resolvable.' }, input, widget);
|
|
294
|
+
const guestRole = this.resolveIsolatedGuestRole(widget);
|
|
295
|
+
if (guestRole.ok === false) {
|
|
296
|
+
return this.audited(guestRole.refusal, input, widget);
|
|
244
297
|
}
|
|
298
|
+
const guestRoleName = guestRole.name;
|
|
245
299
|
|
|
246
300
|
// D1 host-identity strategy: a HostIdentity widget MUST present a valid host assertion.
|
|
247
301
|
let hostIdentity: HostAssertedIdentity | undefined;
|
|
@@ -267,7 +321,21 @@ export class WidgetSessionService {
|
|
|
267
321
|
// anonymous trail to that record and surface the pair so the client stamps the new conversation.
|
|
268
322
|
const resolvedIdentity = await this.resolveHostIdentityIfApplicable(widget, hostIdentity, returningVisitor, contextUser);
|
|
269
323
|
|
|
270
|
-
|
|
324
|
+
let proofKeyThumbprint: string | undefined;
|
|
325
|
+
if (input.ProofKey !== undefined) {
|
|
326
|
+
const proofKey = ToProofPublicJwk(input.ProofKey);
|
|
327
|
+
if (!proofKey) {
|
|
328
|
+
LogError(`[Widget] Mint for widget ${widget.ID} refused: the proof key is not a public P-256 JWK.`);
|
|
329
|
+
return this.audited({ success: false, errorCode: 'not_found', error: 'Widget mint rejected.' }, input, widget);
|
|
330
|
+
}
|
|
331
|
+
proofKeyThumbprint = await ComputeJwkThumbprint(proofKey);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return this.audited(
|
|
335
|
+
this.mintToken(widget, guestRoleName, hostIdentity, returningVisitor, resolvedIdentity, undefined, proofKeyThumbprint),
|
|
336
|
+
input,
|
|
337
|
+
widget,
|
|
338
|
+
);
|
|
271
339
|
} catch (e) {
|
|
272
340
|
LogError(e);
|
|
273
341
|
return { success: false, errorCode: 'server_error', error: e instanceof Error ? e.message : String(e) };
|
|
@@ -275,12 +343,147 @@ export class WidgetSessionService {
|
|
|
275
343
|
}
|
|
276
344
|
|
|
277
345
|
/**
|
|
278
|
-
* Refreshes a live guest session
|
|
279
|
-
*
|
|
280
|
-
*
|
|
346
|
+
* Refreshes a live guest session while preserving its per-visitor `sessionId` (`mj_sid`).
|
|
347
|
+
* Requires the caller's current widget guest JWT (`input.BearerToken`), verified against the
|
|
348
|
+
* magic-link signing key with a {@link REFRESH_GRACE_SECONDS} post-expiry grace window, and
|
|
349
|
+
* bound to the resolved widget instance (`mj_widget_id === widget.ID`, `mj_anon === true`,
|
|
350
|
+
* `mj_magic_link === true`). Any failure returns the same uniform 403 shape as an unknown widget key.
|
|
281
351
|
*/
|
|
282
352
|
public async RefreshGuestSession(input: MintGuestSessionInput): Promise<MintGuestSessionResult> {
|
|
283
|
-
|
|
353
|
+
try {
|
|
354
|
+
const contextUser = this.resolveLookupUser();
|
|
355
|
+
if (!contextUser) {
|
|
356
|
+
LogError('[Widget] No lookup context user available; server not configured.');
|
|
357
|
+
return { success: false, errorCode: 'server_error', error: 'Server not configured for widget sessions.' };
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const widget = await this.loadWidgetByKey(input.widgetKey, contextUser);
|
|
361
|
+
if (!widget) {
|
|
362
|
+
return this.audited({ success: false, errorCode: 'not_found', error: 'Unknown widget key.' }, input, undefined);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const eligibility = EvaluateWidgetMint(
|
|
366
|
+
{ Status: widget.Status, AllowedOrigins: widget.AllowedOrigins, Modality: widget.Modality },
|
|
367
|
+
input.origin,
|
|
368
|
+
);
|
|
369
|
+
if (!eligibility.ok) {
|
|
370
|
+
return this.audited({ success: false, errorCode: eligibility.errorCode, error: 'Widget mint rejected.' }, input, widget);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const guestRole = this.resolveIsolatedGuestRole(widget);
|
|
374
|
+
if (guestRole.ok === false) {
|
|
375
|
+
return this.audited(guestRole.refusal, input, widget);
|
|
376
|
+
}
|
|
377
|
+
const guestRoleName = guestRole.name;
|
|
378
|
+
|
|
379
|
+
let hostIdentity: HostAssertedIdentity | undefined;
|
|
380
|
+
if (widget.AuthStrategy === 'HostIdentity') {
|
|
381
|
+
const verified = this.verifyHost(widget, input.hostAssertion);
|
|
382
|
+
if (!verified) {
|
|
383
|
+
return this.audited({ success: false, errorCode: 'host_assertion_invalid', error: 'Host identity assertion invalid.' }, input, widget);
|
|
384
|
+
}
|
|
385
|
+
hostIdentity = verified;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const existingSession = await this.verifyRefreshRequest(input.BearerToken, input.Proof, widget.ID);
|
|
389
|
+
if (!existingSession) {
|
|
390
|
+
return this.audited({ success: false, errorCode: 'not_found', error: 'Unknown widget key.' }, input, widget);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const returningVisitor = await this.resolveReturningVisitor(widget, input.visitorKey, contextUser);
|
|
394
|
+
const resolvedIdentity = await this.resolveHostIdentityIfApplicable(widget, hostIdentity, returningVisitor, contextUser);
|
|
395
|
+
|
|
396
|
+
return this.audited(
|
|
397
|
+
this.mintToken(widget, guestRoleName, hostIdentity, returningVisitor, resolvedIdentity, existingSession, existingSession.KeyThumbprint),
|
|
398
|
+
input,
|
|
399
|
+
widget,
|
|
400
|
+
);
|
|
401
|
+
} catch (e) {
|
|
402
|
+
LogError(e);
|
|
403
|
+
return { success: false, errorCode: 'server_error', error: e instanceof Error ? e.message : String(e) };
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Verifies a `RefreshGuestSession` request: the caller's current widget guest JWT and the proof that the
|
|
409
|
+
* caller holds the key the token is bound to. Returns the session to carry forward, or `null` when the token
|
|
410
|
+
* is missing, tampered, expired past {@link REFRESH_GRACE_SECONDS}, past the session's hard end
|
|
411
|
+
* ({@link MAX_GUEST_SESSION_SECONDS}) or without a session start, non-anonymous, minted for a different
|
|
412
|
+
* widget, issued by another deployment, or not bound to a key; or when the proof is missing or not made by
|
|
413
|
+
* that key for this request and token.
|
|
414
|
+
*/
|
|
415
|
+
private async verifyRefreshRequest(bearerToken: string | undefined, proof: string | undefined, widgetId: string): Promise<RefreshableGuestSession | null> {
|
|
416
|
+
const session = this.verifyRefreshBearerToken(bearerToken, widgetId);
|
|
417
|
+
if (!session) {
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
const verification = await VerifyProofOfPossessionJwt(proof ?? '', {
|
|
421
|
+
Method: 'POST',
|
|
422
|
+
PathSuffix: WIDGET_REFRESH_PATH,
|
|
423
|
+
AccessToken: (bearerToken ?? '').trim(),
|
|
424
|
+
NowSeconds: Math.floor(Date.now() / 1000),
|
|
425
|
+
MaxSkewSeconds: REFRESH_PROOF_MAX_SKEW_SECONDS,
|
|
426
|
+
});
|
|
427
|
+
if (verification.Valid === false) {
|
|
428
|
+
LogError(`[Widget] Refresh proof refused for widget ${widgetId} (${verification.Reason}).`);
|
|
429
|
+
return null;
|
|
430
|
+
}
|
|
431
|
+
if (verification.Thumbprint !== session.KeyThumbprint) {
|
|
432
|
+
LogError(`[Widget] Refresh proof refused for widget ${widgetId}: signed by a key the token is not bound to.`);
|
|
433
|
+
return null;
|
|
434
|
+
}
|
|
435
|
+
return session;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/** The token half of {@link verifyRefreshRequest}: everything except the proof. */
|
|
439
|
+
private verifyRefreshBearerToken(bearerToken: string | undefined, widgetId: string): RefreshableGuestSession | null {
|
|
440
|
+
const token = (bearerToken ?? '').trim();
|
|
441
|
+
if (!token) {
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
try {
|
|
445
|
+
const jwk = MagicLinkKeyManager.Instance.GetJWKS().keys[0];
|
|
446
|
+
if (!jwk) {
|
|
447
|
+
return null;
|
|
448
|
+
}
|
|
449
|
+
const publicKey = createPublicKey({ key: { ...jwk }, format: 'jwk' });
|
|
450
|
+
const verified = jwt.verify(token, publicKey, {
|
|
451
|
+
algorithms: ['RS256'],
|
|
452
|
+
audience: this.config.audience,
|
|
453
|
+
issuer: this.publicUrl,
|
|
454
|
+
ignoreExpiration: true,
|
|
455
|
+
});
|
|
456
|
+
if (typeof verified !== 'object' || verified === null) {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
const payload = verified as jwt.JwtPayload;
|
|
460
|
+
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
461
|
+
if (typeof payload.exp !== 'number' || nowSeconds > payload.exp + REFRESH_GRACE_SECONDS) {
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
if (payload.mj_magic_link !== true || payload.mj_anon !== true) {
|
|
465
|
+
return null;
|
|
466
|
+
}
|
|
467
|
+
if (typeof payload.mj_widget_id !== 'string' || !UUIDsEqual(payload.mj_widget_id, widgetId)) {
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
const sid = typeof payload.mj_sid === 'string' ? payload.mj_sid.trim() : '';
|
|
471
|
+
if (sid.length === 0) {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
const startedAt = payload.mj_sid_iat;
|
|
475
|
+
if (typeof startedAt !== 'number' || !Number.isFinite(startedAt) || startedAt + MAX_GUEST_SESSION_SECONDS - nowSeconds < MIN_REFRESHED_TOKEN_SECONDS) {
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
const keyThumbprint = typeof payload.cnf?.jkt === 'string' ? payload.cnf.jkt : '';
|
|
479
|
+
if (keyThumbprint.length === 0) {
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
return { SessionId: sid, StartedAtSeconds: startedAt, KeyThumbprint: keyThumbprint };
|
|
483
|
+
} catch (e) {
|
|
484
|
+
LogError(`[Widget] Refresh token verification failed for widget ${widgetId}: ${e instanceof Error ? e.message : String(e)}`);
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
284
487
|
}
|
|
285
488
|
|
|
286
489
|
/**
|
|
@@ -343,7 +546,7 @@ export class WidgetSessionService {
|
|
|
343
546
|
* clicks the emailed link → the existing public `POST /magic-link/redeem` mints a VERIFIED session
|
|
344
547
|
* JWT → the widget swaps it in via `transport.UpdateToken`, preserving the live conversationId.
|
|
345
548
|
*
|
|
346
|
-
* This converges on the SAME `AuthProviderFactory` + `
|
|
549
|
+
* This converges on the SAME `AuthProviderFactory` + `BuildMagicLinkSessionUser` path as the guest
|
|
347
550
|
* mint (D1), so the verified session is just a more-privileged principal on the one pathway. Never
|
|
348
551
|
* throws for business failures — returns a structured result.
|
|
349
552
|
*/
|
|
@@ -412,12 +615,18 @@ export class WidgetSessionService {
|
|
|
412
615
|
hostIdentity?: HostAssertedIdentity,
|
|
413
616
|
returningVisitor?: ReturningVisitorResolution,
|
|
414
617
|
resolvedIdentity?: ResolvedVisitorIdentity,
|
|
618
|
+
existingSession?: RefreshableGuestSession,
|
|
619
|
+
proofKeyThumbprint?: string,
|
|
415
620
|
): MintGuestSessionResult {
|
|
416
621
|
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
417
622
|
const ttlMinutes = widget.SessionTTLMinutes || this.config.defaultSessionTtlMinutes;
|
|
418
|
-
// Generated once and
|
|
419
|
-
// this id so the Widget Guest RLS
|
|
420
|
-
|
|
623
|
+
// Generated once on initial mint and preserved across refreshes: the widget (and server-side
|
|
624
|
+
// voice session creation) stamps Conversation.ExternalID with this id so the Widget Guest RLS
|
|
625
|
+
// filters ({{ScopeResourceID}}) and AuthorizeSessionAccess isolate this guest's rows.
|
|
626
|
+
const sessionId = existingSession?.SessionId ?? GenerateSessionId();
|
|
627
|
+
const startedAtSeconds = existingSession?.StartedAtSeconds ?? nowSeconds;
|
|
628
|
+
// No token outlives the session's hard end, so the cap holds for API calls as well as for refresh.
|
|
629
|
+
const ttlSeconds = Math.min(ttlMinutes * 60, startedAtSeconds + MAX_GUEST_SESSION_SECONDS - nowSeconds);
|
|
421
630
|
const claims = BuildWidgetGuestClaims({
|
|
422
631
|
issuer: this.publicUrl,
|
|
423
632
|
audience: this.config.audience,
|
|
@@ -427,7 +636,9 @@ export class WidgetSessionService {
|
|
|
427
636
|
applicationId: widget.ApplicationID,
|
|
428
637
|
guestRoleName,
|
|
429
638
|
nowSeconds,
|
|
430
|
-
ttlSeconds
|
|
639
|
+
ttlSeconds,
|
|
640
|
+
sessionStartedAtSeconds: startedAtSeconds,
|
|
641
|
+
proofKeyThumbprint,
|
|
431
642
|
hostIdentity,
|
|
432
643
|
// RV1/RV2/RV4: carry the returning-visitor anchor + resolved identity as claims so the voice path
|
|
433
644
|
// (server-created conversation) stamps the same fields the text path stamps client-side.
|
|
@@ -650,6 +861,7 @@ export class WidgetSessionService {
|
|
|
650
861
|
ExtraFilter: `VisitorKey = '${visitorKey}' AND ApplicationID = '${applicationId.replace(/'/g, "''")}'`,
|
|
651
862
|
OrderBy: '__mj_CreatedAt DESC',
|
|
652
863
|
MaxRows: 1,
|
|
864
|
+
SkipTotalRowCount: true,
|
|
653
865
|
Fields: ['ID'],
|
|
654
866
|
ResultType: 'simple',
|
|
655
867
|
},
|
|
@@ -674,6 +886,7 @@ export class WidgetSessionService {
|
|
|
674
886
|
EntityName: WIDGET_ENTITY,
|
|
675
887
|
ExtraFilter: `PublicKey = '${key.replace(/'/g, "''")}'`,
|
|
676
888
|
MaxRows: 1,
|
|
889
|
+
SkipTotalRowCount: true,
|
|
677
890
|
ResultType: 'entity_object',
|
|
678
891
|
},
|
|
679
892
|
contextUser,
|
|
@@ -692,6 +905,30 @@ export class WidgetSessionService {
|
|
|
692
905
|
return role?.Name ?? null;
|
|
693
906
|
}
|
|
694
907
|
|
|
908
|
+
/**
|
|
909
|
+
* The ONE decision, for mint and refresh alike, of which role a guest token carries: the widget's `GuestRoleID`
|
|
910
|
+
* must resolve, and it must be a role the deployment may hand to an anonymous visitor
|
|
911
|
+
* ({@link IsIsolatedGuestRole}). Both refusals are the admin's to fix, so both are logged with the widget id;
|
|
912
|
+
* the visitor gets a uniform rejection.
|
|
913
|
+
*/
|
|
914
|
+
private resolveIsolatedGuestRole(
|
|
915
|
+
widget: MJConversationWidgetInstanceEntity,
|
|
916
|
+
): { ok: true; name: string } | { ok: false; refusal: MintGuestSessionResult } {
|
|
917
|
+
const name = this.resolveGuestRoleName(widget.GuestRoleID);
|
|
918
|
+
if (!name) {
|
|
919
|
+
LogError(`[Widget] Guest role ${widget.GuestRoleID} for widget ${widget.ID} not found in metadata.`);
|
|
920
|
+
return { ok: false, refusal: { success: false, errorCode: 'server_error', error: 'Guest role not resolvable.' } };
|
|
921
|
+
}
|
|
922
|
+
if (!IsIsolatedGuestRole(name, this.guestRolePolicy)) {
|
|
923
|
+
LogError(
|
|
924
|
+
`[Widget] Widget ${widget.ID} grants guest role '${name}', whose row filters do not isolate anonymous visitors ` +
|
|
925
|
+
`from each other. Use the Widget Guest role, or list '${name}' in magicLink.grantableRoleNames to allow it (MJ#6043).`,
|
|
926
|
+
);
|
|
927
|
+
return { ok: false, refusal: { success: false, errorCode: 'guest_role_not_isolated', error: 'Widget mint rejected.' } };
|
|
928
|
+
}
|
|
929
|
+
return { ok: true, name };
|
|
930
|
+
}
|
|
931
|
+
|
|
695
932
|
/** Resolves the server-side context user used to READ widget config (not the guest principal). */
|
|
696
933
|
private resolveLookupUser(): UserInfo | null {
|
|
697
934
|
return ResolveConfiguredPrincipal(this.config.contextUserForLookup, 'Widget');
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `POST /widget/session`, which verifies it against the host's registered public key
|
|
6
6
|
* and folds the host-provided identity into the minted guest claims. The minted token
|
|
7
7
|
* is still validated by the same `magic-link` AuthProviderFactory path + synthesized by
|
|
8
|
-
* `
|
|
8
|
+
* `BuildMagicLinkSessionUser` — host-identity is a MINT-TIME strategy, not a second
|
|
9
9
|
* session-validation provider (it converges on the one pathway, per D1).
|
|
10
10
|
*
|
|
11
11
|
* Pure + unit-testable: verification takes the PEM as an argument.
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
* @module @memberjunction/server/widget
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { BuildSessionClaims } from '../auth/magicLink/magicLinkCore.js';
|
|
15
|
+
import { BuildSessionClaims, IsRoleGrantable } from '../auth/magicLink/magicLinkCore.js';
|
|
16
16
|
import type { MagicLinkJWTClaims } from '../auth/magicLink/types.js';
|
|
17
|
+
import { NormalizeOrigin } from '../requestOrigin.js';
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* The magic-link resource-scope `resourceType` used for a widget guest session. Pairs with the
|
|
@@ -31,8 +32,29 @@ export type WidgetMintErrorCode =
|
|
|
31
32
|
| 'host_assertion_invalid'
|
|
32
33
|
| 'upgrade_not_enabled'
|
|
33
34
|
| 'invalid_email'
|
|
35
|
+
| 'guest_role_not_isolated'
|
|
34
36
|
| 'server_error';
|
|
35
37
|
|
|
38
|
+
/**
|
|
39
|
+
* The one stock role whose row filters key on the per-visitor scope id (`{{ScopeResourceID}}`) rather than on
|
|
40
|
+
* `UserID`. Every anonymous widget guest authenticates as the ONE shared Anonymous user, so a role whose filters
|
|
41
|
+
* compare `UserID` (the stock `UI` role, for instance) lets every guest read and update every other guest's rows
|
|
42
|
+
* through the generic API (MJ#6043). A widget may therefore grant only this role, or a role the deployment has
|
|
43
|
+
* explicitly listed as safe for anonymous visitors — the same opt-in list magic-link invites use.
|
|
44
|
+
*/
|
|
45
|
+
export const WIDGET_GUEST_ROLE_NAME = 'Widget Guest';
|
|
46
|
+
|
|
47
|
+
/** Which roles, beyond {@link WIDGET_GUEST_ROLE_NAME}, a deployment allows a widget to hand to an anonymous guest. */
|
|
48
|
+
export interface GuestRolePolicy {
|
|
49
|
+
/** Role names (case-insensitive) the deployment has opted in, normally `magicLink.grantableRoleNames`. */
|
|
50
|
+
GrantableRoleNames: readonly string[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Pure check: may a widget grant `roleName` to an anonymous guest under `policy`? See {@link WIDGET_GUEST_ROLE_NAME}. */
|
|
54
|
+
export function IsIsolatedGuestRole(roleName: string | null | undefined, policy: GuestRolePolicy): boolean {
|
|
55
|
+
return IsRoleGrantable(roleName, WIDGET_GUEST_ROLE_NAME, policy.GrantableRoleNames);
|
|
56
|
+
}
|
|
57
|
+
|
|
36
58
|
/** The minimal widget-instance shape the pure validators need (a subset of the entity). */
|
|
37
59
|
export interface WidgetInstanceEligibilityInput {
|
|
38
60
|
Status: string;
|
|
@@ -56,12 +78,12 @@ export function ParseAllowedOrigins(allowedOrigins: string | null | undefined):
|
|
|
56
78
|
list = JSON.parse(raw);
|
|
57
79
|
} catch {
|
|
58
80
|
// Not JSON — tolerate a CSV form.
|
|
59
|
-
return raw.split(',').map((s) =>
|
|
81
|
+
return raw.split(',').map((s) => NormalizeOrigin(s)).filter((s): s is string => !!s);
|
|
60
82
|
}
|
|
61
83
|
if (!Array.isArray(list)) {
|
|
62
84
|
return [];
|
|
63
85
|
}
|
|
64
|
-
return list.filter((s): s is string => typeof s === 'string').map(
|
|
86
|
+
return list.filter((s): s is string => typeof s === 'string').map(NormalizeOrigin).filter((s): s is string => !!s);
|
|
65
87
|
}
|
|
66
88
|
|
|
67
89
|
/** @deprecated Use {@link ParseAllowedOrigins}. */
|
|
@@ -69,11 +91,6 @@ export function parseAllowedOrigins(allowedOrigins: string | null | undefined):
|
|
|
69
91
|
return ParseAllowedOrigins(allowedOrigins);
|
|
70
92
|
}
|
|
71
93
|
|
|
72
|
-
/** Lowercases + trims an origin and strips a trailing slash for stable comparison. */
|
|
73
|
-
function normalizeOrigin(origin: string): string {
|
|
74
|
-
return origin.trim().toLowerCase().replace(/\/+$/, '');
|
|
75
|
-
}
|
|
76
|
-
|
|
77
94
|
/**
|
|
78
95
|
* Parses the widget's `EnabledChannels` column into a clean list of channel names (Phase 2). Accepts a
|
|
79
96
|
* JSON array (preferred, e.g. `["Whiteboard"]`) or a comma-separated string (tolerated). Returns an
|
|
@@ -108,7 +125,7 @@ export function IsOriginAllowed(requestOrigin: string | null | undefined, allowe
|
|
|
108
125
|
if (!requestOrigin || allowedOrigins.length === 0) {
|
|
109
126
|
return false;
|
|
110
127
|
}
|
|
111
|
-
const candidate =
|
|
128
|
+
const candidate = NormalizeOrigin(requestOrigin);
|
|
112
129
|
return allowedOrigins.some((o) => o === candidate);
|
|
113
130
|
}
|
|
114
131
|
|
|
@@ -206,6 +223,10 @@ export function BuildWidgetGuestClaims(args: {
|
|
|
206
223
|
guestRoleName: string;
|
|
207
224
|
nowSeconds: number;
|
|
208
225
|
ttlSeconds: number;
|
|
226
|
+
/** When `sessionId` was first minted (`mj_sid_iat`); a refresh passes the original. Defaults to `nowSeconds`. */
|
|
227
|
+
sessionStartedAtSeconds?: number;
|
|
228
|
+
/** Thumbprint of the widget's proof key (`cnf.jkt`). Without it the token cannot be refreshed. */
|
|
229
|
+
proofKeyThumbprint?: string;
|
|
209
230
|
/**
|
|
210
231
|
* Host-asserted identity for a `host-identity` session. Its email/name are carried as
|
|
211
232
|
* INFORMATIONAL claims only — the principal-resolving `email`/`sub` remain the shared
|
|
@@ -248,6 +269,10 @@ export function BuildWidgetGuestClaims(args: {
|
|
|
248
269
|
});
|
|
249
270
|
// Additive widget claim — lets the synthesized principal be bound to one widget.
|
|
250
271
|
claims.mj_widget_id = args.widgetId;
|
|
272
|
+
claims.mj_sid_iat = args.sessionStartedAtSeconds ?? args.nowSeconds;
|
|
273
|
+
if (args.proofKeyThumbprint) {
|
|
274
|
+
claims.cnf = { jkt: args.proofKeyThumbprint };
|
|
275
|
+
}
|
|
251
276
|
if (args.hostIdentity) {
|
|
252
277
|
claims.given_name = args.hostIdentity.firstName ?? claims.given_name;
|
|
253
278
|
claims.family_name = args.hostIdentity.lastName ?? claims.family_name;
|
|
@@ -41,7 +41,7 @@ export interface WidgetGuestRunContext {
|
|
|
41
41
|
* Returns elevation context when the request is a public web-widget guest, else `null` (the common
|
|
42
42
|
* case — every non-widget request). A widget guest is identified by the synthesized principal's
|
|
43
43
|
* `IsMagicLinkAnonymous` flag plus a `WidgetGuestContext.WidgetID` (sourced from the signed
|
|
44
|
-
* `mj_widget_id` claim by `
|
|
44
|
+
* `mj_widget_id` claim by `BuildMagicLinkSessionUser`). The widget instance is loaded under the
|
|
45
45
|
* SYSTEM principal so resolving the pinned agent does not depend on the guest's narrow grants.
|
|
46
46
|
*
|
|
47
47
|
* Never throws: a resolution failure (no system user, widget not found, read error) returns `null`,
|
|
@@ -169,6 +169,7 @@ export function ElevateUserPayload(userPayload: UserPayload, elevatedUser: UserI
|
|
|
169
169
|
email: elevatedUser.Email,
|
|
170
170
|
userRecord: elevatedUser,
|
|
171
171
|
isSystemUser: true,
|
|
172
|
+
ElevatedFrom: userPayload.userRecord,
|
|
172
173
|
};
|
|
173
174
|
}
|
|
174
175
|
|
|
@@ -189,6 +190,7 @@ async function loadWidgetById(
|
|
|
189
190
|
EntityName: WIDGET_ENTITY,
|
|
190
191
|
ExtraFilter: `ID = '${widgetId.replace(/'/g, "''")}'`,
|
|
191
192
|
MaxRows: 1,
|
|
193
|
+
SkipTotalRowCount: true,
|
|
192
194
|
ResultType: 'entity_object',
|
|
193
195
|
},
|
|
194
196
|
elevatedUser,
|