@oneuptime/common 12.0.32 → 12.0.33
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/Models/AnalyticsModels/Span.ts +14 -0
- package/Models/DatabaseModels/EnterpriseLicense.ts +56 -0
- package/Models/DatabaseModels/Index.ts +10 -0
- package/Models/DatabaseModels/Monitor.ts +76 -0
- package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
- package/Models/DatabaseModels/NetworkDevice.ts +176 -1
- package/Models/DatabaseModels/NetworkSite.ts +201 -2
- package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
- package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
- package/Models/DatabaseModels/TelemetryException.ts +119 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupBatch.ts +334 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +370 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupSetting.ts +282 -0
- package/Server/API/EnterpriseLicenseAPI.ts +391 -64
- package/Server/API/LlmProviderAPI.ts +137 -22
- package/Server/EnvironmentConfig.ts +14 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.ts +55 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.ts +124 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.ts +132 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.ts +79 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.ts +191 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
- package/Server/Infrastructure/QueueWorker.ts +38 -8
- package/Server/Middleware/BearerTokenAuthorization.ts +12 -0
- package/Server/Middleware/ProjectAuthorization.ts +11 -0
- package/Server/Middleware/SCIMAuthorization.ts +12 -0
- package/Server/Middleware/TelemetryIngest.ts +11 -0
- package/Server/Services/AIBillingService.ts +101 -27
- package/Server/Services/EnterpriseLicenseInstanceService.ts +197 -0
- package/Server/Services/EnterpriseLicenseService.ts +55 -0
- package/Server/Services/Index.ts +10 -0
- package/Server/Services/MonitorService.ts +143 -21
- package/Server/Services/MonitorStatusTimelineService.ts +150 -8
- package/Server/Services/MonitorTemplateService.ts +217 -1
- package/Server/Services/NetworkAlertPolicyEngineService.ts +2159 -0
- package/Server/Services/NetworkAlertPolicyService.ts +944 -0
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +9 -10
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +60 -15
- package/Server/Services/NetworkDeviceService.ts +1032 -73
- package/Server/Services/NetworkSiteService.ts +1502 -129
- package/Server/Services/NetworkSiteTypeService.ts +1216 -0
- package/Server/Services/NetworkSnmpCredentialProfileService.ts +238 -0
- package/Server/Services/NotificationService.ts +118 -28
- package/Server/Services/ProjectService.ts +105 -48
- package/Server/Services/StatusPagePrivateUserService.ts +103 -3
- package/Server/Services/UserNotificationEmailRollupBatchService.ts +78 -0
- package/Server/Services/UserNotificationEmailRollupItemService.ts +79 -0
- package/Server/Services/UserNotificationEmailRollupSettingService.ts +113 -0
- package/Server/Services/UserNotificationSettingService.ts +62 -25
- package/Server/Services/UserService.ts +95 -0
- package/Server/Types/Database/QueryHelper.ts +2 -2
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +14 -3
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +10 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +10 -0
- package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +62 -1
- package/Server/Utils/AI/Toolbox/AlertTools.ts +15 -1
- package/Server/Utils/Billing/BillingFailureNoticeThrottle.ts +80 -0
- package/Server/Utils/DataSource/HttpFetch.ts +9 -2
- package/Server/Utils/EmailRollup/EmailRollupConstants.ts +98 -0
- package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +872 -0
- package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +781 -0
- package/Server/Utils/EmailRollup/EmailRollupWriter.ts +368 -0
- package/Server/Utils/LLM/LLMService.ts +78 -0
- package/Server/Utils/LogRedaction.ts +8 -0
- package/Server/Utils/Logger.ts +79 -1
- package/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.ts +190 -0
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +9 -2
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +61 -1
- package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +14 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +49 -0
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +255 -4
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +41 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +43 -0
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +499 -19
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +66 -10
- package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +238 -44
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +146 -39
- package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +31 -18
- package/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.ts +213 -0
- package/Server/Utils/OutboundUserAgent.ts +152 -0
- package/Server/Utils/StartServer.ts +51 -19
- package/Server/Utils/Telemetry/CaptureSpan.ts +32 -8
- package/Server/Utils/Telemetry/ErrorClassResolver.ts +120 -0
- package/Server/Utils/Telemetry/SpanUtil.ts +33 -0
- package/Server/Utils/Telemetry.ts +198 -51
- package/Server/Views/Partials/SensitiveUrlToken.ejs +140 -0
- package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +134 -33
- package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
- package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
- package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -0
- package/Tests/App/Dashboard/DeviceStatusHero.test.tsx +588 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +18 -9
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +632 -0
- package/Tests/App/Dashboard/MonitorRecommendationCreateProgress.test.tsx +682 -0
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +4 -2
- package/Tests/App/Dashboard/NetworkDeviceCreateFormMonitorBinding.test.tsx +676 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormPingMonitor.test.tsx +791 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormProbeAndSnmp.test.tsx +833 -0
- package/Tests/App/Dashboard/NetworkDeviceCriteriaFilter.test.ts +161 -0
- package/Tests/App/Dashboard/NetworkDeviceSettingsMonitoringSection.test.tsx +458 -0
- package/Tests/App/Dashboard/NetworkSideMenu.test.tsx +41 -5
- package/Tests/App/Dashboard/PingMonitorProvisioning.test.ts +368 -0
- package/Tests/App/Dashboard/RecommendationCard.test.tsx +796 -0
- package/Tests/App/Dashboard/RecommendationToolbar.test.tsx +519 -0
- package/Tests/App/Dashboard/RecommendationsList.test.tsx +661 -0
- package/Tests/App/Dashboard/UseBulkCreatePingMonitors.test.tsx +899 -0
- package/Tests/App/Dashboard/UseBulkSnmpCredentialProfileActions.test.tsx +732 -0
- package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +256 -0
- package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +11 -1
- package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +9 -4
- package/Tests/Models/NetworkSiteHierarchy.test.ts +41 -4
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +951 -7
- package/Tests/Server/API/LlmProviderConnectionTest.test.ts +522 -0
- package/Tests/Server/Infrastructure/Postgres/NetworkSnmpCredentialProfilesAndAlertPoliciesMigration.test.ts +854 -0
- package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +18 -0
- package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +535 -0
- package/Tests/Server/Services/AIChatPrivacyPin.test.ts +560 -0
- package/Tests/Server/Services/BillingRechargeOwnerEmailGuards.test.ts +783 -0
- package/Tests/Server/Services/EnterpriseLicenseInstanceServiceDeletionUsage.test.ts +707 -0
- package/Tests/Server/Services/EnterpriseLicenseServiceUsageAggregationLock.test.ts +329 -0
- package/Tests/Server/Services/MonitorServiceDeleteNetworkDeviceCleanup.test.ts +294 -0
- package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +802 -0
- package/Tests/Server/Services/MonitorStatusTimelineService.test.ts +72 -2
- package/Tests/Server/Services/NetworkAlertPolicyEngineHooks.test.ts +752 -0
- package/Tests/Server/Services/NetworkAlertPolicyEngineService.test.ts +1849 -0
- package/Tests/Server/Services/NetworkAlertPolicyModel.test.ts +1793 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +47 -4
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +97 -12
- package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +148 -3
- package/Tests/Server/Services/NetworkDeviceMonitorBindingUpdateGuard.test.ts +514 -0
- package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +447 -58
- package/Tests/Server/Services/NetworkDeviceMonitoringMethodTransition.test.ts +739 -0
- package/Tests/Server/Services/NetworkDevicePollingTenancy.test.ts +501 -0
- package/Tests/Server/Services/NetworkDeviceSiteDefaultProbe.test.ts +432 -0
- package/Tests/Server/Services/NetworkSiteMonitoringDefaults.test.ts +498 -0
- package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +337 -55
- package/Tests/Server/Services/NetworkSiteService.test.ts +1868 -131
- package/Tests/Server/Services/NetworkSiteTypeService.test.ts +1109 -0
- package/Tests/Server/Services/NetworkSnmpCredentialProfileModel.test.ts +926 -0
- package/Tests/Server/Services/NetworkSnmpCredentialProfileService.test.ts +796 -0
- package/Tests/Server/Services/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -0
- package/Tests/Server/Services/StatusPagePrivateUserEmailChangePasswordResetExpiry.test.ts +269 -0
- package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +472 -0
- package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +569 -0
- package/Tests/Server/Services/UserNotificationEmailRollupSettingModel.test.ts +314 -0
- package/Tests/Server/Services/UserNotificationEmailRollupSettingService.test.ts +409 -0
- package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +856 -0
- package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +102 -1
- package/Tests/Server/Types/Database/Permissions/DashboardAccessPermission.test.ts +321 -0
- package/Tests/Server/Types/Database/QueryHelperOperators.test.ts +17 -0
- package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +124 -0
- package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +208 -0
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +235 -0
- package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +253 -0
- package/Tests/Server/Utils/Captcha.test.ts +422 -0
- package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +96 -2
- package/Tests/Server/Utils/Database/MigrationFailureLog.test.ts +466 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1096 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerClaim.test.ts +466 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +1428 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +752 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +864 -0
- package/Tests/Server/Utils/LoggerFaultDemotion.test.ts +346 -0
- package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +633 -0
- package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +196 -0
- package/Tests/Server/Utils/Monitor/DatabaseMetricWrite.test.ts +367 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +100 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +5 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +512 -31
- package/Tests/Server/Utils/Monitor/NetworkDeviceMetricUtil.test.ts +252 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +479 -42
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +351 -5
- package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +136 -12
- package/Tests/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.test.ts +306 -0
- package/Tests/Server/Utils/OutboundUserAgent.test.ts +266 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClientUserAgent.test.ts +141 -0
- package/Tests/Server/Utils/Telemetry/ErrorClassResolver.test.ts +298 -0
- package/Tests/Server/Utils/Telemetry.test.ts +456 -66
- package/Tests/Types/Monitor/DatabaseMetricCatalog.test.ts +388 -0
- package/Tests/Types/Monitor/MonitorStepDatabaseMonitor.test.ts +243 -0
- package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +16 -7
- package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +60 -0
- package/Tests/Types/NetworkDevice/NetworkAlertPolicyScope.test.ts +655 -0
- package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +115 -26
- package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +39 -0
- package/Tests/Types/NotificationSetting/NotificationEmailRollupPolicy.test.ts +299 -0
- package/Tests/Types/Telemetry/ErrorClass.test.ts +483 -0
- package/Tests/UI/Components/BasicRadioButtons.test.tsx +336 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +15 -0
- package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
- package/Tests/UI/Components/SideMenuItem.test.tsx +226 -4
- package/Tests/UI/Components/SideMenuSection.test.tsx +310 -0
- package/Tests/UI/Components/SideOverSubmitState.test.tsx +335 -0
- package/Tests/UI/Utils/PageScrollLock.test.tsx +377 -0
- package/Tests/UI/Utils/PermissionGate.test.ts +78 -0
- package/Tests/UI/Utils/SensitiveUrlToken.test.ts +140 -0
- package/Tests/Utils/EnterpriseLicenseSeats.test.ts +69 -0
- package/Tests/Utils/EnterpriseLicenseSync.test.ts +7 -1
- package/Tests/Utils/EnterpriseLicenseUsage.test.ts +433 -2
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +280 -1
- package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +38 -0
- package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +284 -23
- package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +177 -0
- package/Tests/Utils/NetworkDevice/MonitoringMethodThreadedClassifiers.test.ts +992 -0
- package/Tests/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.test.ts +427 -0
- package/Tests/Utils/NetworkDevice/ReachabilityStampConsistency.test.ts +185 -0
- package/Tests/Utils/NetworkDevice/SnmpCredentialUtil.test.ts +268 -0
- package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +55 -5
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +98 -21
- package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +98 -20
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +8 -7
- package/Tests/Utils/NetworkDiscovery/PingMonitorBuilderForAddress.test.ts +274 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +230 -51
- package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +209 -0
- package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +145 -0
- package/Types/AI/ExceptionAIClassification.ts +10 -24
- package/Types/Email/EmailTemplateType.ts +2 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +5 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.ts +13 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.ts +6 -0
- package/Types/Exception/ApiException.ts +10 -0
- package/Types/Exception/BadDataException.ts +11 -0
- package/Types/Exception/BadRequestException.ts +11 -0
- package/Types/Exception/Exception.ts +65 -0
- package/Types/Exception/ForbiddenException.ts +10 -0
- package/Types/Exception/NotAuthenticatedException.ts +10 -0
- package/Types/Exception/NotAuthorizedException.ts +10 -0
- package/Types/Exception/NotFoundException.ts +11 -0
- package/Types/Exception/PayloadTooLargeException.ts +11 -0
- package/Types/Exception/PaymentRequiredException.ts +10 -0
- package/Types/Exception/ServiceUnavailableException.ts +10 -0
- package/Types/Exception/SsoAuthorizationException.ts +10 -0
- package/Types/Exception/TenantNotFoundException.ts +11 -0
- package/Types/Exception/TimeoutException.ts +10 -0
- package/Types/Exception/TooManyRequestsException.ts +10 -0
- package/Types/Exception/UnableToReachServer.ts +10 -0
- package/Types/Exception/WebsiteRequestException.ts +10 -0
- package/Types/Monitor/CriteriaFilter.ts +60 -2
- package/Types/Monitor/DatabaseMetricCatalog.ts +693 -0
- package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +83 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +76 -0
- package/Types/Monitor/MonitorMetricType.ts +71 -0
- package/Types/Monitor/MonitorStep.ts +76 -0
- package/Types/Monitor/MonitorStepDatabaseMonitor.ts +171 -0
- package/Types/Monitor/MonitorStepSqlMonitor.ts +2 -20
- package/Types/Monitor/MonitorType.ts +47 -1
- package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +22 -1
- package/Types/Monitor/SqlConnectionConfig.ts +31 -0
- package/Types/NetworkDevice/NetworkAlertPolicyScope.ts +343 -0
- package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +42 -22
- package/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.ts +30 -0
- package/Types/NotificationSetting/NotificationEmailRollupCategory.ts +255 -0
- package/Types/NotificationSetting/NotificationEmailRollupPolicy.ts +104 -0
- package/Types/Permission.ts +90 -0
- package/Types/Probe/ProbeMonitorResponse.ts +16 -0
- package/Types/Telemetry/ErrorClass.ts +274 -0
- package/Types/Telemetry/UnitOfWork.ts +59 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +2 -8
- package/UI/Components/EditionLabel/EditionLabel.tsx +4 -0
- package/UI/Components/Modal/Modal.tsx +2 -8
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
- package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
- package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
- package/UI/Components/SideMenu/SideMenu.tsx +123 -5
- package/UI/Components/SideMenu/SideMenuItem.tsx +76 -84
- package/UI/Components/SideMenu/SideMenuSection.tsx +55 -23
- package/UI/Components/SideOver/SideOver.tsx +21 -20
- package/UI/Utils/PageScrollLock.ts +79 -3
- package/UI/Utils/PermissionGate.ts +61 -0
- package/UI/Utils/SensitiveUrlToken.ts +112 -0
- package/UI/Utils/TestLLMProvider.ts +11 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +16 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +191 -11
- package/Utils/Monitor/MonitorMetricType.ts +153 -1
- package/Utils/Monitor/NetworkTopologyUtil.ts +23 -3
- package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
- package/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.ts +247 -0
- package/Utils/NetworkDevice/SnmpCredentialUtil.ts +68 -0
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +15 -7
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +52 -17
- package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +55 -23
- package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +115 -13
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +66 -20
- package/Utils/NetworkSite/TypeHierarchyUtil.ts +313 -0
- package/build/dist/Models/AnalyticsModels/Span.js +14 -0
- package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +59 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +10 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +75 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js +713 -0
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +180 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSite.js +200 -2
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js +102 -3
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js +878 -0
- package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js.map +1 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js +123 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js +363 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +402 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js +296 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js.map +1 -0
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +273 -60
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
- package/build/dist/Server/API/LlmProviderAPI.js +108 -13
- package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +12 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js +111 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js +77 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js +50 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js +83 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/QueueWorker.js +33 -5
- package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
- package/build/dist/Server/Middleware/BearerTokenAuthorization.js +12 -0
- package/build/dist/Server/Middleware/BearerTokenAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/ProjectAuthorization.js +11 -0
- package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/SCIMAuthorization.js +12 -0
- package/build/dist/Server/Middleware/SCIMAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +11 -0
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AIBillingService.js +70 -16
- package/build/dist/Server/Services/AIBillingService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js +167 -0
- package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseService.js +39 -0
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +10 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +119 -21
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +127 -8
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +162 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js +1683 -0
- package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkAlertPolicyService.js +732 -0
- package/build/dist/Server/Services/NetworkAlertPolicyService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +10 -9
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +54 -11
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +841 -70
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +1145 -107
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteTypeService.js +863 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js +217 -0
- package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js.map +1 -0
- package/build/dist/Server/Services/NotificationService.js +80 -17
- package/build/dist/Server/Services/NotificationService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +66 -30
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +92 -2
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js +76 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js +77 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js +111 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js +46 -20
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +90 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +14 -3
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +10 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +10 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +54 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +18 -4
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
- package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js +59 -0
- package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +2 -1
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js +91 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +691 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +497 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +257 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -0
- package/build/dist/Server/Utils/LLM/LLMService.js +64 -1
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/LogRedaction.js +8 -0
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
- package/build/dist/Server/Utils/Logger.js +63 -1
- package/build/dist/Server/Utils/Logger.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js +141 -0
- package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +51 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +7 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +37 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +158 -6
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +32 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +330 -21
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +55 -10
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +178 -49
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +119 -29
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +30 -17
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -1
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js +158 -0
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js.map +1 -0
- package/build/dist/Server/Utils/OutboundUserAgent.js +123 -0
- package/build/dist/Server/Utils/OutboundUserAgent.js.map +1 -0
- package/build/dist/Server/Utils/StartServer.js +38 -14
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +28 -8
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js +95 -0
- package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/SpanUtil.js +29 -0
- package/build/dist/Server/Utils/Telemetry/SpanUtil.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry.js +162 -46
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Types/AI/ExceptionAIClassification.js +10 -24
- package/build/dist/Types/AI/ExceptionAIClassification.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js +2 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js.map +1 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js +7 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js.map +1 -0
- package/build/dist/Types/Exception/ApiException.js +9 -0
- package/build/dist/Types/Exception/ApiException.js.map +1 -1
- package/build/dist/Types/Exception/BadDataException.js +10 -0
- package/build/dist/Types/Exception/BadDataException.js.map +1 -1
- package/build/dist/Types/Exception/BadRequestException.js +10 -0
- package/build/dist/Types/Exception/BadRequestException.js.map +1 -1
- package/build/dist/Types/Exception/Exception.js +56 -0
- package/build/dist/Types/Exception/Exception.js.map +1 -1
- package/build/dist/Types/Exception/ForbiddenException.js +9 -0
- package/build/dist/Types/Exception/ForbiddenException.js.map +1 -1
- package/build/dist/Types/Exception/NotAuthenticatedException.js +9 -0
- package/build/dist/Types/Exception/NotAuthenticatedException.js.map +1 -1
- package/build/dist/Types/Exception/NotAuthorizedException.js +9 -0
- package/build/dist/Types/Exception/NotAuthorizedException.js.map +1 -1
- package/build/dist/Types/Exception/NotFoundException.js +10 -0
- package/build/dist/Types/Exception/NotFoundException.js.map +1 -1
- package/build/dist/Types/Exception/PayloadTooLargeException.js +10 -0
- package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -1
- package/build/dist/Types/Exception/PaymentRequiredException.js +9 -0
- package/build/dist/Types/Exception/PaymentRequiredException.js.map +1 -1
- package/build/dist/Types/Exception/ServiceUnavailableException.js +9 -0
- package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -1
- package/build/dist/Types/Exception/SsoAuthorizationException.js +9 -0
- package/build/dist/Types/Exception/SsoAuthorizationException.js.map +1 -1
- package/build/dist/Types/Exception/TenantNotFoundException.js +10 -0
- package/build/dist/Types/Exception/TenantNotFoundException.js.map +1 -1
- package/build/dist/Types/Exception/TimeoutException.js +9 -0
- package/build/dist/Types/Exception/TimeoutException.js.map +1 -1
- package/build/dist/Types/Exception/TooManyRequestsException.js +9 -0
- package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -1
- package/build/dist/Types/Exception/UnableToReachServer.js +9 -0
- package/build/dist/Types/Exception/UnableToReachServer.js.map +1 -1
- package/build/dist/Types/Exception/WebsiteRequestException.js +9 -0
- package/build/dist/Types/Exception/WebsiteRequestException.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +45 -2
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/DatabaseMetricCatalog.js +594 -0
- package/build/dist/Types/Monitor/DatabaseMetricCatalog.js.map +1 -0
- package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js +21 -0
- package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +70 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorMetricType.js +61 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +54 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js +122 -0
- package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +45 -1
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +21 -1
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
- package/build/dist/Types/Monitor/SqlConnectionConfig.js +2 -0
- package/build/dist/Types/Monitor/SqlConnectionConfig.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js +172 -0
- package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +40 -22
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -1
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js +26 -0
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js +186 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js +87 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js.map +1 -0
- package/build/dist/Types/Permission.js +80 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Telemetry/ErrorClass.js +216 -0
- package/build/dist/Types/Telemetry/ErrorClass.js.map +1 -0
- package/build/dist/Types/Telemetry/UnitOfWork.js +59 -0
- package/build/dist/Types/Telemetry/UnitOfWork.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +2 -7
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +3 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +2 -7
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +39 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/ProgressBar/ProgressBar.js +12 -1
- package/build/dist/UI/Components/ProgressBar/ProgressBar.js.map +1 -1
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +6 -6
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js +67 -5
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js +49 -53
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js +25 -7
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +5 -20
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Utils/PageScrollLock.js +31 -3
- package/build/dist/UI/Utils/PageScrollLock.js.map +1 -1
- package/build/dist/UI/Utils/PermissionGate.js +42 -1
- package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
- package/build/dist/UI/Utils/SensitiveUrlToken.js +97 -0
- package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -0
- package/build/dist/UI/Utils/TestLLMProvider.js +4 -5
- package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +15 -0
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +111 -9
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +109 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +8 -3
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +27 -7
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +7 -5
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js +180 -0
- package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js +12 -0
- package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +15 -5
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +44 -15
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +52 -23
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +85 -13
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +30 -15
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +191 -0
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
import CallService from "../../../Server/Services/CallService";
|
|
2
|
+
import MailService from "../../../Server/Services/MailService";
|
|
3
|
+
import ProjectCallSMSConfigService from "../../../Server/Services/ProjectCallSMSConfigService";
|
|
4
|
+
import PushNotificationService from "../../../Server/Services/PushNotificationService";
|
|
5
|
+
import SmsService from "../../../Server/Services/SmsService";
|
|
6
|
+
import TelegramService from "../../../Server/Services/TelegramService";
|
|
7
|
+
import UserCallService from "../../../Server/Services/UserCallService";
|
|
8
|
+
import UserEmailService from "../../../Server/Services/UserEmailService";
|
|
9
|
+
import UserMicrosoftTeamsService from "../../../Server/Services/UserMicrosoftTeamsService";
|
|
10
|
+
import UserNotificationEmailRollupItemService from "../../../Server/Services/UserNotificationEmailRollupItemService";
|
|
11
|
+
import UserNotificationEmailRollupSettingService from "../../../Server/Services/UserNotificationEmailRollupSettingService";
|
|
12
|
+
import UserNotificationSettingService from "../../../Server/Services/UserNotificationSettingService";
|
|
13
|
+
import UserSlackService from "../../../Server/Services/UserSlackService";
|
|
14
|
+
import UserSmsService from "../../../Server/Services/UserSmsService";
|
|
15
|
+
import UserTelegramService from "../../../Server/Services/UserTelegramService";
|
|
16
|
+
import UserWebhookService from "../../../Server/Services/UserWebhookService";
|
|
17
|
+
import UserWhatsAppService from "../../../Server/Services/UserWhatsAppService";
|
|
18
|
+
import WebhookService from "../../../Server/Services/WebhookService";
|
|
19
|
+
import WhatsAppService from "../../../Server/Services/WhatsAppService";
|
|
20
|
+
import WorkspaceUserNotificationService from "../../../Server/Services/WorkspaceUserNotificationService";
|
|
21
|
+
import EmailRollupWriter, {
|
|
22
|
+
SendOrRollupData,
|
|
23
|
+
} from "../../../Server/Utils/EmailRollup/EmailRollupWriter";
|
|
24
|
+
import { BURST_THRESHOLD } from "../../../Server/Utils/EmailRollup/EmailRollupConstants";
|
|
25
|
+
import logger from "../../../Server/Utils/Logger";
|
|
26
|
+
import UserCall from "../../../Models/DatabaseModels/UserCall";
|
|
27
|
+
import UserEmail from "../../../Models/DatabaseModels/UserEmail";
|
|
28
|
+
import UserMicrosoftTeams from "../../../Models/DatabaseModels/UserMicrosoftTeams";
|
|
29
|
+
import UserNotificationEmailRollupItem from "../../../Models/DatabaseModels/UserNotificationEmailRollupItem";
|
|
30
|
+
import UserNotificationSetting from "../../../Models/DatabaseModels/UserNotificationSetting";
|
|
31
|
+
import UserSlack from "../../../Models/DatabaseModels/UserSlack";
|
|
32
|
+
import UserSMS from "../../../Models/DatabaseModels/UserSMS";
|
|
33
|
+
import UserTelegram from "../../../Models/DatabaseModels/UserTelegram";
|
|
34
|
+
import UserWebhook from "../../../Models/DatabaseModels/UserWebhook";
|
|
35
|
+
import UserWhatsApp from "../../../Models/DatabaseModels/UserWhatsApp";
|
|
36
|
+
import { CallRequestMessage } from "../../../Types/Call/CallRequest";
|
|
37
|
+
import { EmailEnvelope } from "../../../Types/Email/EmailMessage";
|
|
38
|
+
import EmailTemplateType from "../../../Types/Email/EmailTemplateType";
|
|
39
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
40
|
+
import NotificationSettingEventType from "../../../Types/NotificationSetting/NotificationSettingEventType";
|
|
41
|
+
import Email from "../../../Types/Email";
|
|
42
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
43
|
+
import PositiveNumber from "../../../Types/PositiveNumber";
|
|
44
|
+
import PushNotificationMessage from "../../../Types/PushNotification/PushNotificationMessage";
|
|
45
|
+
import { SMSMessage } from "../../../Types/SMS/SMS";
|
|
46
|
+
import TelegramMessage from "../../../Types/Telegram/TelegramMessage";
|
|
47
|
+
import { WhatsAppMessagePayload } from "../../../Types/WhatsApp/WhatsAppMessage";
|
|
48
|
+
import {
|
|
49
|
+
WorkspaceMessageBlock,
|
|
50
|
+
WorkspacePayloadMarkdown,
|
|
51
|
+
} from "../../../Types/Workspace/WorkspaceMessagePayload";
|
|
52
|
+
import fs from "fs";
|
|
53
|
+
import path from "path";
|
|
54
|
+
import { describe, expect, test, beforeEach, afterEach } from "@jest/globals";
|
|
55
|
+
|
|
56
|
+
/*
|
|
57
|
+
* sendUserNotification's email branch now runs through EmailRollupWriter
|
|
58
|
+
* instead of calling MailService directly. That single line is the whole
|
|
59
|
+
* feature, and it sits above eight other delivery channels. What breaks in
|
|
60
|
+
* production if the behaviour pinned here regresses:
|
|
61
|
+
*
|
|
62
|
+
* 1. A DEFERRED EMAIL SILENCES THE OTHER CHANNELS. Holding an email back
|
|
63
|
+
* must hold back the EMAIL, and nothing else. SMS, call, push, WhatsApp,
|
|
64
|
+
* Telegram, Slack, Microsoft Teams and webhook are separate opt-ins that
|
|
65
|
+
* a user may be relying on precisely because email is noisy; if a
|
|
66
|
+
* deferral suppressed them the feature would be dropping notifications,
|
|
67
|
+
* not batching them.
|
|
68
|
+
*
|
|
69
|
+
* 2. THE ENVELOPE GETS MUTATED. The Telegram fallback body and the Slack /
|
|
70
|
+
* Microsoft Teams markdown are both synthesised from
|
|
71
|
+
* data.emailEnvelope.subject AFTER the email branch has run. A writer
|
|
72
|
+
* that reused the envelope object to stash a truncated or brace-stripped
|
|
73
|
+
* subject would silently rewrite three other channels' messages.
|
|
74
|
+
*
|
|
75
|
+
* 3. ONE ADDRESS TAKES DOWN THE REST. The call the writer replaced was
|
|
76
|
+
* fire-and-forget, so a failure for one verified address could not affect
|
|
77
|
+
* another - or any later channel. The replacement is awaited, which
|
|
78
|
+
* re-opens that door unless the loop keeps it shut.
|
|
79
|
+
*
|
|
80
|
+
* 4. THE ENQUEUE IS NOT AWAITED. If sendUserNotification could return before
|
|
81
|
+
* the ledger row exists, a worker that exits after its last notification
|
|
82
|
+
* loses the row: the burst counter under-counts and a deferred email is
|
|
83
|
+
* never queued for anyone to flush.
|
|
84
|
+
*
|
|
85
|
+
* 5. forceImmediate DOES NOT REACH THE WRITER. It is the only way an SLA
|
|
86
|
+
* breach - which borrows the incident-created event type - can say it is
|
|
87
|
+
* urgent. Dropped in the hand-off, it fails silently and only under load.
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
const PROJECT_ID: ObjectID = new ObjectID(
|
|
91
|
+
"11111111-1111-4111-8111-111111111111",
|
|
92
|
+
);
|
|
93
|
+
const USER_ID: ObjectID = new ObjectID("22222222-2222-4222-8222-222222222222");
|
|
94
|
+
const INCIDENT_ID: ObjectID = new ObjectID(
|
|
95
|
+
"33333333-3333-4333-8333-333333333333",
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const SUBJECT: string = "Incident created: Checkout is down {{notATemplate}}";
|
|
99
|
+
const SMS_BODY: string = "OneUptime: New incident created: Checkout is down.";
|
|
100
|
+
|
|
101
|
+
const EVENT_TYPE: NotificationSettingEventType =
|
|
102
|
+
NotificationSettingEventType.SEND_INCIDENT_CREATED_OWNER_NOTIFICATION;
|
|
103
|
+
const ON_CALL_ROSTER_EVENT: NotificationSettingEventType =
|
|
104
|
+
NotificationSettingEventType.SEND_WHEN_USER_IS_ON_CALL_ROSTER;
|
|
105
|
+
|
|
106
|
+
type SendUserNotificationData = Parameters<
|
|
107
|
+
typeof UserNotificationSettingService.sendUserNotification
|
|
108
|
+
>[0];
|
|
109
|
+
|
|
110
|
+
function allChannelsOn(): UserNotificationSetting {
|
|
111
|
+
return {
|
|
112
|
+
alertByEmail: true,
|
|
113
|
+
alertBySMS: true,
|
|
114
|
+
alertByCall: true,
|
|
115
|
+
alertByPush: true,
|
|
116
|
+
alertByWhatsApp: true,
|
|
117
|
+
alertByTelegram: true,
|
|
118
|
+
alertBySlack: true,
|
|
119
|
+
alertByMicrosoftTeams: true,
|
|
120
|
+
alertByWebhook: true,
|
|
121
|
+
} as unknown as UserNotificationSetting;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function buildEnvelope(): EmailEnvelope {
|
|
125
|
+
return {
|
|
126
|
+
subject: SUBJECT,
|
|
127
|
+
templateType: EmailTemplateType.BlankTemplate,
|
|
128
|
+
vars: {
|
|
129
|
+
incidentViewLink: "https://oneuptime.com/dashboard/incidents/1",
|
|
130
|
+
},
|
|
131
|
+
} as unknown as EmailEnvelope;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function notificationData(
|
|
135
|
+
overrides: Partial<SendUserNotificationData> = {},
|
|
136
|
+
): SendUserNotificationData {
|
|
137
|
+
return {
|
|
138
|
+
userId: USER_ID,
|
|
139
|
+
projectId: PROJECT_ID,
|
|
140
|
+
eventType: EVENT_TYPE,
|
|
141
|
+
emailEnvelope: buildEnvelope(),
|
|
142
|
+
smsMessage: { message: SMS_BODY } as SMSMessage,
|
|
143
|
+
callRequestMessage: {} as CallRequestMessage,
|
|
144
|
+
pushNotificationMessage: {} as PushNotificationMessage,
|
|
145
|
+
whatsAppMessage: {} as WhatsAppMessagePayload,
|
|
146
|
+
incidentId: INCIDENT_ID,
|
|
147
|
+
...overrides,
|
|
148
|
+
} as SendUserNotificationData;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/*
|
|
152
|
+
* The SLA-breach job lives in App and Common cannot import it, so the one
|
|
153
|
+
* assertion that can be made about it from here is made against its source
|
|
154
|
+
* text. Section (F) explains why that is worth doing at all.
|
|
155
|
+
*/
|
|
156
|
+
const COMMON_DIR: string = path.resolve(__dirname, "../../..");
|
|
157
|
+
const APP_DIR: string = path.resolve(COMMON_DIR, "../App");
|
|
158
|
+
const SLA_BREACH_JOB_PATH: string = path.join(
|
|
159
|
+
APP_DIR,
|
|
160
|
+
"FeatureSet",
|
|
161
|
+
"Workers",
|
|
162
|
+
"Jobs",
|
|
163
|
+
"IncidentSla",
|
|
164
|
+
"CheckSlaBreaches.ts",
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
type SkipStringLiteralFunction = (source: string, start: number) => number;
|
|
168
|
+
|
|
169
|
+
/*
|
|
170
|
+
* The index just past the string literal that starts at `start`. Escapes are
|
|
171
|
+
* honoured, so a quote inside a string cannot end it early.
|
|
172
|
+
*/
|
|
173
|
+
const skipStringLiteral: SkipStringLiteralFunction = (
|
|
174
|
+
source: string,
|
|
175
|
+
start: number,
|
|
176
|
+
): number => {
|
|
177
|
+
const quote: string = source.charAt(start);
|
|
178
|
+
let index: number = start + 1;
|
|
179
|
+
|
|
180
|
+
while (index < source.length) {
|
|
181
|
+
const character: string = source.charAt(index);
|
|
182
|
+
|
|
183
|
+
if (character === "\\") {
|
|
184
|
+
index = index + 2;
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (character === quote) {
|
|
189
|
+
return index + 1;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
index = index + 1;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return source.length;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
type ExtractCallArgumentsFunction = (
|
|
199
|
+
source: string,
|
|
200
|
+
callee: string,
|
|
201
|
+
) => string | null;
|
|
202
|
+
|
|
203
|
+
/*
|
|
204
|
+
* The text between the parentheses of the first call to `callee`, with
|
|
205
|
+
* comments and string bodies blanked out. Null when there is no such call,
|
|
206
|
+
* which is what makes "somebody renamed the call away" a failure rather than
|
|
207
|
+
* a vacuous pass.
|
|
208
|
+
*
|
|
209
|
+
* A character scan rather than a regex, on purpose. The argument object spans
|
|
210
|
+
* twenty lines and the whole point of the assertion is that it survives
|
|
211
|
+
* reformatting, so nothing here may depend on where the newlines fall.
|
|
212
|
+
* Blanking comments is what stops the prose ABOVE a property from satisfying
|
|
213
|
+
* an assertion about the property; skipping string bodies is what stops a
|
|
214
|
+
* parenthesis inside a message from ending the call early.
|
|
215
|
+
*/
|
|
216
|
+
const extractCallArguments: ExtractCallArgumentsFunction = (
|
|
217
|
+
source: string,
|
|
218
|
+
callee: string,
|
|
219
|
+
): string | null => {
|
|
220
|
+
const calleeIndex: number = source.indexOf(callee);
|
|
221
|
+
|
|
222
|
+
if (calleeIndex < 0) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const openIndex: number = source.indexOf("(", calleeIndex + callee.length);
|
|
227
|
+
|
|
228
|
+
if (openIndex < 0) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const collected: Array<string> = [];
|
|
233
|
+
let depth: number = 0;
|
|
234
|
+
let index: number = openIndex;
|
|
235
|
+
|
|
236
|
+
while (index < source.length) {
|
|
237
|
+
const character: string = source.charAt(index);
|
|
238
|
+
const nextCharacter: string = source.charAt(index + 1);
|
|
239
|
+
|
|
240
|
+
if (character === "/" && nextCharacter === "*") {
|
|
241
|
+
const end: number = source.indexOf("*/", index + 2);
|
|
242
|
+
index = end < 0 ? source.length : end + 2;
|
|
243
|
+
collected.push(" ");
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (character === "/" && nextCharacter === "/") {
|
|
248
|
+
const end: number = source.indexOf("\n", index + 2);
|
|
249
|
+
index = end < 0 ? source.length : end;
|
|
250
|
+
collected.push(" ");
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (character === '"' || character === "'" || character === "`") {
|
|
255
|
+
index = skipStringLiteral(source, index);
|
|
256
|
+
collected.push('""');
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (character === "(") {
|
|
261
|
+
depth = depth + 1;
|
|
262
|
+
index = index + 1;
|
|
263
|
+
|
|
264
|
+
if (depth > 1) {
|
|
265
|
+
collected.push(character);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (character === ")") {
|
|
272
|
+
depth = depth - 1;
|
|
273
|
+
index = index + 1;
|
|
274
|
+
|
|
275
|
+
if (depth === 0) {
|
|
276
|
+
return collected.join("");
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
collected.push(character);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
collected.push(character);
|
|
284
|
+
index = index + 1;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return null;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
describe("UserNotificationSettingService.sendUserNotification - rollup routing", () => {
|
|
291
|
+
let findSettings: jest.SpyInstance;
|
|
292
|
+
let findEmails: jest.SpyInstance;
|
|
293
|
+
let sendMail: jest.SpyInstance;
|
|
294
|
+
let countRecent: jest.SpyInstance;
|
|
295
|
+
let createItem: jest.SpyInstance;
|
|
296
|
+
let sendSms: jest.SpyInstance;
|
|
297
|
+
let makeCall: jest.SpyInstance;
|
|
298
|
+
let sendPush: jest.SpyInstance;
|
|
299
|
+
let sendWhatsApp: jest.SpyInstance;
|
|
300
|
+
let sendTelegram: jest.SpyInstance;
|
|
301
|
+
let sendDm: jest.SpyInstance;
|
|
302
|
+
let sendWebhook: jest.SpyInstance;
|
|
303
|
+
let loggerError: jest.SpyInstance;
|
|
304
|
+
|
|
305
|
+
beforeEach(() => {
|
|
306
|
+
loggerError = jest.spyOn(logger, "error").mockImplementation((): void => {
|
|
307
|
+
return undefined;
|
|
308
|
+
});
|
|
309
|
+
jest.spyOn(logger, "warn").mockImplementation((): void => {
|
|
310
|
+
return undefined;
|
|
311
|
+
});
|
|
312
|
+
jest.spyOn(logger, "debug").mockImplementation((): void => {
|
|
313
|
+
return undefined;
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
findSettings = jest
|
|
317
|
+
.spyOn(UserNotificationSettingService, "findOneBy")
|
|
318
|
+
.mockResolvedValue(allChannelsOn() as never);
|
|
319
|
+
|
|
320
|
+
jest
|
|
321
|
+
.spyOn(ProjectCallSMSConfigService, "getProjectDefaultTwilioConfig")
|
|
322
|
+
.mockResolvedValue(undefined as never);
|
|
323
|
+
|
|
324
|
+
findEmails = jest.spyOn(UserEmailService, "findBy").mockResolvedValue([
|
|
325
|
+
{
|
|
326
|
+
email: "owner@example.com",
|
|
327
|
+
} as unknown as UserEmail,
|
|
328
|
+
] as never);
|
|
329
|
+
|
|
330
|
+
sendMail = jest
|
|
331
|
+
.spyOn(MailService, "sendMail")
|
|
332
|
+
.mockResolvedValue(undefined as never);
|
|
333
|
+
|
|
334
|
+
countRecent = jest
|
|
335
|
+
.spyOn(UserNotificationEmailRollupItemService, "countBy")
|
|
336
|
+
.mockResolvedValue(new PositiveNumber(0) as never);
|
|
337
|
+
|
|
338
|
+
createItem = jest
|
|
339
|
+
.spyOn(UserNotificationEmailRollupItemService, "create")
|
|
340
|
+
.mockResolvedValue(new UserNotificationEmailRollupItem() as never);
|
|
341
|
+
|
|
342
|
+
/*
|
|
343
|
+
* The absent-row answer, which is what almost every real user has. Without
|
|
344
|
+
* it the writer reaches the real preference read, that read reaches a
|
|
345
|
+
* Postgres this suite does not have, and the throw lands in the writer's
|
|
346
|
+
* fail-open catch - so every deferral assertion below would quietly become
|
|
347
|
+
* an assertion about what an unreachable database does, and pass or fail
|
|
348
|
+
* for the wrong reason. The escape hatch's own behaviour is pinned in
|
|
349
|
+
* Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts; here it is
|
|
350
|
+
* held constant so the routing between channels is what is being measured.
|
|
351
|
+
*/
|
|
352
|
+
jest
|
|
353
|
+
.spyOn(
|
|
354
|
+
UserNotificationEmailRollupSettingService,
|
|
355
|
+
"isRollupEnabledForUser",
|
|
356
|
+
)
|
|
357
|
+
.mockResolvedValue(true as never);
|
|
358
|
+
|
|
359
|
+
jest.spyOn(UserSmsService, "findBy").mockResolvedValue([
|
|
360
|
+
{
|
|
361
|
+
phone: "+15550000001",
|
|
362
|
+
} as unknown as UserSMS,
|
|
363
|
+
] as never);
|
|
364
|
+
sendSms = jest
|
|
365
|
+
.spyOn(SmsService, "sendSms")
|
|
366
|
+
.mockResolvedValue(undefined as never);
|
|
367
|
+
|
|
368
|
+
jest.spyOn(UserCallService, "findBy").mockResolvedValue([
|
|
369
|
+
{
|
|
370
|
+
phone: "+15550000002",
|
|
371
|
+
} as unknown as UserCall,
|
|
372
|
+
] as never);
|
|
373
|
+
makeCall = jest
|
|
374
|
+
.spyOn(CallService, "makeCall")
|
|
375
|
+
.mockResolvedValue(undefined as never);
|
|
376
|
+
|
|
377
|
+
sendPush = jest
|
|
378
|
+
.spyOn(PushNotificationService, "sendPushNotificationToUser")
|
|
379
|
+
.mockResolvedValue(undefined as never);
|
|
380
|
+
|
|
381
|
+
jest.spyOn(UserWhatsAppService, "findBy").mockResolvedValue([
|
|
382
|
+
{
|
|
383
|
+
phone: "+15550000003",
|
|
384
|
+
} as unknown as UserWhatsApp,
|
|
385
|
+
] as never);
|
|
386
|
+
sendWhatsApp = jest
|
|
387
|
+
.spyOn(WhatsAppService, "sendWhatsAppMessage")
|
|
388
|
+
.mockResolvedValue(undefined as never);
|
|
389
|
+
|
|
390
|
+
jest.spyOn(UserTelegramService, "findBy").mockResolvedValue([
|
|
391
|
+
{
|
|
392
|
+
telegramChatId: "telegram-chat-1",
|
|
393
|
+
} as unknown as UserTelegram,
|
|
394
|
+
] as never);
|
|
395
|
+
sendTelegram = jest
|
|
396
|
+
.spyOn(TelegramService, "sendTelegramMessage")
|
|
397
|
+
.mockResolvedValue(undefined as never);
|
|
398
|
+
|
|
399
|
+
jest.spyOn(UserSlackService, "findBy").mockResolvedValue([
|
|
400
|
+
{
|
|
401
|
+
slackUserId: "U0123ABCD",
|
|
402
|
+
} as unknown as UserSlack,
|
|
403
|
+
] as never);
|
|
404
|
+
jest.spyOn(UserMicrosoftTeamsService, "findBy").mockResolvedValue([
|
|
405
|
+
{
|
|
406
|
+
microsoftTeamsUserId: "entra-object-id-1",
|
|
407
|
+
} as unknown as UserMicrosoftTeams,
|
|
408
|
+
] as never);
|
|
409
|
+
sendDm = jest
|
|
410
|
+
.spyOn(WorkspaceUserNotificationService, "sendDirectMessageToUser")
|
|
411
|
+
.mockResolvedValue(undefined as never);
|
|
412
|
+
|
|
413
|
+
jest.spyOn(UserWebhookService, "findBy").mockResolvedValue([
|
|
414
|
+
{
|
|
415
|
+
webhookUrl: "https://example.com/hook",
|
|
416
|
+
name: "hook",
|
|
417
|
+
} as unknown as UserWebhook,
|
|
418
|
+
] as never);
|
|
419
|
+
sendWebhook = jest
|
|
420
|
+
.spyOn(WebhookService, "sendWebhook")
|
|
421
|
+
.mockResolvedValue(undefined as never);
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
afterEach(() => {
|
|
425
|
+
jest.restoreAllMocks();
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
/*
|
|
429
|
+
* A macrotask, not a microtask hop: the awaited chain inside
|
|
430
|
+
* sendUserNotification is several promises deep, and a fixed number of
|
|
431
|
+
* `await Promise.resolve()` hops would silently start passing (or failing)
|
|
432
|
+
* whenever that depth changes.
|
|
433
|
+
*/
|
|
434
|
+
function flushPendingWork(): Promise<void> {
|
|
435
|
+
return new Promise<void>((resolve: () => void): void => {
|
|
436
|
+
setTimeout(resolve, 0);
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function deferEveryEmail(): void {
|
|
441
|
+
countRecent.mockResolvedValue(
|
|
442
|
+
new PositiveNumber(BURST_THRESHOLD + 1) as never,
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/*
|
|
447
|
+
* ----------------------------------------------------------------------- *
|
|
448
|
+
* (A) A deferred email leaves every other channel alone.
|
|
449
|
+
* -----------------------------------------------------------------------
|
|
450
|
+
*/
|
|
451
|
+
|
|
452
|
+
describe("when the writer defers the email", () => {
|
|
453
|
+
test("no mail is sent but a pending ledger row is written", async () => {
|
|
454
|
+
deferEveryEmail();
|
|
455
|
+
|
|
456
|
+
await UserNotificationSettingService.sendUserNotification(
|
|
457
|
+
notificationData(),
|
|
458
|
+
);
|
|
459
|
+
|
|
460
|
+
expect(findEmails).toHaveBeenCalledTimes(1);
|
|
461
|
+
expect(sendMail).not.toHaveBeenCalled();
|
|
462
|
+
expect(createItem).toHaveBeenCalledTimes(1);
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
test("every other channel still fires", async () => {
|
|
466
|
+
deferEveryEmail();
|
|
467
|
+
|
|
468
|
+
await UserNotificationSettingService.sendUserNotification(
|
|
469
|
+
notificationData(),
|
|
470
|
+
);
|
|
471
|
+
|
|
472
|
+
expect(sendSms).toHaveBeenCalledTimes(1);
|
|
473
|
+
expect(makeCall).toHaveBeenCalledTimes(1);
|
|
474
|
+
expect(sendPush).toHaveBeenCalledTimes(1);
|
|
475
|
+
expect(sendWhatsApp).toHaveBeenCalledTimes(1);
|
|
476
|
+
expect(sendTelegram).toHaveBeenCalledTimes(1);
|
|
477
|
+
// One Slack DM and one Microsoft Teams DM.
|
|
478
|
+
expect(sendDm).toHaveBeenCalledTimes(2);
|
|
479
|
+
expect(sendWebhook).toHaveBeenCalledTimes(1);
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
test("the channels that synthesise from the email subject use the ORIGINAL subject", async () => {
|
|
483
|
+
deferEveryEmail();
|
|
484
|
+
|
|
485
|
+
await UserNotificationSettingService.sendUserNotification(
|
|
486
|
+
notificationData(),
|
|
487
|
+
);
|
|
488
|
+
|
|
489
|
+
const telegram: TelegramMessage = sendTelegram.mock
|
|
490
|
+
.calls[0]?.[0] as TelegramMessage;
|
|
491
|
+
expect(telegram.body).toContain(SUBJECT);
|
|
492
|
+
|
|
493
|
+
const workspaceBlocks: Array<WorkspaceMessageBlock> = (
|
|
494
|
+
sendDm.mock.calls[0]?.[0] as {
|
|
495
|
+
messageBlocks: Array<WorkspaceMessageBlock>;
|
|
496
|
+
}
|
|
497
|
+
).messageBlocks;
|
|
498
|
+
expect((workspaceBlocks[0] as WorkspacePayloadMarkdown).text).toContain(
|
|
499
|
+
SUBJECT,
|
|
500
|
+
);
|
|
501
|
+
|
|
502
|
+
const webhookPayload: JSONObject = (
|
|
503
|
+
sendWebhook.mock.calls[0]?.[0] as { payload: JSONObject }
|
|
504
|
+
).payload;
|
|
505
|
+
expect(webhookPayload["subject"]).toBe(SUBJECT);
|
|
506
|
+
});
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
/*
|
|
510
|
+
* ----------------------------------------------------------------------- *
|
|
511
|
+
* (B) The envelope is never mutated.
|
|
512
|
+
* -----------------------------------------------------------------------
|
|
513
|
+
*/
|
|
514
|
+
|
|
515
|
+
describe("the email envelope", () => {
|
|
516
|
+
test("is deep-equal before and after the call, whether the email is deferred", async () => {
|
|
517
|
+
deferEveryEmail();
|
|
518
|
+
|
|
519
|
+
const data: SendUserNotificationData = notificationData();
|
|
520
|
+
const snapshot: string = JSON.stringify(data.emailEnvelope);
|
|
521
|
+
|
|
522
|
+
await UserNotificationSettingService.sendUserNotification(data);
|
|
523
|
+
|
|
524
|
+
expect(JSON.stringify(data.emailEnvelope)).toBe(snapshot);
|
|
525
|
+
expect(data.emailEnvelope.subject).toBe(SUBJECT);
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
test("is deep-equal before and after the call when the email is sent immediately", async () => {
|
|
529
|
+
/*
|
|
530
|
+
* The immediate path is the one that stores a brace-stripped, truncated
|
|
531
|
+
* copy of the subject, so it is the one where a careless writer would be
|
|
532
|
+
* tempted to edit the envelope in place.
|
|
533
|
+
*/
|
|
534
|
+
const data: SendUserNotificationData = notificationData();
|
|
535
|
+
const snapshot: string = JSON.stringify(data.emailEnvelope);
|
|
536
|
+
|
|
537
|
+
await UserNotificationSettingService.sendUserNotification(data);
|
|
538
|
+
|
|
539
|
+
expect(sendMail).toHaveBeenCalledTimes(1);
|
|
540
|
+
expect(JSON.stringify(data.emailEnvelope)).toBe(snapshot);
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
/*
|
|
545
|
+
* ----------------------------------------------------------------------- *
|
|
546
|
+
* (C) Per-address fan-out and isolation.
|
|
547
|
+
* -----------------------------------------------------------------------
|
|
548
|
+
*/
|
|
549
|
+
|
|
550
|
+
describe("per-address fan-out", () => {
|
|
551
|
+
function threeVerifiedAddresses(): void {
|
|
552
|
+
findEmails.mockResolvedValue([
|
|
553
|
+
{ email: "first@example.com" } as unknown as UserEmail,
|
|
554
|
+
{ email: "second@example.com" } as unknown as UserEmail,
|
|
555
|
+
{ email: "third@example.com" } as unknown as UserEmail,
|
|
556
|
+
] as never);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
test("each verified address gets its own hand-off to the writer", async () => {
|
|
560
|
+
threeVerifiedAddresses();
|
|
561
|
+
|
|
562
|
+
const sendOrRollup: jest.SpyInstance = jest
|
|
563
|
+
.spyOn(EmailRollupWriter, "sendOrRollup")
|
|
564
|
+
.mockResolvedValue(undefined as never);
|
|
565
|
+
|
|
566
|
+
await UserNotificationSettingService.sendUserNotification(
|
|
567
|
+
notificationData(),
|
|
568
|
+
);
|
|
569
|
+
|
|
570
|
+
expect(sendOrRollup).toHaveBeenCalledTimes(3);
|
|
571
|
+
|
|
572
|
+
const addresses: Array<string> = sendOrRollup.mock.calls.map(
|
|
573
|
+
(call: Array<unknown>): string => {
|
|
574
|
+
return (call[0] as SendOrRollupData).toEmail.toString();
|
|
575
|
+
},
|
|
576
|
+
);
|
|
577
|
+
expect(addresses).toEqual([
|
|
578
|
+
"first@example.com",
|
|
579
|
+
"second@example.com",
|
|
580
|
+
"third@example.com",
|
|
581
|
+
]);
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
test("a throw for the middle address costs neither the other two nor the other channels", async () => {
|
|
585
|
+
threeVerifiedAddresses();
|
|
586
|
+
|
|
587
|
+
const sendOrRollup: jest.SpyInstance = jest
|
|
588
|
+
.spyOn(EmailRollupWriter, "sendOrRollup")
|
|
589
|
+
.mockImplementation((data: SendOrRollupData): Promise<void> => {
|
|
590
|
+
if (data.toEmail.toString() === "second@example.com") {
|
|
591
|
+
return Promise.reject(new Error("writer exploded"));
|
|
592
|
+
}
|
|
593
|
+
return Promise.resolve();
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
await expect(
|
|
597
|
+
UserNotificationSettingService.sendUserNotification(notificationData()),
|
|
598
|
+
).resolves.toBeUndefined();
|
|
599
|
+
|
|
600
|
+
expect(sendOrRollup).toHaveBeenCalledTimes(3);
|
|
601
|
+
expect(loggerError).toHaveBeenCalledTimes(1);
|
|
602
|
+
|
|
603
|
+
// The eight non-email channels below the loop still ran.
|
|
604
|
+
expect(sendSms).toHaveBeenCalledTimes(1);
|
|
605
|
+
expect(makeCall).toHaveBeenCalledTimes(1);
|
|
606
|
+
expect(sendPush).toHaveBeenCalledTimes(1);
|
|
607
|
+
expect(sendWhatsApp).toHaveBeenCalledTimes(1);
|
|
608
|
+
expect(sendTelegram).toHaveBeenCalledTimes(1);
|
|
609
|
+
expect(sendDm).toHaveBeenCalledTimes(2);
|
|
610
|
+
expect(sendWebhook).toHaveBeenCalledTimes(1);
|
|
611
|
+
});
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
/*
|
|
615
|
+
* ----------------------------------------------------------------------- *
|
|
616
|
+
* (D) The enqueue is awaited.
|
|
617
|
+
* -----------------------------------------------------------------------
|
|
618
|
+
*/
|
|
619
|
+
|
|
620
|
+
describe("the enqueue", () => {
|
|
621
|
+
test("sendUserNotification does not resolve before the ledger write settles", async () => {
|
|
622
|
+
let releaseCreate: (row: UserNotificationEmailRollupItem) => void = (
|
|
623
|
+
_row: UserNotificationEmailRollupItem,
|
|
624
|
+
): void => {
|
|
625
|
+
return undefined;
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
const gate: Promise<UserNotificationEmailRollupItem> =
|
|
629
|
+
new Promise<UserNotificationEmailRollupItem>(
|
|
630
|
+
(resolve: (row: UserNotificationEmailRollupItem) => void): void => {
|
|
631
|
+
releaseCreate = resolve;
|
|
632
|
+
},
|
|
633
|
+
);
|
|
634
|
+
|
|
635
|
+
createItem.mockReturnValue(gate);
|
|
636
|
+
|
|
637
|
+
let settled: boolean = false;
|
|
638
|
+
const pending: Promise<void> =
|
|
639
|
+
UserNotificationSettingService.sendUserNotification(
|
|
640
|
+
notificationData(),
|
|
641
|
+
).then((): void => {
|
|
642
|
+
settled = true;
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
await flushPendingWork();
|
|
646
|
+
expect(createItem).toHaveBeenCalledTimes(1);
|
|
647
|
+
expect(settled).toBe(false);
|
|
648
|
+
|
|
649
|
+
releaseCreate(new UserNotificationEmailRollupItem());
|
|
650
|
+
await pending;
|
|
651
|
+
|
|
652
|
+
expect(settled).toBe(true);
|
|
653
|
+
});
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
/*
|
|
657
|
+
* ----------------------------------------------------------------------- *
|
|
658
|
+
* (E) forceImmediate threads through, and the on-call bypass survives the
|
|
659
|
+
* round trip through the seam.
|
|
660
|
+
* -----------------------------------------------------------------------
|
|
661
|
+
*/
|
|
662
|
+
|
|
663
|
+
describe("forceImmediate and the on-call bypass", () => {
|
|
664
|
+
test("forceImmediate reaches the writer when the caller sets it", async () => {
|
|
665
|
+
const sendOrRollup: jest.SpyInstance = jest
|
|
666
|
+
.spyOn(EmailRollupWriter, "sendOrRollup")
|
|
667
|
+
.mockResolvedValue(undefined as never);
|
|
668
|
+
|
|
669
|
+
await UserNotificationSettingService.sendUserNotification(
|
|
670
|
+
notificationData({ forceImmediate: true }),
|
|
671
|
+
);
|
|
672
|
+
|
|
673
|
+
expect(
|
|
674
|
+
(sendOrRollup.mock.calls[0]?.[0] as SendOrRollupData).forceImmediate,
|
|
675
|
+
).toBe(true);
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
test("the key is absent entirely when the caller does not set it", async () => {
|
|
679
|
+
/*
|
|
680
|
+
* Spread-conditional rather than `forceImmediate: data.forceImmediate`,
|
|
681
|
+
* because exactOptionalPropertyTypes is on: an explicit undefined would
|
|
682
|
+
* not compile against an optional property.
|
|
683
|
+
*/
|
|
684
|
+
const sendOrRollup: jest.SpyInstance = jest
|
|
685
|
+
.spyOn(EmailRollupWriter, "sendOrRollup")
|
|
686
|
+
.mockResolvedValue(undefined as never);
|
|
687
|
+
|
|
688
|
+
await UserNotificationSettingService.sendUserNotification(
|
|
689
|
+
notificationData(),
|
|
690
|
+
);
|
|
691
|
+
|
|
692
|
+
expect(
|
|
693
|
+
"forceImmediate" in
|
|
694
|
+
(sendOrRollup.mock.calls[0]?.[0] as SendOrRollupData),
|
|
695
|
+
).toBe(false);
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
test("forceImmediate sends immediately end to end, with no counting and no row", async () => {
|
|
699
|
+
deferEveryEmail();
|
|
700
|
+
|
|
701
|
+
await UserNotificationSettingService.sendUserNotification(
|
|
702
|
+
notificationData({ forceImmediate: true }),
|
|
703
|
+
);
|
|
704
|
+
|
|
705
|
+
expect(sendMail).toHaveBeenCalledTimes(1);
|
|
706
|
+
expect(countRecent).not.toHaveBeenCalled();
|
|
707
|
+
expect(createItem).not.toHaveBeenCalled();
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
test("a never-rolled-up event type comes straight back out as an immediate send", async () => {
|
|
711
|
+
/*
|
|
712
|
+
* Driven through the real writer with the counter armed high, so this
|
|
713
|
+
* fails if the eligibility check is ever moved below the count.
|
|
714
|
+
*/
|
|
715
|
+
deferEveryEmail();
|
|
716
|
+
findSettings.mockResolvedValue(allChannelsOn() as never);
|
|
717
|
+
|
|
718
|
+
await UserNotificationSettingService.sendUserNotification(
|
|
719
|
+
notificationData({ eventType: ON_CALL_ROSTER_EVENT }),
|
|
720
|
+
);
|
|
721
|
+
|
|
722
|
+
expect(sendMail).toHaveBeenCalledTimes(1);
|
|
723
|
+
expect(countRecent).not.toHaveBeenCalled();
|
|
724
|
+
expect(createItem).not.toHaveBeenCalled();
|
|
725
|
+
expect(loggerError).not.toHaveBeenCalled();
|
|
726
|
+
});
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
/*
|
|
730
|
+
* ----------------------------------------------------------------------- *
|
|
731
|
+
* (F) The SLA-breach bypass - the only caller of forceImmediate there is.
|
|
732
|
+
*
|
|
733
|
+
* Every other "must never be delayed" case in this design is excluded
|
|
734
|
+
* STRUCTURALLY: NEVER_ROLLED_UP_EVENT_TYPES is a property of the event type
|
|
735
|
+
* itself, so no caller can forget it and no reviewer has to remember it.
|
|
736
|
+
* The SLA-breach job is the one exception. It sends under
|
|
737
|
+
* EmailTemplateType.IncidentOwnerResourceCreated and reuses
|
|
738
|
+
* SEND_INCIDENT_CREATED_OWNER_NOTIFICATION, so its event type cannot say
|
|
739
|
+
* "this deadline has already passed" - only the caller knows that, and it
|
|
740
|
+
* says so with one property in a twenty-line object literal.
|
|
741
|
+
*
|
|
742
|
+
* A property like that gets deleted by accident: in a rebase, in a
|
|
743
|
+
* find-and-replace, by a reformat that drops a line. Nothing downstream
|
|
744
|
+
* notices. The mail still goes out - five minutes late, batched with the
|
|
745
|
+
* incident chatter that caused the breach, and only for the projects noisy
|
|
746
|
+
* enough to cross the threshold, which are exactly the projects whose SLA
|
|
747
|
+
* breaches matter most. So it is pinned twice: as behaviour at the seam,
|
|
748
|
+
* and as source text at the caller, because Common cannot import App.
|
|
749
|
+
* -----------------------------------------------------------------------
|
|
750
|
+
*/
|
|
751
|
+
|
|
752
|
+
describe("the SLA-breach bypass", () => {
|
|
753
|
+
test("far past the burst threshold, forceImmediate is the only reason the mail goes out", async () => {
|
|
754
|
+
/*
|
|
755
|
+
* Twenty-five times the threshold: a recipient this deep into a burst
|
|
756
|
+
* has every other rollup-eligible email deferred, which is what makes
|
|
757
|
+
* the control at the bottom of this test the real assertion.
|
|
758
|
+
*/
|
|
759
|
+
countRecent.mockResolvedValue(
|
|
760
|
+
new PositiveNumber(BURST_THRESHOLD * 25) as never,
|
|
761
|
+
);
|
|
762
|
+
|
|
763
|
+
await UserNotificationSettingService.sendUserNotification(
|
|
764
|
+
notificationData({ forceImmediate: true }),
|
|
765
|
+
);
|
|
766
|
+
|
|
767
|
+
expect(sendMail).toHaveBeenCalledTimes(1);
|
|
768
|
+
|
|
769
|
+
const delivered: EmailEnvelope & { toEmail: Email } = sendMail.mock
|
|
770
|
+
.calls[0]?.[0] as EmailEnvelope & { toEmail: Email };
|
|
771
|
+
expect(delivered.subject).toBe(SUBJECT);
|
|
772
|
+
expect(delivered.toEmail.toString()).toBe("owner@example.com");
|
|
773
|
+
|
|
774
|
+
/*
|
|
775
|
+
* Not merely "sent anyway": the bypass sits above every database line,
|
|
776
|
+
* so an urgent email must not pay for the counter or the ledger row.
|
|
777
|
+
*/
|
|
778
|
+
expect(countRecent).not.toHaveBeenCalled();
|
|
779
|
+
expect(createItem).not.toHaveBeenCalled();
|
|
780
|
+
|
|
781
|
+
/*
|
|
782
|
+
* THE CONTROL. The identical notification without the flag is deferred.
|
|
783
|
+
* Without it, the assertions above would still pass in a world where
|
|
784
|
+
* forceImmediate were ignored end to end and the burst counter were the
|
|
785
|
+
* thing that was broken.
|
|
786
|
+
*/
|
|
787
|
+
sendMail.mockClear();
|
|
788
|
+
createItem.mockClear();
|
|
789
|
+
|
|
790
|
+
await UserNotificationSettingService.sendUserNotification(
|
|
791
|
+
notificationData(),
|
|
792
|
+
);
|
|
793
|
+
|
|
794
|
+
expect(sendMail).not.toHaveBeenCalled();
|
|
795
|
+
expect(createItem).toHaveBeenCalledTimes(1);
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
test("the job file is still where the two source assertions below look for it", () => {
|
|
799
|
+
/*
|
|
800
|
+
* A moved or renamed job would otherwise turn those assertions into a
|
|
801
|
+
* readFileSync throw that says nothing about what was being checked.
|
|
802
|
+
*/
|
|
803
|
+
expect(fs.existsSync(SLA_BREACH_JOB_PATH)).toBe(true);
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
test("CheckSlaBreaches asks for the bypass by name when it sends the breach notification", () => {
|
|
807
|
+
const source: string = fs.readFileSync(SLA_BREACH_JOB_PATH, "utf8");
|
|
808
|
+
|
|
809
|
+
const functionIndex: number = source.indexOf(
|
|
810
|
+
"async function sendBreachNotification",
|
|
811
|
+
);
|
|
812
|
+
expect(functionIndex).toBeGreaterThanOrEqual(0);
|
|
813
|
+
|
|
814
|
+
const argumentText: string | null = extractCallArguments(
|
|
815
|
+
source.slice(functionIndex),
|
|
816
|
+
"UserNotificationSettingService.sendUserNotification",
|
|
817
|
+
);
|
|
818
|
+
|
|
819
|
+
/*
|
|
820
|
+
* Null means sendBreachNotification no longer calls sendUserNotification
|
|
821
|
+
* at all - a bigger change than this test can judge, and one that must
|
|
822
|
+
* not be allowed to read as "the bypass is fine".
|
|
823
|
+
*/
|
|
824
|
+
expect(argumentText).not.toBeNull();
|
|
825
|
+
|
|
826
|
+
/*
|
|
827
|
+
* Whitespace- and position-insensitive: the property may sit anywhere in
|
|
828
|
+
* the object literal, formatted however prettier likes. What it may not
|
|
829
|
+
* be is absent, false, or a variable whose value this test cannot see.
|
|
830
|
+
*/
|
|
831
|
+
expect(argumentText ?? "").toMatch(
|
|
832
|
+
/(^|[{,\s])forceImmediate\s*:\s*true\s*(,|\}|$)/,
|
|
833
|
+
);
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
test("the reason the bypass is needed is still true: the job borrows the incident-created identity", () => {
|
|
837
|
+
/*
|
|
838
|
+
* The bypass exists only because this job cannot express urgency through
|
|
839
|
+
* its event type. If that ever stops being true - the job gets its own
|
|
840
|
+
* NotificationSettingEventType, or its own template - the right fix is
|
|
841
|
+
* to add that type to NEVER_ROLLED_UP_EVENT_TYPES and delete the
|
|
842
|
+
* caller-side flag, making the exclusion structural like every other
|
|
843
|
+
* one. This test going red is the prompt to do that, not a bug in
|
|
844
|
+
* itself.
|
|
845
|
+
*/
|
|
846
|
+
const source: string = fs.readFileSync(SLA_BREACH_JOB_PATH, "utf8");
|
|
847
|
+
|
|
848
|
+
expect(source).toContain(
|
|
849
|
+
"EmailTemplateType.IncidentOwnerResourceCreated",
|
|
850
|
+
);
|
|
851
|
+
expect(source).toContain(
|
|
852
|
+
"NotificationSettingEventType.SEND_INCIDENT_CREATED_OWNER_NOTIFICATION",
|
|
853
|
+
);
|
|
854
|
+
});
|
|
855
|
+
});
|
|
856
|
+
});
|