@memberjunction/server 6.2.0-edge.3 → 6.2.0-edge.4
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/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/BridgeHostInstance.d.ts +25 -0
- package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -0
- package/dist/agentSessions/BridgeHostInstance.js +30 -0
- package/dist/agentSessions/BridgeHostInstance.js.map +1 -0
- package/dist/agentSessions/HostInstance.d.ts +75 -11
- package/dist/agentSessions/HostInstance.d.ts.map +1 -1
- package/dist/agentSessions/HostInstance.js +99 -28
- package/dist/agentSessions/HostInstance.js.map +1 -1
- package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
- package/dist/agentSessions/ReturningVisitorRecap.js +7 -3
- package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
- package/dist/agentSessions/SessionJanitor.d.ts +173 -25
- package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
- package/dist/agentSessions/SessionJanitor.js +452 -54
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/agentSessions/SessionManager.d.ts +43 -2
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +99 -8
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/agentSessions/SessionRunIDVerifier.d.ts +63 -0
- package/dist/agentSessions/SessionRunIDVerifier.d.ts.map +1 -0
- package/dist/agentSessions/SessionRunIDVerifier.js +129 -0
- package/dist/agentSessions/SessionRunIDVerifier.js.map +1 -0
- package/dist/agentSessions/index.d.ts +2 -0
- package/dist/agentSessions/index.d.ts.map +1 -1
- package/dist/agentSessions/index.js +10 -3
- package/dist/agentSessions/index.js.map +1 -1
- package/dist/auth/actionAuthorization.d.ts +40 -0
- package/dist/auth/actionAuthorization.d.ts.map +1 -0
- package/dist/auth/actionAuthorization.js +94 -0
- package/dist/auth/actionAuthorization.js.map +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +3 -10
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +6 -3
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/newUsers.d.ts +10 -0
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +80 -11
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/config.d.ts +2378 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +123 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +8 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +14 -11
- package/dist/context.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts +135 -0
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +706 -0
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js +3 -3
- package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +20 -4
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +39 -10
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +4 -0
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +120 -131
- package/dist/index.js.map +1 -1
- package/dist/isolatedProvider.d.ts +20 -0
- package/dist/isolatedProvider.d.ts.map +1 -0
- package/dist/isolatedProvider.js +22 -0
- package/dist/isolatedProvider.js.map +1 -0
- package/dist/realtimeProxy/RealtimeProxyServer.d.ts +44 -4
- package/dist/realtimeProxy/RealtimeProxyServer.d.ts.map +1 -1
- package/dist/realtimeProxy/RealtimeProxyServer.js +121 -16
- package/dist/realtimeProxy/RealtimeProxyServer.js.map +1 -1
- package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts +171 -0
- package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts.map +1 -0
- package/dist/realtimeProxy/RealtimeRelayTunnel.js +532 -0
- package/dist/realtimeProxy/RealtimeRelayTunnel.js.map +1 -0
- package/dist/realtimeSessions/RealtimeSessionEventService.d.ts +148 -0
- package/dist/realtimeSessions/RealtimeSessionEventService.d.ts.map +1 -0
- package/dist/realtimeSessions/RealtimeSessionEventService.js +191 -0
- package/dist/realtimeSessions/RealtimeSessionEventService.js.map +1 -0
- package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts +66 -0
- package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -0
- package/dist/realtimeSessions/RealtimeSessionVerificationService.js +138 -0
- package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -0
- package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts +38 -0
- package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -0
- package/dist/realtimeSessions/RealtimeVerifyRouter.js +98 -0
- package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -0
- package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts +61 -0
- package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -0
- package/dist/realtimeSessions/SessionVerificationPortsBase.js +149 -0
- package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -0
- package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts +57 -0
- package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts.map +1 -0
- package/dist/realtimeSessions/SlidingWindowRateLimiter.js +69 -0
- package/dist/realtimeSessions/SlidingWindowRateLimiter.js.map +1 -0
- package/dist/realtimeSessions/index.d.ts +17 -0
- package/dist/realtimeSessions/index.d.ts.map +1 -0
- package/dist/realtimeSessions/index.js +17 -0
- package/dist/realtimeSessions/index.js.map +1 -0
- package/dist/realtimeSessions/sessionAccess.d.ts +86 -0
- package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -0
- package/dist/realtimeSessions/sessionAccess.js +90 -0
- package/dist/realtimeSessions/sessionAccess.js.map +1 -0
- package/dist/realtimeSessions/sessionConfigStamps.d.ts +70 -0
- package/dist/realtimeSessions/sessionConfigStamps.d.ts.map +1 -0
- package/dist/realtimeSessions/sessionConfigStamps.js +93 -0
- package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -0
- package/dist/realtimeSessions/subscriptionAuthorization.d.ts +65 -0
- package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -0
- package/dist/realtimeSessions/subscriptionAuthorization.js +71 -0
- package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -0
- package/dist/realtimeSessions/verificationCore.d.ts +243 -0
- package/dist/realtimeSessions/verificationCore.d.ts.map +1 -0
- package/dist/realtimeSessions/verificationCore.js +356 -0
- package/dist/realtimeSessions/verificationCore.js.map +1 -0
- package/dist/realtimeSessions/verificationPages.d.ts +66 -0
- package/dist/realtimeSessions/verificationPages.d.ts.map +1 -0
- package/dist/realtimeSessions/verificationPages.js +110 -0
- package/dist/realtimeSessions/verificationPages.js.map +1 -0
- package/dist/realtimeSessions/verificationPolicy.d.ts +147 -0
- package/dist/realtimeSessions/verificationPolicy.d.ts.map +1 -0
- package/dist/realtimeSessions/verificationPolicy.js +249 -0
- package/dist/realtimeSessions/verificationPolicy.js.map +1 -0
- package/dist/realtimeSessions/verificationWorkflow.d.ts +263 -0
- package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -0
- package/dist/realtimeSessions/verificationWorkflow.js +435 -0
- package/dist/realtimeSessions/verificationWorkflow.js.map +1 -0
- package/dist/realtimeWidget/widgetGuestElevation.d.ts +20 -2
- package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +31 -2
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts +31 -5
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +75 -14
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.d.ts +14 -1
- package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.js +21 -5
- package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
- package/dist/resolvers/CacheStatsResolver.d.ts +27 -0
- package/dist/resolvers/CacheStatsResolver.d.ts.map +1 -1
- package/dist/resolvers/CacheStatsResolver.js +113 -2
- package/dist/resolvers/CacheStatsResolver.js.map +1 -1
- package/dist/resolvers/ClientToolRequestResolver.d.ts +4 -2
- package/dist/resolvers/ClientToolRequestResolver.d.ts.map +1 -1
- package/dist/resolvers/ClientToolRequestResolver.js +28 -10
- package/dist/resolvers/ClientToolRequestResolver.js.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts +12 -1
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js +83 -2
- package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
- package/dist/resolvers/HumanHandoffResolver.d.ts.map +1 -1
- package/dist/resolvers/HumanHandoffResolver.js +7 -1
- package/dist/resolvers/HumanHandoffResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts.map +1 -1
- package/dist/resolvers/MCPResolver.js +9 -4
- package/dist/resolvers/MCPResolver.js.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.d.ts +54 -2
- package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +155 -10
- package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +155 -25
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +394 -90
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RealtimeSessionEventsResolver.d.ts +61 -0
- package/dist/resolvers/RealtimeSessionEventsResolver.d.ts.map +1 -0
- package/dist/resolvers/RealtimeSessionEventsResolver.js +130 -0
- package/dist/resolvers/RealtimeSessionEventsResolver.js.map +1 -0
- package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts +85 -0
- package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts.map +1 -0
- package/dist/resolvers/RealtimeSessionVerificationResolver.js +188 -0
- package/dist/resolvers/RealtimeSessionVerificationResolver.js.map +1 -0
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts +2 -0
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +5 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +10 -0
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +68 -11
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +12 -11
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +6 -2
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts +2 -0
- package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +23 -6
- package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
- package/dist/resolvers/UserAvatarResolver.d.ts +16 -0
- package/dist/resolvers/UserAvatarResolver.d.ts.map +1 -0
- package/dist/resolvers/UserAvatarResolver.js +124 -0
- package/dist/resolvers/UserAvatarResolver.js.map +1 -0
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +2 -17
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/dist/resolvers/agentVisionConsentAudit.d.ts +37 -0
- package/dist/resolvers/agentVisionConsentAudit.d.ts.map +1 -0
- package/dist/resolvers/agentVisionConsentAudit.js +63 -0
- package/dist/resolvers/agentVisionConsentAudit.js.map +1 -0
- package/dist/resolvers/avatarInputValidation.d.ts +40 -0
- package/dist/resolvers/avatarInputValidation.d.ts.map +1 -0
- package/dist/resolvers/avatarInputValidation.js +97 -0
- package/dist/resolvers/avatarInputValidation.js.map +1 -0
- package/dist/resolvers/currentUserRoles.d.ts +29 -0
- package/dist/resolvers/currentUserRoles.d.ts.map +1 -1
- package/dist/resolvers/currentUserRoles.js +30 -0
- package/dist/resolvers/currentUserRoles.js.map +1 -1
- package/dist/resolvers/meetings/meetingMutations.d.ts +6 -0
- package/dist/resolvers/meetings/meetingMutations.d.ts.map +1 -1
- package/dist/resolvers/meetings/meetingMutations.js +21 -0
- package/dist/resolvers/meetings/meetingMutations.js.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.d.ts +4 -3
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +13 -7
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/sharedCache.d.ts +105 -0
- package/dist/sharedCache.d.ts.map +1 -0
- package/dist/sharedCache.js +276 -0
- package/dist/sharedCache.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +97 -95
- package/src/__tests__/ActionResolver.authorization.test.ts +353 -0
- package/src/__tests__/AdhocQueryResolver.sqlAuthorizer.test.ts +104 -0
- package/src/__tests__/BridgeHostInstance.test.ts +232 -0
- package/src/__tests__/ClientToolRequestResolver.test.ts +116 -0
- package/src/__tests__/FetchEntityVectorsResolver.test.ts +285 -0
- package/src/__tests__/HostInstance.test.ts +84 -0
- package/src/__tests__/HumanHandoffResolver.test.ts +17 -0
- package/src/__tests__/MeetingResolver.test.ts +75 -1
- package/src/__tests__/RealtimeBridgeResolver.test.ts +415 -6
- package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +383 -0
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +682 -58
- package/src/__tests__/RealtimeProxyServer.test.ts +16 -1
- package/src/__tests__/RealtimeRelay.test.ts +876 -0
- package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +129 -0
- package/src/__tests__/ResolverBase.aggregateScreen.test.ts +174 -0
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +6 -3
- package/src/__tests__/ReturningVisitorRecap.test.ts +115 -0
- package/src/__tests__/RunAIAgentResolver.branch.test.ts +169 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +4 -4
- package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +166 -0
- package/src/__tests__/RunTemplateResolver.test.ts +132 -0
- package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +63 -0
- package/src/__tests__/SessionJanitor.test.ts +845 -18
- package/src/__tests__/SessionManager.test.ts +213 -17
- package/src/__tests__/SessionRunIDVerifier.test.ts +251 -0
- package/src/__tests__/SyncRolesUsersResolver.userRoles.test.ts +97 -0
- package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +50 -3
- package/src/__tests__/UserAvatarResolver.test.ts +255 -0
- package/src/__tests__/UserResolver.currentUser.test.ts +16 -1
- package/src/__tests__/actionAuthorization.test.ts +130 -0
- package/src/__tests__/agentVisionConsentAudit.test.ts +118 -0
- package/src/__tests__/avatarInputValidation.test.ts +160 -0
- package/src/__tests__/isolatedProviderTransactions.test.ts +169 -0
- package/src/__tests__/magicLinkService.consume.test.ts +6 -0
- package/src/__tests__/magicLinkService.provisionLog.test.ts +5 -0
- package/src/__tests__/newUsers.template.test.ts +151 -0
- package/src/__tests__/newUsers.test.ts +74 -5
- package/src/__tests__/orphanedConversationDetailReconciler.test.ts +17 -2
- package/src/__tests__/realtimeSessions/RealtimeSessionEventService.test.ts +201 -0
- package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +215 -0
- package/src/__tests__/realtimeSessions/RealtimeSessionVerificationResolver.test.ts +102 -0
- package/src/__tests__/realtimeSessions/RealtimeSessionVerificationService.test.ts +349 -0
- package/src/__tests__/realtimeSessions/RealtimeVerifyRouter.test.ts +131 -0
- package/src/__tests__/realtimeSessions/SlidingWindowRateLimiter.test.ts +56 -0
- package/src/__tests__/realtimeSessions/helpers.ts +4 -0
- package/src/__tests__/realtimeSessions/sessionAccess.test.ts +129 -0
- package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +124 -0
- package/src/__tests__/realtimeSessions/verificationCore.test.ts +355 -0
- package/src/__tests__/realtimeSessions/verificationPages.test.ts +84 -0
- package/src/__tests__/realtimeSessions/verificationPolicy.test.ts +226 -0
- package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +633 -0
- package/src/__tests__/resolverBase.fls.test.ts +87 -4
- package/src/__tests__/serverExtensionReservedRoots.test.ts +2 -0
- package/src/__tests__/sharedCache.test.ts +310 -0
- package/src/__tests__/widgetGuestElevation.test.ts +44 -0
- package/src/agentSessions/BridgeHostInstance.ts +32 -0
- package/src/agentSessions/HostInstance.ts +124 -28
- package/src/agentSessions/ReturningVisitorRecap.ts +7 -3
- package/src/agentSessions/SessionJanitor.ts +543 -57
- package/src/agentSessions/SessionManager.ts +125 -25
- package/src/agentSessions/SessionRunIDVerifier.ts +171 -0
- package/src/agentSessions/index.ts +10 -3
- package/src/auth/actionAuthorization.ts +116 -0
- package/src/auth/index.ts +3 -8
- package/src/auth/magicLink/MagicLinkService.ts +6 -3
- package/src/auth/newUsers.ts +99 -11
- package/src/config.ts +125 -0
- package/src/context.ts +15 -10
- package/src/generated/graphql-schemas/__mj.ts +496 -1
- package/src/generic/OrphanedConversationDetailReconciler.ts +3 -3
- package/src/generic/ResolverBase.ts +39 -9
- package/src/generic/RunViewResolver.ts +4 -0
- package/src/index.ts +132 -143
- package/src/isolatedProvider.ts +22 -0
- package/src/realtimeProxy/RealtimeProxyServer.ts +148 -16
- package/src/realtimeProxy/RealtimeRelayTunnel.ts +645 -0
- package/src/realtimeSessions/README.md +179 -0
- package/src/realtimeSessions/RealtimeSessionEventService.ts +274 -0
- package/src/realtimeSessions/RealtimeSessionVerificationService.ts +167 -0
- package/src/realtimeSessions/RealtimeVerifyRouter.ts +108 -0
- package/src/realtimeSessions/SessionVerificationPortsBase.ts +189 -0
- package/src/realtimeSessions/SlidingWindowRateLimiter.ts +92 -0
- package/src/realtimeSessions/index.ts +16 -0
- package/src/realtimeSessions/sessionAccess.ts +141 -0
- package/src/realtimeSessions/sessionConfigStamps.ts +123 -0
- package/src/realtimeSessions/subscriptionAuthorization.ts +116 -0
- package/src/realtimeSessions/verificationCore.ts +502 -0
- package/src/realtimeSessions/verificationPages.ts +149 -0
- package/src/realtimeSessions/verificationPolicy.ts +321 -0
- package/src/realtimeSessions/verificationWorkflow.ts +702 -0
- package/src/realtimeWidget/widgetGuestElevation.ts +34 -2
- package/src/resolvers/ActionResolver.ts +84 -21
- package/src/resolvers/AdhocQueryResolver.ts +24 -6
- package/src/resolvers/CacheStatsResolver.ts +89 -2
- package/src/resolvers/ClientToolRequestResolver.ts +25 -7
- package/src/resolvers/FetchEntityVectorsResolver.ts +97 -2
- package/src/resolvers/HumanHandoffResolver.ts +8 -0
- package/src/resolvers/MCPResolver.ts +8 -5
- package/src/resolvers/RealtimeBridgeResolver.ts +163 -11
- package/src/resolvers/RealtimeClientSessionResolver.ts +501 -96
- package/src/resolvers/RealtimeSessionEventsResolver.ts +133 -0
- package/src/resolvers/RealtimeSessionVerificationResolver.ts +174 -0
- package/src/resolvers/RemoteBrowserActionResolver.ts +11 -1
- package/src/resolvers/RunAIAgentResolver.ts +78 -11
- package/src/resolvers/RunTemplateResolver.ts +13 -12
- package/src/resolvers/SyncDataResolver.ts +6 -2
- package/src/resolvers/SyncRolesUsersResolver.ts +24 -6
- package/src/resolvers/UserAvatarResolver.ts +111 -0
- package/src/resolvers/UserResolver.ts +2 -16
- package/src/resolvers/agentVisionConsentAudit.ts +82 -0
- package/src/resolvers/avatarInputValidation.ts +123 -0
- package/src/resolvers/currentUserRoles.ts +32 -1
- package/src/resolvers/meetings/meetingMutations.ts +21 -0
- package/src/services/TaskGraphContinuationDeliverer.ts +13 -7
- package/src/sharedCache.ts +302 -0
- package/src/types.ts +7 -0
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import dotenv from 'dotenv';
|
|
|
2
2
|
dotenv.config({ quiet: true });
|
|
3
3
|
import { expressMiddleware } from '@as-integrations/express5';
|
|
4
4
|
import { mergeSchemas } from '@graphql-tools/schema';
|
|
5
|
-
import { Metadata, SetProvider, StartupManager as StartupManagerImport, BaseEntity, RunView, DatabaseProviderBase, ResolveStartupMode } from '@memberjunction/core';
|
|
5
|
+
import { Metadata, SetProvider, StartupManager as StartupManagerImport, BaseEntity, RunView, DatabaseProviderBase, ProviderBase, ResolveStartupMode } from '@memberjunction/core';
|
|
6
6
|
import { UserCache, resolveDbPlatformFromEnv } from '@memberjunction/generic-database-provider';
|
|
7
7
|
import { MJGlobal, MJEventType, ShutdownRegistry } from '@memberjunction/global';
|
|
8
8
|
import { setupSQLServerClient, SQLServerDataProvider, SQLServerProviderConfigData } from '@memberjunction/sqlserver-dataprovider';
|
|
@@ -17,9 +17,10 @@ import { default as fg } from 'fast-glob';
|
|
|
17
17
|
import { useServer } from 'graphql-ws/lib/use/ws';
|
|
18
18
|
import { createServer } from 'node:http';
|
|
19
19
|
import { fileURLToPath } from 'node:url';
|
|
20
|
-
import { readFileSync, writeFileSync } from 'node:fs';
|
|
20
|
+
import { mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
|
|
21
|
+
import { tmpdir } from 'node:os';
|
|
21
22
|
import { Session as InspectorSession } from 'node:inspector';
|
|
22
|
-
import { sep } from 'node:path';
|
|
23
|
+
import { join, sep } from 'node:path';
|
|
23
24
|
import 'reflect-metadata';
|
|
24
25
|
import { ReplaySubject } from 'rxjs';
|
|
25
26
|
import { buildSchemaSync, getMetadataStorage, GraphQLTimestamp } from 'type-graphql';
|
|
@@ -32,7 +33,7 @@ import { configInfo, configFilePath, dbDatabase, dbHost, dbPort, dbUsername, gra
|
|
|
32
33
|
import { TranslateBracketsToPG } from './postgresqlCompat.js';
|
|
33
34
|
import { BuildPostgreSQLConnectionConfig, DescribeReadOnlyLoginOverreach, PostgreSQLReadOnlyPool, ResolvePostgreSQLEndpoint, ResolvePostgreSQLReadOnlyCredentials, ToPGPoolConfig } from './postgresqlPoolSettings.js';
|
|
34
35
|
import { default as jwt } from 'jsonwebtoken';
|
|
35
|
-
import { contextFunction, CreateUnifiedAuthMiddleware, getUserPayload } from './context.js';
|
|
36
|
+
import { contextFunction, CreateReadOnlyProvider, CreateUnifiedAuthMiddleware, getUserPayload } from './context.js';
|
|
36
37
|
import { requireSystemUserDirective, publicDirective } from './directives/index.js';
|
|
37
38
|
import { variablesLoggingMiddleware } from './logging/variablesLoggingMiddleware.js';
|
|
38
39
|
import { auditResolversForUndecoratedArgs } from './logging/bootAudit.js';
|
|
@@ -47,6 +48,7 @@ import { createRealtimeSdpBrokerRouter } from './rest/RealtimeSdpBrokerHandler.j
|
|
|
47
48
|
import { REALTIME_SDP_EXCHANGE_PATH } from '@memberjunction/ai';
|
|
48
49
|
import { createMagicLinkHandler, createMagicLinkJwksRouter, registerMagicLinkAuthProvider, MAGIC_LINK_MOUNT_PATH } from './auth/magicLink/index.js';
|
|
49
50
|
import { createWidgetHandler, WIDGET_MOUNT_PATH } from './realtimeWidget/index.js';
|
|
51
|
+
import { CreateRealtimeVerifyRouter, REALTIME_VERIFY_MOUNT_PATH, RealtimeSessionEventService, RealtimeSessionVerificationService, ParseReplicatedRealtimeSessionEvent, } from './realtimeSessions/index.js';
|
|
50
52
|
import { resolve } from 'node:path';
|
|
51
53
|
import { DataSourceInfo, raiseEvent } from './types.js';
|
|
52
54
|
import { ScheduledJobsService } from './services/ScheduledJobsService.js';
|
|
@@ -55,17 +57,18 @@ import { LocalCacheManager, TelemetryManager, LogStatus, LogError, SetVerboseLog
|
|
|
55
57
|
import { validateAuthProvidersRegistered } from './auth/index.js';
|
|
56
58
|
import { createAuthProviderCatalogRouter, AUTH_CATALOG_MOUNT_PATH } from './auth/AuthProviderCatalogRouter.js';
|
|
57
59
|
import { GetAPIKeyEngine } from '@memberjunction/api-keys';
|
|
58
|
-
import {
|
|
60
|
+
import { ActionEngineServer } from '@memberjunction/actions';
|
|
61
|
+
import { CreateAdhocSQLAuthorizer } from './resolvers/AdhocQueryResolver.js';
|
|
62
|
+
import { CacheManagerConfigFromSettings, CreateSharedCacheFromEnvironment, StartEngineSweeper, StartMetadataSweep, StartUserCacheChecks, WarmupLeaseMsFromSettings, WirePushStatusFanOut, WireSharedCacheEvents } from './sharedCache.js';
|
|
59
63
|
import { PubSubManager } from './generic/PubSubManager.js';
|
|
60
64
|
import { ReconcileOrphanedConversationDetails } from './generic/OrphanedConversationDetailReconciler.js';
|
|
61
|
-
import { PUSH_STATUS_UPDATES_TOPIC, SetPushStatusPublishHook, ParseReplicatedStatusUpdate, } from './generic/PushStatusResolver.js';
|
|
62
65
|
import { HANDOFF_OFFER_FANOUT_CHANNEL, HANDOFF_OFFER_TOPIC, SetHandoffOfferPublishHook, ParseReplicatedHandoffOfferUpdate, } from './resolvers/HumanHandoffResolver.js';
|
|
63
66
|
import { RoomHandoffEngine } from '@memberjunction/livekit-room-server';
|
|
64
67
|
import { IntegrationProgressEmitter } from '@memberjunction/integration-progress-artifacts';
|
|
65
68
|
import { PublishIntegrationProgress } from './resolvers/IntegrationProgressResolver.js';
|
|
66
69
|
import { RegisterRSUProgressBridge } from './integration/RSUProgressBridge.js';
|
|
67
70
|
import { ClientToolRequestManager, AgentRunWatchdog } from '@memberjunction/ai-agents';
|
|
68
|
-
import { SessionJanitor } from './agentSessions/index.js';
|
|
71
|
+
import { BindBridgeEngineHostInstance, SessionJanitor, SetHostInstancePort, StartBridgeOrphanReconciliation } from './agentSessions/index.js';
|
|
69
72
|
import { StartTaskGraphDispatcher } from './services/StartTaskGraphDispatcher.js';
|
|
70
73
|
import { MJServerWorkQueueProviderSource, StartWorkQueueHost } from './services/WorkQueueHostService.js';
|
|
71
74
|
import { GetAttachmentService } from '@memberjunction/aiengine';
|
|
@@ -105,6 +108,7 @@ export * from 'type-graphql';
|
|
|
105
108
|
// later importers, which makes schema build fail on ViewResult.RowCount.
|
|
106
109
|
export { Int, Float, ID } from 'type-graphql';
|
|
107
110
|
export { NewUserBase } from './auth/newUsers.js';
|
|
111
|
+
export { CreateIsolatedProvider } from './isolatedProvider.js';
|
|
108
112
|
export { configInfo, DEFAULT_SERVER_CONFIG } from './config.js';
|
|
109
113
|
export { ServerExtensionLoader, BaseServerExtension, DefaultServerExtensionServiceRegistry } from '@memberjunction/server-extensions-core';
|
|
110
114
|
export * from './directives/index.js';
|
|
@@ -151,6 +155,8 @@ export * from './resolvers/GenerateSeedTaxonomyResolver.js';
|
|
|
151
155
|
export * from './resolvers/PipelineProgressResolver.js';
|
|
152
156
|
export * from './resolvers/IntegrationProgressResolver.js';
|
|
153
157
|
export * from './resolvers/IdentityClaimRedemptionResolver.js';
|
|
158
|
+
export * from './resolvers/UserAvatarResolver.js';
|
|
159
|
+
export * from './resolvers/avatarInputValidation.js';
|
|
154
160
|
export * from './resolvers/ClientToolRequestResolver.js';
|
|
155
161
|
export * from './resolvers/AutotagPipelineResolver.js';
|
|
156
162
|
export * from './resolvers/TagGovernanceResolver.js';
|
|
@@ -206,6 +212,9 @@ export * from './resolvers/CurrentUserContextResolver.js';
|
|
|
206
212
|
export * from './resolvers/RSUResolver.js';
|
|
207
213
|
export * from './resolvers/AgentSessionResolver.js';
|
|
208
214
|
export * from './resolvers/RealtimeClientSessionResolver.js';
|
|
215
|
+
export * from './resolvers/RealtimeSessionEventsResolver.js';
|
|
216
|
+
export * from './resolvers/RealtimeSessionVerificationResolver.js';
|
|
217
|
+
export * from './realtimeSessions/index.js';
|
|
209
218
|
export * from './resolvers/MeetingResolver.js';
|
|
210
219
|
export * from './resolvers/RemoteBrowserActionResolver.js';
|
|
211
220
|
export * from './agentSessions/index.js';
|
|
@@ -247,57 +256,6 @@ function resolveServerVersion() {
|
|
|
247
256
|
}
|
|
248
257
|
/** How often to re-check for conversation details left behind by finished runs. */
|
|
249
258
|
const ORPHAN_DETAIL_SWEEP_INTERVAL_MS = 5 * 60_000;
|
|
250
|
-
/** Redis channel carrying replicated push-status updates between server instances. */
|
|
251
|
-
const PUSH_STATUS_FANOUT_CHANNEL = 'push-status-updates';
|
|
252
|
-
/**
|
|
253
|
-
* Replicate push-status updates across server instances over Redis (MJ #4222).
|
|
254
|
-
*
|
|
255
|
-
* Outbound: every locally-published update is forwarded on a shared channel. Inbound: a message
|
|
256
|
-
* from another instance is republished onto THIS instance's local topic, where the normal
|
|
257
|
-
* subscription filter decides who receives it — so the identity gate (`ownerUserId` vs. the
|
|
258
|
-
* connection's authenticated user) still applies to a replicated message exactly as it does to a
|
|
259
|
-
* local one. The replica has no say in who sees what.
|
|
260
|
-
*
|
|
261
|
-
* Republishing goes straight to `PubSubManager`, never back through `publishStatusUpdate`, so an
|
|
262
|
-
* inbound message cannot be re-broadcast and loop. `SourceServerId` guards the remaining case: a
|
|
263
|
-
* publisher also receives its own message from Redis.
|
|
264
|
-
*/
|
|
265
|
-
async function wirePushStatusFanOut(redisProvider, startupLog) {
|
|
266
|
-
try {
|
|
267
|
-
await redisProvider.SubscribeToChannel(PUSH_STATUS_FANOUT_CHANNEL, (raw) => {
|
|
268
|
-
try {
|
|
269
|
-
const payload = ParseReplicatedStatusUpdate(raw, MJGlobal.Instance.ProcessUUID);
|
|
270
|
-
if (!payload) {
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
// Rebuilt as a plain record: the topic's publish signature takes an index-signature type,
|
|
274
|
-
// and listing the fields keeps the wire shape explicit at the one place it crosses hosts.
|
|
275
|
-
PubSubManager.Instance.Publish(PUSH_STATUS_UPDATES_TOPIC, {
|
|
276
|
-
sessionId: payload.sessionId,
|
|
277
|
-
ownerUserId: payload.ownerUserId,
|
|
278
|
-
message: payload.message,
|
|
279
|
-
SourceServerId: payload.SourceServerId,
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
catch (err) {
|
|
283
|
-
// A malformed message on a shared channel must not take down the subscriber.
|
|
284
|
-
LogError('Error processing push-status fan-out message', undefined, err);
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
SetPushStatusPublishHook((payload) => {
|
|
288
|
-
redisProvider.PublishMessage(PUSH_STATUS_FANOUT_CHANNEL, JSON.stringify(payload));
|
|
289
|
-
});
|
|
290
|
-
// Printed unconditionally, not verbose-gated. "Is fan-out actually on?" is the first question
|
|
291
|
-
// anyone debugging a hung conversation behind a load balancer asks, and a silent default left
|
|
292
|
-
// no way to answer it.
|
|
293
|
-
console.log('[MJAPI] Push-status updates: cross-instance fan-out enabled via Redis');
|
|
294
|
-
}
|
|
295
|
-
catch (err) {
|
|
296
|
-
// Single-instance delivery still works, and the durable tail query covers the rest. Degraded,
|
|
297
|
-
// not broken — so this must not stop the server from starting.
|
|
298
|
-
console.warn(`Push-status fan-out unavailable: ${err.message}`);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
259
|
/**
|
|
302
260
|
* Replicate handoff-offer updates across server instances over Redis.
|
|
303
261
|
*
|
|
@@ -336,6 +294,44 @@ async function wireHandoffOfferFanOut(redisProvider, startupLog) {
|
|
|
336
294
|
console.warn(`Handoff-offer fan-out unavailable: ${err instanceof Error ? err.message : String(err)}`);
|
|
337
295
|
}
|
|
338
296
|
}
|
|
297
|
+
/** Redis channel carrying replicated realtime session events between server instances. */
|
|
298
|
+
const REALTIME_SESSION_EVENTS_FANOUT_CHANNEL = 'realtime-session-events';
|
|
299
|
+
/**
|
|
300
|
+
* Replicate realtime session events across server instances over Redis.
|
|
301
|
+
*
|
|
302
|
+
* Behind a load balancer the browser's WebSocket (the `RealtimeSessionEvents` subscription) lives on one
|
|
303
|
+
* replica while the request that raises the event — typically the public verify-link redemption — can be
|
|
304
|
+
* handled by another. The session-events topic is an in-process PubSub, so without this an
|
|
305
|
+
* `identity.verified` published on replica B never reaches the subscriber on replica A.
|
|
306
|
+
*
|
|
307
|
+
* Inbound messages are republished onto THIS instance's local topic only (never back through the
|
|
308
|
+
* replication hook, so there is no loop) and are still judged by the subscription filter against the
|
|
309
|
+
* connection's identity — a replica has no say in who sees what. The durable
|
|
310
|
+
* `RealtimeSessionVerificationStatus` query remains the backstop if Redis is down.
|
|
311
|
+
*/
|
|
312
|
+
async function wireRealtimeSessionEventFanOut(redisProvider) {
|
|
313
|
+
try {
|
|
314
|
+
await redisProvider.SubscribeToChannel(REALTIME_SESSION_EVENTS_FANOUT_CHANNEL, (raw) => {
|
|
315
|
+
try {
|
|
316
|
+
const payload = ParseReplicatedRealtimeSessionEvent(raw, MJGlobal.Instance.ProcessUUID);
|
|
317
|
+
if (payload) {
|
|
318
|
+
RealtimeSessionEventService.Instance.PublishReplicated(payload);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
catch (err) {
|
|
322
|
+
LogError(`Realtime session event fan-out: dropping a malformed replicated event: ${err.message}`);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
RealtimeSessionEventService.Instance.SetReplicationHook((payload) => {
|
|
326
|
+
redisProvider.PublishMessage(REALTIME_SESSION_EVENTS_FANOUT_CHANNEL, JSON.stringify(payload));
|
|
327
|
+
});
|
|
328
|
+
console.log('[MJAPI] Realtime session events: cross-instance fan-out enabled via Redis');
|
|
329
|
+
}
|
|
330
|
+
catch (err) {
|
|
331
|
+
// Single-instance delivery still works and the status query covers the rest: degraded, not broken.
|
|
332
|
+
console.warn(`Realtime session event fan-out unavailable: ${err.message}`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
339
335
|
// Bind MJStorage as the conversation-attachment blob store. The attachment service itself no longer
|
|
340
336
|
// imports `@memberjunction/storage` — that dependency made it unusable from any browser or React
|
|
341
337
|
// Native client, which is why the same attachment rules had been reimplemented three times.
|
|
@@ -348,6 +344,12 @@ async function wireHandoffOfferFanOut(redisProvider, startupLog) {
|
|
|
348
344
|
GetAttachmentService().BlobStore = new MJStorageBlobStore();
|
|
349
345
|
export const Serve = async (resolverPaths, app = CreateApp(), options) => {
|
|
350
346
|
const t0 = performance.now();
|
|
347
|
+
// Name this MJAPI instance by its port before anything stamps a session row with its identity, so the janitor's
|
|
348
|
+
// startup recovery closes only the sessions an earlier boot of this instance left, never those of another MJAPI on
|
|
349
|
+
// the same host (#5309).
|
|
350
|
+
SetHostInstancePort(graphqlPort);
|
|
351
|
+
// The realtime bridge engine stamps its bridge rows with the same identity and reconciles orphans by it (#5310).
|
|
352
|
+
BindBridgeEngineHostInstance();
|
|
351
353
|
// Level-gated startup logger. Resolves verbosity from telemetry.level (single
|
|
352
354
|
// operator knob). At `standard` (default), per-phase timings are collapsed into
|
|
353
355
|
// the one-line summary; at `verbose`+ each phase prints inline as before.
|
|
@@ -371,6 +373,24 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
|
|
|
371
373
|
const setupComplete$ = new ReplaySubject(1);
|
|
372
374
|
const dbType = GetDbType();
|
|
373
375
|
const dataSources = [];
|
|
376
|
+
// Shared cache first: the database provider loads metadata and startup engines through
|
|
377
|
+
// it, so the first server to start fills it and later servers read it instead of each querying
|
|
378
|
+
// the database and broadcasting what they loaded. Subscribed before engines load so they hear
|
|
379
|
+
// other servers while they start.
|
|
380
|
+
const sharedCache = CreateSharedCacheFromEnvironment(configInfo.cacheSettings);
|
|
381
|
+
if (sharedCache) {
|
|
382
|
+
await WireSharedCacheEvents(sharedCache, () => (Metadata.Provider instanceof ProviderBase ? Metadata.Provider : undefined)); // global-provider-ok: bootstrap
|
|
383
|
+
// The cross-instance fan-outs ride this connection. Push-status moved into sharedCache.ts
|
|
384
|
+
// with the rest of the Redis wiring; the handoff and realtime-session ones stay here deliberately —
|
|
385
|
+
// they reach into RoomHandoffEngine and RealtimeSessionEventService, and the cache module should not
|
|
386
|
+
// acquire a dependency on either.
|
|
387
|
+
await WirePushStatusFanOut(sharedCache);
|
|
388
|
+
await wireHandoffOfferFanOut(sharedCache, startupLog);
|
|
389
|
+
await wireRealtimeSessionEventFanOut(sharedCache);
|
|
390
|
+
startupLog.LogIf('verbose', `Redis cache provider connected: ${process.env.REDIS_URL}`);
|
|
391
|
+
}
|
|
392
|
+
const cacheManagerConfig = CacheManagerConfigFromSettings(configInfo.cacheSettings);
|
|
393
|
+
const warmupLeaseMs = WarmupLeaseMsFromSettings(configInfo.cacheSettings);
|
|
374
394
|
if (dbType === 'postgresql') {
|
|
375
395
|
// ─── PostgreSQL Path ───────────────────────────────────────────
|
|
376
396
|
startupLog.BeginPhase('Connecting to database');
|
|
@@ -422,6 +442,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
|
|
|
422
442
|
}));
|
|
423
443
|
// Set up the PostgreSQL provider
|
|
424
444
|
const pgConfigData = new PostgreSQLProviderConfigData(pgConnectionConfig, mj_core_schema, cacheRefreshInterval / 1000);
|
|
445
|
+
pgConfigData.LocalStorageProvider = sharedCache ?? undefined;
|
|
425
446
|
const provider = new PostgreSQLDataProvider();
|
|
426
447
|
await provider.Config(pgConfigData);
|
|
427
448
|
SetProvider(provider);
|
|
@@ -431,7 +452,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
|
|
|
431
452
|
const sysUser = UserCache.Instance.GetSystemUser();
|
|
432
453
|
const backupSysUser = UserCache.Instance.Users.find(u => u.IsActive && u.Type === 'Owner');
|
|
433
454
|
const pgStartupMode = ResolveStartupMode({ configValue: configInfo.startup?.mode, defaultMode: 'full' });
|
|
434
|
-
await StartupManagerImport.Instance.Startup(false, sysUser || backupSysUser, provider, { mode: pgStartupMode.mode });
|
|
455
|
+
await StartupManagerImport.Instance.Startup(false, sysUser || backupSysUser, provider, { mode: pgStartupMode.mode, cacheManagerConfig, warmupLeaseMs });
|
|
435
456
|
// Both provider sources have now had their turn — config/env at module load, metadata via
|
|
436
457
|
// AuthProviderEngine's startup hook — so "no providers at all" is finally a meaningful check.
|
|
437
458
|
validateAuthProvidersRegistered();
|
|
@@ -561,10 +582,11 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
|
|
|
561
582
|
}
|
|
562
583
|
// cacheRefreshInterval is configured in ms; checkRefreshIntervalSeconds declares seconds — see providerConfigUnits.ts
|
|
563
584
|
const config = new SQLServerProviderConfigData(pool, mj_core_schema, MetadataCacheRefreshIntervalSeconds(cacheRefreshInterval));
|
|
585
|
+
config.LocalStorageProvider = sharedCache ?? undefined;
|
|
564
586
|
// MJAPI is a long-running server, so entry-point default is 'full' engine pre-warm;
|
|
565
587
|
// MJ_STARTUP_MODE / mj.config.cjs startup.mode can override per the shared precedence chain
|
|
566
588
|
const startupMode = ResolveStartupMode({ configValue: configInfo.startup?.mode, defaultMode: 'full' });
|
|
567
|
-
await setupSQLServerClient(config, { mode: startupMode.mode });
|
|
589
|
+
await setupSQLServerClient(config, { mode: startupMode.mode, cacheManagerConfig, warmupLeaseMs });
|
|
568
590
|
// See the note on the PostgreSQL path above: this is the first point at which both the
|
|
569
591
|
// config/env providers and the metadata catalog have been registered.
|
|
570
592
|
validateAuthProvidersRegistered();
|
|
@@ -677,77 +699,28 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
|
|
|
677
699
|
tm.SetEnabled(false);
|
|
678
700
|
startupLog.LogIf('verbose', 'Server telemetry disabled');
|
|
679
701
|
}
|
|
680
|
-
//
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
});
|
|
688
|
-
Metadata.Provider.SetLocalStorageProvider(redisProvider); // global-provider-ok: bootstrap (Redis cache wiring)
|
|
689
|
-
await redisProvider.StartListening();
|
|
690
|
-
// Connect Redis pub/sub events to LocalCacheManager callback dispatch
|
|
691
|
-
// so cross-server cache invalidation messages are routed to registered callbacks
|
|
692
|
-
redisProvider.OnCacheChanged((event) => {
|
|
693
|
-
const sourceShort = event.SourceServerId ? event.SourceServerId.substring(0, 8) : 'unknown';
|
|
694
|
-
console.log(`[MJAPI] Redis pub/sub → DispatchCacheChange: ${event.Action} for "${event.CacheKey}" from server ${sourceShort}`);
|
|
695
|
-
LocalCacheManager.Instance.DispatchCacheChange(event);
|
|
696
|
-
// Also broadcast to connected browser clients via GraphQL subscription
|
|
697
|
-
// Extract entity name from the cache key (format: EntityName|Filter|OrderBy|...)
|
|
698
|
-
const entityName = event.CacheKey ? event.CacheKey.split('|')[0] : '';
|
|
699
|
-
if (entityName) {
|
|
700
|
-
PubSubManager.Instance.Publish(CACHE_INVALIDATION_TOPIC, {
|
|
701
|
-
entityName,
|
|
702
|
-
primaryKeyValues: null, // entity-level invalidation
|
|
703
|
-
action: event.Action || 'save',
|
|
704
|
-
sourceServerId: event.SourceServerId || 'unknown',
|
|
705
|
-
timestamp: new Date(),
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
});
|
|
709
|
-
// Fan push-status updates across server instances (MJ #4222).
|
|
710
|
-
//
|
|
711
|
-
// Behind a load balancer the browser's WebSocket lives on one replica while the mutation that
|
|
712
|
-
// drives the agent can be handled by another. The push topic is an in-process PubSub, so a
|
|
713
|
-
// completion published on replica B never reaches a subscriber on replica A — the browser waits
|
|
714
|
-
// forever for an event that was delivered to nobody. Replicating progress and completion over
|
|
715
|
-
// Redis closes that, and the durable tail query remains the backstop if Redis is down.
|
|
716
|
-
await wirePushStatusFanOut(redisProvider, startupLog);
|
|
717
|
-
await wireHandoffOfferFanOut(redisProvider, startupLog);
|
|
718
|
-
startupLog.LogIf('verbose', `Redis cache provider connected: ${process.env.REDIS_URL}`);
|
|
719
|
-
}
|
|
720
|
-
// If Redis is available, swap LocalCacheManager's storage provider to Redis.
|
|
721
|
-
// LocalCacheManager may have already been initialized (with in-memory provider)
|
|
722
|
-
// during engine loading. SetStorageProvider migrates cached data to Redis.
|
|
723
|
-
if (process.env.REDIS_URL) {
|
|
724
|
-
await LocalCacheManager.Instance.SetStorageProvider(Metadata.Provider.LocalStorageProvider); // global-provider-ok: bootstrap
|
|
725
|
-
startupLog.LogIf('verbose', 'LocalCacheManager: storage provider swapped to Redis');
|
|
726
|
-
}
|
|
727
|
-
// Ensure LocalCacheManager is initialized (no-op if already done during engine loading)
|
|
728
|
-
if (!LocalCacheManager.Instance.IsInitialized) {
|
|
729
|
-
// Build cache config from mj.config.cjs cacheSettings
|
|
730
|
-
const cs = configInfo.cacheSettings;
|
|
731
|
-
const cacheConfig = {
|
|
732
|
-
maxSizeBytes: (cs.maxMemoryMB ?? 150) * 1024 * 1024,
|
|
733
|
-
maxPercentOfCachePerEntity: cs.maxPercentOfCachePerEntity ?? 50,
|
|
734
|
-
defaultTTLMs: (cs.defaultTTLSeconds ?? 0) * 1000,
|
|
735
|
-
evictionSweepIntervalMs: (cs.evictionSweepIntervalSeconds ?? 300) * 1000,
|
|
736
|
-
verboseLogging: cs.verboseLogging ?? false,
|
|
737
|
-
};
|
|
738
|
-
await LocalCacheManager.Instance.Initialize(Metadata.Provider.LocalStorageProvider, cacheConfig); // global-provider-ok: bootstrap
|
|
739
|
-
if (startupLog.IsAtLeast('verbose')) {
|
|
740
|
-
// eslint-disable-next-line no-console
|
|
741
|
-
console.log('LocalCacheManager initialized with cache config:', JSON.stringify({
|
|
742
|
-
maxMemoryMB: cs.maxMemoryMB ?? 150,
|
|
743
|
-
maxPercentOfCachePerEntity: cs.maxPercentOfCachePerEntity ?? 50,
|
|
744
|
-
evictionSweepIntervalSeconds: cs.evictionSweepIntervalSeconds ?? 300,
|
|
745
|
-
}));
|
|
746
|
-
}
|
|
702
|
+
// The database provider already initialized LocalCacheManager from inside its own Config(), with
|
|
703
|
+
// no settings — this call is what makes `cacheSettings` take effect (Initialize merges a config
|
|
704
|
+
// handed to it later). Unconditional on purpose: the guard that used to sit here
|
|
705
|
+
// skipped exactly the case that needed it.
|
|
706
|
+
await LocalCacheManager.Instance.Initialize(Metadata.Provider.LocalStorageProvider, cacheManagerConfig); // global-provider-ok: bootstrap
|
|
707
|
+
if (sharedCache) {
|
|
708
|
+
await LocalCacheManager.Instance.SetStorageProvider(sharedCache);
|
|
747
709
|
}
|
|
710
|
+
const engineSweepMs = StartEngineSweeper(configInfo.cacheSettings);
|
|
711
|
+
startupLog.LogIf('verbose', engineSweepMs > 0 ? `Engine/database sweep every ${engineSweepMs / 1000}s` : 'Engine/database sweep disabled');
|
|
712
|
+
const userCacheCheckMs = StartUserCacheChecks(configInfo.cacheSettings);
|
|
713
|
+
startupLog.LogIf('verbose', userCacheCheckMs > 0 ? `User cache staleness check every ${userCacheCheckMs / 1000}s` : 'User cache staleness check disabled');
|
|
714
|
+
// Costs nothing unless a metadata entity declares TrustServerCacheCompletely = false.
|
|
715
|
+
const metadataSweepMs = StartMetadataSweep(configInfo.cacheSettings, () => (Metadata.Provider instanceof ProviderBase ? Metadata.Provider : undefined)); // global-provider-ok: bootstrap (this process's one provider)
|
|
716
|
+
startupLog.LogIf('verbose', metadataSweepMs > 0 ? `Metadata/database sweep every ${metadataSweepMs / 1000}s (only for entities declaring drift)` : 'Metadata/database sweep disabled');
|
|
748
717
|
// Initialize APIKeyEngine singleton — reads apiKeyGeneration from mj.config.cjs automatically
|
|
749
718
|
// This must happen before any request handler calls GetAPIKeyEngine()
|
|
750
719
|
GetAPIKeyEngine();
|
|
720
|
+
// Actions that run caller-supplied SQL (Run Ad-hoc Query) run only on the read-only login, with
|
|
721
|
+
// ExecuteAdhocQuery's table check and timeout limit.
|
|
722
|
+
ActionEngineServer.Instance.SetReadOnlyProviderFactory(() => CreateReadOnlyProvider(dataSources));
|
|
723
|
+
ActionEngineServer.Instance.SetAdhocSQLAuthorizer(CreateAdhocSQLAuthorizer(configInfo.databaseSettings.requestTimeout));
|
|
751
724
|
setupComplete$.next(true);
|
|
752
725
|
raiseEvent('setupComplete', dataSources, null, this);
|
|
753
726
|
/******TEST HARNESS FOR CHANGE DETECTION */
|
|
@@ -957,7 +930,7 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
|
|
|
957
930
|
const buildMs = performance.now() - tBuild;
|
|
958
931
|
if (cpuProf && profSession) {
|
|
959
932
|
const profile = await new Promise((res, rej) => profSession.post('Profiler.stop', (e, r) => (e ? rej(e) : res(r.profile))));
|
|
960
|
-
const outPath =
|
|
933
|
+
const outPath = join(mkdtempSync(join(tmpdir(), 'mjapi-schema-')), `mjapi_schema_build_${process.pid}.cpuprofile`);
|
|
961
934
|
writeFileSync(outPath, JSON.stringify(profile));
|
|
962
935
|
profSession.disconnect();
|
|
963
936
|
// eslint-disable-next-line no-console
|
|
@@ -1204,6 +1177,18 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
|
|
|
1204
1177
|
}
|
|
1205
1178
|
startupLog.LogIf('verbose', `[Widget] Public routes registered at ${WIDGET_MOUNT_PATH}/session and ${WIDGET_MOUNT_PATH}/session/refresh`);
|
|
1206
1179
|
}
|
|
1180
|
+
// ─── Realtime identity verification: PUBLIC verify-link routes (before auth mw) ───
|
|
1181
|
+
// The person opening the emailed link holds no MJ token — the single-use token is the capability.
|
|
1182
|
+
// GET only renders a confirm button; the POST redeems (mail scanners GET every link). Mounted only
|
|
1183
|
+
// when verification is enabled AND able to send mail AND able to protect its codes (see
|
|
1184
|
+
// realtime.identityVerification config: communicationProvider + hmacSecret).
|
|
1185
|
+
if (configInfo.realtime?.identityVerification?.enabled && !RealtimeSessionVerificationService.Instance.IsEnabled) {
|
|
1186
|
+
console.warn('[RealtimeVerify] realtime.identityVerification.enabled is true but verification is unavailable: it needs a communicationProvider and an hmacSecret of at least 16 characters.');
|
|
1187
|
+
}
|
|
1188
|
+
if (RealtimeSessionVerificationService.Instance.IsEnabled) {
|
|
1189
|
+
app.use(REALTIME_VERIFY_MOUNT_PATH, cors(), CreateRealtimeVerifyRouter());
|
|
1190
|
+
startupLog.LogIf('verbose', `[RealtimeVerify] Public routes registered at ${REALTIME_VERIFY_MOUNT_PATH}/:token (GET) and ${REALTIME_VERIFY_MOUNT_PATH} (POST)`);
|
|
1191
|
+
}
|
|
1207
1192
|
// ─── Server extensions loader & shared service registry ───────────────────
|
|
1208
1193
|
const extensionLoader = new ServerExtensionLoader();
|
|
1209
1194
|
_currentExtensionLoader = extensionLoader;
|
|
@@ -1505,12 +1490,16 @@ export const Serve = async (resolverPaths, app = CreateApp(), options) => {
|
|
|
1505
1490
|
Shutdown: () => { clearInterval(orphanDetailTimer); },
|
|
1506
1491
|
});
|
|
1507
1492
|
}
|
|
1508
|
-
// Launch the AI Agent Session janitor: run own-host orphan recovery once at boot, then
|
|
1509
|
-
//
|
|
1510
|
-
//
|
|
1493
|
+
// Launch the AI Agent Session janitor: run own-host orphan recovery once at boot, then a periodic tick
|
|
1494
|
+
// that closes stale and over-deadline sessions and rebuilds lost realtime recordings from their
|
|
1495
|
+
// crash-recovery shards (storage reads and writes). Self-registers with ShutdownRegistry, so its timer
|
|
1496
|
+
// is cleared by the gracefulShutdown drain below (no explicit Stop() wiring needed here).
|
|
1511
1497
|
if (resumeUser && Metadata.Provider instanceof DatabaseProviderBase) { // global-provider-ok: server startup recovery — boot-time session janitor uses the server's own provider
|
|
1512
1498
|
SessionJanitor.Instance.Start(Metadata.Provider, resumeUser) // global-provider-ok: server-owned background reconciler runs under the server's provider + system user
|
|
1513
1499
|
.catch(err => console.warn(`[SessionJanitor] Startup failed: ${err}`));
|
|
1500
|
+
// The bridge engine's orphan reconcile likewise starts only now that this process holds its port, so it can't
|
|
1501
|
+
// take the live bridges of another MJAPI still serving that port for its own orphans (#5310).
|
|
1502
|
+
StartBridgeOrphanReconciliation(Metadata.Provider, resumeUser); // global-provider-ok: server-owned background reconciler runs under the server's provider + system user
|
|
1514
1503
|
}
|
|
1515
1504
|
// Launch the durable task-graph dispatcher: claim Pending tasks, execute them with a fresh
|
|
1516
1505
|
// provider each, and reconcile claims orphaned by a crash. Without this nothing ever picks up a
|