@memberjunction/server 6.1.4 → 6.2.0-edge.1
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/ReturningVisitorRecap.d.ts +2 -0
- package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
- package/dist/agentSessions/ReturningVisitorRecap.js +5 -1
- package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
- package/dist/agentSessions/SessionManager.js +2 -2
- package/dist/agentSessions/remoteBrowserGoalEngine.d.ts +8 -0
- package/dist/agentSessions/remoteBrowserGoalEngine.d.ts.map +1 -1
- package/dist/agentSessions/remoteBrowserGoalEngine.js +21 -5
- package/dist/agentSessions/remoteBrowserGoalEngine.js.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.d.ts +2 -0
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.js +5 -1
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
- package/dist/auth/exampleNewUserSubClass.js +2 -1
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/index.d.ts +20 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +20 -10
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +8 -0
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +21 -5
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.d.ts +9 -0
- package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +22 -10
- package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.d.ts +17 -15
- package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +65 -51
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/magicLink/index.d.ts +2 -2
- package/dist/auth/magicLink/index.d.ts.map +1 -1
- package/dist/auth/magicLink/index.js +2 -2
- package/dist/auth/magicLink/index.js.map +1 -1
- package/dist/auth/magicLink/magicLinkCore.d.ts +54 -33
- package/dist/auth/magicLink/magicLinkCore.d.ts.map +1 -1
- package/dist/auth/magicLink/magicLinkCore.js +61 -61
- package/dist/auth/magicLink/magicLinkCore.js.map +1 -1
- package/dist/auth/magicLink/redeemLanding.d.ts +4 -0
- package/dist/auth/magicLink/redeemLanding.d.ts.map +1 -1
- package/dist/auth/magicLink/redeemLanding.js +12 -4
- package/dist/auth/magicLink/redeemLanding.js.map +1 -1
- package/dist/auth/magicLink/types.d.ts +4 -4
- package/dist/auth/principals.d.ts +2 -0
- package/dist/auth/principals.d.ts.map +1 -1
- package/dist/auth/principals.js +6 -2
- package/dist/auth/principals.js.map +1 -1
- package/dist/cache.d.ts +2 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +3 -1
- package/dist/cache.js.map +1 -1
- package/dist/config.d.ts +293 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -4
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +20 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +27 -19
- package/dist/context.js.map +1 -1
- package/dist/directives/Public.d.ts +2 -0
- package/dist/directives/Public.d.ts.map +1 -1
- package/dist/directives/Public.js +3 -1
- package/dist/directives/Public.js.map +1 -1
- package/dist/directives/RequireSystemUser.d.ts +2 -0
- package/dist/directives/RequireSystemUser.d.ts.map +1 -1
- package/dist/directives/RequireSystemUser.js +3 -1
- package/dist/directives/RequireSystemUser.js.map +1 -1
- package/dist/generated/graphql-schemas/__mj.d.ts +266 -4
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +1304 -0
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +8 -2
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +7 -3
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/FireAndForgetHeartbeat.d.ts +3 -1
- package/dist/generic/FireAndForgetHeartbeat.d.ts.map +1 -1
- package/dist/generic/FireAndForgetHeartbeat.js +8 -4
- package/dist/generic/FireAndForgetHeartbeat.js.map +1 -1
- package/dist/generic/PushStatusResolver.d.ts +10 -1
- package/dist/generic/PushStatusResolver.d.ts.map +1 -1
- package/dist/generic/PushStatusResolver.js +11 -3
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +27 -1
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +64 -6
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -6
- package/dist/index.js.map +1 -1
- package/dist/integration/CustomColumnPromoter.d.ts +2 -0
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +5 -1
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/integration/EntityMapLifecycle.d.ts +4 -0
- package/dist/integration/EntityMapLifecycle.d.ts.map +1 -1
- package/dist/integration/EntityMapLifecycle.js +10 -2
- package/dist/integration/EntityMapLifecycle.js.map +1 -1
- package/dist/logging/NoLog.d.ts +4 -0
- package/dist/logging/NoLog.d.ts.map +1 -1
- package/dist/logging/NoLog.js +10 -2
- package/dist/logging/NoLog.js.map +1 -1
- package/dist/logging/StartupLogger.d.ts +2 -0
- package/dist/logging/StartupLogger.d.ts.map +1 -1
- package/dist/logging/StartupLogger.js +5 -1
- package/dist/logging/StartupLogger.js.map +1 -1
- package/dist/logging/bootAudit.d.ts +11 -7
- package/dist/logging/bootAudit.d.ts.map +1 -1
- package/dist/logging/bootAudit.js +15 -7
- package/dist/logging/bootAudit.js.map +1 -1
- package/dist/logging/boundaryLogPayload.d.ts +4 -0
- package/dist/logging/boundaryLogPayload.d.ts.map +1 -1
- package/dist/logging/boundaryLogPayload.js +5 -1
- package/dist/logging/boundaryLogPayload.js.map +1 -1
- package/dist/logging/secretRedactor.d.ts +2 -0
- package/dist/logging/secretRedactor.d.ts.map +1 -1
- package/dist/logging/secretRedactor.js +8 -4
- package/dist/logging/secretRedactor.js.map +1 -1
- package/dist/logging/shortenForLog.d.ts +2 -0
- package/dist/logging/shortenForLog.d.ts.map +1 -1
- package/dist/logging/shortenForLog.js +7 -3
- package/dist/logging/shortenForLog.js.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.d.ts +2 -0
- package/dist/logging/variablesLoggingMiddleware.d.ts.map +1 -1
- package/dist/logging/variablesLoggingMiddleware.js +8 -6
- package/dist/logging/variablesLoggingMiddleware.js.map +1 -1
- package/dist/metadataRefreshSignal.d.ts +19 -0
- package/dist/metadataRefreshSignal.d.ts.map +1 -0
- package/dist/metadataRefreshSignal.js +45 -0
- package/dist/metadataRefreshSignal.js.map +1 -0
- package/dist/middleware/MJTenantFilterMiddleware.js +4 -4
- package/dist/multiTenancy/index.d.ts +8 -0
- package/dist/multiTenancy/index.d.ts.map +1 -1
- package/dist/multiTenancy/index.js +21 -5
- package/dist/multiTenancy/index.js.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.d.ts +5 -0
- package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.js +14 -10
- package/dist/realtimeWidget/WidgetRouter.js.map +1 -1
- package/dist/realtimeWidget/WidgetSessionService.d.ts +6 -6
- package/dist/realtimeWidget/WidgetSessionService.js +27 -27
- package/dist/realtimeWidget/host-identity.d.ts +5 -1
- package/dist/realtimeWidget/host-identity.d.ts.map +1 -1
- package/dist/realtimeWidget/host-identity.js +11 -3
- package/dist/realtimeWidget/host-identity.js.map +1 -1
- package/dist/realtimeWidget/index.d.ts +2 -2
- package/dist/realtimeWidget/index.d.ts.map +1 -1
- package/dist/realtimeWidget/index.js +2 -2
- package/dist/realtimeWidget/index.js.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.d.ts +21 -1
- package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -1
- package/dist/realtimeWidget/visitorIdentity.js +16 -4
- package/dist/realtimeWidget/visitorIdentity.js.map +1 -1
- package/dist/realtimeWidget/widgetCore.d.ts +48 -0
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetCore.js +38 -10
- package/dist/realtimeWidget/widgetCore.js.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.d.ts +10 -6
- package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
- package/dist/realtimeWidget/widgetGuestElevation.js +14 -6
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.js +3 -3
- package/dist/resolvers/FetchEntityVectorsResolver.js +2 -2
- package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.js +3 -3
- package/dist/resolvers/GeoResolver.d.ts +2 -2
- package/dist/resolvers/GeoResolver.js +4 -4
- package/dist/resolvers/GetDataResolver.d.ts +14 -0
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +43 -15
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +2 -2
- package/dist/resolvers/ListOperationsResolver.d.ts +20 -0
- package/dist/resolvers/ListOperationsResolver.d.ts.map +1 -1
- package/dist/resolvers/ListOperationsResolver.js +68 -28
- package/dist/resolvers/ListOperationsResolver.js.map +1 -1
- package/dist/resolvers/MCPResolver.d.ts +11 -1
- package/dist/resolvers/MCPResolver.d.ts.map +1 -1
- package/dist/resolvers/MCPResolver.js +7 -3
- package/dist/resolvers/MCPResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +2 -1
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +3 -3
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +37 -0
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +101 -11
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +5 -5
- package/dist/resolvers/RunAIAgentResolver.d.ts +10 -4
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +74 -42
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +2 -2
- package/dist/resolvers/RunTestResolver.js +5 -5
- package/dist/resolvers/SearchEntitiesResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchEntitiesResolver.js +3 -1
- package/dist/resolvers/SearchEntitiesResolver.js.map +1 -1
- package/dist/resolvers/SearchKnowledgeResolver.d.ts +1 -0
- package/dist/resolvers/SearchKnowledgeResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeResolver.js +5 -0
- package/dist/resolvers/SearchKnowledgeResolver.js.map +1 -1
- package/dist/resolvers/SearchKnowledgeSystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeSystemUserResolver.js +1 -0
- package/dist/resolvers/SearchKnowledgeSystemUserResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts +8 -4
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +5 -5
- package/dist/resolvers/TaskGraphFrameResolver.d.ts +8 -1
- package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.js +6 -2
- package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +53 -4
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/adhoc-query-helpers.d.ts +6 -0
- package/dist/resolvers/adhoc-query-helpers.d.ts.map +1 -1
- package/dist/resolvers/adhoc-query-helpers.js +10 -2
- package/dist/resolvers/adhoc-query-helpers.js.map +1 -1
- package/dist/resolvers/artifact-routing.d.ts +8 -8
- package/dist/resolvers/artifact-routing.js +2 -2
- package/dist/resolvers/artifact-routing.js.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.d.ts +10 -2
- package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.js +24 -8
- package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
- package/dist/resolvers/peaksSidecar.d.ts +4 -0
- package/dist/resolvers/peaksSidecar.d.ts.map +1 -1
- package/dist/resolvers/peaksSidecar.js +10 -2
- package/dist/resolvers/peaksSidecar.js.map +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts +28 -0
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +20 -4
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/MediaStreamHandler.d.ts +2 -0
- package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
- package/dist/rest/MediaStreamHandler.js +10 -6
- package/dist/rest/MediaStreamHandler.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts +9 -0
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
- package/dist/rest/OAuthCallbackHandler.js +15 -3
- package/dist/rest/OAuthCallbackHandler.js.map +1 -1
- package/dist/rest/RESTEndpointHandler.d.ts +6 -4
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +15 -11
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/RealtimeSdpBrokerHandler.d.ts +5 -1
- package/dist/rest/RealtimeSdpBrokerHandler.d.ts.map +1 -1
- package/dist/rest/RealtimeSdpBrokerHandler.js +12 -4
- package/dist/rest/RealtimeSdpBrokerHandler.js.map +1 -1
- package/dist/rest/SignatureWebhookHandler.d.ts +2 -0
- package/dist/rest/SignatureWebhookHandler.d.ts.map +1 -1
- package/dist/rest/SignatureWebhookHandler.js +5 -1
- package/dist/rest/SignatureWebhookHandler.js.map +1 -1
- package/dist/rest/UploadTokenManager.d.ts +24 -8
- package/dist/rest/UploadTokenManager.d.ts.map +1 -1
- package/dist/rest/UploadTokenManager.js +53 -21
- package/dist/rest/UploadTokenManager.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +20 -0
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +20 -4
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/rest/mediaRange.d.ts +4 -0
- package/dist/rest/mediaRange.d.ts.map +1 -1
- package/dist/rest/mediaRange.js +10 -2
- package/dist/rest/mediaRange.js.map +1 -1
- package/dist/rest/setupRESTEndpoints.d.ts +4 -0
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
- package/dist/rest/setupRESTEndpoints.js +13 -7
- package/dist/rest/setupRESTEndpoints.js.map +1 -1
- package/dist/serverExtensionReservedRoots.d.ts +2 -0
- package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
- package/dist/serverExtensionReservedRoots.js +5 -1
- package/dist/serverExtensionReservedRoots.js.map +1 -1
- package/dist/services/MJStorageBlobStore.d.ts +41 -0
- package/dist/services/MJStorageBlobStore.d.ts.map +1 -0
- package/dist/services/MJStorageBlobStore.js +160 -0
- package/dist/services/MJStorageBlobStore.js.map +1 -0
- package/dist/services/TaskGraphActionRunner.d.ts +13 -8
- package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphActionRunner.js +16 -15
- package/dist/services/TaskGraphActionRunner.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +7 -3
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +12 -3
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +19 -8
- package/dist/util.js.map +1 -1
- package/package.json +92 -92
- package/src/__tests__/FileResolverPeaks.test.ts +13 -13
- package/src/__tests__/ListOperationsResolver.test.ts +17 -17
- package/src/__tests__/MediaStreamHandler.test.ts +28 -28
- package/src/__tests__/NoLog.test.ts +11 -11
- package/src/__tests__/PrimaryKeyAlwaysMapped.test.ts +10 -10
- package/src/__tests__/RESTEndpointHandler.test.ts +14 -14
- package/src/__tests__/RealtimeBridgeResolver.test.ts +4 -2
- package/src/__tests__/RealtimeClientSessionResolver.test.ts +229 -0
- package/src/__tests__/RealtimeSdpBrokerHandler.test.ts +6 -6
- package/src/__tests__/RefreshAdoptsNewColumns.test.ts +8 -8
- package/src/__tests__/RemoteBrowserGoalEngine.test.ts +18 -18
- package/src/__tests__/ResolverBase.isaPromotionCreate.test.ts +412 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +228 -0
- package/src/__tests__/SearchEntitiesResolver.readOnlyFallback.test.ts +78 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +129 -0
- package/src/__tests__/TaskGraphFrameResolver.test.ts +2 -2
- package/src/__tests__/TransactionGroupResolver.refusals.test.ts +290 -0
- package/src/__tests__/WidgetSessionService.test.ts +8 -4
- package/src/__tests__/adhoc-query-helpers.test.ts +21 -21
- package/src/__tests__/bootAudit.test.ts +11 -11
- package/src/__tests__/boundaryLogPayload.test.ts +6 -6
- package/src/__tests__/databaseAbstraction.test.ts +12 -6
- package/src/__tests__/getDataTokenRedaction.test.ts +7 -7
- package/src/__tests__/initializeProviders.refresh.test.ts +4 -4
- package/src/__tests__/magicLink.test.ts +73 -134
- package/src/__tests__/magicLinkService.consume.test.ts +224 -0
- package/src/__tests__/meetingRecordingRegistration.test.ts +12 -12
- package/src/__tests__/metadataRefreshSignal.test.ts +78 -0
- package/src/__tests__/multiTenancy.security.test.ts +40 -40
- package/src/__tests__/multiTenancy.test.ts +18 -18
- package/src/__tests__/newUsers.test.ts +24 -23
- package/src/__tests__/principals.test.ts +22 -22
- package/src/__tests__/pushStatusResolver.filter.test.ts +8 -8
- package/src/__tests__/secretRedactor.failOpen.test.ts +12 -12
- package/src/__tests__/secretRedactor.test.ts +12 -12
- package/src/__tests__/serverExtensionReservedRoots.test.ts +7 -7
- package/src/__tests__/subscriptionRedaction.test.ts +5 -5
- package/src/__tests__/unifiedAuth.test.ts +15 -9
- package/src/__tests__/visitorIdentity.resolve.test.ts +6 -6
- package/src/__tests__/widget.test.ts +45 -45
- package/src/__tests__/widgetGuestElevation.test.ts +7 -7
- package/src/__tests__/widgetHostIdentity.test.ts +14 -14
- package/src/agentSessions/ReturningVisitorRecap.ts +12 -1
- package/src/agentSessions/SessionManager.ts +2 -2
- package/src/agentSessions/remoteBrowserGoalEngine.ts +30 -5
- package/src/auth/AuthProviderCatalogRouter.ts +6 -1
- package/src/auth/__tests__/backward-compatibility.test.ts +3 -3
- package/src/auth/exampleNewUserSubClass.ts +2 -2
- package/src/auth/index.ts +43 -28
- package/src/auth/initializeProviders.ts +25 -5
- package/src/auth/magicLink/MagicLinkRouter.ts +28 -10
- package/src/auth/magicLink/MagicLinkService.ts +71 -52
- package/src/auth/magicLink/index.ts +7 -7
- package/src/auth/magicLink/magicLinkCore.ts +96 -64
- package/src/auth/magicLink/redeemLanding.ts +14 -4
- package/src/auth/magicLink/types.ts +54 -54
- package/src/auth/newUsers.ts +1 -1
- package/src/auth/principals.ts +11 -2
- package/src/cache.ts +4 -1
- package/src/config.ts +14 -4
- package/src/context.ts +37 -24
- package/src/directives/Public.ts +4 -1
- package/src/directives/RequireSystemUser.ts +4 -1
- package/src/generated/graphql-schemas/__mj.ts +933 -5
- package/src/generic/CacheInvalidationResolver.ts +12 -4
- package/src/generic/FireAndForgetHeartbeat.ts +19 -14
- package/src/generic/PushStatusResolver.ts +21 -7
- package/src/generic/ResolverBase.ts +66 -5
- package/src/generic/RunViewResolver.ts +22 -22
- package/src/generic/__tests__/FireAndForgetHeartbeat.test.ts +7 -7
- package/src/index.ts +34 -7
- package/src/integration/CustomColumnPromoter.ts +6 -1
- package/src/integration/EntityMapLifecycle.ts +20 -2
- package/src/logging/NoLog.ts +16 -2
- package/src/logging/StartupLogger.ts +6 -1
- package/src/logging/bootAudit.ts +26 -16
- package/src/logging/boundaryLogPayload.ts +8 -1
- package/src/logging/secretRedactor.ts +14 -9
- package/src/logging/shortenForLog.ts +8 -3
- package/src/logging/variablesLoggingMiddleware.ts +9 -6
- package/src/metadataRefreshSignal.ts +45 -0
- package/src/middleware/MJTenantFilterMiddleware.ts +4 -4
- package/src/multiTenancy/index.ts +29 -5
- package/src/realtimeWidget/WidgetRouter.ts +15 -10
- package/src/realtimeWidget/WidgetSessionService.ts +76 -76
- package/src/realtimeWidget/host-identity.ts +24 -10
- package/src/realtimeWidget/index.ts +3 -3
- package/src/realtimeWidget/visitorIdentity.ts +39 -8
- package/src/realtimeWidget/widgetCore.ts +75 -10
- package/src/realtimeWidget/widgetGuestElevation.ts +25 -12
- package/src/resolvers/AdhocQueryResolver.ts +3 -3
- package/src/resolvers/AgentSessionResolver.ts +3 -3
- package/src/resolvers/ColorResolver.ts +6 -6
- package/src/resolvers/ComponentRegistryResolver.ts +36 -36
- package/src/resolvers/EntityCommunicationsResolver.ts +4 -4
- package/src/resolvers/ExecuteRemoteOperationResolver.ts +9 -9
- package/src/resolvers/FetchEntityVectorsResolver.ts +2 -2
- package/src/resolvers/FileResolver.ts +42 -42
- package/src/resolvers/GeoResolver.ts +4 -4
- package/src/resolvers/GetDataResolver.ts +50 -15
- package/src/resolvers/IntegrationDiscoveryResolver.ts +2 -2
- package/src/resolvers/ListOperationsResolver.ts +78 -28
- package/src/resolvers/MCPResolver.ts +30 -15
- package/src/resolvers/QueryResolver.ts +13 -13
- package/src/resolvers/QuerySystemUserResolver.ts +2 -1
- package/src/resolvers/RealtimeBridgeResolver.ts +3 -3
- package/src/resolvers/RealtimeClientSessionResolver.ts +126 -13
- package/src/resolvers/RemoteBrowserActionResolver.ts +5 -5
- package/src/resolvers/RunAIAgentResolver.ts +118 -76
- package/src/resolvers/RunAIPromptResolver.ts +22 -22
- package/src/resolvers/RunTemplateResolver.ts +4 -4
- package/src/resolvers/RunTestResolver.ts +25 -25
- package/src/resolvers/SearchEntitiesResolver.ts +3 -1
- package/src/resolvers/SearchKnowledgeResolver.ts +4 -0
- package/src/resolvers/SearchKnowledgeSystemUserResolver.ts +1 -0
- package/src/resolvers/SqlLoggingConfigResolver.ts +56 -56
- package/src/resolvers/TaskGraphFrameResolver.ts +37 -28
- package/src/resolvers/TelemetryResolver.ts +79 -79
- package/src/resolvers/TransactionGroupResolver.ts +57 -4
- package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +40 -38
- package/src/resolvers/__tests__/artifact-routing.test.ts +23 -23
- package/src/resolvers/adhoc-query-helpers.ts +19 -2
- package/src/resolvers/artifact-routing.ts +19 -19
- package/src/resolvers/meetingRecordingRegistration.ts +44 -10
- package/src/resolvers/peaksSidecar.ts +12 -2
- package/src/rest/EntityCRUDHandler.ts +24 -4
- package/src/rest/MediaStreamHandler.ts +11 -6
- package/src/rest/OAuthCallbackHandler.ts +25 -7
- package/src/rest/RESTEndpointHandler.ts +20 -15
- package/src/rest/RealtimeSdpBrokerHandler.ts +14 -4
- package/src/rest/SignatureWebhookHandler.ts +6 -1
- package/src/rest/UploadTokenManager.ts +66 -30
- package/src/rest/ViewOperationsHandler.ts +24 -4
- package/src/rest/mediaRange.ts +16 -6
- package/src/rest/setupRESTEndpoints.ts +24 -12
- package/src/serverExtensionReservedRoots.ts +6 -1
- package/src/services/MJStorageBlobStore.ts +209 -0
- package/src/services/TaskGraphActionRunner.ts +16 -15
- package/src/types.ts +21 -16
- package/src/util.ts +22 -9
|
@@ -242,7 +242,7 @@ export interface SelectableSourceField {
|
|
|
242
242
|
* `null`/`undefined` selection means "all fields", which is not the same as an EMPTY selection —
|
|
243
243
|
* an empty array is a real (if unusual) choice, and still yields the keys.
|
|
244
244
|
*/
|
|
245
|
-
export function
|
|
245
|
+
export function SelectFieldsToMap<T extends SelectableSourceField>(
|
|
246
246
|
allFields: readonly T[],
|
|
247
247
|
selectedFieldNames: readonly string[] | null | undefined,
|
|
248
248
|
): T[] {
|
|
@@ -251,6 +251,14 @@ export function selectFieldsToMap<T extends SelectableSourceField>(
|
|
|
251
251
|
return allFields.filter(f => selected.has(f.Name.toLowerCase()) || f.IsPrimaryKey === true);
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
/** @deprecated Use {@link SelectFieldsToMap}. */
|
|
255
|
+
export function selectFieldsToMap<T extends SelectableSourceField>(
|
|
256
|
+
allFields: readonly T[],
|
|
257
|
+
selectedFieldNames: readonly string[] | null | undefined,
|
|
258
|
+
): T[] {
|
|
259
|
+
return SelectFieldsToMap(allFields, selectedFieldNames);
|
|
260
|
+
}
|
|
261
|
+
|
|
254
262
|
/** One existing field map, reduced to what the reconciliation decision needs. */
|
|
255
263
|
export interface ExistingFieldMapRead {
|
|
256
264
|
SourceFieldName: string | null;
|
|
@@ -289,7 +297,7 @@ export interface FieldMapReconcilePlan {
|
|
|
289
297
|
* stopped reporting the column, so it returns to the state it had.
|
|
290
298
|
* - **Vanished column → `Inactive`, never deleted.** Retiring is reversible by the branch above.
|
|
291
299
|
*/
|
|
292
|
-
export function
|
|
300
|
+
export function DecideFieldMapReconcile(
|
|
293
301
|
activeFieldNames: readonly string[],
|
|
294
302
|
existing: readonly ExistingFieldMapRead[],
|
|
295
303
|
mapEnabled: boolean,
|
|
@@ -320,3 +328,13 @@ export function decideFieldMapReconcile(
|
|
|
320
328
|
}
|
|
321
329
|
return plan;
|
|
322
330
|
}
|
|
331
|
+
|
|
332
|
+
/** @deprecated Use {@link DecideFieldMapReconcile}. */
|
|
333
|
+
export function decideFieldMapReconcile(
|
|
334
|
+
activeFieldNames: readonly string[],
|
|
335
|
+
existing: readonly ExistingFieldMapRead[],
|
|
336
|
+
mapEnabled: boolean,
|
|
337
|
+
autoEnableNewColumns = true,
|
|
338
|
+
): FieldMapReconcilePlan {
|
|
339
|
+
return DecideFieldMapReconcile(activeFieldNames, existing, mapEnabled, autoEnableNewColumns);
|
|
340
|
+
}
|
package/src/logging/NoLog.ts
CHANGED
|
@@ -64,7 +64,7 @@ export function NoLog(target: object, propertyKey?: string | symbol, parameterIn
|
|
|
64
64
|
* Pass the resolver class itself (e.g. `MyResolver`) — the function reads from the
|
|
65
65
|
* prototype internally to match how type-graphql stores resolver metadata.
|
|
66
66
|
*/
|
|
67
|
-
export function
|
|
67
|
+
export function HasNoLogParameter(
|
|
68
68
|
resolverClass: Function,
|
|
69
69
|
methodName: string,
|
|
70
70
|
parameterIndex: number,
|
|
@@ -74,6 +74,15 @@ export function hasNoLogParameter(
|
|
|
74
74
|
return marks !== undefined && marks.has(parameterIndex);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/** @deprecated Use {@link HasNoLogParameter}. */
|
|
78
|
+
export function hasNoLogParameter(
|
|
79
|
+
resolverClass: Function,
|
|
80
|
+
methodName: string,
|
|
81
|
+
parameterIndex: number,
|
|
82
|
+
): boolean {
|
|
83
|
+
return HasNoLogParameter(resolverClass, methodName, parameterIndex);
|
|
84
|
+
}
|
|
85
|
+
|
|
77
86
|
/**
|
|
78
87
|
* Returns the set of field names decorated `@NoLog` on the given input class. Empty set
|
|
79
88
|
* if none were marked.
|
|
@@ -81,8 +90,13 @@ export function hasNoLogParameter(
|
|
|
81
90
|
* Pass the input class itself (e.g. `GetDataInputType`) — the function reads from the
|
|
82
91
|
* prototype internally.
|
|
83
92
|
*/
|
|
84
|
-
export function
|
|
93
|
+
export function GetNoLogFields(inputTypeClass: Function): ReadonlySet<string> {
|
|
85
94
|
const target = inputTypeClass.prototype as object;
|
|
86
95
|
const marks = Reflect.getMetadata(NO_LOG_FIELD_KEY, target) as Set<string> | undefined;
|
|
87
96
|
return marks ?? new Set<string>();
|
|
88
97
|
}
|
|
98
|
+
|
|
99
|
+
/** @deprecated Use {@link GetNoLogFields}. */
|
|
100
|
+
export function getNoLogFields(inputTypeClass: Function): ReadonlySet<string> {
|
|
101
|
+
return GetNoLogFields(inputTypeClass);
|
|
102
|
+
}
|
|
@@ -117,7 +117,7 @@ export class StartupLogger {
|
|
|
117
117
|
* operator knob governs both telemetry and server logging. Defaults to
|
|
118
118
|
* `standard` when unset or unrecognized.
|
|
119
119
|
*/
|
|
120
|
-
public static
|
|
120
|
+
public static ResolveLevelFromConfig(): ServerLogLevel {
|
|
121
121
|
const raw = configInfo.telemetry?.level;
|
|
122
122
|
if (raw === 'minimal' || raw === 'standard' || raw === 'verbose' || raw === 'debug') {
|
|
123
123
|
return raw;
|
|
@@ -125,6 +125,11 @@ export class StartupLogger {
|
|
|
125
125
|
return 'standard';
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
/** @deprecated Use {@link ResolveLevelFromConfig}. */
|
|
129
|
+
public static resolveLevelFromConfig(): ServerLogLevel {
|
|
130
|
+
return this.ResolveLevelFromConfig();
|
|
131
|
+
}
|
|
132
|
+
|
|
128
133
|
/**
|
|
129
134
|
* True when the active level is at least `minLevel` (using the ascending
|
|
130
135
|
* `minimal < standard < verbose < debug` ordering).
|
package/src/logging/bootAudit.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getMetadataStorage } from 'type-graphql';
|
|
2
2
|
import { configInfo } from '../config.js';
|
|
3
|
-
import {
|
|
3
|
+
import { HasNoLogParameter } from './NoLog.js';
|
|
4
4
|
|
|
5
5
|
// Delete is included alongside Create/Update so codegen DeleteMJ*Input resolvers count as
|
|
6
6
|
// metadata-bound and don't flood the audit with false positives (their args are PK + Options
|
|
@@ -13,12 +13,12 @@ const INPUT_TYPE_REGEX = /^(Create|Update|Delete).+Input$/;
|
|
|
13
13
|
* Used by the audit walker. Mirrors the subset of `ArgParamMetadata` we need.
|
|
14
14
|
*/
|
|
15
15
|
export type AuditArgParam = {
|
|
16
|
-
kind: 'arg';
|
|
17
|
-
|
|
18
|
-
name: string;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
kind: 'arg'; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined
|
|
17
|
+
Index: number;
|
|
18
|
+
name: string; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined
|
|
19
|
+
Target: Function;
|
|
20
|
+
MethodName: string;
|
|
21
|
+
GetType: () => unknown;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
/**
|
|
@@ -26,9 +26,9 @@ export type AuditArgParam = {
|
|
|
26
26
|
* Includes `@Query`, `@Mutation`, `@Subscription` entries.
|
|
27
27
|
*/
|
|
28
28
|
export type AuditResolver = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
params?: ReadonlyArray<{ kind: string;
|
|
29
|
+
Target: Function;
|
|
30
|
+
MethodName: string;
|
|
31
|
+
params?: ReadonlyArray<{ kind: string; Index: number } & Partial<AuditArgParam>>; // case-violation-ok-legacy-back-compat: optional, and the old name is also read off a value the checker cannot type; renaming it stays assignable and silently yields undefined
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -42,7 +42,7 @@ export type AuditResolver = {
|
|
|
42
42
|
*
|
|
43
43
|
* Never throws. Boot does not fail on a missed `@NoLog`.
|
|
44
44
|
*/
|
|
45
|
-
export function
|
|
45
|
+
export function AuditResolversForUndecoratedArgs(): void {
|
|
46
46
|
if (!configInfo.loggingSettings.graphql.logVariables) {
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
@@ -52,24 +52,34 @@ export function auditResolversForUndecoratedArgs(): void {
|
|
|
52
52
|
mutations: AuditResolver[];
|
|
53
53
|
subscriptions: AuditResolver[];
|
|
54
54
|
};
|
|
55
|
-
|
|
55
|
+
AuditResolverList([
|
|
56
56
|
...storage.queries,
|
|
57
57
|
...storage.mutations,
|
|
58
58
|
...storage.subscriptions,
|
|
59
59
|
]);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
/** @deprecated Use {@link AuditResolversForUndecoratedArgs}. */
|
|
63
|
+
export function auditResolversForUndecoratedArgs(): void {
|
|
64
|
+
return AuditResolversForUndecoratedArgs();
|
|
65
|
+
}
|
|
66
|
+
|
|
62
67
|
/**
|
|
63
68
|
* Internal helper exported for test injection. Takes a list of resolver metadata directly,
|
|
64
69
|
* skipping the global `getMetadataStorage()` lookup. The boot-time scan uses this after
|
|
65
70
|
* pulling from the global storage; tests pass in a synthetic fixture.
|
|
66
71
|
*/
|
|
67
|
-
export function
|
|
72
|
+
export function AuditResolverList(resolvers: ReadonlyArray<AuditResolver>): void {
|
|
68
73
|
for (const resolver of resolvers) {
|
|
69
74
|
auditResolver(resolver);
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
|
|
78
|
+
/** @deprecated Use {@link AuditResolverList}. */
|
|
79
|
+
export function auditResolverList(resolvers: ReadonlyArray<AuditResolver>): void {
|
|
80
|
+
return AuditResolverList(resolvers);
|
|
81
|
+
}
|
|
82
|
+
|
|
73
83
|
function auditResolver(resolver: AuditResolver): void {
|
|
74
84
|
for (const param of resolver.params ?? []) {
|
|
75
85
|
if (param.kind !== 'arg') {
|
|
@@ -84,10 +94,10 @@ function auditArg(resolver: AuditResolver, argParam: AuditArgParam): void {
|
|
|
84
94
|
if (typeName && INPUT_TYPE_REGEX.test(typeName)) {
|
|
85
95
|
return;
|
|
86
96
|
}
|
|
87
|
-
if (
|
|
97
|
+
if (HasNoLogParameter(resolver.Target, resolver.MethodName, argParam.Index)) {
|
|
88
98
|
return;
|
|
89
99
|
}
|
|
90
|
-
const resolverName = `${resolver.
|
|
100
|
+
const resolverName = `${resolver.Target.name}.${resolver.MethodName}`;
|
|
91
101
|
console.warn(
|
|
92
102
|
`[mj:NoLog audit] Custom resolver ${resolverName} takes argument '${argParam.name}' ` +
|
|
93
103
|
`(type ${typeName ?? 'unknown'}) which is not marked @NoLog. Verify this argument does ` +
|
|
@@ -103,7 +113,7 @@ function auditArg(resolver: AuditResolver, argParam: AuditArgParam): void {
|
|
|
103
113
|
*/
|
|
104
114
|
function readArgTypeName(argParam: AuditArgParam): string | undefined {
|
|
105
115
|
try {
|
|
106
|
-
const type = argParam.
|
|
116
|
+
const type = argParam.GetType();
|
|
107
117
|
if (typeof type === 'function') {
|
|
108
118
|
return (type as { name?: string }).name;
|
|
109
119
|
}
|
|
@@ -12,8 +12,15 @@
|
|
|
12
12
|
*
|
|
13
13
|
* See docs/adr/0001-graphql-variables-logging-tiered-by-verbose.md.
|
|
14
14
|
*/
|
|
15
|
-
export function
|
|
15
|
+
export function BuildBoundaryLogPayload(
|
|
16
16
|
operationName: string | undefined,
|
|
17
17
|
): { operationName: string | undefined } {
|
|
18
18
|
return { operationName };
|
|
19
19
|
}
|
|
20
|
+
|
|
21
|
+
/** @deprecated Use {@link BuildBoundaryLogPayload}. */
|
|
22
|
+
export function buildBoundaryLogPayload(
|
|
23
|
+
operationName: string | undefined,
|
|
24
|
+
): { operationName: string | undefined } {
|
|
25
|
+
return BuildBoundaryLogPayload(operationName);
|
|
26
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IMetadataProvider } from '@memberjunction/core';
|
|
2
|
-
import {
|
|
2
|
+
import { ShortenForLog } from './shortenForLog.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Input to the redactor. Built per `@Arg` per resolver call by the variables-logging middleware.
|
|
@@ -15,11 +15,11 @@ import { shortenForLog } from './shortenForLog.js';
|
|
|
15
15
|
* this set (decorator-driven) when walking top-level keys.
|
|
16
16
|
*/
|
|
17
17
|
export type RedactionContext = {
|
|
18
|
-
inputTypeName: string;
|
|
19
|
-
rawValue: unknown;
|
|
20
|
-
provider: IMetadataProvider;
|
|
21
|
-
noLogParameter: boolean;
|
|
22
|
-
noLogFields: ReadonlySet<string>;
|
|
18
|
+
inputTypeName: string; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
|
|
19
|
+
rawValue: unknown; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
|
|
20
|
+
provider: IMetadataProvider; // case-violation-ok-legacy-back-compat: the old name is also read off a value typed `any`, where a rename would compile and silently return undefined
|
|
21
|
+
noLogParameter: boolean; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
|
|
22
|
+
noLogFields: ReadonlySet<string>; // case-violation-ok-legacy-back-compat: renaming it broke a use the checker could not see from the declaration — the compile proved it
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
// Delete is included so DeleteMJ*Input resolvers resolve to their entity (yielding an empty
|
|
@@ -33,7 +33,7 @@ const INPUT_TYPE_REGEX = /^(Create|Update|Delete)(?<name>.+)Input$/;
|
|
|
33
33
|
// type-graphql allows @Field({ name: 'overrideName' }) to rename fields at the
|
|
34
34
|
// GraphQL layer; MJ codegen does not use this. A future maintainer renaming an
|
|
35
35
|
// encrypted field at the GraphQL layer would silently miss redaction.
|
|
36
|
-
export function
|
|
36
|
+
export function RedactArg(ctx: RedactionContext): unknown {
|
|
37
37
|
if (ctx.noLogParameter) {
|
|
38
38
|
return '<redacted>';
|
|
39
39
|
}
|
|
@@ -79,7 +79,7 @@ export function redactArg(ctx: RedactionContext): unknown {
|
|
|
79
79
|
!Array.isArray(ctx.rawValue);
|
|
80
80
|
|
|
81
81
|
if (!canWalk) {
|
|
82
|
-
return
|
|
82
|
+
return ShortenForLog(ctx.rawValue);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
const result: Record<string, unknown> = {};
|
|
@@ -87,12 +87,17 @@ export function redactArg(ctx: RedactionContext): unknown {
|
|
|
87
87
|
if (encryptedFieldNames.has(key) || ctx.noLogFields.has(key)) {
|
|
88
88
|
result[key] = '<redacted>';
|
|
89
89
|
} else {
|
|
90
|
-
result[key] =
|
|
90
|
+
result[key] = ShortenForLog(value);
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
return result;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
/** @deprecated Use {@link RedactArg}. */
|
|
97
|
+
export function redactArg(ctx: RedactionContext): unknown {
|
|
98
|
+
return RedactArg(ctx);
|
|
99
|
+
}
|
|
100
|
+
|
|
96
101
|
const EMPTY_SET: ReadonlySet<string> = new Set<string>();
|
|
97
102
|
|
|
98
103
|
/**
|
|
@@ -4,14 +4,19 @@
|
|
|
4
4
|
* Objects whose JSON exceeds `maxLen` and contain nested structure are recursed into so
|
|
5
5
|
* outer keys remain visible.
|
|
6
6
|
*/
|
|
7
|
-
export function
|
|
7
|
+
export function ShortenForLog(value: unknown, maxLen = 300): unknown {
|
|
8
8
|
if (value === null || typeof value !== 'object') return value;
|
|
9
|
-
if (Array.isArray(value)) return value.map((v) =>
|
|
9
|
+
if (Array.isArray(value)) return value.map((v) => ShortenForLog(v, maxLen));
|
|
10
10
|
const json = JSON.stringify(value);
|
|
11
11
|
if (json.length <= maxLen) return json;
|
|
12
12
|
const result: Record<string, unknown> = {};
|
|
13
13
|
for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
|
|
14
|
-
result[k] =
|
|
14
|
+
result[k] = ShortenForLog(v, maxLen);
|
|
15
15
|
}
|
|
16
16
|
return result;
|
|
17
17
|
}
|
|
18
|
+
|
|
19
|
+
/** @deprecated Use {@link ShortenForLog}. */
|
|
20
|
+
export function shortenForLog(value: unknown, maxLen = 300): unknown {
|
|
21
|
+
return ShortenForLog(value, maxLen);
|
|
22
|
+
}
|
|
@@ -4,8 +4,8 @@ import { getNamedType } from 'graphql';
|
|
|
4
4
|
import type { GraphQLArgument } from 'graphql';
|
|
5
5
|
import { configInfo } from '../config.js';
|
|
6
6
|
import type { AppContext } from '../types.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { RedactArg } from './secretRedactor.js';
|
|
8
|
+
import { HasNoLogParameter, GetNoLogFields } from './NoLog.js';
|
|
9
9
|
import { StartupLogger } from './StartupLogger.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -112,7 +112,7 @@ const warnedResolverSignatures = new Set<string>();
|
|
|
112
112
|
* differ from the always-on log line (`operationName` vs `operation`, `variables` vs `args`)
|
|
113
113
|
* — operators with log-grep automation should update their patterns.
|
|
114
114
|
*/
|
|
115
|
-
export const
|
|
115
|
+
export const VariablesLoggingMiddleware: MiddlewareFn<AppContext> = async (action, next) => {
|
|
116
116
|
// Field resolvers (info.path.prev !== undefined) are skipped — only root @Query/@Mutation/@Subscription.
|
|
117
117
|
if (action.info.path.prev !== undefined) {
|
|
118
118
|
return next();
|
|
@@ -144,13 +144,13 @@ export const variablesLoggingMiddleware: MiddlewareFn<AppContext> = async (actio
|
|
|
144
144
|
|
|
145
145
|
const paramMeta = argParams.find((p) => p.name === argDef.name);
|
|
146
146
|
const noLogParameter = paramMeta && resolverEntry
|
|
147
|
-
?
|
|
147
|
+
? HasNoLogParameter(resolverEntry.target, resolverEntry.methodName, paramMeta.index)
|
|
148
148
|
: false;
|
|
149
149
|
|
|
150
150
|
const inputClass = findInputClass(inputTypeName);
|
|
151
|
-
const noLogFields = inputClass ?
|
|
151
|
+
const noLogFields = inputClass ? GetNoLogFields(inputClass) : new Set<string>();
|
|
152
152
|
|
|
153
|
-
redactedArgs[argDef.name] =
|
|
153
|
+
redactedArgs[argDef.name] = RedactArg({
|
|
154
154
|
inputTypeName,
|
|
155
155
|
rawValue,
|
|
156
156
|
provider,
|
|
@@ -188,6 +188,9 @@ export const variablesLoggingMiddleware: MiddlewareFn<AppContext> = async (actio
|
|
|
188
188
|
return next();
|
|
189
189
|
};
|
|
190
190
|
|
|
191
|
+
/** @deprecated Use {@link VariablesLoggingMiddleware}. */
|
|
192
|
+
export const variablesLoggingMiddleware: MiddlewareFn<AppContext> = VariablesLoggingMiddleware;
|
|
193
|
+
|
|
191
194
|
/**
|
|
192
195
|
* Heuristic: an arg is "custom" (i.e. needs `@NoLog` discipline because metadata can't redact it)
|
|
193
196
|
* when its GraphQL input type is not a known `Create<X>Input` / `Update<X>Input` for an entity
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { LogError, LogStatus } from '@memberjunction/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Operator control: `kill -HUP <pid>` (or `docker kill -s HUP`, `pm2 sendSignal SIGHUP`) makes a
|
|
5
|
+
* running MJAPI hard-reload its metadata from the database, without a restart and without a
|
|
6
|
+
* user-facing endpoint. SIGHUP is the conventional "reload" signal; SIGUSR1 is reserved by Node
|
|
7
|
+
* for the inspector.
|
|
8
|
+
*
|
|
9
|
+
* Only the global provider needs refreshing: per-request providers adopt the global provider's
|
|
10
|
+
* metadata on every request (ProviderBase.CopyMetadataFromGlobalProvider).
|
|
11
|
+
*/
|
|
12
|
+
export const METADATA_REFRESH_SIGNAL = 'SIGHUP';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Builds the signal handler. A signal that arrives while a refresh is still running is ignored
|
|
16
|
+
* (and logged) rather than stacked, so a burst of signals cannot queue a burst of full reloads.
|
|
17
|
+
* The handler never rejects — a failed refresh is logged.
|
|
18
|
+
*
|
|
19
|
+
* @param refresh - performs the hard reload, e.g. `() => Metadata.Provider.Refresh()`
|
|
20
|
+
*/
|
|
21
|
+
export function CreateMetadataRefreshSignalHandler(refresh: () => Promise<boolean>): () => Promise<void> {
|
|
22
|
+
let inFlight = false;
|
|
23
|
+
|
|
24
|
+
return async () => {
|
|
25
|
+
if (inFlight) {
|
|
26
|
+
LogStatus(`🔄 ${METADATA_REFRESH_SIGNAL} received while a metadata refresh is already running; ignored. Send it again once the current refresh finishes.`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
inFlight = true;
|
|
31
|
+
LogStatus(`🔄 ${METADATA_REFRESH_SIGNAL} received, refreshing metadata from the database`);
|
|
32
|
+
try {
|
|
33
|
+
const ok = await refresh();
|
|
34
|
+
if (ok) {
|
|
35
|
+
LogStatus('✅ Metadata refreshed');
|
|
36
|
+
} else {
|
|
37
|
+
LogError(`❌ ${METADATA_REFRESH_SIGNAL} metadata refresh reported failure`);
|
|
38
|
+
}
|
|
39
|
+
} catch (err) {
|
|
40
|
+
LogError(`❌ ${METADATA_REFRESH_SIGNAL} metadata refresh failed`, undefined, err);
|
|
41
|
+
} finally {
|
|
42
|
+
inFlight = false;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { RegisterClass } from '@memberjunction/global';
|
|
11
11
|
import { BaseServerMiddleware } from './BaseServerMiddleware.js';
|
|
12
12
|
import { configInfo } from '../config.js';
|
|
13
|
-
import {
|
|
13
|
+
import { CreateTenantMiddleware, CreateTenantPreRunViewHook, CreateTenantPreSaveHook } from '../multiTenancy/index.js';
|
|
14
14
|
import type { RequestHandler } from 'express';
|
|
15
15
|
import type { RunViewParams, UserInfo, BaseEntity } from '@memberjunction/core';
|
|
16
16
|
|
|
@@ -26,14 +26,14 @@ export class MJTenantFilterMiddleware extends BaseServerMiddleware {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
GetPostAuthMiddleware(): RequestHandler[] {
|
|
29
|
-
return [
|
|
29
|
+
return [CreateTenantMiddleware(configInfo.multiTenancy!)];
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
PreRunView(params: RunViewParams, contextUser: UserInfo | undefined): RunViewParams | Promise<RunViewParams> {
|
|
33
|
-
return
|
|
33
|
+
return CreateTenantPreRunViewHook(configInfo.multiTenancy!)(params, contextUser);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
PreSave(entity: BaseEntity, contextUser: UserInfo | undefined): boolean | string | Promise<boolean | string> {
|
|
37
|
-
return
|
|
37
|
+
return CreateTenantPreSaveHook(configInfo.multiTenancy!)(entity, contextUser);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -48,7 +48,7 @@ export type TenantContextExtractor = (
|
|
|
48
48
|
* By the time GraphQL resolvers or REST handlers run, the contextUser already
|
|
49
49
|
* has TenantContext set — no deferred pickup via `req['__mj_tenantId']` needed.
|
|
50
50
|
*/
|
|
51
|
-
export function
|
|
51
|
+
export function CreateTenantMiddleware(config: MultiTenancyConfig): RequestHandler {
|
|
52
52
|
return (req, res, next) => {
|
|
53
53
|
const userPayload = (req as { userPayload?: UserPayload }).userPayload;
|
|
54
54
|
if (!userPayload?.userRecord) {
|
|
@@ -79,7 +79,7 @@ export function createTenantMiddleware(config: MultiTenancyConfig): RequestHandl
|
|
|
79
79
|
// instance, and stamping it in place races concurrent requests for the
|
|
80
80
|
// same user (one request's tenant becomes another's, same-instant).
|
|
81
81
|
const sessionUser = CloneUserForSessionContext(userPayload.userRecord as UserInfo);
|
|
82
|
-
|
|
82
|
+
AttachTenantContext(sessionUser, tenantId, 'header');
|
|
83
83
|
userPayload.userRecord = sessionUser;
|
|
84
84
|
}
|
|
85
85
|
}
|
|
@@ -87,6 +87,11 @@ export function createTenantMiddleware(config: MultiTenancyConfig): RequestHandl
|
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
/** @deprecated Use {@link CreateTenantMiddleware}. */
|
|
91
|
+
export function createTenantMiddleware(config: MultiTenancyConfig): RequestHandler {
|
|
92
|
+
return CreateTenantMiddleware(config);
|
|
93
|
+
}
|
|
94
|
+
|
|
90
95
|
/**
|
|
91
96
|
* Attaches TenantContext to a UserInfo object.
|
|
92
97
|
* Called from the GraphQL context function after authentication.
|
|
@@ -98,7 +103,7 @@ export function createTenantMiddleware(config: MultiTenancyConfig): RequestHandl
|
|
|
98
103
|
* so a future caller from a different source ('linkedEntity', 'custom') cannot
|
|
99
104
|
* reintroduce the injection path.
|
|
100
105
|
*/
|
|
101
|
-
export function
|
|
106
|
+
export function AttachTenantContext(
|
|
102
107
|
user: UserInfo,
|
|
103
108
|
tenantId: string,
|
|
104
109
|
source: TenantContext['Source']
|
|
@@ -109,6 +114,15 @@ export function attachTenantContext(
|
|
|
109
114
|
user.TenantContext = { TenantID: tenantId, Source: source };
|
|
110
115
|
}
|
|
111
116
|
|
|
117
|
+
/** @deprecated Use {@link AttachTenantContext}. */
|
|
118
|
+
export function attachTenantContext(
|
|
119
|
+
user: UserInfo,
|
|
120
|
+
tenantId: string,
|
|
121
|
+
source: TenantContext['Source']
|
|
122
|
+
): void {
|
|
123
|
+
return AttachTenantContext(user, tenantId, source);
|
|
124
|
+
}
|
|
125
|
+
|
|
112
126
|
/**
|
|
113
127
|
* Determines whether a given entity name should have tenant filtering applied.
|
|
114
128
|
*/
|
|
@@ -151,7 +165,7 @@ function isAdminUser(user: UserInfo, adminRoles: string[]): boolean {
|
|
|
151
165
|
* Creates a PreRunViewHook that auto-injects tenant WHERE clauses
|
|
152
166
|
* into RunView queries for scoped entities.
|
|
153
167
|
*/
|
|
154
|
-
export function
|
|
168
|
+
export function CreateTenantPreRunViewHook(config: MultiTenancyConfig): PreRunViewHook {
|
|
155
169
|
return (params, contextUser) => {
|
|
156
170
|
// No tenant context → no filtering
|
|
157
171
|
if (!contextUser?.TenantContext) return params;
|
|
@@ -201,6 +215,11 @@ export function createTenantPreRunViewHook(config: MultiTenancyConfig): PreRunVi
|
|
|
201
215
|
};
|
|
202
216
|
}
|
|
203
217
|
|
|
218
|
+
/** @deprecated Use {@link CreateTenantPreRunViewHook}. */
|
|
219
|
+
export function createTenantPreRunViewHook(config: MultiTenancyConfig): PreRunViewHook {
|
|
220
|
+
return CreateTenantPreRunViewHook(config);
|
|
221
|
+
}
|
|
222
|
+
|
|
204
223
|
/**
|
|
205
224
|
* Quotes an identifier for use in a tenant predicate via the active provider's
|
|
206
225
|
* QuoteIdentifier (DatabaseProviderBase always exposes one server-side, yielding [x]
|
|
@@ -227,7 +246,7 @@ export function QuoteFilterIdentifier(name: string): string {
|
|
|
227
246
|
* match the user's TenantContext. In 'log' mode, warns but allows. In
|
|
228
247
|
* 'off' mode, this hook is a no-op.
|
|
229
248
|
*/
|
|
230
|
-
export function
|
|
249
|
+
export function CreateTenantPreSaveHook(config: MultiTenancyConfig): PreSaveHook {
|
|
231
250
|
return (entity, contextUser) => {
|
|
232
251
|
// No validation needed if write protection is off
|
|
233
252
|
if (config.writeProtection === 'off') return true;
|
|
@@ -268,3 +287,8 @@ export function createTenantPreSaveHook(config: MultiTenancyConfig): PreSaveHook
|
|
|
268
287
|
return true;
|
|
269
288
|
};
|
|
270
289
|
}
|
|
290
|
+
|
|
291
|
+
/** @deprecated Use {@link CreateTenantPreSaveHook}. */
|
|
292
|
+
export function createTenantPreSaveHook(config: MultiTenancyConfig): PreSaveHook {
|
|
293
|
+
return CreateTenantPreSaveHook(config);
|
|
294
|
+
}
|
|
@@ -15,9 +15,9 @@ import { rateLimit, ipKeyGenerator } from 'express-rate-limit';
|
|
|
15
15
|
import { LogStatus } from '@memberjunction/core';
|
|
16
16
|
import { configInfo, type WidgetConfig } from '../config.js';
|
|
17
17
|
import { MagicLinkKeyManager } from '../auth/magicLink/MagicLinkKeys.js';
|
|
18
|
-
import {
|
|
18
|
+
import { RegisterMagicLinkAuthProvider } from '../auth/magicLink/MagicLinkRouter.js';
|
|
19
19
|
import { WidgetSessionService, type MintGuestSessionResult } from './WidgetSessionService.js';
|
|
20
|
-
import {
|
|
20
|
+
import { LooksLikeBot } from './widgetCore.js';
|
|
21
21
|
|
|
22
22
|
/** The mount path for the widget public router (`/widget`). */
|
|
23
23
|
export const WIDGET_MOUNT_PATH = '/widget';
|
|
@@ -41,7 +41,7 @@ function ensureWidgetSigning(publicUrl: string, widgetConfig: WidgetConfig): voi
|
|
|
41
41
|
// Register the magic-link provider against the magic-link config (its audience),
|
|
42
42
|
// which is what validates widget tokens. No-op if already registered.
|
|
43
43
|
if (mlConfig) {
|
|
44
|
-
|
|
44
|
+
RegisterMagicLinkAuthProvider(publicUrl, mlConfig);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -51,7 +51,7 @@ function ensureWidgetSigning(publicUrl: string, widgetConfig: WidgetConfig): voi
|
|
|
51
51
|
* `authenticatedRouter` at the same path AFTER it (the RV4 resolve-identity endpoint needs the
|
|
52
52
|
* verified principal from `req.userPayload`).
|
|
53
53
|
*/
|
|
54
|
-
export function
|
|
54
|
+
export function CreateWidgetHandler(publicUrl: string, config: WidgetConfig): { publicRouter: Router; authenticatedRouter: Router } {
|
|
55
55
|
ensureWidgetSigning(publicUrl, config);
|
|
56
56
|
|
|
57
57
|
const service = new WidgetSessionService(publicUrl, config);
|
|
@@ -106,6 +106,11 @@ export function createWidgetHandler(publicUrl: string, config: WidgetConfig): {
|
|
|
106
106
|
return { publicRouter, authenticatedRouter };
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
/** @deprecated Use {@link CreateWidgetHandler}. */
|
|
110
|
+
export function createWidgetHandler(publicUrl: string, config: WidgetConfig): { publicRouter: Router; authenticatedRouter: Router } {
|
|
111
|
+
return CreateWidgetHandler(publicUrl, config);
|
|
112
|
+
}
|
|
113
|
+
|
|
109
114
|
/** Reads the `widgetKey` from a parsed JSON body, or '' when absent (used to key the dynamic limiter). */
|
|
110
115
|
function readWidgetKey(req: Request): string {
|
|
111
116
|
const body = (req.body ?? {}) as { widgetKey?: string };
|
|
@@ -121,7 +126,7 @@ async function handleForget(service: WidgetSessionService, req: Request, res: Re
|
|
|
121
126
|
res.status(400).json({ success: false, errorCode: 'not_found', error: 'widgetKey is required.' });
|
|
122
127
|
return;
|
|
123
128
|
}
|
|
124
|
-
const result = await service.ForgetVisitor({ widgetKey, visitorKey, origin: req.get('origin') ?? undefined });
|
|
129
|
+
const result = await service.ForgetVisitor({ WidgetKey: widgetKey, VisitorKey: visitorKey, origin: req.get('origin') ?? undefined });
|
|
125
130
|
res.status(result.success ? 200 : result.errorCode === 'server_error' ? 500 : 403).json(result);
|
|
126
131
|
}
|
|
127
132
|
|
|
@@ -143,9 +148,9 @@ async function handleResolveIdentity(service: WidgetSessionService, req: Request
|
|
|
143
148
|
return;
|
|
144
149
|
}
|
|
145
150
|
const result = await service.ResolveVisitorIdentity({
|
|
146
|
-
widgetKey,
|
|
147
|
-
visitorKey,
|
|
148
|
-
|
|
151
|
+
WidgetKey: widgetKey,
|
|
152
|
+
VisitorKey: visitorKey,
|
|
153
|
+
VerifiedEmail: verifiedUser.Email,
|
|
149
154
|
origin: req.get('origin') ?? undefined,
|
|
150
155
|
});
|
|
151
156
|
res.status(result.success ? 200 : result.errorCode === 'server_error' ? 500 : 403).json(result);
|
|
@@ -160,7 +165,7 @@ async function handleUpgrade(service: WidgetSessionService, req: Request, res: R
|
|
|
160
165
|
res.status(400).json({ success: false, errorCode: 'not_found', error: 'widgetKey is required.' });
|
|
161
166
|
return;
|
|
162
167
|
}
|
|
163
|
-
const result = await service.RequestUpgrade({ widgetKey, email, origin: req.get('origin') ?? undefined });
|
|
168
|
+
const result = await service.RequestUpgrade({ WidgetKey: widgetKey, email, origin: req.get('origin') ?? undefined });
|
|
164
169
|
// 400 for a bad email (client can fix it); 403 for any policy rejection (uniform, non-enumerable); 500 for faults.
|
|
165
170
|
const status = result.success ? 200 : result.errorCode === 'invalid_email' ? 400 : result.errorCode === 'server_error' ? 500 : 403;
|
|
166
171
|
res.status(status).json(result);
|
|
@@ -177,7 +182,7 @@ async function handleMint(service: WidgetSessionService, req: Request, res: Resp
|
|
|
177
182
|
|
|
178
183
|
// W6 hardening: coarse bot/automation rejection before any DB lookup or token mint. Returns the same
|
|
179
184
|
// 403 as a policy rejection so a probe can't distinguish "bot-blocked" from "bad key/origin".
|
|
180
|
-
if (
|
|
185
|
+
if (LooksLikeBot(req.get('user-agent'))) {
|
|
181
186
|
res.status(403).json({ success: false, errorCode: 'origin_not_allowed', error: 'Widget mint rejected.' });
|
|
182
187
|
return;
|
|
183
188
|
}
|