@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
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Who may see and act on ONE realtime session.
|
|
3
|
+
*
|
|
4
|
+
* One pure decision ({@link AuthorizeSessionAccess}) shared by everything that addresses a live
|
|
5
|
+
* session on behalf of a caller: the `RealtimeSessionEvents` subscription (at subscribe time AND for
|
|
6
|
+
* every delivered event), the verification mutations, and the status query. Keeping it in one place
|
|
7
|
+
* is what stops "who owns this session?" from being re-derived — slightly differently — in each.
|
|
8
|
+
*
|
|
9
|
+
* ## The two ownership rules
|
|
10
|
+
*
|
|
11
|
+
* 1. **Owner.** The session's `UserID` must be the caller's user.
|
|
12
|
+
* 2. **Scope.** A *named* user is fully identified by (1). An **anonymous widget guest** is not:
|
|
13
|
+
* every guest authenticates as the one shared Anonymous user, so (1) alone would let any guest
|
|
14
|
+
* address any other guest's session. What separates guests is the signed per-session scope in
|
|
15
|
+
* their token (`MagicLinkScope.ResourceID`), which `SessionManager` stamps onto the session's
|
|
16
|
+
* Conversation as `ExternalID`. So a principal that carries a scope must match it, and an
|
|
17
|
+
* anonymous principal that carries NO scope is refused outright — it cannot be told apart from
|
|
18
|
+
* every other anonymous principal.
|
|
19
|
+
*
|
|
20
|
+
* The decision is deliberately pure (no I/O) so it can be applied identically to a freshly loaded
|
|
21
|
+
* row at subscribe time and to the owner/scope snapshot carried inside each published event.
|
|
22
|
+
*
|
|
23
|
+
* @module @memberjunction/server/realtimeSessions
|
|
24
|
+
*/
|
|
25
|
+
import { LogError } from '@memberjunction/core';
|
|
26
|
+
import { IsValidUUID, UUIDsEqual } from '@memberjunction/global';
|
|
27
|
+
/** Entity names, centralised so the `MJ: ` prefix convention lives in one place. */
|
|
28
|
+
const SESSION_ENTITY = 'MJ: AI Agent Sessions';
|
|
29
|
+
const CONVERSATION_ENTITY = 'MJ: Conversations';
|
|
30
|
+
/**
|
|
31
|
+
* Decides whether `principal` may address the session described by `subject`.
|
|
32
|
+
*
|
|
33
|
+
* Fails closed: anything that cannot be positively matched is refused.
|
|
34
|
+
*
|
|
35
|
+
* @param subject - owner + scope of the session
|
|
36
|
+
* @param principal - the authenticated caller (from the server-built `UserInfo`, never from client args)
|
|
37
|
+
*/
|
|
38
|
+
export function AuthorizeSessionAccess(subject, principal) {
|
|
39
|
+
if (!principal?.ID || !subject.SessionUserID || !UUIDsEqual(subject.SessionUserID, principal.ID)) {
|
|
40
|
+
return { Allowed: false, Reason: 'not_owner' };
|
|
41
|
+
}
|
|
42
|
+
const scopeId = principal.MagicLinkScope?.ResourceID;
|
|
43
|
+
if (!scopeId) {
|
|
44
|
+
// An anonymous principal without a per-session scope is indistinguishable from every other
|
|
45
|
+
// anonymous principal: owning "the Anonymous user's" session proves nothing.
|
|
46
|
+
return principal.IsMagicLinkAnonymous ? { Allowed: false, Reason: 'scope_missing' } : { Allowed: true };
|
|
47
|
+
}
|
|
48
|
+
// Scope ids are opaque base64url strings (case-significant), so compare exactly — not UUIDsEqual.
|
|
49
|
+
return subject.ConversationExternalID === scopeId ? { Allowed: true } : { Allowed: false, Reason: 'scope_mismatch' };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Loads a session (and its conversation's scope id) under `contextUser`'s identity.
|
|
53
|
+
*
|
|
54
|
+
* Loading as the caller — rather than as a privileged user — means the entity layer's row-level
|
|
55
|
+
* security (`Widget Guest: Own Agent Sessions`, `UI: Own Agent Sessions`) is the FIRST gate; the
|
|
56
|
+
* explicit {@link AuthorizeSessionAccess} check that follows is defence in depth.
|
|
57
|
+
*
|
|
58
|
+
* @returns the loaded session, or `null` when the id is malformed, the row does not exist, or the
|
|
59
|
+
* caller cannot read it. Failure to read the conversation yields `ConversationExternalID: null`,
|
|
60
|
+
* which {@link AuthorizeSessionAccess} then treats as "no scope to match" (refused for a scoped caller).
|
|
61
|
+
*/
|
|
62
|
+
export async function LoadSessionForAccess(agentSessionId, contextUser, provider) {
|
|
63
|
+
if (!IsValidUUID(agentSessionId)) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const session = await provider.GetEntityObject(SESSION_ENTITY, contextUser);
|
|
67
|
+
if (!(await session.Load(agentSessionId))) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return { Session: session, ConversationExternalID: await loadConversationExternalID(session, contextUser, provider) };
|
|
71
|
+
}
|
|
72
|
+
/** Reads the session conversation's `ExternalID`; null when there is no conversation or it cannot be read. */
|
|
73
|
+
async function loadConversationExternalID(session, contextUser, provider) {
|
|
74
|
+
if (!session.ConversationID) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const conversation = await provider.GetEntityObject(CONVERSATION_ENTITY, contextUser);
|
|
79
|
+
if (!(await conversation.Load(session.ConversationID))) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return conversation.ExternalID ?? null;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
86
|
+
LogError(`LoadSessionForAccess: could not read conversation ${session.ConversationID} of session ${session.ID}: ${message}`);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=sessionAccess.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionAccess.js","sourceRoot":"","sources":["../../src/realtimeSessions/sessionAccess.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAqB,QAAQ,EAAY,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGjE,oFAAoF;AACpF,MAAM,cAAc,GAAG,uBAAuB,CAAC;AAC/C,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AA8BhD;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAClC,OAA6B,EAC7B,SAAoD;IAEpD,IAAI,CAAC,SAAS,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,aAAa,EAAE,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC;QAC/F,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACnD,CAAC;IACD,MAAM,OAAO,GAAG,SAAS,CAAC,cAAc,EAAE,UAAU,CAAC;IACrD,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,2FAA2F;QAC3F,6EAA6E;QAC7E,OAAO,SAAS,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC5G,CAAC;IACD,kGAAkG;IAClG,OAAO,OAAO,CAAC,sBAAsB,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;AACzH,CAAC;AAUD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACtC,cAAsB,EACtB,WAAqB,EACrB,QAA2B;IAE3B,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAyB,cAAc,EAAE,WAAW,CAAC,CAAC;IACpG,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,CAAC;AAC1H,CAAC;AAED,8GAA8G;AAC9G,KAAK,UAAU,0BAA0B,CACrC,OAA+B,EAC/B,WAAqB,EACrB,QAA2B;IAE3B,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAuB,mBAAmB,EAAE,WAAW,CAAC,CAAC;QAC5G,IAAI,CAAC,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,OAAO,YAAY,CAAC,UAAU,IAAI,IAAI,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,QAAQ,CAAC,qDAAqD,OAAO,CAAC,cAAc,eAAe,OAAO,CAAC,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC;QAC7H,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview What the session-start path stamps into a new realtime session's `Config` for identity
|
|
3
|
+
* verification: the policy snapshot, the unverified duration cap, and any verified identity carried
|
|
4
|
+
* forward from the session being resumed.
|
|
5
|
+
*
|
|
6
|
+
* Split in two so the decision is testable without a database:
|
|
7
|
+
*
|
|
8
|
+
* - {@link BuildMintConfigStamps} — **pure**. Given the resolved realtime config, the existing `Config`
|
|
9
|
+
* and an optional inherited identity, returns the `Config` to write (or `null` when there is nothing
|
|
10
|
+
* to stamp).
|
|
11
|
+
* - {@link LoadInheritedVerifiedIdentity} — the one read: the prior session's verified identity, only
|
|
12
|
+
* when the new caller is authorized on that prior session.
|
|
13
|
+
*
|
|
14
|
+
* Everything stamped here lives under server-authoritative keys (`identityVerification`,
|
|
15
|
+
* `maxSessionDeadlineIso`); the caller writes it inside `RunWithTrustedSessionConfigWrites`.
|
|
16
|
+
*
|
|
17
|
+
* ## Resume after the cap
|
|
18
|
+
*
|
|
19
|
+
* If an unverified session hits its cap before the person verifies, the janitor closes it. A verify link
|
|
20
|
+
* redeemed afterwards still records the verification on that (closed) session, and a **new** session
|
|
21
|
+
* started with `lastSessionId` pointing at it inherits the verified identity (and, with it, the
|
|
22
|
+
* `verifiedMaxSeconds` cap instead of the unverified one). Inheritance requires the same ownership/scope
|
|
23
|
+
* authorization as any other access to the prior session, so a stranger cannot adopt someone else's
|
|
24
|
+
* verification by naming their session id.
|
|
25
|
+
*
|
|
26
|
+
* @module @memberjunction/server/realtimeSessions
|
|
27
|
+
*/
|
|
28
|
+
import type { IMetadataProvider, UserInfo } from '@memberjunction/core';
|
|
29
|
+
import { type VerifiedIdentity } from './verificationCore.js';
|
|
30
|
+
/** The `Config` to persist at session start. */
|
|
31
|
+
export interface MintConfigStampPlan {
|
|
32
|
+
NextConfigRaw: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Decides what to stamp into a freshly created session's `Config`.
|
|
36
|
+
*
|
|
37
|
+
* - **Policy snapshot.** The cascade's verification layer (`channels.config.IdentityVerification` plus the
|
|
38
|
+
* duration caps) is copied onto the session, so the rules a person is held to are fixed at mint,
|
|
39
|
+
* server-side, and cannot be chosen by the caller later.
|
|
40
|
+
* - **Duration cap.** When the cascade configures `unverifiedMaxSeconds` (or, for a session that inherited
|
|
41
|
+
* a verified identity, `verifiedMaxSeconds`), the session's absolute deadline is set to now + cap —
|
|
42
|
+
* applied to ANY principal, not only widget guests — and never loosens a tighter deadline already
|
|
43
|
+
* stamped (the widget voice cap).
|
|
44
|
+
* - **Inherited identity.** A verified identity carried forward from the resumed session.
|
|
45
|
+
*
|
|
46
|
+
* @param args.EffectiveRealtime - `EffectiveConfig.realtime` of the resolved config (any shape; read defensively)
|
|
47
|
+
* @param args.ExistingConfigRaw - the session's current `Config`
|
|
48
|
+
* @param args.InheritedVerified - verified identity from the session being resumed, if any
|
|
49
|
+
* @param args.NowMs - the current time, epoch ms
|
|
50
|
+
* @returns the `Config` to write, or `null` when nothing needs stamping
|
|
51
|
+
*/
|
|
52
|
+
export declare function BuildMintConfigStamps(args: {
|
|
53
|
+
EffectiveRealtime: unknown;
|
|
54
|
+
ExistingConfigRaw: string | null;
|
|
55
|
+
InheritedVerified?: VerifiedIdentity;
|
|
56
|
+
NowMs: number;
|
|
57
|
+
}): MintConfigStampPlan | null;
|
|
58
|
+
/**
|
|
59
|
+
* The verified identity of the session being resumed, when the caller may inherit it.
|
|
60
|
+
*
|
|
61
|
+
* Reads the prior session as the caller and requires {@link AuthorizeSessionAccess} to allow it; any
|
|
62
|
+
* failure (no such session, not the caller's, unreadable) yields `undefined` — inheritance is a
|
|
63
|
+
* convenience and must never block a session start.
|
|
64
|
+
*
|
|
65
|
+
* @param lastSessionId - the `lastSessionId` the client supplied at start
|
|
66
|
+
* @param contextUser - the starting caller
|
|
67
|
+
* @param provider - request-scoped provider
|
|
68
|
+
*/
|
|
69
|
+
export declare function LoadInheritedVerifiedIdentity(lastSessionId: string | undefined, contextUser: UserInfo, provider: IMetadataProvider): Promise<VerifiedIdentity | undefined>;
|
|
70
|
+
//# sourceMappingURL=sessionConfigStamps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionConfigStamps.d.ts","sourceRoot":"","sources":["../../src/realtimeSessions/sessionConfigStamps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAOxE,OAAO,EAKH,KAAK,gBAAgB,EACxB,MAAM,uBAAuB,CAAC;AAE/B,gDAAgD;AAChD,MAAM,WAAW,mBAAmB;IAChC,aAAa,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IACxC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iBAAiB,CAAC,EAAE,gBAAgB,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;CACjB,GAAG,mBAAmB,GAAG,IAAI,CAkB7B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,6BAA6B,CAC/C,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,WAAW,EAAE,QAAQ,EACrB,QAAQ,EAAE,iBAAiB,GAC5B,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAgBvC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview What the session-start path stamps into a new realtime session's `Config` for identity
|
|
3
|
+
* verification: the policy snapshot, the unverified duration cap, and any verified identity carried
|
|
4
|
+
* forward from the session being resumed.
|
|
5
|
+
*
|
|
6
|
+
* Split in two so the decision is testable without a database:
|
|
7
|
+
*
|
|
8
|
+
* - {@link BuildMintConfigStamps} — **pure**. Given the resolved realtime config, the existing `Config`
|
|
9
|
+
* and an optional inherited identity, returns the `Config` to write (or `null` when there is nothing
|
|
10
|
+
* to stamp).
|
|
11
|
+
* - {@link LoadInheritedVerifiedIdentity} — the one read: the prior session's verified identity, only
|
|
12
|
+
* when the new caller is authorized on that prior session.
|
|
13
|
+
*
|
|
14
|
+
* Everything stamped here lives under server-authoritative keys (`identityVerification`,
|
|
15
|
+
* `maxSessionDeadlineIso`); the caller writes it inside `RunWithTrustedSessionConfigWrites`.
|
|
16
|
+
*
|
|
17
|
+
* ## Resume after the cap
|
|
18
|
+
*
|
|
19
|
+
* If an unverified session hits its cap before the person verifies, the janitor closes it. A verify link
|
|
20
|
+
* redeemed afterwards still records the verification on that (closed) session, and a **new** session
|
|
21
|
+
* started with `lastSessionId` pointing at it inherits the verified identity (and, with it, the
|
|
22
|
+
* `verifiedMaxSeconds` cap instead of the unverified one). Inheritance requires the same ownership/scope
|
|
23
|
+
* authorization as any other access to the prior session, so a stranger cannot adopt someone else's
|
|
24
|
+
* verification by naming their session id.
|
|
25
|
+
*
|
|
26
|
+
* @module @memberjunction/server/realtimeSessions
|
|
27
|
+
*/
|
|
28
|
+
import { AuthorizeSessionAccess, LoadSessionForAccess } from './sessionAccess.js';
|
|
29
|
+
import { ExtractIdentityVerificationPolicyFromRealtimeConfig, ReadIdentityVerificationPolicyLayer, TightenSessionDeadline, } from './verificationPolicy.js';
|
|
30
|
+
import { ParseConfigObject, ReadIdentityVerificationState, WriteIdentityVerificationState, } from './verificationCore.js';
|
|
31
|
+
/**
|
|
32
|
+
* Decides what to stamp into a freshly created session's `Config`.
|
|
33
|
+
*
|
|
34
|
+
* - **Policy snapshot.** The cascade's verification layer (`channels.config.IdentityVerification` plus the
|
|
35
|
+
* duration caps) is copied onto the session, so the rules a person is held to are fixed at mint,
|
|
36
|
+
* server-side, and cannot be chosen by the caller later.
|
|
37
|
+
* - **Duration cap.** When the cascade configures `unverifiedMaxSeconds` (or, for a session that inherited
|
|
38
|
+
* a verified identity, `verifiedMaxSeconds`), the session's absolute deadline is set to now + cap —
|
|
39
|
+
* applied to ANY principal, not only widget guests — and never loosens a tighter deadline already
|
|
40
|
+
* stamped (the widget voice cap).
|
|
41
|
+
* - **Inherited identity.** A verified identity carried forward from the resumed session.
|
|
42
|
+
*
|
|
43
|
+
* @param args.EffectiveRealtime - `EffectiveConfig.realtime` of the resolved config (any shape; read defensively)
|
|
44
|
+
* @param args.ExistingConfigRaw - the session's current `Config`
|
|
45
|
+
* @param args.InheritedVerified - verified identity from the session being resumed, if any
|
|
46
|
+
* @param args.NowMs - the current time, epoch ms
|
|
47
|
+
* @returns the `Config` to write, or `null` when nothing needs stamping
|
|
48
|
+
*/
|
|
49
|
+
export function BuildMintConfigStamps(args) {
|
|
50
|
+
const layer = ExtractIdentityVerificationPolicyFromRealtimeConfig(args.EffectiveRealtime);
|
|
51
|
+
const hasPolicy = Object.keys(layer).length > 0;
|
|
52
|
+
if (!hasPolicy && !args.InheritedVerified) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const existingState = ReadIdentityVerificationState(args.ExistingConfigRaw, ReadIdentityVerificationPolicyLayer);
|
|
56
|
+
const state = {
|
|
57
|
+
...existingState,
|
|
58
|
+
...(hasPolicy ? { Policy: layer } : {}),
|
|
59
|
+
...(args.InheritedVerified ? { Verified: args.InheritedVerified } : {}),
|
|
60
|
+
};
|
|
61
|
+
const capSeconds = args.InheritedVerified ? (layer.verifiedMaxSeconds ?? layer.unverifiedMaxSeconds) : layer.unverifiedMaxSeconds;
|
|
62
|
+
const existingDeadline = ParseConfigObject(args.ExistingConfigRaw)['maxSessionDeadlineIso'];
|
|
63
|
+
const deadlineIso = capSeconds
|
|
64
|
+
? TightenSessionDeadline(typeof existingDeadline === 'string' ? existingDeadline : undefined, args.NowMs + capSeconds * 1000)
|
|
65
|
+
: undefined;
|
|
66
|
+
return { NextConfigRaw: WriteIdentityVerificationState(args.ExistingConfigRaw, state, deadlineIso) };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The verified identity of the session being resumed, when the caller may inherit it.
|
|
70
|
+
*
|
|
71
|
+
* Reads the prior session as the caller and requires {@link AuthorizeSessionAccess} to allow it; any
|
|
72
|
+
* failure (no such session, not the caller's, unreadable) yields `undefined` — inheritance is a
|
|
73
|
+
* convenience and must never block a session start.
|
|
74
|
+
*
|
|
75
|
+
* @param lastSessionId - the `lastSessionId` the client supplied at start
|
|
76
|
+
* @param contextUser - the starting caller
|
|
77
|
+
* @param provider - request-scoped provider
|
|
78
|
+
*/
|
|
79
|
+
export async function LoadInheritedVerifiedIdentity(lastSessionId, contextUser, provider) {
|
|
80
|
+
if (!lastSessionId) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
const prior = await LoadSessionForAccess(lastSessionId, contextUser, provider);
|
|
84
|
+
if (!prior) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
const decision = AuthorizeSessionAccess({ SessionUserID: prior.Session.UserID, ConversationExternalID: prior.ConversationExternalID }, contextUser);
|
|
88
|
+
if (decision.Allowed === false) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
return ReadIdentityVerificationState(prior.Session.Config_, ReadIdentityVerificationPolicyLayer).Verified;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=sessionConfigStamps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionConfigStamps.js","sourceRoot":"","sources":["../../src/realtimeSessions/sessionConfigStamps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EACH,mDAAmD,EACnD,mCAAmC,EACnC,sBAAsB,GACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACH,iBAAiB,EACjB,6BAA6B,EAC7B,8BAA8B,GAGjC,MAAM,uBAAuB,CAAC;AAO/B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAKrC;IACG,MAAM,KAAK,GAAG,mDAAmD,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC1F,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAChD,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,MAAM,aAAa,GAAG,6BAA6B,CAAC,IAAI,CAAC,iBAAiB,EAAE,mCAAmC,CAAC,CAAC;IACjH,MAAM,KAAK,GAA8B;QACrC,GAAG,aAAa;QAChB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvC,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC;IACF,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC;IAClI,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,uBAAuB,CAAC,CAAC;IAC5F,MAAM,WAAW,GAAG,UAAU;QAC1B,CAAC,CAAC,sBAAsB,CAAC,OAAO,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,GAAG,UAAU,GAAG,IAAI,CAAC;QAC7H,CAAC,CAAC,SAAS,CAAC;IAChB,OAAO,EAAE,aAAa,EAAE,8BAA8B,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC;AACzG,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAC/C,aAAiC,EACjC,WAAqB,EACrB,QAA2B;IAE3B,IAAI,CAAC,aAAa,EAAE,CAAC;QACjB,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,oBAAoB,CAAC,aAAa,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC/E,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,MAAM,QAAQ,GAAG,sBAAsB,CACnC,EAAE,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,sBAAsB,EAAE,KAAK,CAAC,sBAAsB,EAAE,EAC7F,WAAW,CACd,CAAC;IACF,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QAC7B,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,OAAO,6BAA6B,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,mCAAmC,CAAC,CAAC,QAAQ,CAAC;AAC9G,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The authorization of the `RealtimeSessionEvents` subscription, free of GraphQL schema
|
|
3
|
+
* decorators and server configuration so it can be exercised — and reused — without loading either.
|
|
4
|
+
*
|
|
5
|
+
* It is applied twice on purpose (see `RealtimeSessionEventsResolver`): once when the subscription is
|
|
6
|
+
* opened ({@link AuthorizeRealtimeSessionSubscription}) and once for every event
|
|
7
|
+
* ({@link RealtimeSessionEventsFilter}). In neither check does a client-supplied value decide who
|
|
8
|
+
* receives anything: `agentSessionId` only selects WHICH of the caller's own sessions to listen to; the
|
|
9
|
+
* identity it is checked against comes from the server-authenticated connection context.
|
|
10
|
+
*
|
|
11
|
+
* @module @memberjunction/server/realtimeSessions
|
|
12
|
+
*/
|
|
13
|
+
import { IMetadataProvider, UserInfo } from '@memberjunction/core';
|
|
14
|
+
import type { UserPayload } from '../types.js';
|
|
15
|
+
import { type LoadedSessionForAccess } from './sessionAccess.js';
|
|
16
|
+
import type { RealtimeSessionEventTopicPayload } from './RealtimeSessionEventService.js';
|
|
17
|
+
/**
|
|
18
|
+
* Arguments of the subscription. `agentSessionId` is camelCase because it is the GraphQL argument name
|
|
19
|
+
* graphql-js hands to `subscribe` and to the filter — it is the wire contract, not an API of ours.
|
|
20
|
+
*/
|
|
21
|
+
export interface RealtimeSessionEventsArgs {
|
|
22
|
+
agentSessionId?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The slice of the WebSocket connection context the authorization reads. `userPayload` is camelCase to
|
|
26
|
+
* match `AppContext.userPayload`, the member graphql-ws populates and every resolver already destructures.
|
|
27
|
+
*/
|
|
28
|
+
export interface RealtimeSessionEventsContext {
|
|
29
|
+
userPayload?: UserPayload;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Per-event filter. Exported because it is the security-critical gate and must be testable in isolation.
|
|
33
|
+
*
|
|
34
|
+
* An event reaches a subscriber only when BOTH hold:
|
|
35
|
+
* 1. it is addressed to the session the subscriber asked for, and
|
|
36
|
+
* 2. the event's owner/scope snapshot passes {@link AuthorizeSessionAccess} for the connection's
|
|
37
|
+
* authenticated principal.
|
|
38
|
+
*
|
|
39
|
+
* Fails closed: a missing connection identity, a missing owner on the event, or a missing argument never matches.
|
|
40
|
+
*/
|
|
41
|
+
export declare function RealtimeSessionEventsFilter(data: {
|
|
42
|
+
payload: RealtimeSessionEventTopicPayload;
|
|
43
|
+
args: RealtimeSessionEventsArgs;
|
|
44
|
+
context: RealtimeSessionEventsContext | undefined;
|
|
45
|
+
}): boolean;
|
|
46
|
+
/** Dependencies of {@link AuthorizeRealtimeSessionSubscription}, injectable for tests. */
|
|
47
|
+
export interface SubscriptionAuthorizationDeps {
|
|
48
|
+
/** Loads a session under the caller's identity. */
|
|
49
|
+
LoadSession: (agentSessionId: string, user: UserInfo, provider: IMetadataProvider) => Promise<LoadedSessionForAccess | null>;
|
|
50
|
+
/** The provider to read with (a WebSocket context carries no request-scoped providers). */
|
|
51
|
+
GetProvider: () => IMetadataProvider;
|
|
52
|
+
}
|
|
53
|
+
/** Production dependencies. */
|
|
54
|
+
export declare const DEFAULT_SUBSCRIPTION_AUTHORIZATION_DEPS: SubscriptionAuthorizationDeps;
|
|
55
|
+
/**
|
|
56
|
+
* Subscribe-time authorization: loads the session as the connection's principal and requires
|
|
57
|
+
* {@link AuthorizeSessionAccess} to allow it. Throws {@link REFUSAL_MESSAGE} (uniformly) otherwise.
|
|
58
|
+
*
|
|
59
|
+
* @param args - the subscription arguments
|
|
60
|
+
* @param context - the connection context (server-authenticated)
|
|
61
|
+
* @param deps - injectable dependencies (tests)
|
|
62
|
+
* @returns the validated session id
|
|
63
|
+
*/
|
|
64
|
+
export declare function AuthorizeRealtimeSessionSubscription(args: RealtimeSessionEventsArgs, context: RealtimeSessionEventsContext | undefined, deps?: SubscriptionAuthorizationDeps): Promise<string>;
|
|
65
|
+
//# sourceMappingURL=subscriptionAuthorization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscriptionAuthorization.d.ts","sourceRoot":"","sources":["../../src/realtimeSessions/subscriptionAuthorization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,iBAAiB,EAAsB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEvF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAgD,KAAK,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC/G,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,kCAAkC,CAAC;AAEzF;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,4BAA4B;IACzC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC7B;AAUD;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAC9C,OAAO,EAAE,gCAAgC,CAAC;IAC1C,IAAI,EAAE,yBAAyB,CAAC;IAChC,OAAO,EAAE,4BAA4B,GAAG,SAAS,CAAC;CACrD,GAAG,OAAO,CAUV;AAED,0FAA0F;AAC1F,MAAM,WAAW,6BAA6B;IAC1C,mDAAmD;IACnD,WAAW,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,KAAK,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IAC7H,2FAA2F;IAC3F,WAAW,EAAE,MAAM,iBAAiB,CAAC;CACxC;AAED,+BAA+B;AAC/B,eAAO,MAAM,uCAAuC,EAAE,6BAGrD,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,oCAAoC,CACtD,IAAI,EAAE,yBAAyB,EAC/B,OAAO,EAAE,4BAA4B,GAAG,SAAS,EACjD,IAAI,GAAE,6BAAuE,GAC9E,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The authorization of the `RealtimeSessionEvents` subscription, free of GraphQL schema
|
|
3
|
+
* decorators and server configuration so it can be exercised — and reused — without loading either.
|
|
4
|
+
*
|
|
5
|
+
* It is applied twice on purpose (see `RealtimeSessionEventsResolver`): once when the subscription is
|
|
6
|
+
* opened ({@link AuthorizeRealtimeSessionSubscription}) and once for every event
|
|
7
|
+
* ({@link RealtimeSessionEventsFilter}). In neither check does a client-supplied value decide who
|
|
8
|
+
* receives anything: `agentSessionId` only selects WHICH of the caller's own sessions to listen to; the
|
|
9
|
+
* identity it is checked against comes from the server-authenticated connection context.
|
|
10
|
+
*
|
|
11
|
+
* @module @memberjunction/server/realtimeSessions
|
|
12
|
+
*/
|
|
13
|
+
import { LogError, Metadata } from '@memberjunction/core';
|
|
14
|
+
import { IsValidUUID, UUIDsEqual } from '@memberjunction/global';
|
|
15
|
+
import { AuthorizeSessionAccess, LoadSessionForAccess } from './sessionAccess.js';
|
|
16
|
+
/** Why a subscription request was refused (logged; the client always gets the same message). */
|
|
17
|
+
const REFUSAL_MESSAGE = 'Realtime session not found.';
|
|
18
|
+
/** The principal the connection authenticated as, or undefined. */
|
|
19
|
+
function connectionPrincipal(context) {
|
|
20
|
+
return context?.userPayload?.userRecord;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Per-event filter. Exported because it is the security-critical gate and must be testable in isolation.
|
|
24
|
+
*
|
|
25
|
+
* An event reaches a subscriber only when BOTH hold:
|
|
26
|
+
* 1. it is addressed to the session the subscriber asked for, and
|
|
27
|
+
* 2. the event's owner/scope snapshot passes {@link AuthorizeSessionAccess} for the connection's
|
|
28
|
+
* authenticated principal.
|
|
29
|
+
*
|
|
30
|
+
* Fails closed: a missing connection identity, a missing owner on the event, or a missing argument never matches.
|
|
31
|
+
*/
|
|
32
|
+
export function RealtimeSessionEventsFilter(data) {
|
|
33
|
+
const { payload, args, context } = data;
|
|
34
|
+
if (typeof args?.agentSessionId !== 'string' || !payload?.AgentSessionID || !UUIDsEqual(payload.AgentSessionID, args.agentSessionId)) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
const decision = AuthorizeSessionAccess({ SessionUserID: payload.OwnerUserID, ConversationExternalID: payload.ScopeKey }, connectionPrincipal(context));
|
|
38
|
+
return decision.Allowed;
|
|
39
|
+
}
|
|
40
|
+
/** Production dependencies. */
|
|
41
|
+
export const DEFAULT_SUBSCRIPTION_AUTHORIZATION_DEPS = {
|
|
42
|
+
LoadSession: LoadSessionForAccess,
|
|
43
|
+
GetProvider: () => Metadata.Provider, // global-provider-ok: a WebSocket subscription context has no per-request providers
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Subscribe-time authorization: loads the session as the connection's principal and requires
|
|
47
|
+
* {@link AuthorizeSessionAccess} to allow it. Throws {@link REFUSAL_MESSAGE} (uniformly) otherwise.
|
|
48
|
+
*
|
|
49
|
+
* @param args - the subscription arguments
|
|
50
|
+
* @param context - the connection context (server-authenticated)
|
|
51
|
+
* @param deps - injectable dependencies (tests)
|
|
52
|
+
* @returns the validated session id
|
|
53
|
+
*/
|
|
54
|
+
export async function AuthorizeRealtimeSessionSubscription(args, context, deps = DEFAULT_SUBSCRIPTION_AUTHORIZATION_DEPS) {
|
|
55
|
+
const principal = connectionPrincipal(context);
|
|
56
|
+
const agentSessionId = args?.agentSessionId;
|
|
57
|
+
if (!principal || typeof agentSessionId !== 'string' || !IsValidUUID(agentSessionId)) {
|
|
58
|
+
throw new Error(REFUSAL_MESSAGE);
|
|
59
|
+
}
|
|
60
|
+
const loaded = await deps.LoadSession(agentSessionId, principal, deps.GetProvider());
|
|
61
|
+
if (!loaded) {
|
|
62
|
+
throw new Error(REFUSAL_MESSAGE);
|
|
63
|
+
}
|
|
64
|
+
const decision = AuthorizeSessionAccess({ SessionUserID: loaded.Session.UserID, ConversationExternalID: loaded.ConversationExternalID }, principal);
|
|
65
|
+
if (decision.Allowed === false) {
|
|
66
|
+
LogError(`RealtimeSessionEvents: refused subscription by user ${principal.ID} to session ${agentSessionId} (${decision.Reason}).`);
|
|
67
|
+
throw new Error(REFUSAL_MESSAGE);
|
|
68
|
+
}
|
|
69
|
+
return agentSessionId;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=subscriptionAuthorization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscriptionAuthorization.js","sourceRoot":"","sources":["../../src/realtimeSessions/subscriptionAuthorization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAqB,QAAQ,EAAE,QAAQ,EAAY,MAAM,sBAAsB,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEjE,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAA+B,MAAM,oBAAoB,CAAC;AAmB/G,gGAAgG;AAChG,MAAM,eAAe,GAAG,6BAA6B,CAAC;AAEtD,mEAAmE;AACnE,SAAS,mBAAmB,CAAC,OAAiD;IAC1E,OAAO,OAAO,EAAE,WAAW,EAAE,UAAkC,CAAC;AACpE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAI3C;IACG,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACxC,IAAI,OAAO,IAAI,EAAE,cAAc,KAAK,QAAQ,IAAI,CAAC,OAAO,EAAE,cAAc,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;QACnI,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,MAAM,QAAQ,GAAG,sBAAsB,CACnC,EAAE,aAAa,EAAE,OAAO,CAAC,WAAW,EAAE,sBAAsB,EAAE,OAAO,CAAC,QAAQ,EAAE,EAChF,mBAAmB,CAAC,OAAO,CAAC,CAC/B,CAAC;IACF,OAAO,QAAQ,CAAC,OAAO,CAAC;AAC5B,CAAC;AAUD,+BAA+B;AAC/B,MAAM,CAAC,MAAM,uCAAuC,GAAkC;IAClF,WAAW,EAAE,oBAAoB;IACjC,WAAW,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,oFAAoF;CAC7H,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,oCAAoC,CACtD,IAA+B,EAC/B,OAAiD,EACjD,OAAsC,uCAAuC;IAE7E,MAAM,SAAS,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,cAAc,GAAG,IAAI,EAAE,cAAc,CAAC;IAC5C,IAAI,CAAC,SAAS,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC;QACnF,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE,SAAS,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACrF,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,QAAQ,GAAG,sBAAsB,CACnC,EAAE,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,sBAAsB,EAAE,MAAM,CAAC,sBAAsB,EAAE,EAC/F,SAAS,CACZ,CAAC;IACF,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QAC7B,QAAQ,CAAC,uDAAuD,SAAS,CAAC,EAAE,eAAe,cAAc,KAAK,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;QACnI,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,cAAc,CAAC;AAC1B,CAAC"}
|