@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.
Files changed (597) hide show
  1. package/Models/AnalyticsModels/Span.ts +14 -0
  2. package/Models/DatabaseModels/EnterpriseLicense.ts +56 -0
  3. package/Models/DatabaseModels/Index.ts +10 -0
  4. package/Models/DatabaseModels/Monitor.ts +76 -0
  5. package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
  6. package/Models/DatabaseModels/NetworkDevice.ts +176 -1
  7. package/Models/DatabaseModels/NetworkSite.ts +201 -2
  8. package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
  9. package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
  10. package/Models/DatabaseModels/TelemetryException.ts +119 -0
  11. package/Models/DatabaseModels/UserNotificationEmailRollupBatch.ts +334 -0
  12. package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +370 -0
  13. package/Models/DatabaseModels/UserNotificationEmailRollupSetting.ts +282 -0
  14. package/Server/API/EnterpriseLicenseAPI.ts +391 -64
  15. package/Server/API/LlmProviderAPI.ts +137 -22
  16. package/Server/EnvironmentConfig.ts +14 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.ts +55 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.ts +31 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.ts +124 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.ts +132 -0
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.ts +79 -0
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.ts +191 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
  24. package/Server/Infrastructure/QueueWorker.ts +38 -8
  25. package/Server/Middleware/BearerTokenAuthorization.ts +12 -0
  26. package/Server/Middleware/ProjectAuthorization.ts +11 -0
  27. package/Server/Middleware/SCIMAuthorization.ts +12 -0
  28. package/Server/Middleware/TelemetryIngest.ts +11 -0
  29. package/Server/Services/AIBillingService.ts +101 -27
  30. package/Server/Services/EnterpriseLicenseInstanceService.ts +197 -0
  31. package/Server/Services/EnterpriseLicenseService.ts +55 -0
  32. package/Server/Services/Index.ts +10 -0
  33. package/Server/Services/MonitorService.ts +143 -21
  34. package/Server/Services/MonitorStatusTimelineService.ts +150 -8
  35. package/Server/Services/MonitorTemplateService.ts +217 -1
  36. package/Server/Services/NetworkAlertPolicyEngineService.ts +2159 -0
  37. package/Server/Services/NetworkAlertPolicyService.ts +944 -0
  38. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +9 -10
  39. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +60 -15
  40. package/Server/Services/NetworkDeviceService.ts +1032 -73
  41. package/Server/Services/NetworkSiteService.ts +1502 -129
  42. package/Server/Services/NetworkSiteTypeService.ts +1216 -0
  43. package/Server/Services/NetworkSnmpCredentialProfileService.ts +238 -0
  44. package/Server/Services/NotificationService.ts +118 -28
  45. package/Server/Services/ProjectService.ts +105 -48
  46. package/Server/Services/StatusPagePrivateUserService.ts +103 -3
  47. package/Server/Services/UserNotificationEmailRollupBatchService.ts +78 -0
  48. package/Server/Services/UserNotificationEmailRollupItemService.ts +79 -0
  49. package/Server/Services/UserNotificationEmailRollupSettingService.ts +113 -0
  50. package/Server/Services/UserNotificationSettingService.ts +62 -25
  51. package/Server/Services/UserService.ts +95 -0
  52. package/Server/Types/Database/QueryHelper.ts +2 -2
  53. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +14 -3
  54. package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +10 -0
  55. package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +10 -0
  56. package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +62 -1
  57. package/Server/Utils/AI/Toolbox/AlertTools.ts +15 -1
  58. package/Server/Utils/Billing/BillingFailureNoticeThrottle.ts +80 -0
  59. package/Server/Utils/DataSource/HttpFetch.ts +9 -2
  60. package/Server/Utils/EmailRollup/EmailRollupConstants.ts +98 -0
  61. package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +872 -0
  62. package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +781 -0
  63. package/Server/Utils/EmailRollup/EmailRollupWriter.ts +368 -0
  64. package/Server/Utils/LLM/LLMService.ts +78 -0
  65. package/Server/Utils/LogRedaction.ts +8 -0
  66. package/Server/Utils/Logger.ts +79 -1
  67. package/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.ts +190 -0
  68. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +9 -2
  69. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +61 -1
  70. package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +14 -0
  71. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +49 -0
  72. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +255 -4
  73. package/Server/Utils/Monitor/MonitorMetricUtil.ts +41 -0
  74. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +43 -0
  75. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +499 -19
  76. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +66 -10
  77. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +238 -44
  78. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +146 -39
  79. package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +31 -18
  80. package/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.ts +213 -0
  81. package/Server/Utils/OutboundUserAgent.ts +152 -0
  82. package/Server/Utils/StartServer.ts +51 -19
  83. package/Server/Utils/Telemetry/CaptureSpan.ts +32 -8
  84. package/Server/Utils/Telemetry/ErrorClassResolver.ts +120 -0
  85. package/Server/Utils/Telemetry/SpanUtil.ts +33 -0
  86. package/Server/Utils/Telemetry.ts +198 -51
  87. package/Server/Views/Partials/SensitiveUrlToken.ejs +140 -0
  88. package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +134 -33
  89. package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
  90. package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
  91. package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -0
  92. package/Tests/App/Dashboard/DeviceStatusHero.test.tsx +588 -0
  93. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +18 -9
  94. package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +632 -0
  95. package/Tests/App/Dashboard/MonitorRecommendationCreateProgress.test.tsx +682 -0
  96. package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +4 -2
  97. package/Tests/App/Dashboard/NetworkDeviceCreateFormMonitorBinding.test.tsx +676 -0
  98. package/Tests/App/Dashboard/NetworkDeviceCreateFormPingMonitor.test.tsx +791 -0
  99. package/Tests/App/Dashboard/NetworkDeviceCreateFormProbeAndSnmp.test.tsx +833 -0
  100. package/Tests/App/Dashboard/NetworkDeviceCriteriaFilter.test.ts +161 -0
  101. package/Tests/App/Dashboard/NetworkDeviceSettingsMonitoringSection.test.tsx +458 -0
  102. package/Tests/App/Dashboard/NetworkSideMenu.test.tsx +41 -5
  103. package/Tests/App/Dashboard/PingMonitorProvisioning.test.ts +368 -0
  104. package/Tests/App/Dashboard/RecommendationCard.test.tsx +796 -0
  105. package/Tests/App/Dashboard/RecommendationToolbar.test.tsx +519 -0
  106. package/Tests/App/Dashboard/RecommendationsList.test.tsx +661 -0
  107. package/Tests/App/Dashboard/UseBulkCreatePingMonitors.test.tsx +899 -0
  108. package/Tests/App/Dashboard/UseBulkSnmpCredentialProfileActions.test.tsx +732 -0
  109. package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +256 -0
  110. package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +11 -1
  111. package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +9 -4
  112. package/Tests/Models/NetworkSiteHierarchy.test.ts +41 -4
  113. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +951 -7
  114. package/Tests/Server/API/LlmProviderConnectionTest.test.ts +522 -0
  115. package/Tests/Server/Infrastructure/Postgres/NetworkSnmpCredentialProfilesAndAlertPoliciesMigration.test.ts +854 -0
  116. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +18 -0
  117. package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +535 -0
  118. package/Tests/Server/Services/AIChatPrivacyPin.test.ts +560 -0
  119. package/Tests/Server/Services/BillingRechargeOwnerEmailGuards.test.ts +783 -0
  120. package/Tests/Server/Services/EnterpriseLicenseInstanceServiceDeletionUsage.test.ts +707 -0
  121. package/Tests/Server/Services/EnterpriseLicenseServiceUsageAggregationLock.test.ts +329 -0
  122. package/Tests/Server/Services/MonitorServiceDeleteNetworkDeviceCleanup.test.ts +294 -0
  123. package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +802 -0
  124. package/Tests/Server/Services/MonitorStatusTimelineService.test.ts +72 -2
  125. package/Tests/Server/Services/NetworkAlertPolicyEngineHooks.test.ts +752 -0
  126. package/Tests/Server/Services/NetworkAlertPolicyEngineService.test.ts +1849 -0
  127. package/Tests/Server/Services/NetworkAlertPolicyModel.test.ts +1793 -0
  128. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +47 -4
  129. package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +97 -12
  130. package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +148 -3
  131. package/Tests/Server/Services/NetworkDeviceMonitorBindingUpdateGuard.test.ts +514 -0
  132. package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +447 -58
  133. package/Tests/Server/Services/NetworkDeviceMonitoringMethodTransition.test.ts +739 -0
  134. package/Tests/Server/Services/NetworkDevicePollingTenancy.test.ts +501 -0
  135. package/Tests/Server/Services/NetworkDeviceSiteDefaultProbe.test.ts +432 -0
  136. package/Tests/Server/Services/NetworkSiteMonitoringDefaults.test.ts +498 -0
  137. package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +337 -55
  138. package/Tests/Server/Services/NetworkSiteService.test.ts +1868 -131
  139. package/Tests/Server/Services/NetworkSiteTypeService.test.ts +1109 -0
  140. package/Tests/Server/Services/NetworkSnmpCredentialProfileModel.test.ts +926 -0
  141. package/Tests/Server/Services/NetworkSnmpCredentialProfileService.test.ts +796 -0
  142. package/Tests/Server/Services/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -0
  143. package/Tests/Server/Services/StatusPagePrivateUserEmailChangePasswordResetExpiry.test.ts +269 -0
  144. package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +472 -0
  145. package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +569 -0
  146. package/Tests/Server/Services/UserNotificationEmailRollupSettingModel.test.ts +314 -0
  147. package/Tests/Server/Services/UserNotificationEmailRollupSettingService.test.ts +409 -0
  148. package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +856 -0
  149. package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +102 -1
  150. package/Tests/Server/Types/Database/Permissions/DashboardAccessPermission.test.ts +321 -0
  151. package/Tests/Server/Types/Database/QueryHelperOperators.test.ts +17 -0
  152. package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +124 -0
  153. package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +208 -0
  154. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +235 -0
  155. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +253 -0
  156. package/Tests/Server/Utils/Captcha.test.ts +422 -0
  157. package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +96 -2
  158. package/Tests/Server/Utils/Database/MigrationFailureLog.test.ts +466 -0
  159. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1096 -0
  160. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerClaim.test.ts +466 -0
  161. package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +1428 -0
  162. package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +752 -0
  163. package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +864 -0
  164. package/Tests/Server/Utils/LoggerFaultDemotion.test.ts +346 -0
  165. package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +633 -0
  166. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +196 -0
  167. package/Tests/Server/Utils/Monitor/DatabaseMetricWrite.test.ts +367 -0
  168. package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +100 -0
  169. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +5 -0
  170. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +512 -31
  171. package/Tests/Server/Utils/Monitor/NetworkDeviceMetricUtil.test.ts +252 -0
  172. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +479 -42
  173. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +351 -5
  174. package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +136 -12
  175. package/Tests/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.test.ts +306 -0
  176. package/Tests/Server/Utils/OutboundUserAgent.test.ts +266 -0
  177. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClientUserAgent.test.ts +141 -0
  178. package/Tests/Server/Utils/Telemetry/ErrorClassResolver.test.ts +298 -0
  179. package/Tests/Server/Utils/Telemetry.test.ts +456 -66
  180. package/Tests/Types/Monitor/DatabaseMetricCatalog.test.ts +388 -0
  181. package/Tests/Types/Monitor/MonitorStepDatabaseMonitor.test.ts +243 -0
  182. package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
  183. package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
  184. package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +16 -7
  185. package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +60 -0
  186. package/Tests/Types/NetworkDevice/NetworkAlertPolicyScope.test.ts +655 -0
  187. package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +115 -26
  188. package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +39 -0
  189. package/Tests/Types/NotificationSetting/NotificationEmailRollupPolicy.test.ts +299 -0
  190. package/Tests/Types/Telemetry/ErrorClass.test.ts +483 -0
  191. package/Tests/UI/Components/BasicRadioButtons.test.tsx +336 -0
  192. package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +15 -0
  193. package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
  194. package/Tests/UI/Components/SideMenuItem.test.tsx +226 -4
  195. package/Tests/UI/Components/SideMenuSection.test.tsx +310 -0
  196. package/Tests/UI/Components/SideOverSubmitState.test.tsx +335 -0
  197. package/Tests/UI/Utils/PageScrollLock.test.tsx +377 -0
  198. package/Tests/UI/Utils/PermissionGate.test.ts +78 -0
  199. package/Tests/UI/Utils/SensitiveUrlToken.test.ts +140 -0
  200. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +69 -0
  201. package/Tests/Utils/EnterpriseLicenseSync.test.ts +7 -1
  202. package/Tests/Utils/EnterpriseLicenseUsage.test.ts +433 -2
  203. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +280 -1
  204. package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
  205. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +38 -0
  206. package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +284 -23
  207. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +177 -0
  208. package/Tests/Utils/NetworkDevice/MonitoringMethodThreadedClassifiers.test.ts +992 -0
  209. package/Tests/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.test.ts +427 -0
  210. package/Tests/Utils/NetworkDevice/ReachabilityStampConsistency.test.ts +185 -0
  211. package/Tests/Utils/NetworkDevice/SnmpCredentialUtil.test.ts +268 -0
  212. package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +55 -5
  213. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +98 -21
  214. package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +98 -20
  215. package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +8 -7
  216. package/Tests/Utils/NetworkDiscovery/PingMonitorBuilderForAddress.test.ts +274 -0
  217. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +230 -51
  218. package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +209 -0
  219. package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +145 -0
  220. package/Types/AI/ExceptionAIClassification.ts +10 -24
  221. package/Types/Email/EmailTemplateType.ts +2 -0
  222. package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +5 -0
  223. package/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.ts +13 -0
  224. package/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.ts +6 -0
  225. package/Types/Exception/ApiException.ts +10 -0
  226. package/Types/Exception/BadDataException.ts +11 -0
  227. package/Types/Exception/BadRequestException.ts +11 -0
  228. package/Types/Exception/Exception.ts +65 -0
  229. package/Types/Exception/ForbiddenException.ts +10 -0
  230. package/Types/Exception/NotAuthenticatedException.ts +10 -0
  231. package/Types/Exception/NotAuthorizedException.ts +10 -0
  232. package/Types/Exception/NotFoundException.ts +11 -0
  233. package/Types/Exception/PayloadTooLargeException.ts +11 -0
  234. package/Types/Exception/PaymentRequiredException.ts +10 -0
  235. package/Types/Exception/ServiceUnavailableException.ts +10 -0
  236. package/Types/Exception/SsoAuthorizationException.ts +10 -0
  237. package/Types/Exception/TenantNotFoundException.ts +11 -0
  238. package/Types/Exception/TimeoutException.ts +10 -0
  239. package/Types/Exception/TooManyRequestsException.ts +10 -0
  240. package/Types/Exception/UnableToReachServer.ts +10 -0
  241. package/Types/Exception/WebsiteRequestException.ts +10 -0
  242. package/Types/Monitor/CriteriaFilter.ts +60 -2
  243. package/Types/Monitor/DatabaseMetricCatalog.ts +693 -0
  244. package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +83 -0
  245. package/Types/Monitor/MonitorCriteriaInstance.ts +76 -0
  246. package/Types/Monitor/MonitorMetricType.ts +71 -0
  247. package/Types/Monitor/MonitorStep.ts +76 -0
  248. package/Types/Monitor/MonitorStepDatabaseMonitor.ts +171 -0
  249. package/Types/Monitor/MonitorStepSqlMonitor.ts +2 -20
  250. package/Types/Monitor/MonitorType.ts +47 -1
  251. package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +22 -1
  252. package/Types/Monitor/SqlConnectionConfig.ts +31 -0
  253. package/Types/NetworkDevice/NetworkAlertPolicyScope.ts +343 -0
  254. package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +42 -22
  255. package/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.ts +30 -0
  256. package/Types/NotificationSetting/NotificationEmailRollupCategory.ts +255 -0
  257. package/Types/NotificationSetting/NotificationEmailRollupPolicy.ts +104 -0
  258. package/Types/Permission.ts +90 -0
  259. package/Types/Probe/ProbeMonitorResponse.ts +16 -0
  260. package/Types/Telemetry/ErrorClass.ts +274 -0
  261. package/Types/Telemetry/UnitOfWork.ts +59 -0
  262. package/UI/Components/CommandPalette/CommandPalette.tsx +2 -8
  263. package/UI/Components/EditionLabel/EditionLabel.tsx +4 -0
  264. package/UI/Components/Modal/Modal.tsx +2 -8
  265. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
  266. package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
  267. package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
  268. package/UI/Components/SideMenu/SideMenu.tsx +123 -5
  269. package/UI/Components/SideMenu/SideMenuItem.tsx +76 -84
  270. package/UI/Components/SideMenu/SideMenuSection.tsx +55 -23
  271. package/UI/Components/SideOver/SideOver.tsx +21 -20
  272. package/UI/Utils/PageScrollLock.ts +79 -3
  273. package/UI/Utils/PermissionGate.ts +61 -0
  274. package/UI/Utils/SensitiveUrlToken.ts +112 -0
  275. package/UI/Utils/TestLLMProvider.ts +11 -0
  276. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +16 -0
  277. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +191 -11
  278. package/Utils/Monitor/MonitorMetricType.ts +153 -1
  279. package/Utils/Monitor/NetworkTopologyUtil.ts +23 -3
  280. package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
  281. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
  282. package/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.ts +247 -0
  283. package/Utils/NetworkDevice/SnmpCredentialUtil.ts +68 -0
  284. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +15 -7
  285. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +52 -17
  286. package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +55 -23
  287. package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +115 -13
  288. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +66 -20
  289. package/Utils/NetworkSite/TypeHierarchyUtil.ts +313 -0
  290. package/build/dist/Models/AnalyticsModels/Span.js +14 -0
  291. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  292. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +59 -0
  293. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
  294. package/build/dist/Models/DatabaseModels/Index.js +10 -0
  295. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  296. package/build/dist/Models/DatabaseModels/Monitor.js +75 -0
  297. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  298. package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js +713 -0
  299. package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js.map +1 -0
  300. package/build/dist/Models/DatabaseModels/NetworkDevice.js +180 -1
  301. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  302. package/build/dist/Models/DatabaseModels/NetworkSite.js +200 -2
  303. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
  304. package/build/dist/Models/DatabaseModels/NetworkSiteType.js +102 -3
  305. package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -1
  306. package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js +878 -0
  307. package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js.map +1 -0
  308. package/build/dist/Models/DatabaseModels/TelemetryException.js +123 -0
  309. package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
  310. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js +363 -0
  311. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js.map +1 -0
  312. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +402 -0
  313. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -0
  314. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js +296 -0
  315. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js.map +1 -0
  316. package/build/dist/Server/API/EnterpriseLicenseAPI.js +273 -60
  317. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
  318. package/build/dist/Server/API/LlmProviderAPI.js +108 -13
  319. package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
  320. package/build/dist/Server/EnvironmentConfig.js +12 -0
  321. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  322. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js +24 -0
  323. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js.map +1 -0
  324. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js +16 -0
  325. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js.map +1 -0
  326. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js +111 -0
  327. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js.map +1 -0
  328. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js +77 -0
  329. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js.map +1 -0
  330. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js +50 -0
  331. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js.map +1 -0
  332. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js +83 -0
  333. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js.map +1 -0
  334. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
  335. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  336. package/build/dist/Server/Infrastructure/QueueWorker.js +33 -5
  337. package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
  338. package/build/dist/Server/Middleware/BearerTokenAuthorization.js +12 -0
  339. package/build/dist/Server/Middleware/BearerTokenAuthorization.js.map +1 -1
  340. package/build/dist/Server/Middleware/ProjectAuthorization.js +11 -0
  341. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  342. package/build/dist/Server/Middleware/SCIMAuthorization.js +12 -0
  343. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +1 -1
  344. package/build/dist/Server/Middleware/TelemetryIngest.js +11 -0
  345. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  346. package/build/dist/Server/Services/AIBillingService.js +70 -16
  347. package/build/dist/Server/Services/AIBillingService.js.map +1 -1
  348. package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js +167 -0
  349. package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js.map +1 -1
  350. package/build/dist/Server/Services/EnterpriseLicenseService.js +39 -0
  351. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  352. package/build/dist/Server/Services/Index.js +10 -0
  353. package/build/dist/Server/Services/Index.js.map +1 -1
  354. package/build/dist/Server/Services/MonitorService.js +119 -21
  355. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  356. package/build/dist/Server/Services/MonitorStatusTimelineService.js +127 -8
  357. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  358. package/build/dist/Server/Services/MonitorTemplateService.js +162 -0
  359. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  360. package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js +1683 -0
  361. package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js.map +1 -0
  362. package/build/dist/Server/Services/NetworkAlertPolicyService.js +732 -0
  363. package/build/dist/Server/Services/NetworkAlertPolicyService.js.map +1 -0
  364. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +10 -9
  365. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  366. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +54 -11
  367. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
  368. package/build/dist/Server/Services/NetworkDeviceService.js +841 -70
  369. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  370. package/build/dist/Server/Services/NetworkSiteService.js +1145 -107
  371. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  372. package/build/dist/Server/Services/NetworkSiteTypeService.js +863 -0
  373. package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
  374. package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js +217 -0
  375. package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js.map +1 -0
  376. package/build/dist/Server/Services/NotificationService.js +80 -17
  377. package/build/dist/Server/Services/NotificationService.js.map +1 -1
  378. package/build/dist/Server/Services/ProjectService.js +66 -30
  379. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  380. package/build/dist/Server/Services/StatusPagePrivateUserService.js +92 -2
  381. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  382. package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js +76 -0
  383. package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js.map +1 -0
  384. package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js +77 -0
  385. package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js.map +1 -0
  386. package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js +111 -0
  387. package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js.map +1 -0
  388. package/build/dist/Server/Services/UserNotificationSettingService.js +46 -20
  389. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  390. package/build/dist/Server/Services/UserService.js +90 -0
  391. package/build/dist/Server/Services/UserService.js.map +1 -1
  392. package/build/dist/Server/Types/Database/QueryHelper.js +1 -1
  393. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  394. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +14 -3
  395. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
  396. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +10 -0
  397. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
  398. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +10 -0
  399. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
  400. package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +54 -1
  401. package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -1
  402. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +18 -4
  403. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
  404. package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js +59 -0
  405. package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js.map +1 -0
  406. package/build/dist/Server/Utils/DataSource/HttpFetch.js +2 -1
  407. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
  408. package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js +91 -0
  409. package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -0
  410. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +691 -0
  411. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -0
  412. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +497 -0
  413. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -0
  414. package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +257 -0
  415. package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -0
  416. package/build/dist/Server/Utils/LLM/LLMService.js +64 -1
  417. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  418. package/build/dist/Server/Utils/LogRedaction.js +8 -0
  419. package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
  420. package/build/dist/Server/Utils/Logger.js +63 -1
  421. package/build/dist/Server/Utils/Logger.js.map +1 -1
  422. package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js +141 -0
  423. package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js.map +1 -0
  424. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  425. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  426. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +51 -1
  427. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  428. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +7 -0
  429. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
  430. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +37 -0
  431. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  432. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +158 -6
  433. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  434. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
  435. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  436. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +32 -0
  437. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  438. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +330 -21
  439. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  440. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +55 -10
  441. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
  442. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +178 -49
  443. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
  444. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +119 -29
  445. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  446. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +30 -17
  447. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -1
  448. package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js +158 -0
  449. package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js.map +1 -0
  450. package/build/dist/Server/Utils/OutboundUserAgent.js +123 -0
  451. package/build/dist/Server/Utils/OutboundUserAgent.js.map +1 -0
  452. package/build/dist/Server/Utils/StartServer.js +38 -14
  453. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  454. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +28 -8
  455. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
  456. package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js +95 -0
  457. package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js.map +1 -0
  458. package/build/dist/Server/Utils/Telemetry/SpanUtil.js +29 -0
  459. package/build/dist/Server/Utils/Telemetry/SpanUtil.js.map +1 -1
  460. package/build/dist/Server/Utils/Telemetry.js +162 -46
  461. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  462. package/build/dist/Types/AI/ExceptionAIClassification.js +10 -24
  463. package/build/dist/Types/AI/ExceptionAIClassification.js.map +1 -1
  464. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  465. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  466. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js +2 -0
  467. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js.map +1 -0
  468. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js +7 -0
  469. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js.map +1 -0
  470. package/build/dist/Types/Exception/ApiException.js +9 -0
  471. package/build/dist/Types/Exception/ApiException.js.map +1 -1
  472. package/build/dist/Types/Exception/BadDataException.js +10 -0
  473. package/build/dist/Types/Exception/BadDataException.js.map +1 -1
  474. package/build/dist/Types/Exception/BadRequestException.js +10 -0
  475. package/build/dist/Types/Exception/BadRequestException.js.map +1 -1
  476. package/build/dist/Types/Exception/Exception.js +56 -0
  477. package/build/dist/Types/Exception/Exception.js.map +1 -1
  478. package/build/dist/Types/Exception/ForbiddenException.js +9 -0
  479. package/build/dist/Types/Exception/ForbiddenException.js.map +1 -1
  480. package/build/dist/Types/Exception/NotAuthenticatedException.js +9 -0
  481. package/build/dist/Types/Exception/NotAuthenticatedException.js.map +1 -1
  482. package/build/dist/Types/Exception/NotAuthorizedException.js +9 -0
  483. package/build/dist/Types/Exception/NotAuthorizedException.js.map +1 -1
  484. package/build/dist/Types/Exception/NotFoundException.js +10 -0
  485. package/build/dist/Types/Exception/NotFoundException.js.map +1 -1
  486. package/build/dist/Types/Exception/PayloadTooLargeException.js +10 -0
  487. package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -1
  488. package/build/dist/Types/Exception/PaymentRequiredException.js +9 -0
  489. package/build/dist/Types/Exception/PaymentRequiredException.js.map +1 -1
  490. package/build/dist/Types/Exception/ServiceUnavailableException.js +9 -0
  491. package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -1
  492. package/build/dist/Types/Exception/SsoAuthorizationException.js +9 -0
  493. package/build/dist/Types/Exception/SsoAuthorizationException.js.map +1 -1
  494. package/build/dist/Types/Exception/TenantNotFoundException.js +10 -0
  495. package/build/dist/Types/Exception/TenantNotFoundException.js.map +1 -1
  496. package/build/dist/Types/Exception/TimeoutException.js +9 -0
  497. package/build/dist/Types/Exception/TimeoutException.js.map +1 -1
  498. package/build/dist/Types/Exception/TooManyRequestsException.js +9 -0
  499. package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -1
  500. package/build/dist/Types/Exception/UnableToReachServer.js +9 -0
  501. package/build/dist/Types/Exception/UnableToReachServer.js.map +1 -1
  502. package/build/dist/Types/Exception/WebsiteRequestException.js +9 -0
  503. package/build/dist/Types/Exception/WebsiteRequestException.js.map +1 -1
  504. package/build/dist/Types/Monitor/CriteriaFilter.js +45 -2
  505. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  506. package/build/dist/Types/Monitor/DatabaseMetricCatalog.js +594 -0
  507. package/build/dist/Types/Monitor/DatabaseMetricCatalog.js.map +1 -0
  508. package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js +21 -0
  509. package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js.map +1 -0
  510. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +70 -0
  511. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  512. package/build/dist/Types/Monitor/MonitorMetricType.js +61 -0
  513. package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
  514. package/build/dist/Types/Monitor/MonitorStep.js +54 -0
  515. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  516. package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js +122 -0
  517. package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js.map +1 -0
  518. package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -1
  519. package/build/dist/Types/Monitor/MonitorType.js +45 -1
  520. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  521. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +21 -1
  522. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
  523. package/build/dist/Types/Monitor/SqlConnectionConfig.js +2 -0
  524. package/build/dist/Types/Monitor/SqlConnectionConfig.js.map +1 -0
  525. package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js +172 -0
  526. package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js.map +1 -0
  527. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +40 -22
  528. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -1
  529. package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js +26 -0
  530. package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js.map +1 -0
  531. package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js +186 -0
  532. package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js.map +1 -0
  533. package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js +87 -0
  534. package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js.map +1 -0
  535. package/build/dist/Types/Permission.js +80 -0
  536. package/build/dist/Types/Permission.js.map +1 -1
  537. package/build/dist/Types/Telemetry/ErrorClass.js +216 -0
  538. package/build/dist/Types/Telemetry/ErrorClass.js.map +1 -0
  539. package/build/dist/Types/Telemetry/UnitOfWork.js +59 -0
  540. package/build/dist/Types/Telemetry/UnitOfWork.js.map +1 -0
  541. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +2 -7
  542. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
  543. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +3 -0
  544. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  545. package/build/dist/UI/Components/Modal/Modal.js +2 -7
  546. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  547. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +39 -0
  548. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  549. package/build/dist/UI/Components/ProgressBar/ProgressBar.js +12 -1
  550. package/build/dist/UI/Components/ProgressBar/ProgressBar.js.map +1 -1
  551. package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +6 -6
  552. package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
  553. package/build/dist/UI/Components/SideMenu/SideMenu.js +67 -5
  554. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  555. package/build/dist/UI/Components/SideMenu/SideMenuItem.js +49 -53
  556. package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
  557. package/build/dist/UI/Components/SideMenu/SideMenuSection.js +25 -7
  558. package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
  559. package/build/dist/UI/Components/SideOver/SideOver.js +5 -20
  560. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  561. package/build/dist/UI/Utils/PageScrollLock.js +31 -3
  562. package/build/dist/UI/Utils/PageScrollLock.js.map +1 -1
  563. package/build/dist/UI/Utils/PermissionGate.js +42 -1
  564. package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
  565. package/build/dist/UI/Utils/SensitiveUrlToken.js +97 -0
  566. package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -0
  567. package/build/dist/UI/Utils/TestLLMProvider.js +4 -5
  568. package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -1
  569. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +15 -0
  570. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -1
  571. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +111 -9
  572. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  573. package/build/dist/Utils/Monitor/MonitorMetricType.js +109 -1
  574. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  575. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +8 -3
  576. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  577. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +27 -7
  578. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
  579. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +7 -5
  580. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
  581. package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js +180 -0
  582. package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js.map +1 -0
  583. package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js +12 -0
  584. package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js.map +1 -0
  585. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +15 -5
  586. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
  587. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +44 -15
  588. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
  589. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +52 -23
  590. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -1
  591. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +85 -13
  592. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -1
  593. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +30 -15
  594. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
  595. package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +191 -0
  596. package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -0
  597. 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
+ });