@memberjunction/server 6.2.0-edge.6 → 6.2.0-edge.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/agentSessions/BridgeHostInstance.d.ts +8 -3
- package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -1
- package/dist/agentSessions/BridgeHostInstance.js +14 -4
- package/dist/agentSessions/BridgeHostInstance.js.map +1 -1
- package/dist/agentSessions/HandoffOfferExpiry.d.ts +10 -0
- package/dist/agentSessions/HandoffOfferExpiry.d.ts.map +1 -0
- package/dist/agentSessions/HandoffOfferExpiry.js +18 -0
- package/dist/agentSessions/HandoffOfferExpiry.js.map +1 -0
- package/dist/agentSessions/ReturningVisitorRecap.js +1 -0
- package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
- package/dist/agentSessions/SessionJanitor.d.ts +31 -8
- package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
- package/dist/agentSessions/SessionJanitor.js +85 -41
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/agentSessions/SessionManager.d.ts +14 -4
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +28 -4
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/agentSessions/conversationBrowsers.d.ts +61 -0
- package/dist/agentSessions/conversationBrowsers.d.ts.map +1 -0
- package/dist/agentSessions/conversationBrowsers.js +118 -0
- package/dist/agentSessions/conversationBrowsers.js.map +1 -0
- package/dist/agentSessions/sessionDeadline.d.ts +43 -0
- package/dist/agentSessions/sessionDeadline.d.ts.map +1 -0
- package/dist/agentSessions/sessionDeadline.js +68 -0
- package/dist/agentSessions/sessionDeadline.js.map +1 -0
- package/dist/auth/APIKeyScopeAuth.d.ts.map +1 -1
- package/dist/auth/APIKeyScopeAuth.js +5 -4
- package/dist/auth/APIKeyScopeAuth.js.map +1 -1
- package/dist/auth/loginEmailResolution.d.ts +41 -0
- package/dist/auth/loginEmailResolution.d.ts.map +1 -0
- package/dist/auth/loginEmailResolution.js +47 -0
- package/dist/auth/loginEmailResolution.js.map +1 -0
- package/dist/auth/magicLink/MagicLinkKeys.d.ts +50 -2
- package/dist/auth/magicLink/MagicLinkKeys.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkKeys.js +129 -12
- package/dist/auth/magicLink/MagicLinkKeys.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.d.ts +3 -0
- package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +23 -5
- package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.d.ts +39 -5
- package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +221 -9
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/magicLink/index.d.ts +1 -1
- package/dist/auth/magicLink/index.d.ts.map +1 -1
- package/dist/auth/magicLink/index.js +1 -1
- package/dist/auth/magicLink/index.js.map +1 -1
- package/dist/auth/magicLink/redeemLanding.d.ts +2 -2
- package/dist/auth/magicLink/redeemLanding.d.ts.map +1 -1
- package/dist/auth/magicLink/redeemLanding.js +7 -4
- package/dist/auth/magicLink/redeemLanding.js.map +1 -1
- package/dist/auth/magicLink/types.d.ts +27 -3
- package/dist/auth/magicLink/types.d.ts.map +1 -1
- package/dist/auth/magicLink/types.js +0 -4
- package/dist/auth/magicLink/types.js.map +1 -1
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +1 -0
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/backgroundSweepConfigUnits.d.ts +231 -0
- package/dist/backgroundSweepConfigUnits.d.ts.map +1 -0
- package/dist/backgroundSweepConfigUnits.js +180 -0
- package/dist/backgroundSweepConfigUnits.js.map +1 -0
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.d.ts.map +1 -1
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js +2 -1
- package/dist/broadcast/BaseCacheInvalidationBroadcastProvider.js.map +1 -1
- package/dist/config.d.ts +906 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +59 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +41 -12
- package/dist/context.js.map +1 -1
- package/dist/coreRoutes.d.ts +3 -1
- package/dist/coreRoutes.d.ts.map +1 -1
- package/dist/coreRoutes.js +6 -4
- package/dist/coreRoutes.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts +1072 -5
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +10174 -4618
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts +11 -0
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js +27 -1
- package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +50 -5
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +329 -132
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +4 -0
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +47 -7
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/globalCors.d.ts.map +1 -1
- package/dist/globalCors.js +1 -0
- package/dist/globalCors.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +201 -43
- package/dist/index.js.map +1 -1
- package/dist/integration/ConnectionPause.d.ts +121 -0
- package/dist/integration/ConnectionPause.d.ts.map +1 -0
- package/dist/integration/ConnectionPause.js +183 -0
- package/dist/integration/ConnectionPause.js.map +1 -0
- package/dist/integration/CustomColumnPromoter.d.ts +72 -6
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +87 -46
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/integration/EntityMapLifecycle.d.ts +78 -4
- package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
- package/dist/integration/EntityMapLifecycle.js +199 -5
- package/dist/integration/EntityMapLifecycle.js.map +1 -1
- package/dist/integration/InactiveRowWarnings.d.ts +31 -0
- package/dist/integration/InactiveRowWarnings.d.ts.map +1 -1
- package/dist/integration/InactiveRowWarnings.js +29 -0
- package/dist/integration/InactiveRowWarnings.js.map +1 -1
- package/dist/integration/ObjectNamesByID.d.ts +28 -0
- package/dist/integration/ObjectNamesByID.d.ts.map +1 -0
- package/dist/integration/ObjectNamesByID.js +87 -0
- package/dist/integration/ObjectNamesByID.js.map +1 -0
- package/dist/integration/PostRestartIntrospect.d.ts +26 -0
- package/dist/integration/PostRestartIntrospect.d.ts.map +1 -0
- package/dist/integration/PostRestartIntrospect.js +27 -0
- package/dist/integration/PostRestartIntrospect.js.map +1 -0
- package/dist/integration/RSUPostRestartProgress.d.ts +176 -0
- package/dist/integration/RSUPostRestartProgress.d.ts.map +1 -0
- package/dist/integration/RSUPostRestartProgress.js +323 -0
- package/dist/integration/RSUPostRestartProgress.js.map +1 -0
- package/dist/integration/RSUProgressBridge.d.ts +41 -2
- package/dist/integration/RSUProgressBridge.d.ts.map +1 -1
- package/dist/integration/RSUProgressBridge.js +84 -1
- package/dist/integration/RSUProgressBridge.js.map +1 -1
- package/dist/integration/RunArtifactAuthorization.d.ts +39 -0
- package/dist/integration/RunArtifactAuthorization.d.ts.map +1 -0
- package/dist/integration/RunArtifactAuthorization.js +45 -0
- package/dist/integration/RunArtifactAuthorization.js.map +1 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts +9 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts.map +1 -1
- package/dist/integration/SchemaRefreshLaunch.js +3 -2
- package/dist/integration/SchemaRefreshLaunch.js.map +1 -1
- package/dist/integration/ScopedFieldsForBuild.d.ts +46 -0
- package/dist/integration/ScopedFieldsForBuild.d.ts.map +1 -0
- package/dist/integration/ScopedFieldsForBuild.js +91 -0
- package/dist/integration/ScopedFieldsForBuild.js.map +1 -0
- package/dist/integration/TargetConfigGuard.d.ts +40 -0
- package/dist/integration/TargetConfigGuard.d.ts.map +1 -0
- package/dist/integration/TargetConfigGuard.js +40 -0
- package/dist/integration/TargetConfigGuard.js.map +1 -0
- package/dist/logging/StartupLogger.d.ts +50 -0
- package/dist/logging/StartupLogger.d.ts.map +1 -1
- package/dist/logging/StartupLogger.js +15 -22
- package/dist/logging/StartupLogger.js.map +1 -1
- package/dist/middleware/BaseServerMiddleware.d.ts +21 -3
- package/dist/middleware/BaseServerMiddleware.d.ts.map +1 -1
- package/dist/middleware/BaseServerMiddleware.js +4 -2
- package/dist/middleware/BaseServerMiddleware.js.map +1 -1
- package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -1
- package/dist/realtimeSessions/ownedRealtimeSession.js +2 -3
- package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -1
- package/dist/realtimeSessions/sessionAccess.d.ts +15 -0
- package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
- package/dist/realtimeSessions/sessionAccess.js +22 -0
- package/dist/realtimeSessions/sessionAccess.js.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.js +2 -0
- package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.js +1 -0
- package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetCore.js +4 -7
- package/dist/realtimeWidget/widgetCore.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +1 -0
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/requestOrigin.d.ts +22 -0
- package/dist/requestOrigin.d.ts.map +1 -0
- package/dist/requestOrigin.js +60 -0
- package/dist/requestOrigin.js.map +1 -0
- package/dist/resolvers/AgentRunStatusPublisher.d.ts +10 -0
- package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -1
- package/dist/resolvers/AgentRunStatusPublisher.js +18 -2
- package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -1
- package/dist/resolvers/AgentSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/AgentSessionResolver.js +6 -2
- package/dist/resolvers/AgentSessionResolver.js.map +1 -1
- package/dist/resolvers/AutotagPipelineResolver.d.ts +1 -1
- package/dist/resolvers/AutotagPipelineResolver.d.ts.map +1 -1
- package/dist/resolvers/AutotagPipelineResolver.js +61 -16
- package/dist/resolvers/AutotagPipelineResolver.js.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
- package/dist/resolvers/ConversationRunEventsResolver.js +2 -0
- package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
- package/dist/resolvers/ExecuteRemoteOperationResolver.d.ts +6 -0
- package/dist/resolvers/ExecuteRemoteOperationResolver.d.ts.map +1 -1
- package/dist/resolvers/ExecuteRemoteOperationResolver.js +30 -7
- package/dist/resolvers/ExecuteRemoteOperationResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +34 -13
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/InfoResolver.js +1 -1
- package/dist/resolvers/InfoResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +401 -11
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +2690 -1305
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts.map +1 -1
- package/dist/resolvers/MCPResolver.js +13 -2
- package/dist/resolvers/MCPResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +38 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +181 -88
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +1 -0
- package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +6 -0
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +36 -5
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts +62 -10
- package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +217 -34
- package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +24 -8
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +185 -67
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts +5 -3
- package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +19 -18
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +3 -1
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +7 -8
- package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
- package/dist/resolvers/TagGovernanceResolver.d.ts +12 -0
- package/dist/resolvers/TagGovernanceResolver.d.ts.map +1 -1
- package/dist/resolvers/TagGovernanceResolver.js +84 -0
- package/dist/resolvers/TagGovernanceResolver.js.map +1 -1
- package/dist/resolvers/TelemetryResolver.d.ts +13 -8
- package/dist/resolvers/TelemetryResolver.d.ts.map +1 -1
- package/dist/resolvers/TelemetryResolver.js +40 -9
- package/dist/resolvers/TelemetryResolver.js.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.js +2 -0
- package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
- package/dist/resolvers/meetings/meetingMutations.d.ts.map +1 -1
- package/dist/resolvers/meetings/meetingMutations.js +34 -4
- package/dist/resolvers/meetings/meetingMutations.js.map +1 -1
- package/dist/rest/MediaAccessKeys.d.ts.map +1 -1
- package/dist/rest/MediaAccessKeys.js +6 -2
- package/dist/rest/MediaAccessKeys.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
- package/dist/rest/OAuthCallbackHandler.js +11 -5
- package/dist/rest/OAuthCallbackHandler.js.map +1 -1
- package/dist/rest/RealtimeRecordingHandler.d.ts +3 -3
- package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -1
- package/dist/rest/RealtimeRecordingHandler.js +2 -4
- package/dist/rest/RealtimeRecordingHandler.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +2 -1
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +3 -1
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +11 -2
- package/dist/rest/setupRESTEndpoints.js.map +1 -1
- package/dist/services/DurableEntityActionTaskSubmitter.d.ts.map +1 -1
- package/dist/services/DurableEntityActionTaskSubmitter.js +6 -1
- package/dist/services/DurableEntityActionTaskSubmitter.js.map +1 -1
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphActionRunner.js +2 -26
- package/dist/services/TaskGraphActionRunner.js.map +1 -1
- package/dist/services/TaskGraphAgentRunner.d.ts +6 -0
- package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphAgentRunner.js +38 -0
- package/dist/services/TaskGraphAgentRunner.js.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +1 -0
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/services/WorkQueueHostService.d.ts +2 -1
- package/dist/services/WorkQueueHostService.d.ts.map +1 -1
- package/dist/services/WorkQueueHostService.js +19 -4
- package/dist/services/WorkQueueHostService.js.map +1 -1
- package/dist/services/workQueueConfig.d.ts +2 -2
- package/dist/services/workQueueConfig.js +5 -5
- package/dist/services/workQueueConfig.js.map +1 -1
- package/dist/sharedCache.js +1 -1
- package/dist/sharedCache.js.map +1 -1
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +55 -2
- package/dist/util.js.map +1 -1
- package/package.json +107 -100
- package/src/__tests__/APIKeyScopeAuth.test.ts +4 -8
- package/src/__tests__/ActiveOperations.test.ts +68 -0
- package/src/__tests__/AgentSessionResolver.ownership.test.ts +13 -0
- package/src/__tests__/AssertTargetConfigs.test.ts +75 -0
- package/src/__tests__/BatchApplyParity.test.ts +109 -0
- package/src/__tests__/BridgeHostInstance.test.ts +42 -0
- package/src/__tests__/CollectInactiveRowWarnings.test.ts +115 -0
- package/src/__tests__/ConnectionPause.test.ts +192 -0
- package/src/__tests__/ConnectionPauseResolver.test.ts +166 -0
- package/src/__tests__/ConnectionPauseSave.test.ts +143 -0
- package/src/__tests__/CustomColumnPromoterCompletion.test.ts +142 -0
- package/src/__tests__/DeleteConnectionRemovesPerConnectionCatalog.test.ts +51 -0
- package/src/__tests__/DetachedDiscoveryStart.test.ts +65 -0
- package/src/__tests__/DurableEntityActionTaskSubmitter.test.ts +73 -0
- package/src/__tests__/EntityMapLifecycle.rekey.test.ts +252 -0
- package/src/__tests__/ExecuteRemoteOperationResolver.test.ts +213 -0
- package/src/__tests__/HandoffOfferExpiry.test.ts +40 -0
- package/src/__tests__/IntegrationRunArtifactAuthorization.test.ts +126 -0
- package/src/__tests__/MagicLinkKeys.test.ts +102 -0
- package/src/__tests__/MediaAccessKeys.test.ts +57 -10
- package/src/__tests__/NewArrivalsDefaultDisabled.test.ts +50 -0
- package/src/__tests__/ObjectNamesByID.test.ts +176 -0
- package/src/__tests__/PostRestartMapsInCatalogScope.test.ts +146 -0
- package/src/__tests__/QuerySystemUserResolver.childRows.test.ts +80 -0
- package/src/__tests__/QuerySystemUserResolver.collision.test.ts +200 -0
- package/src/__tests__/QuerySystemUserResolver.permissions.test.ts +132 -0
- package/src/__tests__/RSUPostRestartProgress.test.ts +343 -0
- package/src/__tests__/RSUProgressBridge.test.ts +188 -5
- package/src/__tests__/RSUStartupSweepWiring.test.ts +30 -0
- package/src/__tests__/ReactivateRefreshMessage.test.ts +10 -3
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +22 -0
- package/src/__tests__/{RefreshAdoptsNewColumns.test.ts → RefreshReportsNewColumns.test.ts} +25 -16
- package/src/__tests__/RemoteBrowserActionRecovery.test.ts +287 -0
- package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +3 -0
- package/src/__tests__/RemoteBrowserActionResolver.ownership.test.ts +6 -4
- package/src/__tests__/RemoteBrowserAudioStream.test.ts +3 -0
- package/src/__tests__/RemoteBrowserSnapshot.test.ts +3 -0
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +327 -26
- package/src/__tests__/ResolverBase.diagnosticSenderRegistrations.test.ts +26 -0
- package/src/__tests__/ResolverBase.encryptedApiZeroReencrypt.test.ts +307 -0
- package/src/__tests__/ResolverBase.entityMessageRelay.test.ts +53 -2
- package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +60 -0
- package/src/__tests__/RunAIAgentResolver.branch.test.ts +4 -0
- package/src/__tests__/RunAIAgentResolver.consultPredecessor.test.ts +289 -0
- package/src/__tests__/RunAIAgentResolver.handoff.test.ts +649 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +2 -0
- package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +2 -0
- package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +87 -12
- package/src/__tests__/RunAIAgentResolver.streaming.test.ts +28 -4
- package/src/__tests__/SchemaEvolutionCustomColumns.test.ts +119 -0
- package/src/__tests__/SchemaRefreshLaunch.test.ts +24 -2
- package/src/__tests__/ScopedFieldsForBuild.test.ts +192 -0
- package/src/__tests__/SessionJanitor.test.ts +195 -4
- package/src/__tests__/SessionManager.test.ts +69 -0
- package/src/__tests__/TagGovernanceAndAutotagResolvers.test.ts +261 -0
- package/src/__tests__/TagGovernanceResolver.test.ts +60 -2
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +2 -2
- package/src/__tests__/TaskGraphAgentRunner.test.ts +272 -16
- package/src/__tests__/ViewOperationsHandler.test.ts +2 -5
- package/src/__tests__/WorkQueueHostService.test.ts +25 -7
- package/src/__tests__/backgroundSweepConfigUnits.test.ts +153 -0
- package/src/__tests__/contextRequestOrigin.test.ts +105 -0
- package/src/__tests__/conversationBrowsers.test.ts +62 -0
- package/src/__tests__/globalCors.test.ts +12 -0
- package/src/__tests__/magicLinkExtensionCapabilities.test.ts +413 -0
- package/src/__tests__/orphanedConversationDetailReconciler.start.test.ts +82 -0
- package/src/__tests__/ownedRealtimeSession.test.ts +14 -0
- package/src/__tests__/realtimeRecordingHandler.test.ts +7 -2
- package/src/__tests__/realtimeSessions/sessionAccess.test.ts +79 -1
- package/src/__tests__/requestOrigin.test.ts +104 -0
- package/src/__tests__/review-capture-valid-token-log.test.ts +98 -0
- package/src/__tests__/runStreams.fieldSecurity.test.ts +5 -5
- package/src/__tests__/securityHardeningPr6034.test.ts +120 -0
- package/src/__tests__/sessionDeadline.test.ts +51 -0
- package/src/__tests__/sharedCache.test.ts +11 -0
- package/src/__tests__/unifiedAuth.test.ts +73 -1
- package/src/agentSessions/BridgeHostInstance.ts +20 -5
- package/src/agentSessions/HandoffOfferExpiry.ts +18 -0
- package/src/agentSessions/ReturningVisitorRecap.ts +1 -0
- package/src/agentSessions/SessionJanitor.ts +92 -42
- package/src/agentSessions/SessionManager.ts +38 -8
- package/src/agentSessions/conversationBrowsers.ts +143 -0
- package/src/agentSessions/sessionDeadline.ts +81 -0
- package/src/auth/APIKeyScopeAuth.ts +5 -4
- package/src/auth/__tests__/loginEmailResolution.test.ts +67 -0
- package/src/auth/loginEmailResolution.ts +67 -0
- package/src/auth/magicLink/MagicLinkKeys.ts +146 -14
- package/src/auth/magicLink/MagicLinkRouter.ts +33 -6
- package/src/auth/magicLink/MagicLinkService.ts +250 -10
- package/src/auth/magicLink/index.ts +1 -1
- package/src/auth/magicLink/redeemLanding.ts +7 -4
- package/src/auth/magicLink/types.ts +28 -3
- package/src/auth/newUsers.ts +1 -0
- package/src/backgroundSweepConfigUnits.ts +213 -0
- package/src/broadcast/BaseCacheInvalidationBroadcastProvider.ts +2 -1
- package/src/config.ts +69 -0
- package/src/context.ts +46 -15
- package/src/coreRoutes.ts +14 -7
- package/src/generated/graphql-schemas/__mj.ts +10360 -6479
- package/src/generic/OrphanedConversationDetailReconciler.ts +32 -1
- package/src/generic/ResolverBase.ts +422 -143
- package/src/generic/RunViewResolver.ts +96 -49
- package/src/globalCors.ts +1 -0
- package/src/index.ts +246 -44
- package/src/integration/ConnectionPause.ts +222 -0
- package/src/integration/CustomColumnPromoter.ts +123 -53
- package/src/integration/EntityMapLifecycle.ts +229 -6
- package/src/integration/InactiveRowWarnings.ts +50 -0
- package/src/integration/ObjectNamesByID.ts +97 -0
- package/src/integration/PostRestartIntrospect.ts +49 -0
- package/src/integration/RSUPostRestartProgress.ts +359 -0
- package/src/integration/RSUProgressBridge.ts +85 -2
- package/src/integration/RunArtifactAuthorization.ts +65 -0
- package/src/integration/SchemaRefreshLaunch.ts +12 -2
- package/src/integration/ScopedFieldsForBuild.ts +113 -0
- package/src/integration/TargetConfigGuard.ts +71 -0
- package/src/logging/StartupLogger.ts +24 -0
- package/src/middleware/BaseServerMiddleware.ts +20 -3
- package/src/realtimeSessions/ownedRealtimeSession.ts +2 -6
- package/src/realtimeSessions/sessionAccess.ts +30 -0
- package/src/realtimeWidget/WidgetSessionService.ts +2 -0
- package/src/realtimeWidget/visitorIdentity.ts +1 -0
- package/src/realtimeWidget/widgetCore.ts +4 -8
- package/src/realtimeWidget/widgetGuestElevation.ts +1 -0
- package/src/requestOrigin.ts +64 -0
- package/src/resolvers/AgentRunStatusPublisher.ts +27 -2
- package/src/resolvers/AgentSessionResolver.ts +6 -2
- package/src/resolvers/AutotagPipelineResolver.ts +59 -14
- package/src/resolvers/ConversationRunEventsResolver.ts +2 -0
- package/src/resolvers/ExecuteRemoteOperationResolver.ts +41 -9
- package/src/resolvers/GetDataResolver.ts +35 -13
- package/src/resolvers/InfoResolver.ts +1 -1
- package/src/resolvers/IntegrationDiscoveryResolver.ts +1522 -203
- package/src/resolvers/MCPResolver.ts +15 -2
- package/src/resolvers/QuerySystemUserResolver.ts +211 -100
- package/src/resolvers/RealtimeBridgeResolver.ts +1 -0
- package/src/resolvers/RealtimeClientSessionResolver.ts +40 -7
- package/src/resolvers/RemoteBrowserActionResolver.ts +242 -32
- package/src/resolvers/RunAIAgentResolver.ts +265 -86
- package/src/resolvers/RunAIPromptResolver.ts +18 -18
- package/src/resolvers/RunTemplateResolver.ts +3 -1
- package/src/resolvers/SqlLoggingConfigResolver.ts +7 -9
- package/src/resolvers/TagGovernanceResolver.ts +65 -0
- package/src/resolvers/TelemetryResolver.ts +44 -9
- package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +52 -0
- package/src/resolvers/meetingRecordingRegistration.ts +2 -0
- package/src/resolvers/meetings/meetingMutations.ts +37 -7
- package/src/rest/MediaAccessKeys.ts +6 -2
- package/src/rest/OAuthCallbackHandler.ts +13 -5
- package/src/rest/RealtimeRecordingHandler.ts +5 -9
- package/src/rest/ViewOperationsHandler.ts +2 -1
- package/src/rest/setupRESTEndpoints.ts +11 -2
- package/src/services/DurableEntityActionTaskSubmitter.ts +10 -2
- package/src/services/TaskGraphActionRunner.ts +2 -23
- package/src/services/TaskGraphAgentRunner.ts +43 -0
- package/src/services/TaskGraphContinuationDeliverer.ts +1 -0
- package/src/services/WorkQueueHostService.ts +26 -4
- package/src/services/workQueueConfig.ts +5 -5
- package/src/sharedCache.ts +1 -1
- package/src/types.ts +18 -0
- package/src/util.ts +55 -3
- package/src/services/TaskOrchestration-Integration.md +0 -188
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses the absolute deadline (ms) from a session's `Config_` JSON, or null when absent/malformed.
|
|
3
|
+
* A malformed deadline counts as absent by design: a sweep must never throw on one bad row, so null
|
|
4
|
+
* is the documented failure result here, not a swallowed error.
|
|
5
|
+
*/
|
|
6
|
+
export function ParseSessionDeadlineMs(configJson) {
|
|
7
|
+
if (!configJson) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
const parsed = JSON.parse(configJson);
|
|
12
|
+
if (typeof parsed.maxSessionDeadlineIso !== 'string') {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const ms = Date.parse(parsed.maxSessionDeadlineIso);
|
|
16
|
+
return Number.isNaN(ms) ? null : ms;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// Malformed JSON: treated as "no deadline" (see doc comment).
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Decides why a session has expired, or null when it has not.
|
|
25
|
+
*
|
|
26
|
+
* Two moments can expire a session: its idle moment (`LastActiveAt + closeThresholdMs`) and its authored
|
|
27
|
+
* hard deadline (`Config_.maxSessionDeadlineIso`). Only a moment that has already passed (`<= nowMs`)
|
|
28
|
+
* counts, and the EARLIER of the passed moments wins. A tie at the same instant yields `TimeLimit`:
|
|
29
|
+
* the authored rule beats the safety net. A row without a usable `LastActiveAt` (null, or a value that
|
|
30
|
+
* does not parse to a date) is never `Idle`, and neither is any row when `closeThresholdMs` is non-finite.
|
|
31
|
+
* `LastActiveAt` is typed `Date` but may arrive as an ISO string from a provider, so both are accepted.
|
|
32
|
+
*/
|
|
33
|
+
export function ExpiryCloseReason(session, nowMs, closeThresholdMs) {
|
|
34
|
+
const lastActiveMs = session.LastActiveAt ? new Date(session.LastActiveAt).getTime() : Number.NaN;
|
|
35
|
+
const idleMs = lastActiveMs + closeThresholdMs;
|
|
36
|
+
const idleAt = Number.isFinite(idleMs) ? idleMs : null;
|
|
37
|
+
const deadlineAt = ParseSessionDeadlineMs(session.Config_);
|
|
38
|
+
const idlePassed = idleAt !== null && idleAt <= nowMs;
|
|
39
|
+
const deadlinePassed = deadlineAt !== null && deadlineAt <= nowMs;
|
|
40
|
+
if (deadlinePassed && idlePassed) {
|
|
41
|
+
return deadlineAt <= idleAt ? 'TimeLimit' : 'Idle';
|
|
42
|
+
}
|
|
43
|
+
if (deadlinePassed) {
|
|
44
|
+
return 'TimeLimit';
|
|
45
|
+
}
|
|
46
|
+
return idlePassed ? 'Idle' : null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* How far ahead of a stored deadline a browser's `TimeLimit` claim is still believed. The browser's
|
|
50
|
+
* alarm runs on its own clock: when it extends to a server ISO deadline it anchors that time against its
|
|
51
|
+
* own `Date.now()`, so a client clock running ahead of the server fires early by the difference (a throttled
|
|
52
|
+
* tab only fires late). A minute absorbs that skew without letting a client end a session meant to run for
|
|
53
|
+
* minutes more.
|
|
54
|
+
*/
|
|
55
|
+
export const DEADLINE_CLAIM_SKEW_MS = 60_000;
|
|
56
|
+
/**
|
|
57
|
+
* Verifies a `TimeLimit` close claim against the session's stored deadline. The browser claims, the server
|
|
58
|
+
* verifies: the claim holds when the stored deadline has passed or falls within {@link DEADLINE_CLAIM_SKEW_MS},
|
|
59
|
+
* otherwise (no deadline, or one far in the future) the close is recorded as `Explicit`. The janitor's own
|
|
60
|
+
* `TimeLimit` trivially passes, so every caller shares one path, and this module remains the single place that
|
|
61
|
+
* answers "did the deadline pass?" for both the sweep and the client claim. Idleness never counts here.
|
|
62
|
+
*/
|
|
63
|
+
export function VerifyTimeLimitClaim(session, nowMs) {
|
|
64
|
+
return ExpiryCloseReason(session, nowMs + DEADLINE_CLAIM_SKEW_MS, Number.POSITIVE_INFINITY) === 'TimeLimit'
|
|
65
|
+
? 'TimeLimit'
|
|
66
|
+
: 'Explicit';
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=sessionDeadline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionDeadline.js","sourceRoot":"","sources":["../../src/agentSessions/sessionDeadline.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,UAAqC;IACxE,IAAI,CAAC,UAAU,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAwC,CAAC;QAC7E,IAAI,OAAO,MAAM,CAAC,qBAAqB,KAAK,QAAQ,EAAE,CAAC;YACnD,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;QACpD,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACL,8DAA8D;QAC9D,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC7B,OAA+F,EAC/F,KAAa,EACb,gBAAwB;IAExB,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;IAClG,MAAM,MAAM,GAAG,YAAY,GAAG,gBAAgB,CAAC;IAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IACvD,MAAM,UAAU,GAAG,sBAAsB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,CAAC;IACtD,MAAM,cAAc,GAAG,UAAU,KAAK,IAAI,IAAI,UAAU,IAAI,KAAK,CAAC;IAClE,IAAI,cAAc,IAAI,UAAU,EAAE,CAAC;QAC/B,OAAO,UAAU,IAAI,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;IACvD,CAAC;IACD,IAAI,cAAc,EAAE,CAAC;QACjB,OAAO,WAAW,CAAC;IACvB,CAAC;IACD,OAAO,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACtC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAChC,OAA+F,EAC/F,KAAa;IAEb,OAAO,iBAAiB,CAAC,OAAO,EAAE,KAAK,GAAG,sBAAsB,EAAE,MAAM,CAAC,iBAAiB,CAAC,KAAK,WAAW;QACvG,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,UAAU,CAAC;AACrB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"APIKeyScopeAuth.d.ts","sourceRoot":"","sources":["../../src/auth/APIKeyScopeAuth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAmB,mBAAmB,EAAwB,MAAM,0BAA0B,CAAC;AACtG,OAAO,EAAE,QAAQ,EAAW,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"APIKeyScopeAuth.d.ts","sourceRoot":"","sources":["../../src/auth/APIKeyScopeAuth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAmB,mBAAmB,EAAwB,MAAM,0BAA0B,CAAC;AACtG,OAAO,EAAE,QAAQ,EAAW,MAAM,sBAAsB,CAAC;AAIzD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,WAAW,GAAG,WAAW,GAAG,MAAM,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,4DAA4D;IAC5D,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,gCAAgC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yFAAyF;IACzF,OAAO,EAAE,OAAO,CAAC;IACjB,2CAA2C;IAC3C,cAAc,CAAC,EAAE,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;CAC1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,gBAAgB,CAClC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,QAAQ,EACrB,OAAO,GAAE,gBAAqB,GAC/B,OAAO,CAAC,eAAe,CAAC,CAmG1B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CACxC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,QAAQ,EACrB,YAAY,EAAE;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B,EACD,OAAO,GAAE,gBAAqB,GAC/B,OAAO,CAAC,eAAe,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA8H/C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAM,IAC9E,KAAK;IAAE,WAAW,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,QAAQ,CAAA;KAAE,CAAA;CAAE,EAAE,WAAW,MAAM,mBAQrG;AAGD,eAAO,MAAM,cAAc,QAXJ;IAAE,WAAW,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,QAAQ,CAAA;KAAE,CAAA;CAAE,aAAa,MAAM,kBAWhD,CAAC;AACvD,eAAO,MAAM,eAAe,QAZL;IAAE,WAAW,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,QAAQ,CAAA;KAAE,CAAA;CAAE,aAAa,MAAM,kBAY9C,CAAC;AACzD,eAAO,MAAM,mBAAmB,QAbT;IAAE,WAAW,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,QAAQ,CAAA;KAAE,CAAA;CAAE,aAAa,MAAM,kBAatC,CAAC"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { AuthorizationError } from 'type-graphql';
|
|
7
7
|
import { GetAPIKeyEngine } from '@memberjunction/api-keys';
|
|
8
8
|
import { RunView } from '@memberjunction/core';
|
|
9
|
+
import { EscapeSQLString } from '@memberjunction/global';
|
|
9
10
|
/**
|
|
10
11
|
* Check if an API key has the required scope for an operation.
|
|
11
12
|
*
|
|
@@ -50,7 +51,7 @@ export async function CheckAPIKeyScope(apiKeyId, scopePath, contextUser, options
|
|
|
50
51
|
const rv = new RunView();
|
|
51
52
|
const keyResult = await rv.RunView({
|
|
52
53
|
EntityName: 'MJ: API Keys',
|
|
53
|
-
ExtraFilter: `ID='${apiKeyId}'`,
|
|
54
|
+
ExtraFilter: `ID='${EscapeSQLString(apiKeyId)}'`,
|
|
54
55
|
ResultType: 'entity_object'
|
|
55
56
|
}, contextUser);
|
|
56
57
|
if (!keyResult.Success || keyResult.Results.length === 0) {
|
|
@@ -68,7 +69,7 @@ export async function CheckAPIKeyScope(apiKeyId, scopePath, contextUser, options
|
|
|
68
69
|
// Get the application by name
|
|
69
70
|
const appResult = await rv.RunView({
|
|
70
71
|
EntityName: 'MJ: API Applications',
|
|
71
|
-
ExtraFilter: `Name='${applicationName}'`,
|
|
72
|
+
ExtraFilter: `Name='${EscapeSQLString(applicationName)}'`,
|
|
72
73
|
ResultType: 'entity_object'
|
|
73
74
|
}, contextUser);
|
|
74
75
|
if (!appResult.Success || appResult.Results.length === 0) {
|
|
@@ -144,7 +145,7 @@ export async function CheckAPIKeyScopeAndLog(apiKeyId, scopePath, contextUser, u
|
|
|
144
145
|
// Get the API key
|
|
145
146
|
const keyResult = await rv.RunView({
|
|
146
147
|
EntityName: 'MJ: API Keys',
|
|
147
|
-
ExtraFilter: `ID='${apiKeyId}'`,
|
|
148
|
+
ExtraFilter: `ID='${EscapeSQLString(apiKeyId)}'`,
|
|
148
149
|
ResultType: 'entity_object'
|
|
149
150
|
}, contextUser);
|
|
150
151
|
if (!keyResult.Success || keyResult.Results.length === 0) {
|
|
@@ -162,7 +163,7 @@ export async function CheckAPIKeyScopeAndLog(apiKeyId, scopePath, contextUser, u
|
|
|
162
163
|
// Get the application
|
|
163
164
|
const appResult = await rv.RunView({
|
|
164
165
|
EntityName: 'MJ: API Applications',
|
|
165
|
-
ExtraFilter: `Name='${applicationName}'`,
|
|
166
|
+
ExtraFilter: `Name='${EscapeSQLString(applicationName)}'`,
|
|
166
167
|
ResultType: 'entity_object'
|
|
167
168
|
}, contextUser);
|
|
168
169
|
if (!appResult.Success || appResult.Results.length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"APIKeyScopeAuth.js","sourceRoot":"","sources":["../../src/auth/APIKeyScopeAuth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,eAAe,EAA6C,MAAM,0BAA0B,CAAC;AACtG,OAAO,EAAY,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAkCzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAClC,QAA4B,EAC5B,SAAiB,EACjB,WAAqB,EACrB,UAA4B,EAAE;IAE9B,MAAM,EACF,eAAe,GAAG,OAAO,EACzB,QAAQ,GAAG,GAAG,EACd,aAAa,GAAG,IAAI,EACvB,GAAG,OAAO,CAAC;IAEZ,qEAAqE;IACrE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,OAAO;YACH,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,+BAA+B;SAC1C,CAAC;IACN,CAAC;IAED,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IAEjC,sCAAsC;IACtC,MAAM,EAAE,GAAG,IAAI,OAAO,EAAE,CAAC;IACzB,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,OAAO,CAAiB;QAC/C,UAAU,EAAE,cAAc;QAC1B,WAAW,EAAE,OAAO,QAAQ,GAAG;
|
|
1
|
+
{"version":3,"file":"APIKeyScopeAuth.js","sourceRoot":"","sources":["../../src/auth/APIKeyScopeAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which email a verified login is matched to a User record by, and whether that differs from the
|
|
3
|
+
* identity the token carries.
|
|
4
|
+
*
|
|
5
|
+
* The server links a login to a User row by email alone. `USER_EMAIL_MAP` can rewrite that email
|
|
6
|
+
* before the lookup, which makes a login run as a different person's record. That is a legitimate
|
|
7
|
+
* development aid, but it is silent, so a misconfigured map on a shared machine looks exactly like
|
|
8
|
+
* an authentication bug. These helpers keep the token's identity next to the one actually used, so
|
|
9
|
+
* the session audit and the server log can say when the two differ.
|
|
10
|
+
*/
|
|
11
|
+
/** The identity fields of a verified token that the lookup can use. */
|
|
12
|
+
export interface LoginIdentityClaims {
|
|
13
|
+
email?: string;
|
|
14
|
+
preferredUsername?: string;
|
|
15
|
+
}
|
|
16
|
+
/** The email the token carries and the email the User lookup will use. */
|
|
17
|
+
export interface LoginEmailResolution {
|
|
18
|
+
/** The identity from the verified token: its email claim, or its preferred username when it has none. */
|
|
19
|
+
TokenEmail: string | undefined;
|
|
20
|
+
/** The email the User record is looked up by, after any `USER_EMAIL_MAP` rewrite. */
|
|
21
|
+
LookupEmail: string | undefined;
|
|
22
|
+
/** True when `USER_EMAIL_MAP` replaced the token's email with a different one. */
|
|
23
|
+
Remapped: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolves the lookup email for a verified token. The map applies only to the email claim, with an
|
|
27
|
+
* exact (case-sensitive) key match, as it always has; a preferred username is never remapped.
|
|
28
|
+
*
|
|
29
|
+
* Named without "login"/"auth"/"verify": CodeQL treats calls with those words as authentication
|
|
30
|
+
* actions and reports the `if (!token)` guard above this call in GetUserPayload as a user-controlled
|
|
31
|
+
* bypass. This is a plain lookup, not an authentication step.
|
|
32
|
+
*/
|
|
33
|
+
export declare function ResolveUserLookupEmail(claims: LoginIdentityClaims, emailMap: Record<string, string> | undefined): LoginEmailResolution;
|
|
34
|
+
/** Case-insensitive, whitespace-trimmed comparison, matching how the User lookup compares emails. */
|
|
35
|
+
export declare function EmailsMatch(a: string | undefined, b: string | undefined): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The startup warning for a configured `USER_EMAIL_MAP`, or null when the map is absent or rewrites
|
|
38
|
+
* nothing. Lists every entry so whoever starts the server can see whose record each login will use.
|
|
39
|
+
*/
|
|
40
|
+
export declare function DescribeUserEmailMap(emailMap: Record<string, string> | undefined): string | null;
|
|
41
|
+
//# sourceMappingURL=loginEmailResolution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loginEmailResolution.d.ts","sourceRoot":"","sources":["../../src/auth/loginEmailResolution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,uEAAuE;AACvE,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,0EAA0E;AAC1E,MAAM,WAAW,oBAAoB;IACnC,yGAAyG;IACzG,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,qFAAqF;IACrF,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,kFAAkF;IAClF,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,oBAAoB,CAOtI;AAED,qGAAqG;AACrG,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAKjF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAUhG"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which email a verified login is matched to a User record by, and whether that differs from the
|
|
3
|
+
* identity the token carries.
|
|
4
|
+
*
|
|
5
|
+
* The server links a login to a User row by email alone. `USER_EMAIL_MAP` can rewrite that email
|
|
6
|
+
* before the lookup, which makes a login run as a different person's record. That is a legitimate
|
|
7
|
+
* development aid, but it is silent, so a misconfigured map on a shared machine looks exactly like
|
|
8
|
+
* an authentication bug. These helpers keep the token's identity next to the one actually used, so
|
|
9
|
+
* the session audit and the server log can say when the two differ.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Resolves the lookup email for a verified token. The map applies only to the email claim, with an
|
|
13
|
+
* exact (case-sensitive) key match, as it always has; a preferred username is never remapped.
|
|
14
|
+
*
|
|
15
|
+
* Named without "login"/"auth"/"verify": CodeQL treats calls with those words as authentication
|
|
16
|
+
* actions and reports the `if (!token)` guard above this call in GetUserPayload as a user-controlled
|
|
17
|
+
* bypass. This is a plain lookup, not an authentication step.
|
|
18
|
+
*/
|
|
19
|
+
export function ResolveUserLookupEmail(claims, emailMap) {
|
|
20
|
+
if (!claims.email) {
|
|
21
|
+
return { TokenEmail: claims.preferredUsername, LookupEmail: claims.preferredUsername, Remapped: false };
|
|
22
|
+
}
|
|
23
|
+
const mapped = emailMap?.[claims.email];
|
|
24
|
+
const lookupEmail = mapped ?? claims.email;
|
|
25
|
+
return { TokenEmail: claims.email, LookupEmail: lookupEmail, Remapped: mapped !== undefined && !EmailsMatch(mapped, claims.email) };
|
|
26
|
+
}
|
|
27
|
+
/** Case-insensitive, whitespace-trimmed comparison, matching how the User lookup compares emails. */
|
|
28
|
+
export function EmailsMatch(a, b) {
|
|
29
|
+
if (!a || !b) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return a.trim().toLowerCase() === b.trim().toLowerCase();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The startup warning for a configured `USER_EMAIL_MAP`, or null when the map is absent or rewrites
|
|
36
|
+
* nothing. Lists every entry so whoever starts the server can see whose record each login will use.
|
|
37
|
+
*/
|
|
38
|
+
export function DescribeUserEmailMap(emailMap) {
|
|
39
|
+
const entries = Object.entries(emailMap ?? {}).filter(([from, to]) => !EmailsMatch(from, to));
|
|
40
|
+
if (entries.length === 0) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const lines = entries.map(([from, to]) => ` ${from} -> ${to}`).join('\n');
|
|
44
|
+
return (`[Auth] USER_EMAIL_MAP is set: ${entries.length} login email(s) will be matched to a different user's record. ` +
|
|
45
|
+
`A login with the first address runs as the user with the second. Remove the setting unless this is intended.\n${lines}`);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=loginEmailResolution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loginEmailResolution.js","sourceRoot":"","sources":["../../src/auth/loginEmailResolution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAkBH;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAA2B,EAAE,QAA4C;IAC9G,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,iBAAiB,EAAE,WAAW,EAAE,MAAM,CAAC,iBAAiB,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC1G,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC;IAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,KAAK,SAAS,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACtI,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,WAAW,CAAC,CAAqB,EAAE,CAAqB;IACtE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACb,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAA4C;IAC/E,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9F,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3E,OAAO,CACL,iCAAiC,OAAO,CAAC,MAAM,gEAAgE;QAC/G,iHAAiH,KAAK,EAAE,CACzH,CAAC;AACJ,CAAC"}
|
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { BaseSingleton } from '@memberjunction/global';
|
|
12
12
|
import type { MagicLinkJWTClaims } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* True when the process is NOT running with `NODE_ENV=production`. This is the same
|
|
15
|
+
* production/local-dev line MJServer already uses to forbid local dev auth in production.
|
|
16
|
+
*/
|
|
17
|
+
export declare function IsMagicLinkLocalDevEnvironment(env?: NodeJS.ProcessEnv): boolean;
|
|
18
|
+
/** Warning logged when a non-local-dev server falls back to an ephemeral keypair. */
|
|
19
|
+
export declare const EPHEMERAL_MAGIC_LINK_KEY_WARNING: string;
|
|
13
20
|
/** A single JSON Web Key plus the metadata jwks-rsa needs to match it. */
|
|
14
21
|
interface PublishedJWK extends JsonWebKey {
|
|
15
22
|
kid: string;
|
|
@@ -28,26 +35,67 @@ export declare class MagicLinkKeyManager extends BaseSingleton<MagicLinkKeyManag
|
|
|
28
35
|
private publicKey?;
|
|
29
36
|
private _kid;
|
|
30
37
|
private _initialized;
|
|
38
|
+
private _isEphemeral;
|
|
31
39
|
constructor();
|
|
32
40
|
static get Instance(): MagicLinkKeyManager;
|
|
33
41
|
get IsInitialized(): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* True when no private key was configured and the keypair was generated for this process
|
|
44
|
+
* only. Tokens signed with an ephemeral key do not survive a restart and do not validate on
|
|
45
|
+
* other instances. Downstream code should ask this rather than reading the raw config value.
|
|
46
|
+
*/
|
|
47
|
+
get IsEphemeral(): boolean;
|
|
34
48
|
get Kid(): string;
|
|
35
49
|
/**
|
|
36
50
|
* Initializes the keypair from a provided PEM (raw or base64-encoded) or, if
|
|
37
51
|
* none is supplied, generates an ephemeral 2048-bit RSA keypair. Idempotent.
|
|
52
|
+
*
|
|
53
|
+
* @param env - process environment used to decide whether the ephemeral fallback is a local-dev
|
|
54
|
+
* default (verbose-only notice) or a production misconfiguration (warning). Defaults to `process.env`.
|
|
38
55
|
*/
|
|
39
|
-
Initialize(privateKeyPem?: string): void;
|
|
56
|
+
Initialize(privateKeyPem?: string, env?: NodeJS.ProcessEnv): void;
|
|
40
57
|
/**
|
|
41
58
|
* Signs a set of magic-link (or local-dev) claims and returns the compact JWT.
|
|
42
59
|
* `iat`/`exp` are expected to already be set on the claims.
|
|
43
60
|
*/
|
|
44
|
-
Sign(claims:
|
|
61
|
+
Sign<T extends object>(claims: T): string;
|
|
62
|
+
/**
|
|
63
|
+
* Verifies a magic-link session JWT signed by this key manager (`RS256`, `mj_magic_link === true`).
|
|
64
|
+
* Returns `null` if invalid, expired, or forged.
|
|
65
|
+
*/
|
|
66
|
+
VerifySessionToken(token: string, options?: {
|
|
67
|
+
issuer?: string;
|
|
68
|
+
audience?: string;
|
|
69
|
+
}): MagicLinkJWTClaims | null;
|
|
70
|
+
/**
|
|
71
|
+
* Signs a redirect binding JWT (`mj_purpose = 'magic-link-redirect'`) that cryptographically
|
|
72
|
+
* binds a validated `redirectUrl` to a specific invite's `tokenHash`.
|
|
73
|
+
*
|
|
74
|
+
* Note: Expiration is intentionally omitted from the redirect binding JWT because the database
|
|
75
|
+
* invite row's `ExpiresAt` (enforced atomically during `RedeemInvite`) is the authoritative,
|
|
76
|
+
* mutable expiration — allowing `UpdateInviteExpiry()` to extend an invite without invalidating
|
|
77
|
+
* an already-delivered `&rt=` parameter.
|
|
78
|
+
*/
|
|
79
|
+
SignRedirectBinding(tokenHash: string, redirectUrl: string, _expiresAtEpochSeconds?: number): string;
|
|
80
|
+
/**
|
|
81
|
+
* Verifies a redirect binding JWT produced by {@link SignRedirectBinding} and ensures it matches
|
|
82
|
+
* `expectedTokenHash` (preventing cross-invite substitution) and carries a valid `http(s)` URL.
|
|
83
|
+
* Ignores JWT `exp` so bindings minted before an `UpdateInviteExpiry()` extension remain valid
|
|
84
|
+
* while the underlying invite row is valid. Returns the bound URL or `null`.
|
|
85
|
+
*/
|
|
86
|
+
VerifyRedirectBinding(bindingToken: string, expectedTokenHash: string): string | null;
|
|
45
87
|
/**
|
|
46
88
|
* Returns the JWKS document (public key set) for the JWKS endpoint.
|
|
47
89
|
*/
|
|
48
90
|
GetJWKS(): {
|
|
49
91
|
keys: PublishedJWK[];
|
|
50
92
|
};
|
|
93
|
+
/**
|
|
94
|
+
* Local dev (NODE_ENV not 'production'): the ephemeral fallback is the designed behavior and
|
|
95
|
+
* fires on every boot, so the notice stays verbose-only. Otherwise it is a data-loss-on-restart
|
|
96
|
+
* misconfiguration, so it is a warning in the default output.
|
|
97
|
+
*/
|
|
98
|
+
private reportEphemeralKey;
|
|
51
99
|
private ensureInitialized;
|
|
52
100
|
/** Accepts raw PEM or base64-encoded PEM and returns raw PEM. */
|
|
53
101
|
private normalizePem;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MagicLinkKeys.d.ts","sourceRoot":"","sources":["../../../src/auth/magicLink/MagicLinkKeys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAIvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,0EAA0E;AAC1E,UAAU,YAAa,SAAQ,UAAU;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,KAAK,CAAC;IACX,GAAG,EAAE,OAAO,CAAC;CACd;AAED;;;;;;GAMG;AACH,qBAAa,mBAAoB,SAAQ,aAAa,CAAC,mBAAmB,CAAC;IACzE,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,YAAY,CAAS;;IAQ7B,WAAkB,QAAQ,IAAI,mBAAmB,CAEhD;IAED,IAAW,aAAa,IAAI,OAAO,CAElC;IAED,IAAW,GAAG,IAAI,MAAM,CAEvB;IAED
|
|
1
|
+
{"version":3,"file":"MagicLinkKeys.d.ts","sourceRoot":"","sources":["../../../src/auth/magicLink/MagicLinkKeys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAIvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAE5F;AAED,qFAAqF;AACrF,eAAO,MAAM,gCAAgC,QAMJ,CAAC;AAE1C,0EAA0E;AAC1E,UAAU,YAAa,SAAQ,UAAU;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,KAAK,CAAC;IACX,GAAG,EAAE,OAAO,CAAC;CACd;AAED;;;;;;GAMG;AACH,qBAAa,mBAAoB,SAAQ,aAAa,CAAC,mBAAmB,CAAC;IACzE,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAS;;IAQ7B,WAAkB,QAAQ,IAAI,mBAAmB,CAEhD;IAED,IAAW,aAAa,IAAI,OAAO,CAElC;IAED;;;;OAIG;IACH,IAAW,WAAW,IAAI,OAAO,CAEhC;IAED,IAAW,GAAG,IAAI,MAAM,CAEvB;IAED;;;;;;OAMG;IACI,UAAU,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,IAAI;IAsBrF;;;OAGG;IACI,IAAI,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM;IAKhD;;;OAGG;IACI,kBAAkB,CACvB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/C,kBAAkB,GAAG,IAAI;IAyB5B;;;;;;;;OAQG;IACI,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,sBAAsB,CAAC,EAAE,MAAM,GAAG,MAAM;IAe3G;;;;;OAKG;IACI,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IA8B5F;;OAEG;IACI,OAAO,IAAI;QAAE,IAAI,EAAE,YAAY,EAAE,CAAA;KAAE;IAM1C;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,iBAAiB;IAMzB,iEAAiE;IACjE,OAAO,CAAC,YAAY;IAOpB,wFAAwF;IACxF,OAAO,CAAC,UAAU;CAInB"}
|
|
@@ -9,9 +9,23 @@
|
|
|
9
9
|
* @module @memberjunction/server/auth/magicLink
|
|
10
10
|
*/
|
|
11
11
|
import { BaseSingleton } from '@memberjunction/global';
|
|
12
|
-
import { LogStatusEx } from '@memberjunction/core';
|
|
12
|
+
import { LogStatusEx, LogWarning } from '@memberjunction/core';
|
|
13
13
|
import { createPrivateKey, createPublicKey, generateKeyPairSync, createHash } from 'node:crypto';
|
|
14
14
|
import jwt from 'jsonwebtoken';
|
|
15
|
+
/**
|
|
16
|
+
* True when the process is NOT running with `NODE_ENV=production`. This is the same
|
|
17
|
+
* production/local-dev line MJServer already uses to forbid local dev auth in production.
|
|
18
|
+
*/
|
|
19
|
+
export function IsMagicLinkLocalDevEnvironment(env = process.env) {
|
|
20
|
+
return env.NODE_ENV?.trim().toLowerCase() !== 'production';
|
|
21
|
+
}
|
|
22
|
+
/** Warning logged when a non-local-dev server falls back to an ephemeral keypair. */
|
|
23
|
+
export const EPHEMERAL_MAGIC_LINK_KEY_WARNING = '[MagicLink] No rsaPrivateKey configured and NODE_ENV=production — generated an EPHEMERAL RS256 keypair. ' +
|
|
24
|
+
'Magic-link session tokens signed with it will stop validating when this process restarts, and they will not ' +
|
|
25
|
+
'validate on any other MJAPI instance behind the same load balancer, because each process generates its own key. ' +
|
|
26
|
+
'To fix, generate one RSA private key (e.g. `openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048`) and set it ' +
|
|
27
|
+
'as magicLink.rsaPrivateKey in mj.config.cjs or as MJ_MAGIC_LINK_PRIVATE_KEY (raw or base64-encoded PEM), ' +
|
|
28
|
+
'using the same key on every instance.';
|
|
15
29
|
/**
|
|
16
30
|
* Manages the RS256 keypair used to sign and publish magic-link session tokens.
|
|
17
31
|
* Singleton so the keypair (and therefore the `kid`) is stable for the process
|
|
@@ -27,6 +41,7 @@ export class MagicLinkKeyManager extends BaseSingleton {
|
|
|
27
41
|
this.privateKeyPem = '';
|
|
28
42
|
this._kid = '';
|
|
29
43
|
this._initialized = false;
|
|
44
|
+
this._isEphemeral = false;
|
|
30
45
|
}
|
|
31
46
|
static get Instance() {
|
|
32
47
|
return MagicLinkKeyManager.getInstance();
|
|
@@ -34,14 +49,25 @@ export class MagicLinkKeyManager extends BaseSingleton {
|
|
|
34
49
|
get IsInitialized() {
|
|
35
50
|
return this._initialized;
|
|
36
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* True when no private key was configured and the keypair was generated for this process
|
|
54
|
+
* only. Tokens signed with an ephemeral key do not survive a restart and do not validate on
|
|
55
|
+
* other instances. Downstream code should ask this rather than reading the raw config value.
|
|
56
|
+
*/
|
|
57
|
+
get IsEphemeral() {
|
|
58
|
+
return this._isEphemeral;
|
|
59
|
+
}
|
|
37
60
|
get Kid() {
|
|
38
61
|
return this._kid;
|
|
39
62
|
}
|
|
40
63
|
/**
|
|
41
64
|
* Initializes the keypair from a provided PEM (raw or base64-encoded) or, if
|
|
42
65
|
* none is supplied, generates an ephemeral 2048-bit RSA keypair. Idempotent.
|
|
66
|
+
*
|
|
67
|
+
* @param env - process environment used to decide whether the ephemeral fallback is a local-dev
|
|
68
|
+
* default (verbose-only notice) or a production misconfiguration (warning). Defaults to `process.env`.
|
|
43
69
|
*/
|
|
44
|
-
Initialize(privateKeyPem) {
|
|
70
|
+
Initialize(privateKeyPem, env = process.env) {
|
|
45
71
|
if (this._initialized) {
|
|
46
72
|
return;
|
|
47
73
|
}
|
|
@@ -53,16 +79,8 @@ export class MagicLinkKeyManager extends BaseSingleton {
|
|
|
53
79
|
else {
|
|
54
80
|
const { privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 });
|
|
55
81
|
priv = privateKey;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// the default startup output. Deployments that care set the key; operators diagnosing
|
|
59
|
-
// magic-link session loss can re-run with verbose logging.
|
|
60
|
-
LogStatusEx({
|
|
61
|
-
message: '[MagicLink] No rsaPrivateKey configured — generated an EPHEMERAL RS256 keypair. ' +
|
|
62
|
-
'Outstanding magic-link sessions will be invalidated on restart. Set magicLink.rsaPrivateKey ' +
|
|
63
|
-
'(or MJ_MAGIC_LINK_PRIVATE_KEY) for stable production keys.',
|
|
64
|
-
verboseOnly: true
|
|
65
|
-
});
|
|
82
|
+
this._isEphemeral = true;
|
|
83
|
+
this.reportEphemeralKey(env);
|
|
66
84
|
}
|
|
67
85
|
this.privateKeyPem = priv.export({ type: 'pkcs8', format: 'pem' });
|
|
68
86
|
this.publicKey = createPublicKey(priv);
|
|
@@ -77,6 +95,88 @@ export class MagicLinkKeyManager extends BaseSingleton {
|
|
|
77
95
|
this.ensureInitialized();
|
|
78
96
|
return jwt.sign(claims, this.privateKeyPem, { algorithm: 'RS256', keyid: this._kid });
|
|
79
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Verifies a magic-link session JWT signed by this key manager (`RS256`, `mj_magic_link === true`).
|
|
100
|
+
* Returns `null` if invalid, expired, or forged.
|
|
101
|
+
*/
|
|
102
|
+
VerifySessionToken(token, options) {
|
|
103
|
+
this.ensureInitialized();
|
|
104
|
+
try {
|
|
105
|
+
const publicPem = this.publicKey.export({ type: 'spki', format: 'pem' });
|
|
106
|
+
const verifyOptions = { algorithms: ['RS256'] };
|
|
107
|
+
if (options?.issuer) {
|
|
108
|
+
verifyOptions.issuer = options.issuer;
|
|
109
|
+
}
|
|
110
|
+
if (options?.audience) {
|
|
111
|
+
verifyOptions.audience = options.audience;
|
|
112
|
+
}
|
|
113
|
+
const decoded = jwt.verify(token, publicPem, verifyOptions);
|
|
114
|
+
if (!decoded || typeof decoded !== 'object') {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
const claims = decoded;
|
|
118
|
+
if (claims.mj_magic_link !== true || typeof claims.sub !== 'string') {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
return claims;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Signs a redirect binding JWT (`mj_purpose = 'magic-link-redirect'`) that cryptographically
|
|
129
|
+
* binds a validated `redirectUrl` to a specific invite's `tokenHash`.
|
|
130
|
+
*
|
|
131
|
+
* Note: Expiration is intentionally omitted from the redirect binding JWT because the database
|
|
132
|
+
* invite row's `ExpiresAt` (enforced atomically during `RedeemInvite`) is the authoritative,
|
|
133
|
+
* mutable expiration — allowing `UpdateInviteExpiry()` to extend an invite without invalidating
|
|
134
|
+
* an already-delivered `&rt=` parameter.
|
|
135
|
+
*/
|
|
136
|
+
SignRedirectBinding(tokenHash, redirectUrl, _expiresAtEpochSeconds) {
|
|
137
|
+
this.ensureInitialized();
|
|
138
|
+
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
139
|
+
return jwt.sign({
|
|
140
|
+
mj_purpose: 'magic-link-redirect',
|
|
141
|
+
mj_th: tokenHash,
|
|
142
|
+
mj_redirect: redirectUrl,
|
|
143
|
+
iat: nowSeconds,
|
|
144
|
+
}, this.privateKeyPem, { algorithm: 'RS256', keyid: this._kid });
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Verifies a redirect binding JWT produced by {@link SignRedirectBinding} and ensures it matches
|
|
148
|
+
* `expectedTokenHash` (preventing cross-invite substitution) and carries a valid `http(s)` URL.
|
|
149
|
+
* Ignores JWT `exp` so bindings minted before an `UpdateInviteExpiry()` extension remain valid
|
|
150
|
+
* while the underlying invite row is valid. Returns the bound URL or `null`.
|
|
151
|
+
*/
|
|
152
|
+
VerifyRedirectBinding(bindingToken, expectedTokenHash) {
|
|
153
|
+
this.ensureInitialized();
|
|
154
|
+
try {
|
|
155
|
+
const publicPem = this.publicKey.export({ type: 'spki', format: 'pem' });
|
|
156
|
+
const decoded = jwt.verify(bindingToken, publicPem, {
|
|
157
|
+
algorithms: ['RS256'],
|
|
158
|
+
ignoreExpiration: true,
|
|
159
|
+
});
|
|
160
|
+
if (!decoded || typeof decoded !== 'object') {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
const record = decoded;
|
|
164
|
+
if (record.mj_purpose !== 'magic-link-redirect' ||
|
|
165
|
+
record.mj_th !== expectedTokenHash ||
|
|
166
|
+
typeof record.mj_redirect !== 'string' ||
|
|
167
|
+
!record.mj_redirect) {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
const parsed = new URL(record.mj_redirect);
|
|
171
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
return record.mj_redirect;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
80
180
|
/**
|
|
81
181
|
* Returns the JWKS document (public key set) for the JWKS endpoint.
|
|
82
182
|
*/
|
|
@@ -85,6 +185,23 @@ export class MagicLinkKeyManager extends BaseSingleton {
|
|
|
85
185
|
const jwk = this.publicKey.export({ format: 'jwk' });
|
|
86
186
|
return { keys: [{ ...jwk, kid: this._kid, use: 'sig', alg: 'RS256' }] };
|
|
87
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Local dev (NODE_ENV not 'production'): the ephemeral fallback is the designed behavior and
|
|
190
|
+
* fires on every boot, so the notice stays verbose-only. Otherwise it is a data-loss-on-restart
|
|
191
|
+
* misconfiguration, so it is a warning in the default output.
|
|
192
|
+
*/
|
|
193
|
+
reportEphemeralKey(env) {
|
|
194
|
+
if (!IsMagicLinkLocalDevEnvironment(env)) {
|
|
195
|
+
LogWarning(EPHEMERAL_MAGIC_LINK_KEY_WARNING);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
LogStatusEx({
|
|
199
|
+
message: '[MagicLink] No rsaPrivateKey configured — generated an EPHEMERAL RS256 keypair. ' +
|
|
200
|
+
'Outstanding magic-link sessions will be invalidated on restart. Set magicLink.rsaPrivateKey ' +
|
|
201
|
+
'(or MJ_MAGIC_LINK_PRIVATE_KEY) for stable production keys.',
|
|
202
|
+
verboseOnly: true
|
|
203
|
+
});
|
|
204
|
+
}
|
|
88
205
|
ensureInitialized() {
|
|
89
206
|
if (!this._initialized) {
|
|
90
207
|
throw new Error('MagicLinkKeyManager not initialized — call Initialize() during server startup.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MagicLinkKeys.js","sourceRoot":"","sources":["../../../src/auth/magicLink/MagicLinkKeys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"MagicLinkKeys.js","sourceRoot":"","sources":["../../../src/auth/magicLink/MagicLinkKeys.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { Router } from 'express';
|
|
11
11
|
import { type MagicLinkConfig } from '../../config.js';
|
|
12
|
+
import { MagicLinkService } from './MagicLinkService.js';
|
|
12
13
|
/** The mount path for both routers (`/magic-link`). */
|
|
13
14
|
export declare const MAGIC_LINK_MOUNT_PATH = "/magic-link";
|
|
14
15
|
/** Path of the JWKS endpoint relative to the public URL. */
|
|
@@ -20,11 +21,13 @@ export declare const MAGIC_LINK_JWKS_PATH = "/magic-link/jwks.json";
|
|
|
20
21
|
export declare function CreateMagicLinkHandler(publicUrl: string, config: MagicLinkConfig): {
|
|
21
22
|
publicRouter: Router;
|
|
22
23
|
authenticatedRouter: Router;
|
|
24
|
+
service: MagicLinkService;
|
|
23
25
|
};
|
|
24
26
|
/** @deprecated Use {@link CreateMagicLinkHandler}. */
|
|
25
27
|
export declare function createMagicLinkHandler(publicUrl: string, config: MagicLinkConfig): {
|
|
26
28
|
publicRouter: Router;
|
|
27
29
|
authenticatedRouter: Router;
|
|
30
|
+
service: MagicLinkService;
|
|
28
31
|
};
|
|
29
32
|
/**
|
|
30
33
|
* A minimal PUBLIC router that serves ONLY the JWKS endpoint (the magic-link
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MagicLinkRouter.d.ts","sourceRoot":"","sources":["../../../src/auth/magicLink/MagicLinkRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAiD,MAAM,SAAS,CAAC;AAIhF,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"MagicLinkRouter.d.ts","sourceRoot":"","sources":["../../../src/auth/magicLink/MagicLinkRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAiD,MAAM,SAAS,CAAC;AAIhF,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAKzD,uDAAuD;AACvD,eAAO,MAAM,qBAAqB,gBAAgB,CAAC;AAEnD,4DAA4D;AAC5D,eAAO,MAAM,oBAAoB,0BAAuC,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG;IAClF,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,OAAO,EAAE,gBAAgB,CAAC;CAC3B,CAyKA;AAED,sDAAsD;AACtD,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG;IAClF,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,OAAO,EAAE,gBAAgB,CAAC;CAC3B,CAEA;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAMlD;AAED,yDAAyD;AACzD,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAqB9F;AAED,6DAA6D;AAC7D,wBAAgB,6BAA6B,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAE9F"}
|