@memberjunction/server 6.2.0-edge.4 → 6.2.0-edge.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/SessionJanitor.d.ts +91 -30
- package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
- package/dist/agentSessions/SessionJanitor.js +311 -81
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/agentSessions/SessionManager.d.ts +17 -3
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +44 -10
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/apiRoot.d.ts +32 -0
- package/dist/apiRoot.d.ts.map +1 -0
- package/dist/apiRoot.js +67 -0
- package/dist/apiRoot.js.map +1 -0
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.js +27 -0
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
- package/dist/auth/LoginScreenEngine.d.ts +22 -0
- package/dist/auth/LoginScreenEngine.d.ts.map +1 -0
- package/dist/auth/LoginScreenEngine.js +57 -0
- package/dist/auth/LoginScreenEngine.js.map +1 -0
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +52 -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/magicLink/MagicLinkKeys.d.ts +2 -2
- package/dist/auth/magicLink/MagicLinkKeys.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkKeys.js +1 -1
- package/dist/auth/magicLink/MagicLinkKeys.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +3 -2
- package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
- package/dist/auth/magicLink/types.d.ts +12 -0
- package/dist/auth/magicLink/types.d.ts.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/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 +632 -22
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +104 -4
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +3 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +29 -8
- package/dist/context.js.map +1 -1
- package/dist/coreRoutes.d.ts +29 -0
- package/dist/coreRoutes.d.ts.map +1 -0
- package/dist/coreRoutes.js +156 -0
- package/dist/coreRoutes.js.map +1 -0
- package/dist/generated/graphql-schemas/__mj.d.ts +1016 -29
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +5125 -434
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +85 -30
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +175 -60
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js +2 -0
- 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 +94 -12
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +168 -69
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +464 -405
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +11 -3
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +91 -13
- 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/globalCors.d.ts +33 -0
- package/dist/globalCors.d.ts.map +1 -0
- package/dist/globalCors.js +58 -0
- package/dist/globalCors.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +230 -222
- package/dist/index.js.map +1 -1
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +6 -1
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- 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/multiTenancy/index.d.ts.map +1 -1
- package/dist/multiTenancy/index.js +22 -2
- package/dist/multiTenancy/index.js.map +1 -1
- package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -1
- package/dist/realtimeSessions/RealtimeSessionVerificationService.js +2 -1
- package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -1
- package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -1
- package/dist/realtimeSessions/RealtimeVerifyRouter.js +2 -1
- package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -1
- package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts +100 -0
- package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts.map +1 -0
- package/dist/realtimeSessions/RecordingAssemblyScheduler.js +173 -0
- package/dist/realtimeSessions/RecordingAssemblyScheduler.js.map +1 -0
- 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/index.d.ts +2 -0
- package/dist/realtimeSessions/index.d.ts.map +1 -1
- package/dist/realtimeSessions/index.js +2 -0
- package/dist/realtimeSessions/index.js.map +1 -1
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts +32 -0
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -0
- package/dist/realtimeSessions/ownedRealtimeSession.js +56 -0
- package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -0
- package/dist/realtimeSessions/sessionAccess.d.ts +91 -8
- package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
- package/dist/realtimeSessions/sessionAccess.js +127 -20
- 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 +201 -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/widgetCore.d.ts +20 -1
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetCore.js +17 -1
- 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 +2 -1
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- 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 +40 -17
- package/dist/resolvers/AgentSessionResolver.js.map +1 -1
- package/dist/resolvers/ArtifactFileResolver.d.ts +5 -1
- package/dist/resolvers/ArtifactFileResolver.d.ts.map +1 -1
- package/dist/resolvers/ArtifactFileResolver.js +9 -7
- package/dist/resolvers/ArtifactFileResolver.js.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.d.ts +8 -4
- package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.js +6 -6
- package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
- package/dist/resolvers/DatasetResolver.d.ts +24 -3
- package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
- package/dist/resolvers/DatasetResolver.js +57 -8
- package/dist/resolvers/DatasetResolver.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/EntityRecordNameResolver.d.ts +2 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js +3 -2
- package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts +46 -3
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js +211 -50
- 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 +87 -11
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +292 -105
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts +33 -7
- package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.js +117 -38
- package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +6 -3
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +49 -9
- package/dist/resolvers/IntegrationDiscoveryResolver.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 +2 -0
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +33 -6
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +2 -0
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +15 -6
- 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/RealtimeClientSessionResolver.d.ts +18 -10
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +92 -54
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +11 -9
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +56 -8
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +241 -67
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +4 -4
- 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/SearchKnowledgeStreamResolver.d.ts +12 -1
- package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeStreamResolver.js +15 -2
- package/dist/resolvers/SearchKnowledgeStreamResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +2 -3
- package/dist/resolvers/SqlLoggingConfigResolver.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/TaskGraphFrameResolver.d.ts +2 -1
- package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.js +28 -1
- package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.d.ts +24 -0
- package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.js +66 -13
- package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts +34 -2
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +150 -27
- 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/agent-run-data-guard.d.ts +31 -0
- package/dist/resolvers/agent-run-data-guard.d.ts.map +1 -0
- package/dist/resolvers/agent-run-data-guard.js +72 -0
- package/dist/resolvers/agent-run-data-guard.js.map +1 -0
- 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/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 +49 -0
- package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -0
- package/dist/rest/RealtimeRecordingHandler.js +383 -0
- package/dist/rest/RealtimeRecordingHandler.js.map +1 -0
- package/dist/rest/ViewOperationsHandler.d.ts +9 -1
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +43 -17
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +6 -0
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +6 -0
- package/dist/rest/setupRESTEndpoints.js.map +1 -1
- package/dist/serverExtensionReservedRoots.d.ts +12 -10
- package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
- package/dist/serverExtensionReservedRoots.js +14 -17
- package/dist/serverExtensionReservedRoots.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/MJStorageBlobStore.d.ts +8 -1
- package/dist/services/MJStorageBlobStore.d.ts.map +1 -1
- package/dist/services/MJStorageBlobStore.js +25 -19
- package/dist/services/MJStorageBlobStore.js.map +1 -1
- package/dist/services/StartTaskGraphDispatcher.js +2 -2
- package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
- package/dist/services/TaskGraphActionRunner.d.ts +5 -3
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphActionRunner.js +27 -5
- package/dist/services/TaskGraphActionRunner.js.map +1 -1
- package/dist/services/TaskGraphAgentRunner.d.ts +14 -2
- package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphAgentRunner.js +157 -9
- package/dist/services/TaskGraphAgentRunner.js.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.d.ts +59 -2
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +626 -16
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/sharedCache.d.ts.map +1 -1
- package/dist/sharedCache.js +3 -0
- package/dist/sharedCache.js.map +1 -1
- package/dist/types.d.ts +23 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +99 -98
- package/src/__tests__/ActionResolver.fieldSecurity.test.ts +237 -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 +137 -0
- package/src/__tests__/CustomColumnPromoterOnePass.test.ts +15 -1
- package/src/__tests__/DatasetResolver.itemFilters.test.ts +201 -0
- package/src/__tests__/EntityCommunicationsResolver.actingUser.test.ts +151 -0
- package/src/__tests__/EntityRecordNameResolver.rowSecurity.test.ts +152 -0
- package/src/__tests__/EvolutionActsOnWhatItDetects.test.ts +113 -0
- package/src/__tests__/FetchEntityVectorsResolver.test.ts +369 -18
- package/src/__tests__/FileResolver.fieldSecurity.test.ts +82 -0
- package/src/__tests__/FileResolver.storageAccess.test.ts +562 -0
- package/src/__tests__/GetDataContextDataResolver.sqlItems.test.ts +416 -0
- package/src/__tests__/ListOperationsResolver.adhocScreen.test.ts +137 -0
- package/src/__tests__/LoginScreenEngine.test.ts +86 -0
- package/src/__tests__/MJStorageBlobStore.storageGate.test.ts +63 -0
- package/src/__tests__/PipelineProgressResolver.filter.test.ts +58 -0
- package/src/__tests__/QuerySystemUserResolver.fieldSecurity.test.ts +49 -0
- package/src/__tests__/RESTEndpointHandler.test.ts +25 -0
- package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +23 -3
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +324 -46
- package/src/__tests__/RecordingAssemblyScheduler.test.ts +178 -0
- package/src/__tests__/RemoteBrowserActionResolver.ownership.test.ts +98 -0
- package/src/__tests__/ResolverBase.adhocReadScope.test.ts +133 -2
- package/src/__tests__/ResolverBase.balancedClause.test.ts +155 -0
- package/src/__tests__/ResolverBase.clauseUnscopedRead.test.ts +127 -0
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +243 -7
- package/src/__tests__/ResolverBase.deleteReturnProjection.test.ts +52 -0
- package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +176 -0
- package/src/__tests__/ResolverBase.filterEscaping.test.ts +5 -2
- package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +23 -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 +69 -13
- package/src/__tests__/RunAIAgentResolver.conversationWriter.test.ts +210 -0
- package/src/__tests__/RunAIAgentResolver.fireAndForgetCompletion.test.ts +209 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +20 -28
- package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +264 -0
- package/src/__tests__/RunAIAgentResolver.serverReply.test.ts +358 -0
- package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +4 -1
- package/src/__tests__/RunTemplateResolver.test.ts +35 -2
- package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +11 -0
- package/src/__tests__/RunViewResolver.cacheCheckScreen.test.ts +165 -0
- package/src/__tests__/SearchKnowledgeStreamResolver.test.ts +161 -0
- package/src/__tests__/SessionJanitor.test.ts +365 -10
- package/src/__tests__/SessionManager.test.ts +122 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +25 -0
- package/src/__tests__/TaskGraphAgentRunner.test.ts +266 -0
- package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +468 -23
- package/src/__tests__/TaskGraphFrameResolver.test.ts +22 -0
- package/src/__tests__/TestQuerySQLResolver.test.ts +274 -0
- package/src/__tests__/TransactionGroupResolver.fieldSecurity.test.ts +199 -0
- package/src/__tests__/TransactionGroupResolver.refusals.test.ts +98 -1
- package/src/__tests__/UpdateMJDataContextItem.oldValues.test.ts +220 -0
- package/src/__tests__/UserViewResolver.updateWhereClause.test.ts +15 -0
- package/src/__tests__/ViewOperationsHandler.clauseScreen.test.ts +157 -0
- package/src/__tests__/ViewOperationsHandler.test.ts +7 -2
- package/src/__tests__/WidgetSessionService.test.ts +583 -4
- package/src/__tests__/agent-run-data-guard.test.ts +130 -0
- package/src/__tests__/apiRootBoot.test.ts +202 -0
- package/src/__tests__/buildMagicLinkSessionUser.test.ts +96 -0
- package/src/__tests__/cacheBroadcastProviders.test.ts +403 -0
- package/src/__tests__/cacheInvalidationRecordData.test.ts +109 -0
- package/src/__tests__/conversationRunEvents.test.ts +56 -14
- package/src/__tests__/fieldSecurityFixtures.ts +91 -0
- package/src/__tests__/globalCors.test.ts +217 -0
- package/src/__tests__/localDevAuth.test.ts +196 -0
- package/src/__tests__/multiTenancy.postgresRewrite.test.ts +181 -0
- package/src/__tests__/multiTenancy.security.test.ts +51 -0
- package/src/__tests__/multiTenancy.test.ts +1 -1
- package/src/__tests__/orphanedConversationDetailReconciler.test.ts +10 -0
- package/src/__tests__/ownedRealtimeSession.test.ts +39 -0
- package/src/__tests__/pushStatusResolver.filter.test.ts +64 -1
- package/src/__tests__/realtimeRecordingHandler.test.ts +669 -0
- 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 +146 -7
- package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +1 -1
- package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +25 -4
- 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__/serverExtensionHostOverlay.test.ts +66 -0
- package/src/__tests__/serverExtensionReservedRoots.test.ts +11 -98
- package/src/__tests__/sessionUserClone.test.ts +5 -1
- package/src/__tests__/sharedCache.test.ts +5 -3
- package/src/__tests__/startupSweepOrder.test.ts +40 -0
- package/src/__tests__/unifiedAuth.test.ts +28 -0
- package/src/__tests__/widgetGuestElevation.test.ts +2 -0
- package/src/agentSessions/SessionJanitor.ts +369 -93
- package/src/agentSessions/SessionManager.ts +45 -10
- package/src/apiRoot.ts +78 -0
- package/src/auth/AuthProviderCatalogRouter.ts +29 -0
- package/src/auth/LoginScreenEngine.ts +50 -0
- package/src/auth/index.ts +57 -12
- package/src/auth/initializeProviders.ts +43 -1
- package/src/auth/localDevAuth.ts +528 -0
- package/src/auth/magicLink/MagicLinkKeys.ts +2 -2
- package/src/auth/magicLink/MagicLinkRouter.ts +3 -2
- package/src/auth/magicLink/types.ts +10 -0
- package/src/auth/sessionUserClone.ts +3 -2
- 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 +115 -5
- package/src/context.ts +32 -8
- package/src/coreRoutes.ts +181 -0
- package/src/generated/graphql-schemas/__mj.ts +3684 -284
- package/src/generic/CacheInvalidationResolver.ts +172 -60
- package/src/generic/OrphanedConversationDetailReconciler.ts +4 -2
- package/src/generic/PubSubManager.ts +54 -1
- package/src/generic/PushStatusResolver.ts +109 -12
- package/src/generic/ResolverBase.ts +540 -431
- package/src/generic/RunViewResolver.ts +97 -15
- package/src/generic/actionOutputFieldSecurity.ts +75 -0
- package/src/generic/fieldSecurityTransport.ts +62 -0
- package/src/globalCors.ts +71 -0
- package/src/index.ts +239 -238
- package/src/integration/CustomColumnPromoter.ts +6 -1
- package/src/logging/variablesLoggingMiddleware.ts +59 -3
- package/src/multiTenancy/index.ts +24 -2
- package/src/realtimeSessions/README.md +7 -3
- package/src/realtimeSessions/RealtimeSessionVerificationService.ts +2 -1
- package/src/realtimeSessions/RealtimeVerifyRouter.ts +2 -1
- package/src/realtimeSessions/RecordingAssemblyScheduler.ts +234 -0
- package/src/realtimeSessions/SessionVerificationPortsBase.ts +1 -0
- package/src/realtimeSessions/index.ts +2 -0
- package/src/realtimeSessions/ownedRealtimeSession.ts +69 -0
- package/src/realtimeSessions/sessionAccess.ts +183 -23
- 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 +252 -17
- package/src/realtimeWidget/host-identity.ts +1 -1
- package/src/realtimeWidget/widgetCore.ts +30 -1
- package/src/realtimeWidget/widgetGuestElevation.ts +2 -1
- 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 +46 -18
- package/src/resolvers/ArtifactFileResolver.ts +9 -8
- package/src/resolvers/ConversationRunEventsResolver.ts +15 -11
- package/src/resolvers/DatasetResolver.ts +70 -10
- package/src/resolvers/EntityCommunicationsResolver.ts +56 -15
- package/src/resolvers/EntityRecordNameResolver.ts +3 -2
- package/src/resolvers/FetchEntityVectorsResolver.ts +248 -55
- package/src/resolvers/FileCategoryResolver.ts +1 -0
- package/src/resolvers/FileResolver.ts +334 -109
- package/src/resolvers/GetDataContextDataResolver.ts +139 -41
- package/src/resolvers/GetDataResolver.ts +6 -3
- package/src/resolvers/IntegrationDiscoveryResolver.ts +53 -9
- package/src/resolvers/MergeRecordsResolver.ts +23 -2
- package/src/resolvers/PipelineProgressResolver.ts +12 -3
- package/src/resolvers/QueryResolver.ts +31 -6
- package/src/resolvers/QuerySystemUserResolver.ts +15 -6
- package/src/resolvers/RSUResolver.ts +12 -0
- package/src/resolvers/RealtimeClientSessionResolver.ts +114 -66
- package/src/resolvers/RemoteBrowserActionResolver.ts +15 -10
- package/src/resolvers/RunAIAgentResolver.ts +296 -85
- package/src/resolvers/RunTemplateResolver.ts +6 -4
- package/src/resolvers/RunTestResolver.ts +3 -1
- package/src/resolvers/SearchKnowledgeStreamResolver.ts +19 -3
- package/src/resolvers/SqlLoggingConfigResolver.ts +2 -4
- package/src/resolvers/SyncDataResolver.ts +4 -0
- package/src/resolvers/TaskGraphFrameResolver.ts +33 -1
- package/src/resolvers/TestQuerySQLResolver.ts +69 -13
- package/src/resolvers/TransactionGroupResolver.ts +185 -30
- package/src/resolvers/UserViewResolver.ts +2 -1
- package/src/resolvers/__tests__/GetDataResolver.validation.test.ts +95 -0
- package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +43 -0
- package/src/resolvers/agent-run-data-guard.ts +89 -0
- package/src/rest/EntityCRUDHandler.ts +22 -5
- package/src/rest/RESTEndpointHandler.ts +8 -5
- package/src/rest/RealtimeRecordingHandler.ts +467 -0
- package/src/rest/ViewOperationsHandler.ts +52 -18
- package/src/rest/setupRESTEndpoints.ts +6 -0
- package/src/serverExtensionReservedRoots.ts +14 -17
- package/src/serverRoleConfigUnits.ts +48 -0
- package/src/services/MJStorageBlobStore.ts +31 -30
- package/src/services/StartTaskGraphDispatcher.ts +2 -2
- package/src/services/TaskGraphActionRunner.ts +25 -5
- package/src/services/TaskGraphAgentRunner.ts +188 -11
- package/src/services/TaskGraphContinuationDeliverer.ts +738 -16
- package/src/sharedCache.ts +3 -0
- package/src/types.ts +23 -1
|
@@ -12,6 +12,8 @@ import { GetHostInstanceID } from './HostInstance.js';
|
|
|
12
12
|
import { WriteReturningVisitorRecap } from './ReturningVisitorRecap.js';
|
|
13
13
|
import { SessionRunIDVerifier, SessionRunIDs } from './SessionRunIDVerifier.js';
|
|
14
14
|
import { ResolveScopedAnonymousRunUser } from '../realtimeWidget/widgetGuestElevation.js';
|
|
15
|
+
import { RecordingAssemblyScheduler } from '../realtimeSessions/RecordingAssemblyScheduler.js';
|
|
16
|
+
import { ResolveSessionScopeIdentity } from '../realtimeSessions/sessionAccess.js';
|
|
15
17
|
|
|
16
18
|
/** Entity names — centralised so the `MJ:`-prefix convention is applied in exactly one place. */
|
|
17
19
|
const SESSION_ENTITY = 'MJ: AI Agent Sessions';
|
|
@@ -152,11 +154,13 @@ export class SessionManager {
|
|
|
152
154
|
/**
|
|
153
155
|
* Authorize and create a new session. Flow:
|
|
154
156
|
* 1. `CanRun` check on the agent — denied → {@link SessionAuthorizationError}, no row written.
|
|
155
|
-
* 2. Resolve the conversation (use the supplied one, or create+link a fresh Conversation).
|
|
157
|
+
* 2. Resolve the conversation (use the supplied one, or create+link a fresh Conversation). An anonymous
|
|
158
|
+
* caller may only supply a conversation stamped with its own scope identity.
|
|
156
159
|
* 3. Persist the `AIAgentSession` as `Active`, stamped with this host and `LastActiveAt = now`.
|
|
157
160
|
*
|
|
158
161
|
* @returns the saved {@link MJAIAgentSessionEntity}.
|
|
159
|
-
* @throws {SessionAuthorizationError} when the user may not run the agent
|
|
162
|
+
* @throws {SessionAuthorizationError} when the user may not run the agent, or an anonymous caller supplies a
|
|
163
|
+
* conversation that is not its own.
|
|
160
164
|
* @throws {Error} when conversation creation or session save fails.
|
|
161
165
|
*/
|
|
162
166
|
public async CreateSession(
|
|
@@ -165,6 +169,9 @@ export class SessionManager {
|
|
|
165
169
|
provider: IMetadataProvider,
|
|
166
170
|
): Promise<MJAIAgentSessionEntity> {
|
|
167
171
|
await this.assertCanRun(input.agentID, contextUser);
|
|
172
|
+
if (input.conversationID && contextUser.IsMagicLinkAnonymous) {
|
|
173
|
+
await this.assertAnonymousOwnsConversation(input.conversationID, contextUser, provider);
|
|
174
|
+
}
|
|
168
175
|
|
|
169
176
|
const conversationID = input.conversationID
|
|
170
177
|
?? await this.createConversation(input, contextUser, provider);
|
|
@@ -212,6 +219,13 @@ export class SessionManager {
|
|
|
212
219
|
if (!closed) {
|
|
213
220
|
return false;
|
|
214
221
|
}
|
|
222
|
+
if (session.RecordingStartedAt) {
|
|
223
|
+
// A client-direct recording is assembled only after the grace period while its call is open
|
|
224
|
+
// (a hidden tab must not rewrite recording.wav on every switch; see RealtimeRecordingHandler).
|
|
225
|
+
// The call has ended now, so assemble it right away. The ledger's claim arbitrates instances,
|
|
226
|
+
// and a recording with nothing to assemble (none, or server-bridged) is simply not claimable.
|
|
227
|
+
RecordingAssemblyScheduler.Instance.ScheduleAssembly(agentSessionID, 0, false);
|
|
228
|
+
}
|
|
215
229
|
await this.disconnectChannels(agentSessionID, contextUser, provider, preloadedChannels);
|
|
216
230
|
await this.finalizeObservabilityRuns(session, contextUser, provider);
|
|
217
231
|
await this.notifyChannelPluginsSessionClosed(agentSessionID, closeReason);
|
|
@@ -440,6 +454,23 @@ export class SessionManager {
|
|
|
440
454
|
|
|
441
455
|
// ----- internals -------------------------------------------------------------------------
|
|
442
456
|
|
|
457
|
+
/**
|
|
458
|
+
* Throws {@link SessionAuthorizationError} unless the anonymous caller owns the conversation it wants to bind a
|
|
459
|
+
* new session to: the conversation, read as the caller, loads, and its `ExternalID` equals the caller's scope
|
|
460
|
+
* identity ({@link ResolveSessionScopeIdentity}). A caller with no scope identity is refused. Every anonymous
|
|
461
|
+
* visitor shares one Anonymous user, so row-level security alone may let one visitor read another's
|
|
462
|
+
* conversation; without this check the new session row and its relays would point into that conversation.
|
|
463
|
+
*/
|
|
464
|
+
private async assertAnonymousOwnsConversation(conversationID: string, contextUser: UserInfo, provider: IMetadataProvider): Promise<void> {
|
|
465
|
+
const conversation = await provider.GetEntityObject<MJConversationEntity>(CONVERSATION_ENTITY, contextUser);
|
|
466
|
+
const loaded = await conversation.Load(conversationID);
|
|
467
|
+
const scopeIdentity = ResolveSessionScopeIdentity(contextUser);
|
|
468
|
+
if (!loaded || !scopeIdentity || conversation.ExternalID !== scopeIdentity) {
|
|
469
|
+
LogError(`SessionManager.CreateSession: refused anonymous user ${contextUser.ID} binding a session to conversation ${conversationID} (${loaded ? 'not its own' : 'not readable'}).`);
|
|
470
|
+
throw new SessionAuthorizationError('Not authorized to start a session on this conversation.');
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
443
474
|
/** Throws {@link SessionAuthorizationError} unless the user has `CanRun` on the agent. */
|
|
444
475
|
private async assertCanRun(agentID: string, contextUser: UserInfo): Promise<void> {
|
|
445
476
|
const canRun = await AIAgentPermissionHelper.HasPermission(agentID, contextUser, 'run');
|
|
@@ -460,13 +491,13 @@ export class SessionManager {
|
|
|
460
491
|
conversation.NewRecord();
|
|
461
492
|
conversation.UserID = input.userID;
|
|
462
493
|
conversation.Name = 'Agent Session';
|
|
463
|
-
//
|
|
464
|
-
//
|
|
465
|
-
//
|
|
466
|
-
//
|
|
467
|
-
|
|
468
|
-
if (
|
|
469
|
-
conversation.ExternalID =
|
|
494
|
+
// Stamp the scope identity AuthorizeSessionAccess compares against (one rule, one place:
|
|
495
|
+
// ResolveSessionScopeIdentity) — the token's resource scope when it has one, else an anonymous
|
|
496
|
+
// visitor's mj_sid. This isolates anonymous visitors that share the Anonymous UserID, and keeps
|
|
497
|
+
// the {{ScopeResourceID}} RLS filters matching the visitor's own rows. No-op for unscoped named principals.
|
|
498
|
+
const scopeIdentity = ResolveSessionScopeIdentity(contextUser);
|
|
499
|
+
if (scopeIdentity) {
|
|
500
|
+
conversation.ExternalID = scopeIdentity;
|
|
470
501
|
}
|
|
471
502
|
|
|
472
503
|
// Returning-visitor memory (RV1/RV2/RV4) for the VOICE path: the widget guest token carries the
|
|
@@ -530,7 +561,11 @@ export class SessionManager {
|
|
|
530
561
|
return session;
|
|
531
562
|
}
|
|
532
563
|
|
|
533
|
-
/**
|
|
564
|
+
/**
|
|
565
|
+
* Loads a session entity by ID, returning null when it cannot be loaded. The lifecycle saves that
|
|
566
|
+
* follow cannot write back the recording ledger's columns: those have `AllowUpdateAPI=0`, so they are
|
|
567
|
+
* not parameters of `spUpdateAIAgentSession` (#5294, #6010).
|
|
568
|
+
*/
|
|
534
569
|
private async loadSession(
|
|
535
570
|
agentSessionID: string,
|
|
536
571
|
contextUser: UserInfo,
|
package/src/apiRoot.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MJAPI's base path: the single prefix every route MJAPI serves is mounted under (MJ #5674).
|
|
3
|
+
*
|
|
4
|
+
* MJAPI does not know where a proxy exposes it. Behind a proxy that forwards a prefix WITHOUT stripping it
|
|
5
|
+
* (CloudFront `/api/*` → MJAPI), MJAPI must listen under that prefix, so the host sets
|
|
6
|
+
* `MJAPI_BASE_PATH=/api`. Behind a stripping proxy, or with no proxy, it stays `/`. Every mount and every
|
|
7
|
+
* URL handed to a browser, an email or a webhook provider goes through {@link ApiRoute}, so one setting moves
|
|
8
|
+
* them all. CI enforces this (`check:api-root` and `__tests__/apiRootBoot.test.ts`).
|
|
9
|
+
*
|
|
10
|
+
* `GRAPHQL_ROOT_PATH` is a separate thing: only where Apollo listens. Do not derive routes from it.
|
|
11
|
+
*
|
|
12
|
+
* At the default base path `/` every value here is byte-identical to the root-mounted paths MJAPI always used.
|
|
13
|
+
*/
|
|
14
|
+
import { TrimTrailingSlashes } from '@memberjunction/global';
|
|
15
|
+
import { configInfo } from './config.js';
|
|
16
|
+
|
|
17
|
+
/** Options for {@link ApiRoute}. */
|
|
18
|
+
export interface ApiRouteOptions {
|
|
19
|
+
/** Return the public absolute URL (`MJAPI_PUBLIC_URL` + subpath) instead of the server mount path. */
|
|
20
|
+
absolute?: boolean; // case-violation-ok-legacy-back-compat: the `{ absolute: true }` option shape is the documented #5674 contract
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Normalizes a base-path value to a prefix with no trailing slash: `''` for `/`, `'/api'` for `/api/` or
|
|
25
|
+
* `/api`. Throws on a value that does not start with `/`, since Express would mount it nowhere.
|
|
26
|
+
*/
|
|
27
|
+
export function NormalizeApiRootPath(rootPath: string | undefined): string {
|
|
28
|
+
const trimmed = (rootPath ?? '').trim();
|
|
29
|
+
if (trimmed && !trimmed.startsWith('/')) {
|
|
30
|
+
throw new Error(`MJAPI_BASE_PATH must start with '/', got '${trimmed}'`);
|
|
31
|
+
}
|
|
32
|
+
return TrimTrailingSlashes(trimmed);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function assertSubpath(subpath: string): void {
|
|
36
|
+
if (typeof subpath !== 'string' || !subpath.startsWith('/')) {
|
|
37
|
+
throw new Error(`ApiRoute subpath must start with '/', got '${String(subpath)}'`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Joins a base path and a subpath relative to it. Pure, so tests can drive any base path. */
|
|
42
|
+
export function JoinApiRoute(apiRootPath: string, subpath: string): string {
|
|
43
|
+
assertSubpath(subpath);
|
|
44
|
+
return `${NormalizeApiRootPath(apiRootPath)}${subpath}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The running server's base path (`MJAPI_BASE_PATH`, no trailing slash; `''` at `/`). */
|
|
48
|
+
export function ApiRootPath(): string {
|
|
49
|
+
return NormalizeApiRootPath(configInfo.apiBasePath);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The server's configured public URL, derived exactly as it always has been: `MJAPI_PUBLIC_URL`, else
|
|
54
|
+
* `baseUrl:graphqlPort` + `graphqlRootPath`. Unchanged and untrimmed on purpose: it is the magic-link JWT
|
|
55
|
+
* issuer and the `publicUrl` handed to OAuth and server extensions, and changing it would invalidate issued
|
|
56
|
+
* tokens. Build URLs with `ApiRoute(subpath, { absolute: true })`, not from this.
|
|
57
|
+
*/
|
|
58
|
+
export function ConfiguredPublicUrl(): string {
|
|
59
|
+
return configInfo.publicUrl || `${configInfo.baseUrl}:${configInfo.graphqlPort}${configInfo.graphqlRootPath || ''}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The path (or, with `{ absolute: true }`, the public URL) of a route under MJAPI's base path.
|
|
64
|
+
*
|
|
65
|
+
* `subpath` is relative to the base path and must start with `/`.
|
|
66
|
+
* - `ApiRoute('/media')` → `/media` at base `/`, `/api/media` at `MJAPI_BASE_PATH=/api`.
|
|
67
|
+
* - `ApiRoute('/media/abc', { absolute: true })` → `${MJAPI_PUBLIC_URL}/media/abc`. `MJAPI_PUBLIC_URL` is
|
|
68
|
+
* wherever the world reaches MJAPI (prefix included), so the base path is never added to it. Without it,
|
|
69
|
+
* the local fallback is `baseUrl:graphqlPort` + the base path.
|
|
70
|
+
*/
|
|
71
|
+
export function ApiRoute(subpath: string, options?: ApiRouteOptions): string {
|
|
72
|
+
if (!options?.absolute) {
|
|
73
|
+
return JoinApiRoute(ApiRootPath(), subpath);
|
|
74
|
+
}
|
|
75
|
+
assertSubpath(subpath);
|
|
76
|
+
const base = configInfo.publicUrl || `${configInfo.baseUrl}:${configInfo.graphqlPort}${ApiRootPath()}`;
|
|
77
|
+
return `${TrimTrailingSlashes(base)}${subpath}`;
|
|
78
|
+
}
|
|
@@ -12,6 +12,8 @@ import { Router, type Request, type Response } from 'express';
|
|
|
12
12
|
import { rateLimit } from 'express-rate-limit';
|
|
13
13
|
import { LogError, type PublicAuthProviderCatalog } from '@memberjunction/core';
|
|
14
14
|
import { AuthProviderEngine } from './AuthProviderEngine.js';
|
|
15
|
+
import { EMPTY_PUBLIC_LOGIN_SCREEN, LoginScreenEngine } from './LoginScreenEngine.js';
|
|
16
|
+
import { AttachLocalDevAuthRoutes } from './localDevAuth.js';
|
|
15
17
|
|
|
16
18
|
/** Mount path for the public catalog router. */
|
|
17
19
|
export const AUTH_CATALOG_MOUNT_PATH = '/auth';
|
|
@@ -72,6 +74,33 @@ export function CreateAuthProviderCatalogRouter(): Router {
|
|
|
72
74
|
}
|
|
73
75
|
});
|
|
74
76
|
|
|
77
|
+
/**
|
|
78
|
+
* `GET /auth/login-screen`: the default theme's PUBLISHED sign-in page, logos and seeds, for the login
|
|
79
|
+
* screen to draw before anyone signs in. Its own rate-limit budget (a 429 must answer in this route's
|
|
80
|
+
* shape), the catalog's cache window, and the same failure rule: empty, never an error.
|
|
81
|
+
*/
|
|
82
|
+
const loginScreenLimiter = rateLimit({
|
|
83
|
+
windowMs: DEFAULT_RATE_LIMIT_WINDOW_MS,
|
|
84
|
+
limit: DEFAULT_RATE_LIMIT_MAX,
|
|
85
|
+
standardHeaders: 'draft-7',
|
|
86
|
+
legacyHeaders: false,
|
|
87
|
+
message: EMPTY_PUBLIC_LOGIN_SCREEN
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
router.get('/login-screen', loginScreenLimiter, (_req: Request, res: Response) => {
|
|
91
|
+
try {
|
|
92
|
+
const body = LoginScreenEngine.Instance.GetPublicLoginScreen();
|
|
93
|
+
res.set('Cache-Control', `public, max-age=${CACHE_MAX_AGE_SECONDS}`);
|
|
94
|
+
res.status(200).json(body);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
97
|
+
LogError(`[Auth] Failed to serve the public login screen: ${message}`);
|
|
98
|
+
res.status(200).json(EMPTY_PUBLIC_LOGIN_SCREEN);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
AttachLocalDevAuthRoutes(router);
|
|
103
|
+
|
|
75
104
|
return router;
|
|
76
105
|
}
|
|
77
106
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Caches the default theme for the public login-screen route.
|
|
3
|
+
*
|
|
4
|
+
* @module @memberjunction/server/auth
|
|
5
|
+
*/
|
|
6
|
+
import { BaseEngine, BaseEnginePropertyConfig, RegisterForStartup, UserInfo, type IMetadataProvider } from '@memberjunction/core';
|
|
7
|
+
import { MJThemeEntity } from '@memberjunction/core-entities';
|
|
8
|
+
import { PublicLoginScreenFromTheme, type PublicLoginScreen } from '@memberjunction/theme-engine';
|
|
9
|
+
|
|
10
|
+
/** What the route serves when there is no default theme, or it cannot be read. */
|
|
11
|
+
export const EMPTY_PUBLIC_LOGIN_SCREEN: Readonly<PublicLoginScreen> = { ThemeName: null, Design: null, Seeds: null, Logos: {} };
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Holds the default Active theme, so `GET /auth/login-screen` answers every anonymous page load from
|
|
15
|
+
* memory. Saving a theme refreshes it, so a publish in Login Studio reaches the login screen without a
|
|
16
|
+
* restart. Severity `warn`: a failed load must not stop the server; the route then serves the stock page.
|
|
17
|
+
*/
|
|
18
|
+
@RegisterForStartup({
|
|
19
|
+
priority: 20,
|
|
20
|
+
severity: 'warn',
|
|
21
|
+
deferred: false,
|
|
22
|
+
description: 'Caches the default theme that GET /auth/login-screen serves to the login screen'
|
|
23
|
+
})
|
|
24
|
+
export class LoginScreenEngine extends BaseEngine<LoginScreenEngine> {
|
|
25
|
+
private _defaultThemes: MJThemeEntity[] = [];
|
|
26
|
+
|
|
27
|
+
public static get Instance(): LoginScreenEngine {
|
|
28
|
+
return super.getInstance<LoginScreenEngine>();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public async Config(forceRefresh?: boolean, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<void> {
|
|
32
|
+
const configs: Partial<BaseEnginePropertyConfig>[] = [
|
|
33
|
+
{
|
|
34
|
+
PropertyName: '_defaultThemes',
|
|
35
|
+
EntityName: 'MJ: Themes',
|
|
36
|
+
// One default is enforced by the app, not the schema; the most recently changed one wins (as in Login Studio).
|
|
37
|
+
Filter: `IsDefault = 1 AND Status = 'Active'`,
|
|
38
|
+
OrderBy: '__mj_UpdatedAt DESC',
|
|
39
|
+
CacheLocal: true
|
|
40
|
+
}
|
|
41
|
+
];
|
|
42
|
+
await this.Load(configs, provider, forceRefresh, contextUser);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** The default theme's public projection: its PUBLISHED design (never the draft), seeds and logos made safe. */
|
|
46
|
+
public GetPublicLoginScreen(): PublicLoginScreen {
|
|
47
|
+
const theme = this.GetConfigData<MJThemeEntity>('_defaultThemes')[0];
|
|
48
|
+
return theme ? PublicLoginScreenFromTheme(theme) : EMPTY_PUBLIC_LOGIN_SCREEN;
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/auth/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { JwtHeader, SigningKeyCallback, JwtPayload } from 'jsonwebtoken';
|
|
|
2
2
|
import { configInfo } from '../config.js';
|
|
3
3
|
import { UserCache } from '@memberjunction/generic-database-provider';
|
|
4
4
|
import sql from 'mssql';
|
|
5
|
-
import { DatabaseProviderBase, Metadata, RoleInfo, UserInfo } from '@memberjunction/core';
|
|
5
|
+
import { DatabaseProviderBase, LogError, Metadata, RoleInfo, UserInfo } from '@memberjunction/core';
|
|
6
6
|
import { NewUserBase } from './newUsers.js';
|
|
7
7
|
import { MJGlobal } from '@memberjunction/global';
|
|
8
8
|
import { MJUserEntity, MJUserEntityType } from '@memberjunction/core-entities';
|
|
@@ -13,6 +13,7 @@ export * from './APIKeyScopeAuth.js';
|
|
|
13
13
|
export * from './scopeLimitedPrincipal.js';
|
|
14
14
|
export * from './actingContextResolver.js';
|
|
15
15
|
export * from './AuthProviderEngine.js';
|
|
16
|
+
export * from './LoginScreenEngine.js';
|
|
16
17
|
export * from './AuthProviderCatalogRouter.js';
|
|
17
18
|
export { InitializeAuthProviders, initializeAuthProviders, InitializeAuthProvidersFromMetadata, initializeAuthProvidersFromMetadata, RefreshAuthProviders, refreshAuthProviders, ValidateAuthProvidersRegistered, validateAuthProvidersRegistered } from './initializeProviders.js';
|
|
18
19
|
|
|
@@ -253,11 +254,63 @@ export const VerifyUserRecord = async (
|
|
|
253
254
|
): Promise<UserInfo | undefined> => {
|
|
254
255
|
if (!email) return undefined;
|
|
255
256
|
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
|
|
257
|
+
// Collect ALL matches rather than taking .find()'s first hit. Two User rows can share an email
|
|
258
|
+
// case-insensitively (see the duplicate-provisioning path below), and .find() then resolved to
|
|
259
|
+
// whichever row happened to sit earlier in UserCache.Instance.Users — i.e. database row order.
|
|
260
|
+
// That order changes when the cache is rebuilt, so an MJAPI restart silently moved a user onto a
|
|
261
|
+
// different record: their conversations, artifacts, items shared with them and their profile
|
|
262
|
+
// picture (UserImageURL lives on the User row) all vanished at once, and came back if the order
|
|
263
|
+
// flipped again. Observed in production 2026-09-15. Resolution must not depend on row order.
|
|
264
|
+
const emailMatches = UserCache.Instance.Users.filter((u) => {
|
|
265
|
+
if (!u.Email || u.Email.trim() === '') {
|
|
266
|
+
// this condition should never occur. If it doesn throw a console error including the user id
|
|
267
|
+
// DB requires non-null but this is just an extra check and we could in theory have a blank string in the DB
|
|
268
|
+
console.error(`SYSTEM METADATA ISSUE: User ${u.ID} has no email address`);
|
|
269
|
+
return false;
|
|
270
|
+
} else return u.Email.toLowerCase().trim() === email.toLowerCase().trim();
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
if (emailMatches.length > 1) {
|
|
274
|
+
// Deterministic tie-break by ID so every process and every restart agrees, and a LOUD error
|
|
275
|
+
// because this is a data problem an operator has to resolve — silently picking a row is what
|
|
276
|
+
// made it look like data loss to the customer. Sorting by ID is arbitrary but stable; the point
|
|
277
|
+
// is that it never changes, not that it picks the "right" one.
|
|
278
|
+
emailMatches.sort((a, b) => a.ID.localeCompare(b.ID));
|
|
279
|
+
LogError(
|
|
280
|
+
`AMBIGUOUS LOGIN: ${emailMatches.length} User records share the email '${email}' ` +
|
|
281
|
+
`(case-insensitively): ${emailMatches.map((u) => `${u.ID} (${u.Email})`).join(', ')}. ` +
|
|
282
|
+
`Resolving to ${emailMatches[0].ID} by stable ID order. Until the duplicates are merged, ` +
|
|
283
|
+
`content owned by the other records is invisible to this login. Find every affected user ` +
|
|
284
|
+
`with: SELECT LOWER(Email), COUNT(*) FROM __mj.[User] GROUP BY LOWER(Email) HAVING COUNT(*) > 1`
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Nothing cached: ask FindUser, which reads the database for a user this process has not loaded
|
|
289
|
+
// yet (created seconds ago on another server) instead of treating them as nonexistent.
|
|
290
|
+
let user = emailMatches[0] ?? (await UserCache.Instance.FindUser({ Email: email }));
|
|
259
291
|
|
|
260
292
|
if (!user) {
|
|
293
|
+
// REFRESH THE CACHE BEFORE PROVISIONING. This block used to sit AFTER the auto-create below,
|
|
294
|
+
// gated on `!user`, so it could only ever run when creation had already failed or was not
|
|
295
|
+
// attempted. That made it dead code in the exact case it exists to handle: a user who IS in the
|
|
296
|
+
// database but is NOT yet in this process's UserCache. Users provisioned out of band (an admin,
|
|
297
|
+
// an invite, a direct insert) are absent from the cache until it is rebuilt, so the lookup above
|
|
298
|
+
// missed and auto-create minted a SECOND record for someone who already had one — which is how
|
|
299
|
+
// the duplicate emails that Fix 1 above has to tolerate get created in the first place.
|
|
300
|
+
// Observed in production: three users created 2026-09-14 18:18, a duplicate for one of them
|
|
301
|
+
// created 2026-09-15 01:38 on that user's next sign-in.
|
|
302
|
+
//
|
|
303
|
+
// The recursive call passes attemptCacheUpdateIfNeeded=false, so the second pass skips straight
|
|
304
|
+
// to auto-create if the refreshed cache still has no match. Auto-provisioning of genuinely new
|
|
305
|
+
// users is therefore unchanged — it just no longer runs before we have looked properly.
|
|
306
|
+
if (configInfo.userHandling.updateCacheWhenNotFound && dataSource && attemptCacheUpdateIfNeeded) {
|
|
307
|
+
console.warn(`User ${email} not found in cache. Updating cache in attempt to find the user...`);
|
|
308
|
+
|
|
309
|
+
await refreshUserCache();
|
|
310
|
+
|
|
311
|
+
return VerifyUserRecord(email, firstName, lastName, requestDomain, dataSource, false);
|
|
312
|
+
}
|
|
313
|
+
|
|
261
314
|
// NOTE: `requestDomain` (parsed from the spoofable `Origin` header) is deliberately NOT part of
|
|
262
315
|
// this condition. It was previously required here, which meant a non-browser client sending no
|
|
263
316
|
// Origin could never auto-provision while an attacker simply forged one — it gated entry without
|
|
@@ -312,14 +365,6 @@ export const VerifyUserRecord = async (
|
|
|
312
365
|
}
|
|
313
366
|
}
|
|
314
367
|
|
|
315
|
-
if (!user && configInfo.userHandling.updateCacheWhenNotFound && dataSource && attemptCacheUpdateIfNeeded) {
|
|
316
|
-
// if we get here that means in the above, if we were attempting to create a new user, it did not work, or it wasn't attempted and we have a config that asks us to auto update the cache
|
|
317
|
-
console.warn(`User ${email} not found in cache. Updating cache in attempt to find the user...`);
|
|
318
|
-
|
|
319
|
-
await refreshUserCache();
|
|
320
|
-
|
|
321
|
-
return VerifyUserRecord(email, firstName, lastName, requestDomain, dataSource, false); // try one more time but do not update cache next time if not found
|
|
322
|
-
}
|
|
323
368
|
}
|
|
324
369
|
|
|
325
370
|
return user;
|
|
@@ -1,8 +1,35 @@
|
|
|
1
1
|
import { configInfo } from '../config.js';
|
|
2
2
|
import { AuthProviderConfig, LogError, LogStatus, LogStatusEx, UserInfo, type IMetadataProvider } from '@memberjunction/core';
|
|
3
|
-
import { AuthProviderFactory } from '@memberjunction/auth-providers';
|
|
3
|
+
import { AuthProviderFactory, LocalDevProvider } from '@memberjunction/auth-providers';
|
|
4
4
|
import { AuthProviderEngine } from './AuthProviderEngine.js';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Returns true when local development auth is enabled via `MJ_DEV_AUTH_ENABLED=true`
|
|
8
|
+
* or `configInfo.devAuth?.enabled === true`.
|
|
9
|
+
*/
|
|
10
|
+
export function IsLocalDevAuthEnabled(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
11
|
+
const rawEnv = env.MJ_DEV_AUTH_ENABLED?.trim().toLowerCase();
|
|
12
|
+
if (rawEnv === 'true' || rawEnv === '1') {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
if (rawEnv === 'false' || rawEnv === '0') {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
return configInfo?.devAuth?.enabled === true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Enforces the production safety invariant: throws a fatal error if local dev auth
|
|
23
|
+
* is enabled while `NODE_ENV === 'production'`.
|
|
24
|
+
*/
|
|
25
|
+
export function AssertLocalDevAuthAllowed(env: NodeJS.ProcessEnv = process.env): void {
|
|
26
|
+
if (IsLocalDevAuthEnabled(env) && env.NODE_ENV?.trim().toLowerCase() === 'production') {
|
|
27
|
+
throw new Error(
|
|
28
|
+
'[SECURITY] Local dev auth (MJ_DEV_AUTH_ENABLED) is strictly forbidden when NODE_ENV=production. Refusing to start.'
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
6
33
|
/**
|
|
7
34
|
* Initialize authentication providers from configuration.
|
|
8
35
|
*
|
|
@@ -15,6 +42,8 @@ import { AuthProviderEngine } from './AuthProviderEngine.js';
|
|
|
15
42
|
* connection and a system user exist.
|
|
16
43
|
*/
|
|
17
44
|
export function InitializeAuthProviders(): void {
|
|
45
|
+
AssertLocalDevAuthAllowed();
|
|
46
|
+
|
|
18
47
|
const factory = AuthProviderFactory.Instance;
|
|
19
48
|
|
|
20
49
|
// Clear any existing providers
|
|
@@ -40,6 +69,19 @@ export function InitializeAuthProviders(): void {
|
|
|
40
69
|
}
|
|
41
70
|
}
|
|
42
71
|
|
|
72
|
+
if (IsLocalDevAuthEnabled()) {
|
|
73
|
+
configInfo.authProviders = configInfo.authProviders ?? [];
|
|
74
|
+
if (!configInfo.authProviders.some((p) => p.type === 'local' || p.name === 'local')) {
|
|
75
|
+
const localConfig = LocalDevProvider.ConfigFromEnvironment({
|
|
76
|
+
...process.env,
|
|
77
|
+
MJ_DEV_AUTH_ENABLED: 'true',
|
|
78
|
+
});
|
|
79
|
+
if (localConfig) {
|
|
80
|
+
configInfo.authProviders.push(localConfig);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
43
85
|
// Initialize providers from authProviders config
|
|
44
86
|
if (configInfo.authProviders && configInfo.authProviders.length > 0) {
|
|
45
87
|
for (const providerConfig of configInfo.authProviders) {
|