@memberjunction/server 6.2.0-edge.0 → 6.2.0-edge.2
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/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 +346 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +34 -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 +1021 -0
- package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
- package/dist/generated/graphql-schemas/__mj.js +7368 -2145
- package/dist/generated/graphql-schemas/__mj.js.map +1 -1
- package/dist/generic/CacheInvalidationResolver.d.ts +94 -4
- package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
- package/dist/generic/CacheInvalidationResolver.js +122 -3
- package/dist/generic/CacheInvalidationResolver.js.map +1 -1
- package/dist/generic/DeleteOptionsInput.d.ts +8 -1
- package/dist/generic/DeleteOptionsInput.d.ts.map +1 -1
- package/dist/generic/DeleteOptionsInput.js +1 -1
- package/dist/generic/DeleteOptionsInput.js.map +1 -1
- package/dist/generic/FireAndForgetHeartbeat.d.ts +18 -2
- package/dist/generic/FireAndForgetHeartbeat.d.ts.map +1 -1
- package/dist/generic/FireAndForgetHeartbeat.js +24 -6
- package/dist/generic/FireAndForgetHeartbeat.js.map +1 -1
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts +31 -0
- package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -0
- package/dist/generic/OrphanedConversationDetailReconciler.js +215 -0
- package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -0
- package/dist/generic/PushStatusResolver.d.ts +48 -1
- package/dist/generic/PushStatusResolver.d.ts.map +1 -1
- package/dist/generic/PushStatusResolver.js +95 -4
- package/dist/generic/PushStatusResolver.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +18 -2
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +64 -55
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +120 -11
- 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/AgentRunStatusPublisher.d.ts +55 -0
- package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -0
- package/dist/resolvers/AgentRunStatusPublisher.js +141 -0
- package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -0
- package/dist/resolvers/ConversationRunEventsResolver.d.ts +90 -0
- package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -0
- package/dist/resolvers/ConversationRunEventsResolver.js +283 -0
- package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -0
- package/dist/resolvers/DuplicateEntryCheckResolver.d.ts +98 -0
- package/dist/resolvers/DuplicateEntryCheckResolver.d.ts.map +1 -0
- package/dist/resolvers/DuplicateEntryCheckResolver.js +227 -0
- package/dist/resolvers/DuplicateEntryCheckResolver.js.map +1 -0
- package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
- package/dist/resolvers/FetchEntityVectorsResolver.js +2 -1
- 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/MergeRecordsResolver.d.ts +7 -0
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +16 -2
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/RealtimeBridgeResolver.js +3 -3
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +44 -6
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +93 -37
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RemoteBrowserActionResolver.js +5 -5
- package/dist/resolvers/RunAIAgentResolver.d.ts +8 -18
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +85 -184
- 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/RunDecisionResolver.d.ts +149 -0
- package/dist/resolvers/RunDecisionResolver.d.ts.map +1 -0
- package/dist/resolvers/RunDecisionResolver.js +396 -0
- package/dist/resolvers/RunDecisionResolver.js.map +1 -0
- package/dist/resolvers/RunTestResolver.js +5 -5
- 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/VectorizeEntityResolver.d.ts +1 -1
- package/dist/resolvers/VectorizeEntityResolver.d.ts.map +1 -1
- package/dist/resolvers/VectorizeEntityResolver.js +14 -10
- package/dist/resolvers/VectorizeEntityResolver.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/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 +6 -0
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +13 -5
- package/dist/util.js.map +1 -1
- package/package.json +94 -92
- package/src/__tests__/AgentRunStatusPublisher.test.ts +175 -0
- package/src/__tests__/DeleteOptionsInput.wireShape.test.ts +62 -0
- package/src/__tests__/DuplicateEntryCheckResolver.test.ts +300 -0
- 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 +216 -2
- package/src/__tests__/RealtimeSdpBrokerHandler.test.ts +6 -6
- package/src/__tests__/RefreshAdoptsNewColumns.test.ts +8 -8
- package/src/__tests__/RemoteBrowserActionRecovery.test.ts +7 -1
- package/src/__tests__/RemoteBrowserAudioStream.test.ts +7 -1
- package/src/__tests__/RemoteBrowserGoalEngine.test.ts +18 -18
- package/src/__tests__/RemoteBrowserSnapshot.test.ts +7 -1
- package/src/__tests__/ResolverBase.clientOldValues.test.ts +52 -0
- package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +398 -0
- package/src/__tests__/RunAIAgentResolver.streaming.test.ts +18 -27
- package/src/__tests__/RunDecisionResolver.test.ts +699 -0
- package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +131 -0
- package/src/__tests__/TaskGraphFrameResolver.test.ts +2 -2
- package/src/__tests__/VectorizeEntityResolver.test.ts +106 -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__/cacheInvalidationRecordData.test.ts +177 -0
- package/src/__tests__/conversationRunEvents.test.ts +399 -0
- 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__/orphanedConversationDetailReconciler.test.ts +283 -0
- package/src/__tests__/principals.test.ts +22 -22
- package/src/__tests__/pushStatusFanOut.test.ts +206 -0
- 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 +4 -3
- 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 +37 -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 +3674 -4
- package/src/generic/CacheInvalidationResolver.ts +148 -4
- package/src/generic/DeleteOptionsInput.ts +9 -2
- package/src/generic/FireAndForgetHeartbeat.ts +35 -16
- package/src/generic/OrphanedConversationDetailReconciler.ts +267 -0
- package/src/generic/PushStatusResolver.ts +118 -8
- package/src/generic/ResolverBase.ts +65 -57
- package/src/generic/RunViewResolver.ts +22 -22
- package/src/generic/__tests__/FireAndForgetHeartbeat.test.ts +7 -7
- package/src/index.ts +137 -11
- 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/AgentRunStatusPublisher.ts +175 -0
- package/src/resolvers/AgentSessionResolver.ts +3 -3
- package/src/resolvers/ColorResolver.ts +6 -6
- package/src/resolvers/ComponentRegistryResolver.ts +36 -36
- package/src/resolvers/ConversationRunEventsResolver.ts +308 -0
- package/src/resolvers/DuplicateEntryCheckResolver.ts +232 -0
- package/src/resolvers/EntityCommunicationsResolver.ts +4 -4
- package/src/resolvers/ExecuteRemoteOperationResolver.ts +9 -9
- package/src/resolvers/FetchEntityVectorsResolver.ts +2 -1
- 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/MergeRecordsResolver.ts +14 -2
- package/src/resolvers/QueryResolver.ts +13 -13
- package/src/resolvers/RealtimeBridgeResolver.ts +3 -3
- package/src/resolvers/RealtimeClientSessionResolver.ts +96 -38
- package/src/resolvers/RemoteBrowserActionResolver.ts +5 -5
- package/src/resolvers/RunAIAgentResolver.ts +134 -239
- package/src/resolvers/RunAIPromptResolver.ts +22 -22
- package/src/resolvers/RunDecisionResolver.ts +435 -0
- package/src/resolvers/RunTemplateResolver.ts +4 -4
- package/src/resolvers/RunTestResolver.ts +25 -25
- package/src/resolvers/SqlLoggingConfigResolver.ts +56 -56
- package/src/resolvers/TaskGraphFrameResolver.ts +37 -28
- package/src/resolvers/TelemetryResolver.ts +79 -79
- package/src/resolvers/VectorizeEntityResolver.ts +16 -11
- package/src/resolvers/__tests__/GetDataResolver.tokens.test.ts +40 -38
- package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +93 -0
- 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/TaskGraphActionRunner.ts +16 -15
- package/src/types.ts +21 -16
- package/src/util.ts +16 -6
|
@@ -13,25 +13,40 @@ import type { MagicLinkJWTClaims, MagicLinkScopeEntry, RedeemErrorCode } from '.
|
|
|
13
13
|
export const MAGIC_LINK_TOKEN_PREFIX = 'mj_ml_';
|
|
14
14
|
|
|
15
15
|
/** Generates a cryptographically random raw magic-link token. */
|
|
16
|
-
export function
|
|
16
|
+
export function GenerateRawToken(): string {
|
|
17
17
|
return MAGIC_LINK_TOKEN_PREFIX + randomBytes(32).toString('hex');
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/** @deprecated Use {@link GenerateRawToken}. */
|
|
21
|
+
export function generateRawToken(): string {
|
|
22
|
+
return GenerateRawToken();
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
/** Generates an opaque per-session id (anonymous-session forensics correlation). */
|
|
21
|
-
export function
|
|
26
|
+
export function GenerateSessionId(): string {
|
|
22
27
|
return randomBytes(16).toString('base64url');
|
|
23
28
|
}
|
|
24
29
|
|
|
30
|
+
/** @deprecated Use {@link GenerateSessionId}. */
|
|
31
|
+
export function generateSessionId(): string {
|
|
32
|
+
return GenerateSessionId();
|
|
33
|
+
}
|
|
34
|
+
|
|
25
35
|
/**
|
|
26
36
|
* SHA-256 hash of a raw token, base64url-encoded — only the hash is ever
|
|
27
37
|
* persisted. base64url (43 chars) is shorter than hex (64 chars), URL-safe, and
|
|
28
38
|
* carries the full 256 bits. Both write (CreateInvite) and read (RedeemInvite)
|
|
29
39
|
* paths call this, so the encoding stays internally consistent.
|
|
30
40
|
*/
|
|
31
|
-
export function
|
|
41
|
+
export function HashToken(rawToken: string): string {
|
|
32
42
|
return createHash('sha256').update(rawToken).digest('base64url');
|
|
33
43
|
}
|
|
34
44
|
|
|
45
|
+
/** @deprecated Use {@link HashToken}. */
|
|
46
|
+
export function hashToken(rawToken: string): string {
|
|
47
|
+
return HashToken(rawToken);
|
|
48
|
+
}
|
|
49
|
+
|
|
35
50
|
/** Minimal shape of an invite needed for redemption eligibility. */
|
|
36
51
|
export interface InviteEvaluationInput {
|
|
37
52
|
Status: string;
|
|
@@ -54,7 +69,7 @@ function normalizeName(name: string): string {
|
|
|
54
69
|
* (including an external user already holding a restricted magic-link session)
|
|
55
70
|
* from minting invites.
|
|
56
71
|
*/
|
|
57
|
-
export function
|
|
72
|
+
export function CanIssueInvites(
|
|
58
73
|
userType: string | null | undefined,
|
|
59
74
|
userRoleNames: readonly string[],
|
|
60
75
|
issuerRoleNames: readonly string[],
|
|
@@ -69,13 +84,22 @@ export function canIssueInvites(
|
|
|
69
84
|
return userRoleNames.some((r) => allowed.has(normalizeName(r)));
|
|
70
85
|
}
|
|
71
86
|
|
|
87
|
+
/** @deprecated Use {@link CanIssueInvites}. */
|
|
88
|
+
export function canIssueInvites(
|
|
89
|
+
userType: string | null | undefined,
|
|
90
|
+
userRoleNames: readonly string[],
|
|
91
|
+
issuerRoleNames: readonly string[],
|
|
92
|
+
): boolean {
|
|
93
|
+
return CanIssueInvites(userType, userRoleNames, issuerRoleNames);
|
|
94
|
+
}
|
|
95
|
+
|
|
72
96
|
/**
|
|
73
97
|
* Pure check for WHAT role an invite may grant. The restricted role is always
|
|
74
98
|
* grantable; any other role must be explicitly listed in `grantableRoleNames`.
|
|
75
99
|
* Applied to every caller (Owners included) so a privileged role can never be
|
|
76
100
|
* attached to an external magic-link user unless the deployment opts in.
|
|
77
101
|
*/
|
|
78
|
-
export function
|
|
102
|
+
export function IsRoleGrantable(
|
|
79
103
|
roleName: string | null | undefined,
|
|
80
104
|
restrictedRoleName: string,
|
|
81
105
|
grantableRoleNames: readonly string[],
|
|
@@ -88,8 +112,17 @@ export function isRoleGrantable(
|
|
|
88
112
|
return allowed.has(target);
|
|
89
113
|
}
|
|
90
114
|
|
|
115
|
+
/** @deprecated Use {@link IsRoleGrantable}. */
|
|
116
|
+
export function isRoleGrantable(
|
|
117
|
+
roleName: string | null | undefined,
|
|
118
|
+
restrictedRoleName: string,
|
|
119
|
+
grantableRoleNames: readonly string[],
|
|
120
|
+
): boolean {
|
|
121
|
+
return IsRoleGrantable(roleName, restrictedRoleName, grantableRoleNames);
|
|
122
|
+
}
|
|
123
|
+
|
|
91
124
|
/** Pure redemption-eligibility check. Returns ok + an error code when not. */
|
|
92
|
-
export function
|
|
125
|
+
export function EvaluateInvite(invite: InviteEvaluationInput, nowMs: number): { ok: boolean; errorCode?: RedeemErrorCode } {
|
|
93
126
|
if (invite.Status === 'Revoked') {
|
|
94
127
|
return { ok: false, errorCode: 'revoked' };
|
|
95
128
|
}
|
|
@@ -106,75 +139,43 @@ export function evaluateInvite(invite: InviteEvaluationInput, nowMs: number): {
|
|
|
106
139
|
return { ok: true };
|
|
107
140
|
}
|
|
108
141
|
|
|
109
|
-
/**
|
|
110
|
-
export
|
|
142
|
+
/** @deprecated Use {@link EvaluateInvite}. */
|
|
143
|
+
export function evaluateInvite(invite: InviteEvaluationInput, nowMs: number): { ok: boolean; errorCode?: RedeemErrorCode } {
|
|
144
|
+
return EvaluateInvite(invite, nowMs);
|
|
145
|
+
}
|
|
111
146
|
|
|
112
|
-
/** SQL Server table identifier — bracket-quoted `[schema].[table]` (word chars only). */
|
|
113
|
-
const QUALIFIED_TABLE_PATTERN = /^\[\w+\]\.\[\w+\]$/;
|
|
114
147
|
/** PostgreSQL table identifier — `schema.table` (word chars only); auto-quoted downstream. */
|
|
115
148
|
const QUALIFIED_TABLE_PATTERN_PG = /^\w+\.\w+$/;
|
|
116
149
|
|
|
117
150
|
/**
|
|
118
|
-
* Builds the atomic compare-and-swap UPDATE that consumes one use of an invite
|
|
119
|
-
* in the given SQL dialect.
|
|
120
|
-
*
|
|
121
|
-
* The WHERE clause re-checks every eligibility condition at the DB level, so the
|
|
122
|
-
* increment and the guard are a single atomic operation: concurrent redemptions
|
|
123
|
-
* of a single-use link race on the row and exactly one matches. This is what
|
|
124
|
-
* actually enforces single-use — the JS-side `evaluateInvite` is only a friendly
|
|
125
|
-
* pre-check. The matched row's ID is returned to the caller (via `OUTPUT` on SQL
|
|
126
|
-
* Server, `RETURNING` on PostgreSQL) so it can detect a win (exactly one row).
|
|
151
|
+
* Builds the PostgreSQL atomic compare-and-swap UPDATE that consumes one use of an invite.
|
|
127
152
|
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
153
|
+
* PostgreSQL only. SQL Server consumes through the granted `spConsumeMagicLinkInvite` procedure,
|
|
154
|
+
* because its runtime roles are never granted table DML (#4753). PostgreSQL needs neither: its
|
|
155
|
+
* runtime roles hold INSERT/UPDATE/DELETE on every `__mj` table
|
|
156
|
+
* (V202605040300__v5.33.x__Unblock_PostgreSQL_End_To_End.pg-only.sql), and no PG counterpart of
|
|
157
|
+
* the procedure exists — the release-time converter leaves `CREATE PROCEDURE` unhandled.
|
|
131
158
|
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
* and
|
|
135
|
-
*
|
|
159
|
+
* The WHERE re-checks every eligibility condition (the same predicate as the procedure), so the
|
|
160
|
+
* increment and the guard are one atomic statement: concurrent redemptions of a single-use link
|
|
161
|
+
* serialize on the row lock and exactly one matches. `RETURNING ID` yields the row iff the guard
|
|
162
|
+
* matched. The invite ID MUST be bound by the caller as `$1` — it is never interpolated.
|
|
136
163
|
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* wins; `RETURNING` yields the row iff the guard matched (equivalent to the SS
|
|
141
|
-
* `OUTPUT`-into-table win-detect). PascalCase identifiers are auto-quoted by
|
|
142
|
-
* `PostgreSQLDataProvider.ExecuteSQL`, so the table is passed unquoted (`schema.table`).
|
|
143
|
-
*
|
|
144
|
-
* `qualifiedTable` is asserted to match the dialect's whitelist pattern before
|
|
145
|
-
* interpolation. The caller derives it from `EntityInfo` (never user input), so
|
|
146
|
-
* this is defense-in-depth: even a future careless caller cannot turn this into
|
|
147
|
-
* an injection vector — a non-conforming table throws.
|
|
148
|
-
*
|
|
149
|
-
* @param qualifiedTable `[schema].[table]` (sqlserver) or `schema.table` (postgresql) for MagicLinkInvite
|
|
150
|
-
* @param dialect target SQL dialect (defaults to `'sqlserver'`)
|
|
164
|
+
* `qualifiedTable` is `schema.table` unquoted (PostgreSQLDataProvider.ExecuteSQL auto-quotes the
|
|
165
|
+
* PascalCase identifiers) and is asserted against a whitelist before interpolation — the caller
|
|
166
|
+
* never passes user input, so this is defense-in-depth.
|
|
151
167
|
*/
|
|
152
|
-
export function
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
throw new Error(`buildConsumeInviteSQL: refusing to build SQL for non-whitelisted table identifier '${qualifiedTable}'.`);
|
|
156
|
-
}
|
|
157
|
-
return (
|
|
158
|
-
`UPDATE ${qualifiedTable} ` +
|
|
159
|
-
`SET UseCount = UseCount + 1, ` +
|
|
160
|
-
`ConsumedAt = COALESCE(ConsumedAt, (now() AT TIME ZONE 'utc')), ` +
|
|
161
|
-
`Status = CASE WHEN UseCount + 1 >= MaxUses THEN 'Consumed' ELSE Status END ` +
|
|
162
|
-
`WHERE ID = $1 AND Status = 'Active' AND UseCount < MaxUses AND ExpiresAt > (now() AT TIME ZONE 'utc') ` +
|
|
163
|
-
`RETURNING ID;`
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
if (!QUALIFIED_TABLE_PATTERN.test(qualifiedTable)) {
|
|
167
|
-
throw new Error(`buildConsumeInviteSQL: refusing to build SQL for non-whitelisted table identifier '${qualifiedTable}'.`);
|
|
168
|
+
export function BuildConsumeInvitePostgresSQL(qualifiedTable: string): string {
|
|
169
|
+
if (!QUALIFIED_TABLE_PATTERN_PG.test(qualifiedTable)) {
|
|
170
|
+
throw new Error(`BuildConsumeInvitePostgresSQL: refusing to build SQL for non-whitelisted table identifier '${qualifiedTable}'.`);
|
|
168
171
|
}
|
|
169
172
|
return (
|
|
170
|
-
`DECLARE @consumed TABLE (ID UNIQUEIDENTIFIER); ` +
|
|
171
173
|
`UPDATE ${qualifiedTable} ` +
|
|
172
174
|
`SET UseCount = UseCount + 1, ` +
|
|
173
|
-
`ConsumedAt = COALESCE(ConsumedAt,
|
|
175
|
+
`ConsumedAt = COALESCE(ConsumedAt, (now() AT TIME ZONE 'utc')), ` +
|
|
174
176
|
`Status = CASE WHEN UseCount + 1 >= MaxUses THEN 'Consumed' ELSE Status END ` +
|
|
175
|
-
`
|
|
176
|
-
`
|
|
177
|
-
`SELECT ID FROM @consumed;`
|
|
177
|
+
`WHERE ID = $1 AND Status = 'Active' AND UseCount < MaxUses AND ExpiresAt > (now() AT TIME ZONE 'utc') ` +
|
|
178
|
+
`RETURNING ID;`
|
|
178
179
|
);
|
|
179
180
|
}
|
|
180
181
|
|
|
@@ -184,7 +185,7 @@ export function buildConsumeInviteSQL(qualifiedTable: string, dialect: ConsumeIn
|
|
|
184
185
|
* of scopes across multiple redeemed links — carried in the re-minted JWT, never as
|
|
185
186
|
* roles on a shared user, so anonymous sessions can't accrete into a superuser.
|
|
186
187
|
*/
|
|
187
|
-
export function
|
|
188
|
+
export function UnionScopes(prior: readonly MagicLinkScopeEntry[] | undefined, next: MagicLinkScopeEntry): MagicLinkScopeEntry[] {
|
|
188
189
|
const result = [...(prior ?? [])];
|
|
189
190
|
if (!result.some((s) => s.inviteId === next.inviteId)) {
|
|
190
191
|
result.push(next);
|
|
@@ -192,8 +193,13 @@ export function unionScopes(prior: readonly MagicLinkScopeEntry[] | undefined, n
|
|
|
192
193
|
return result;
|
|
193
194
|
}
|
|
194
195
|
|
|
196
|
+
/** @deprecated Use {@link UnionScopes}. */
|
|
197
|
+
export function unionScopes(prior: readonly MagicLinkScopeEntry[] | undefined, next: MagicLinkScopeEntry): MagicLinkScopeEntry[] {
|
|
198
|
+
return UnionScopes(prior, next);
|
|
199
|
+
}
|
|
200
|
+
|
|
195
201
|
/** Builds the session-token claims (pure). */
|
|
196
|
-
export function
|
|
202
|
+
export function BuildSessionClaims(args: {
|
|
197
203
|
issuer: string;
|
|
198
204
|
audience: string;
|
|
199
205
|
inviteId: string;
|
|
@@ -236,9 +242,35 @@ export function buildSessionClaims(args: {
|
|
|
236
242
|
mj_app_id: args.applicationId,
|
|
237
243
|
mj_role: args.roleName,
|
|
238
244
|
mj_invited_by: args.invitedByUserId,
|
|
239
|
-
mj_scopes:
|
|
245
|
+
mj_scopes: UnionScopes(args.priorScopes, scopeEntry),
|
|
240
246
|
mj_anon: args.anonymous ? true : undefined,
|
|
241
247
|
mj_sid: args.sessionId,
|
|
242
248
|
mj_magic_link: true,
|
|
243
249
|
};
|
|
244
250
|
}
|
|
251
|
+
|
|
252
|
+
/** @deprecated Use {@link BuildSessionClaims}. */
|
|
253
|
+
export function buildSessionClaims(args: {
|
|
254
|
+
issuer: string;
|
|
255
|
+
audience: string;
|
|
256
|
+
inviteId: string;
|
|
257
|
+
email: string;
|
|
258
|
+
firstName?: string;
|
|
259
|
+
lastName?: string;
|
|
260
|
+
applicationId: string;
|
|
261
|
+
roleName: string;
|
|
262
|
+
invitedByUserId?: string;
|
|
263
|
+
/** True for anonymous sessions — the server enforces scope from mj_scopes, not roles. */
|
|
264
|
+
anonymous?: boolean;
|
|
265
|
+
/** Opaque per-session id (anonymous forensics correlation). */
|
|
266
|
+
sessionId?: string;
|
|
267
|
+
/** Prior session's scope union to carry forward (multi-link anonymous sessions). */
|
|
268
|
+
priorScopes?: readonly MagicLinkScopeEntry[];
|
|
269
|
+
/** Resource-share/embed scope for this link's entry. */
|
|
270
|
+
resourceType?: string;
|
|
271
|
+
resourceId?: string;
|
|
272
|
+
nowSeconds: number;
|
|
273
|
+
ttlSeconds: number;
|
|
274
|
+
}): MagicLinkJWTClaims {
|
|
275
|
+
return BuildSessionClaims(args);
|
|
276
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/** Minimal HTML-escape for safe interpolation into attribute/text content. */
|
|
8
|
-
export function
|
|
8
|
+
export function EscapeHtml(s: string): string {
|
|
9
9
|
return s
|
|
10
10
|
.replace(/&/g, '&')
|
|
11
11
|
.replace(/</g, '<')
|
|
@@ -14,6 +14,11 @@ export function escapeHtml(s: string): string {
|
|
|
14
14
|
.replace(/'/g, ''');
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/** @deprecated Use {@link EscapeHtml}. */
|
|
18
|
+
export function escapeHtml(s: string): string {
|
|
19
|
+
return EscapeHtml(s);
|
|
20
|
+
}
|
|
21
|
+
|
|
17
22
|
/**
|
|
18
23
|
* Builds the redemption landing page served by `GET /magic-link/redeem`.
|
|
19
24
|
*
|
|
@@ -27,9 +32,9 @@ export function escapeHtml(s: string): string {
|
|
|
27
32
|
* @param token the raw magic-link token (embedded in a hidden field)
|
|
28
33
|
* @param actionPath the same-origin path the form POSTs to (e.g. `/magic-link/redeem`)
|
|
29
34
|
*/
|
|
30
|
-
export function
|
|
31
|
-
const t =
|
|
32
|
-
const action =
|
|
35
|
+
export function BuildRedeemLandingHtml(token: string, actionPath: string): string {
|
|
36
|
+
const t = EscapeHtml(token);
|
|
37
|
+
const action = EscapeHtml(actionPath);
|
|
33
38
|
// Hardcoded colors are intentional here — this is a standalone server-rendered
|
|
34
39
|
// HTML response, not Angular component CSS, so the design-token rule doesn't apply.
|
|
35
40
|
return `<!doctype html>
|
|
@@ -60,3 +65,8 @@ export function buildRedeemLandingHtml(token: string, actionPath: string): strin
|
|
|
60
65
|
</body>
|
|
61
66
|
</html>`;
|
|
62
67
|
}
|
|
68
|
+
|
|
69
|
+
/** @deprecated Use {@link BuildRedeemLandingHtml}. */
|
|
70
|
+
export function buildRedeemLandingHtml(token: string, actionPath: string): string {
|
|
71
|
+
return BuildRedeemLandingHtml(token, actionPath);
|
|
72
|
+
}
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export interface MagicLinkScopeEntry {
|
|
12
12
|
/** The invite that granted this scope entry. */
|
|
13
|
-
inviteId: string;
|
|
13
|
+
inviteId: 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
|
|
14
14
|
/** The Application this entry grants access to. */
|
|
15
|
-
appId: string;
|
|
15
|
+
appId: 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
|
|
16
16
|
/** The role name this entry carries (email/app-session links). */
|
|
17
|
-
role?: string;
|
|
17
|
+
role?: string; // 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
|
|
18
18
|
/** For resource-share/embed links: the shared resource's type + id. */
|
|
19
|
-
resourceType?: string;
|
|
20
|
-
resourceId?: string;
|
|
19
|
+
resourceType?: string; // 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
|
|
20
|
+
resourceId?: string; // 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
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -27,25 +27,25 @@ export interface MagicLinkScopeEntry {
|
|
|
27
27
|
*/
|
|
28
28
|
export interface MagicLinkJWTClaims {
|
|
29
29
|
/** Issuer — MJ's public URL; resolves to the registered `magic-link` auth provider. */
|
|
30
|
-
iss: string;
|
|
30
|
+
iss: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
31
31
|
/** Audience — the configured magic-link audience (default `mj-magic-link`). */
|
|
32
|
-
aud: string;
|
|
32
|
+
aud: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
33
33
|
/** Subject — `magic-link|<inviteId>`. */
|
|
34
|
-
sub: string;
|
|
34
|
+
sub: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
35
35
|
/** Issued-at (epoch seconds). */
|
|
36
|
-
iat: number;
|
|
36
|
+
iat: number; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
37
37
|
/** Expiry (epoch seconds). */
|
|
38
|
-
exp: number;
|
|
39
|
-
email: string;
|
|
40
|
-
given_name?: string;
|
|
41
|
-
family_name?: string;
|
|
42
|
-
name?: string;
|
|
38
|
+
exp: number; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
39
|
+
email: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
40
|
+
given_name?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
41
|
+
family_name?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
42
|
+
name?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
43
43
|
/** The single Application this session is scoped to. */
|
|
44
|
-
mj_app_id: string;
|
|
44
|
+
mj_app_id: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
45
45
|
/** The restricted role name assigned to this user (informational; enforcement is server-side via the role's entity permissions). */
|
|
46
|
-
mj_role: string;
|
|
46
|
+
mj_role: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
47
47
|
/** UserID of the internal user who issued the invite (attribution/audit). Absent on links whose inviter could not be resolved. */
|
|
48
|
-
mj_invited_by?: string;
|
|
48
|
+
mj_invited_by?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
49
49
|
/**
|
|
50
50
|
* Per-session scope UNION (Phase 4+). Each entry is one redeemed link's grant.
|
|
51
51
|
* The server enforces anonymous sessions against THIS set (not the user's role
|
|
@@ -53,81 +53,81 @@ export interface MagicLinkJWTClaims {
|
|
|
53
53
|
* different scopes without accretion. For email sessions the singular mj_app_id/
|
|
54
54
|
* mj_role remain authoritative; this carries the union when links are stacked.
|
|
55
55
|
*/
|
|
56
|
-
mj_scopes?: MagicLinkScopeEntry[];
|
|
56
|
+
mj_scopes?: MagicLinkScopeEntry[]; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
57
57
|
/** True when this session resolves to the shared Anonymous principal (claims-based enforcement). */
|
|
58
|
-
mj_anon?: boolean;
|
|
58
|
+
mj_anon?: boolean; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
59
59
|
/** Opaque per-session id — correlates one anonymous session's activity across audit rows without a real user. */
|
|
60
|
-
mj_sid?: string;
|
|
60
|
+
mj_sid?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
61
61
|
/**
|
|
62
62
|
* Public web widget instance id (additive — set only for widget guest sessions
|
|
63
63
|
* minted by WidgetSessionService). Binds the synthesized guest principal to one
|
|
64
64
|
* widget instance so its pinned agent / guest role can be locked down. Absent on
|
|
65
65
|
* ordinary magic-link sessions.
|
|
66
66
|
*/
|
|
67
|
-
mj_widget_id?: string;
|
|
67
|
+
mj_widget_id?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
68
68
|
/**
|
|
69
69
|
* Host-asserted visitor email for a widget `host-identity` session (additive). The
|
|
70
70
|
* authoritative `email`/`sub` still resolve the constrained shared Anonymous principal;
|
|
71
71
|
* this carries WHO the host says the visitor is, for the agent to look up their account —
|
|
72
72
|
* without granting that account's permissions. Absent on anonymous/ordinary sessions.
|
|
73
73
|
*/
|
|
74
|
-
mj_host_email?: string;
|
|
74
|
+
mj_host_email?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
75
75
|
/**
|
|
76
76
|
* Returning-visitor anchor for a widget guest session (additive, RV1). Carried so the VOICE path —
|
|
77
77
|
* whose conversation is created server-side — can stamp the same Conversation.VisitorKey the text
|
|
78
78
|
* path stamps client-side. Present only when the widget remembers returning visitors.
|
|
79
79
|
*/
|
|
80
|
-
mj_visitor_key?: string;
|
|
80
|
+
mj_visitor_key?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
81
81
|
/** The prior conversation this visit chains from (RV2), for the voice path to stamp Conversation.LastConversationID. */
|
|
82
|
-
mj_last_conversation_id?: string;
|
|
82
|
+
mj_last_conversation_id?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
83
83
|
/** Resolved polymorphic identity entity id (RV4), for the voice path to stamp the existing Conversation.LinkedEntityID / AIAgentSession.LinkedEntityID. */
|
|
84
|
-
mj_linked_entity_id?: string;
|
|
84
|
+
mj_linked_entity_id?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
85
85
|
/** Resolved polymorphic identity record id (RV4), for the voice path to stamp the existing Conversation.LinkedRecordID / AIAgentSession.LinkedRecordID. */
|
|
86
|
-
mj_linked_record_id?: string;
|
|
86
|
+
mj_linked_record_id?: string; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
87
87
|
/** Marks the session as magic-link so the Explorer can confine the UI. */
|
|
88
|
-
mj_magic_link: true;
|
|
88
|
+
mj_magic_link: true; // case-violation-ok-legacy-back-compat: snake_case mirrors an external payload — the remote spelling is the contract, not MJ convention
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/** Parameters for creating a magic-link invite (POST /magic-link/create). */
|
|
92
92
|
export interface CreateMagicLinkInviteParams {
|
|
93
93
|
/** Recipient email — becomes the provisioned user's email. */
|
|
94
|
-
email: string;
|
|
94
|
+
email: 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
|
|
95
95
|
/** The Application the invite grants access to. */
|
|
96
|
-
|
|
96
|
+
ApplicationId: string;
|
|
97
97
|
/** Restricted role to assign. Defaults to the configured `restrictedRoleName`. */
|
|
98
|
-
|
|
98
|
+
RoleId?: string;
|
|
99
99
|
/** Hours until the link expires. Defaults to config `defaultExpiresInHours`. */
|
|
100
|
-
|
|
100
|
+
ExpiresInHours?: number;
|
|
101
101
|
/** Maximum redemptions. Defaults to 1 (single-use). */
|
|
102
|
-
|
|
102
|
+
MaxUses?: number;
|
|
103
103
|
/** Optional given/family name to seed the provisioned user. */
|
|
104
|
-
firstName?: string;
|
|
105
|
-
lastName?: string;
|
|
104
|
+
firstName?: string; // 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
|
|
105
|
+
lastName?: string; // 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
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
/** Result of creating an invite. */
|
|
109
109
|
export interface CreateMagicLinkInviteResult {
|
|
110
|
-
success: boolean;
|
|
111
|
-
inviteId?: string;
|
|
110
|
+
success: boolean; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
111
|
+
inviteId?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
112
112
|
/** Full redemption URL to share. */
|
|
113
|
-
redemptionUrl?: string;
|
|
113
|
+
redemptionUrl?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
114
114
|
/**
|
|
115
115
|
* The raw token, returned ONLY when no email provider is configured (so the
|
|
116
116
|
* caller can deliver the link out of band). Never returned once email send
|
|
117
117
|
* succeeds, and never persisted.
|
|
118
118
|
*/
|
|
119
|
-
rawToken?: string;
|
|
119
|
+
rawToken?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
120
120
|
/** Whether the invite email was dispatched. */
|
|
121
|
-
emailSent?: boolean;
|
|
121
|
+
emailSent?: boolean; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
122
122
|
/** ISO expiry timestamp. */
|
|
123
|
-
expiresAt?: string;
|
|
124
|
-
error?: string;
|
|
123
|
+
expiresAt?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
124
|
+
error?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
125
125
|
/**
|
|
126
126
|
* Set when the request was rejected for authorization reasons:
|
|
127
127
|
* `forbidden` — caller may not issue invites; `invalid_role` — the requested
|
|
128
128
|
* role is not grantable via magic-link. Drives the HTTP status in the router.
|
|
129
129
|
*/
|
|
130
|
-
errorCode?: 'forbidden' | 'invalid_role';
|
|
130
|
+
errorCode?: 'forbidden' | 'invalid_role'; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
/** Why a redemption failed. */
|
|
@@ -139,25 +139,25 @@ export type RedeemErrorCode = 'not_found' | 'expired' | 'consumed' | 'revoked' |
|
|
|
139
139
|
* all fields optional because the API/JSON flow may omit them.
|
|
140
140
|
*/
|
|
141
141
|
export interface RedeemAuditContext {
|
|
142
|
-
ipAddress?: string;
|
|
143
|
-
userAgent?: string;
|
|
144
|
-
origin?: string;
|
|
142
|
+
ipAddress?: string; // 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
|
|
143
|
+
userAgent?: string; // 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
|
|
144
|
+
origin?: string; // 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
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
/** Result of redeeming an invite. */
|
|
148
148
|
export interface RedeemMagicLinkResult {
|
|
149
|
-
success: boolean;
|
|
149
|
+
success: boolean; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
150
150
|
/** The minted session JWT (RS256). */
|
|
151
|
-
token?: string;
|
|
151
|
+
token?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
152
152
|
/** ISO expiry of the session token. */
|
|
153
|
-
expiresAt?: string;
|
|
153
|
+
expiresAt?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
154
154
|
/** The Application the session is scoped to. */
|
|
155
|
-
applicationId?: string;
|
|
155
|
+
applicationId?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
156
156
|
/** The Application's display name (used to deep-link the browser into that app). */
|
|
157
|
-
applicationName?: string;
|
|
157
|
+
applicationName?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
158
158
|
/** The Application's URL path slug (preferred for deep-linking; falls back to name). */
|
|
159
|
-
applicationPath?: string;
|
|
160
|
-
email?: string;
|
|
161
|
-
error?: string;
|
|
162
|
-
errorCode?: RedeemErrorCode;
|
|
159
|
+
applicationPath?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
160
|
+
email?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
161
|
+
error?: string; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
162
|
+
errorCode?: RedeemErrorCode; // case-violation-ok-legacy-back-compat: the type crosses a serialization boundary (JSON / HTTP body), so this member name is part of a wire or on-disk shape
|
|
163
163
|
}
|
package/src/auth/newUsers.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { configInfo } from "../config.js";
|
|
|
5
5
|
import { MJUserEntity, MJUserRoleEntity, MJUserApplicationEntity, MJUserApplicationEntityEntity, MJApplicationEntityType, MJApplicationEntityEntityType, UserInfoEngine } from "@memberjunction/core-entities";
|
|
6
6
|
|
|
7
7
|
export class NewUserBase {
|
|
8
|
-
public async createNewUser(firstName: string, lastName: string, email: string, linkedRecordType: string = 'None', linkedEntityId?: string, linkedEntityRecordId?: string): Promise<MJUserEntity | null> {
|
|
8
|
+
public async createNewUser(firstName: string, lastName: string, email: string, linkedRecordType: string = 'None', linkedEntityId?: string, linkedEntityRecordId?: string): Promise<MJUserEntity | null> { // case-violation-ok-legacy-back-compat: a subclass overrides this; a stub preserves CALLING the old name but not OVERRIDING it
|
|
9
9
|
try {
|
|
10
10
|
const contextUser: UserInfo | null = ResolveConfiguredPrincipal(
|
|
11
11
|
configInfo?.userHandling?.contextUserForNewUserCreation,
|
package/src/auth/principals.ts
CHANGED
|
@@ -116,7 +116,7 @@ function lowestActiveById<T extends ResolvablePrincipal>(matches: readonly T[]):
|
|
|
116
116
|
* @param users the candidate pool, normally `UserCache.Users`
|
|
117
117
|
* @param systemUserId the deployment's system user ID (`UserCache.Instance.SYSTEM_USER_ID`)
|
|
118
118
|
*/
|
|
119
|
-
export function
|
|
119
|
+
export function ResolvePrincipalFrom<T extends ResolvablePrincipal>(
|
|
120
120
|
candidate: string | undefined,
|
|
121
121
|
users: readonly T[],
|
|
122
122
|
systemUserId: string,
|
|
@@ -156,6 +156,15 @@ export function resolvePrincipalFrom<T extends ResolvablePrincipal>(
|
|
|
156
156
|
};
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
/** @deprecated Use {@link ResolvePrincipalFrom}. */
|
|
160
|
+
export function resolvePrincipalFrom<T extends ResolvablePrincipal>(
|
|
161
|
+
candidate: string | undefined,
|
|
162
|
+
users: readonly T[],
|
|
163
|
+
systemUserId: string,
|
|
164
|
+
): PrincipalResolution<T> {
|
|
165
|
+
return ResolvePrincipalFrom(candidate, users, systemUserId);
|
|
166
|
+
}
|
|
167
|
+
|
|
159
168
|
/**
|
|
160
169
|
* Why a configured candidate yielded nothing. The two causes need opposite fixes, so the message
|
|
161
170
|
* has to tell them apart: "no such user" is a typo or the wrong column, while "matched, but
|
|
@@ -230,7 +239,7 @@ export function ReportedMisconfigurationCount(): number {
|
|
|
230
239
|
* handle null rather than assume a principal is always available
|
|
231
240
|
*/
|
|
232
241
|
export function ResolveConfiguredPrincipal(candidate: string | undefined, purpose: string): UserInfo | null {
|
|
233
|
-
const resolution =
|
|
242
|
+
const resolution = ResolvePrincipalFrom(candidate, UserCache.Instance.Users, UserCache.Instance.SYSTEM_USER_ID);
|
|
234
243
|
|
|
235
244
|
if (resolution.warning) {
|
|
236
245
|
const key = `${purpose} :: ${candidate ?? ''}`;
|
package/src/cache.ts
CHANGED
|
@@ -2,9 +2,12 @@ import { LRUCache } from 'lru-cache';
|
|
|
2
2
|
|
|
3
3
|
const oneHourMs = 60 * 60 * 1000;
|
|
4
4
|
|
|
5
|
-
export const
|
|
5
|
+
export const AuthCache = new LRUCache({
|
|
6
6
|
max: 50000,
|
|
7
7
|
ttl: oneHourMs,
|
|
8
8
|
ttlAutopurge: false,
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
+
/** @deprecated Use {@link AuthCache}. */
|
|
12
|
+
export const authCache = AuthCache;
|
|
13
|
+
|
package/src/config.ts
CHANGED
|
@@ -230,6 +230,29 @@ const cacheSettingsSchema = z.object({
|
|
|
230
230
|
evictionSweepIntervalSeconds: z.number().optional().default(300),
|
|
231
231
|
/** Enable verbose cache logging (hits, misses, evictions). Default: false. */
|
|
232
232
|
verboseLogging: z.boolean().optional().default(false),
|
|
233
|
+
/**
|
|
234
|
+
* Entity names whose FULL ROW may ride along with a cache-invalidation broadcast.
|
|
235
|
+
*
|
|
236
|
+
* The cache-invalidation subscription is delivered to EVERY connected client with no per-user
|
|
237
|
+
* filter (see CacheInvalidationResolver), so any row named here is disclosed to every signed-in
|
|
238
|
+
* session, whatever row-level security or tenant scoping would otherwise apply to reading it.
|
|
239
|
+
*
|
|
240
|
+
* Defaults to `[]`: invalidation still carries the entity name and primary key, which is all a
|
|
241
|
+
* client needs to evict, and the client re-fetches through the normal read path where access
|
|
242
|
+
* control applies. Listing an entity re-enables the apply-in-place optimisation for it — correct
|
|
243
|
+
* only for reference data every signed-in user is allowed to read.
|
|
244
|
+
*
|
|
245
|
+
* What the re-fetch costs depends on the consumer. `ConversationEngine` re-reads the ONE record
|
|
246
|
+
* by primary key. `BaseEngine` (every engine subclass with `AutoRefresh`, the default) applies a
|
|
247
|
+
* remote save in place only when the row is present, so without it a remote save falls through to
|
|
248
|
+
* a full reload of each matching config — a `RunView` of that entity, not a keyed read. Remote
|
|
249
|
+
* deletes still apply in place from the primary key. Engine-cached reference entities that every
|
|
250
|
+
* signed-in user may read are the ones worth listing here.
|
|
251
|
+
*
|
|
252
|
+
* `['*']` opts every entity in, restoring the previous behaviour. Only safe on a deployment where
|
|
253
|
+
* every signed-in user may read every row of every entity.
|
|
254
|
+
*/
|
|
255
|
+
recordDataBroadcastEntities: z.array(z.string()).optional().default([]),
|
|
233
256
|
});
|
|
234
257
|
|
|
235
258
|
const loggingSettingsSchema = z.object({
|
|
@@ -812,9 +835,14 @@ export const DEFAULT_SERVER_CONFIG: Partial<ConfigInfo> = {
|
|
|
812
835
|
* startup summary `Config` line. Declared before `configInfo` so the assignment
|
|
813
836
|
* inside `loadConfig()` (invoked below) is not in its temporal dead zone.
|
|
814
837
|
*/
|
|
815
|
-
export let
|
|
838
|
+
export let ConfigFilePath: string | undefined;
|
|
816
839
|
|
|
817
|
-
export
|
|
840
|
+
export {
|
|
841
|
+
/** @deprecated Use {@link ConfigFilePath} instead. */
|
|
842
|
+
ConfigFilePath as configFilePath,
|
|
843
|
+
};
|
|
844
|
+
|
|
845
|
+
export const configInfo: ConfigInfo = LoadConfig(); // case-violation-ok-legacy-back-compat: the PascalCase name is already taken in this scope
|
|
818
846
|
|
|
819
847
|
export const {
|
|
820
848
|
dbUsername,
|
|
@@ -841,7 +869,7 @@ export const {
|
|
|
841
869
|
restApiOptions: RESTApiOptions,
|
|
842
870
|
} = configInfo;
|
|
843
871
|
|
|
844
|
-
export function
|
|
872
|
+
export function LoadConfig() {
|
|
845
873
|
const configSearchResult = explorer.search(process.cwd());
|
|
846
874
|
|
|
847
875
|
// Start with DEFAULT_SERVER_CONFIG as base
|
|
@@ -851,7 +879,7 @@ export function loadConfig() {
|
|
|
851
879
|
if (configSearchResult && !configSearchResult.isEmpty) {
|
|
852
880
|
// Resolved config-file path. Surfaced in the startup summary `Config` line at standard
|
|
853
881
|
// level (see StartupLogger). Demoted to verbose-only here to avoid a duplicate inline line.
|
|
854
|
-
|
|
882
|
+
ConfigFilePath = configSearchResult.filepath;
|
|
855
883
|
LogStatusEx({ message: `Config file found at ${configSearchResult.filepath}`, verboseOnly: true });
|
|
856
884
|
|
|
857
885
|
// Merge user config with defaults (user config takes precedence)
|
|
@@ -868,3 +896,8 @@ export function loadConfig() {
|
|
|
868
896
|
}
|
|
869
897
|
return configParsing.data;
|
|
870
898
|
}
|
|
899
|
+
|
|
900
|
+
/** @deprecated Use {@link LoadConfig}. */
|
|
901
|
+
export function loadConfig() {
|
|
902
|
+
return LoadConfig();
|
|
903
|
+
}
|