@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,752 @@
1
+ /*
2
+ * Contract under test — WHERE the Network Alert Policy engine is called from,
3
+ * and with what.
4
+ *
5
+ * NetworkAlertPolicyEngineService.test.ts pins what the engine does once it
6
+ * is running. This file pins the seams, because every one of them is a place
7
+ * where a wrong condition means monitors that silently never appear, or a
8
+ * request that hangs for minutes, or a policy row deleted while the monitors
9
+ * it explained stay behind and keep being billed:
10
+ *
11
+ * - A DEVICE WRITE reconciles inline only for a HANDFUL of devices. One
12
+ * device is a few queries; a bulk write ("move 1,200 devices into this
13
+ * site", "archive the warehouse") matches thousands of rows, and
14
+ * reconciling thousands inside the request would turn one statement into
15
+ * an hour of monitor provisioning with the caller still waiting. Past the
16
+ * threshold the write returns and the five-minute sweep converges.
17
+ * - A DEVICE WRITE reconciles for the SCOPE AXES and for PROVISIONABILITY —
18
+ * site, role, labels, isArchived, monitoringMethod, probeId — and for
19
+ * nothing else. A poll writing sysName every five minutes must not start
20
+ * a reconciliation per device per cycle.
21
+ * - A DEVICE CREATE reconciles LAST in its out-of-band chain, after the
22
+ * label and site rules have run. A policy can be scoped by label, and a
23
+ * discovery import arrives with no labels at all: asking first would
24
+ * provision nothing and leave the device uncovered until the sweep.
25
+ * - A POLICY SAVE hands the work over DETACHED. Provisioning a warehouse is
26
+ * hundreds of monitor creates; doing it inside the save would time out.
27
+ * - A POLICY DELETE does NOT detach: the monitors go before the row does,
28
+ * or nothing is left that knows they were the policy's.
29
+ * - DISABLING pauses, ENABLING resumes, and neither fires when the payload
30
+ * merely re-sends the value the row already had — the settings form does
31
+ * that on every save, and it would be a write per monitor each time.
32
+ * - A TEMPLATE A POLICY USES CANNOT BE DELETED. Both foreign keys are SET
33
+ * NULL, so without the guard the delete succeeds and the policy quietly
34
+ * stops covering anything new.
35
+ */
36
+
37
+ jest.mock("../../../Server/Services/NetworkAlertPolicyEngineService", () => {
38
+ return {
39
+ __esModule: true,
40
+ MAX_INLINE_RECONCILE_DEVICES: 5,
41
+ MAX_MONITORS_PER_POLICY_SYNC: 500,
42
+ default: {
43
+ reconcileDevice: jest.fn(),
44
+ reconcileDevices: jest.fn(),
45
+ syncPolicy: jest.fn(),
46
+ deleteMonitorsOwnedByPolicy: jest.fn(),
47
+ deletePolicyMonitorsForDevices: jest.fn(),
48
+ setPolicyMonitorsPaused: jest.fn(),
49
+ onMonitorTemplateSynced: jest.fn(),
50
+ createRunContext: jest.fn(),
51
+ },
52
+ };
53
+ });
54
+
55
+ import NetworkAlertPolicyEngineService from "../../../Server/Services/NetworkAlertPolicyEngineService";
56
+ import NetworkAlertPolicyService from "../../../Server/Services/NetworkAlertPolicyService";
57
+ import NetworkDeviceService from "../../../Server/Services/NetworkDeviceService";
58
+ import NetworkDeviceLabelRuleEngineService from "../../../Server/Services/NetworkDeviceLabelRuleEngineService";
59
+ import NetworkDeviceOwnerRuleEngineService from "../../../Server/Services/NetworkDeviceOwnerRuleEngineService";
60
+ import NetworkSiteService from "../../../Server/Services/NetworkSiteService";
61
+ import MonitorTemplateService from "../../../Server/Services/MonitorTemplateService";
62
+ import NetworkDeviceAutoImportRuleService from "../../../Server/Services/NetworkDeviceAutoImportRuleService";
63
+ import ModelPermission from "../../../Server/Types/Database/Permissions/Index";
64
+ import MonitorTemplate from "../../../Models/DatabaseModels/MonitorTemplate";
65
+ import NetworkAlertPolicy from "../../../Models/DatabaseModels/NetworkAlertPolicy";
66
+ import NetworkDevice from "../../../Models/DatabaseModels/NetworkDevice";
67
+ import NetworkDeviceAutoImportRule from "../../../Models/DatabaseModels/NetworkDeviceAutoImportRule";
68
+ import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
69
+ import Query from "../../../Server/Types/Database/Query";
70
+ import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
71
+ import BadDataException from "../../../Types/Exception/BadDataException";
72
+ import NetworkDeviceMonitoringMethod from "../../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
73
+ import ObjectID from "../../../Types/ObjectID";
74
+ import { afterEach, describe, expect, it, jest } from "@jest/globals";
75
+ import type { SpyInstance } from "jest-mock";
76
+
77
+ const PROJECT_ID: ObjectID = new ObjectID(
78
+ "11111111-1111-4111-8111-111111111111",
79
+ );
80
+ const OTHER_PROJECT_ID: ObjectID = new ObjectID(
81
+ "1b1b1b1b-1b1b-4b1b-8b1b-1b1b1b1b1b1b",
82
+ );
83
+ const DEVICE_ID: ObjectID = new ObjectID(
84
+ "22222222-2222-4222-8222-222222222222",
85
+ );
86
+ const POLICY_ID: ObjectID = new ObjectID(
87
+ "33333333-3333-4333-8333-333333333333",
88
+ );
89
+ const TEMPLATE_ID: ObjectID = new ObjectID(
90
+ "44444444-4444-4444-8444-444444444444",
91
+ );
92
+
93
+ const reconcileDeviceMock: jest.Mock =
94
+ NetworkAlertPolicyEngineService.reconcileDevice as unknown as jest.Mock;
95
+ const syncPolicyMock: jest.Mock =
96
+ NetworkAlertPolicyEngineService.syncPolicy as unknown as jest.Mock;
97
+ const deletePolicyMonitorsMock: jest.Mock =
98
+ NetworkAlertPolicyEngineService.deleteMonitorsOwnedByPolicy as unknown as jest.Mock;
99
+ const setPausedMock: jest.Mock =
100
+ NetworkAlertPolicyEngineService.setPolicyMonitorsPaused as unknown as jest.Mock;
101
+
102
+ /*
103
+ * The device create and the policy update hand their work to the engine
104
+ * DETACHED, so the assertions have to wait for the microtask chain to drain.
105
+ */
106
+ async function flushDetachedWork(): Promise<void> {
107
+ await new Promise((resolve: (value: unknown) => void) => {
108
+ setTimeout(resolve, 0);
109
+ });
110
+ }
111
+
112
+ function deviceRow(overrides: Partial<NetworkDevice> = {}): NetworkDevice {
113
+ const device: NetworkDevice = new NetworkDevice();
114
+ device.id = DEVICE_ID;
115
+ device.projectId = PROJECT_ID;
116
+ device.monitoringMethod = NetworkDeviceMonitoringMethod.Probe;
117
+ Object.assign(device, overrides);
118
+
119
+ return device;
120
+ }
121
+
122
+ afterEach(() => {
123
+ jest.restoreAllMocks();
124
+ /*
125
+ * reset, not clear. The engine's methods are jest.fn()s from the module
126
+ * factory rather than spies, so restoreAllMocks does not touch them and a
127
+ * mockRejectedValue set by one case would still be in place for the next —
128
+ * where it would abort a loop and make an assertion pass for entirely the
129
+ * wrong reason.
130
+ */
131
+ jest.resetAllMocks();
132
+ });
133
+
134
+ describe("NetworkDeviceService.onCreateSuccess hands the new device to the engine", () => {
135
+ function silenceTheRestOfTheChain(): void {
136
+ jest
137
+ .spyOn(NetworkDeviceLabelRuleEngineService, "applyRulesToNetworkDevice")
138
+ .mockResolvedValue(undefined as never);
139
+ jest
140
+ .spyOn(NetworkDeviceOwnerRuleEngineService, "applyRulesToNetworkDevice")
141
+ .mockResolvedValue(undefined as never);
142
+ jest
143
+ .spyOn(NetworkSiteService, "recomputeRollupForSiteAndAncestors")
144
+ .mockResolvedValue(undefined as never);
145
+ jest
146
+ .spyOn(NetworkDeviceService, "applySiteAssignmentRulesToDevice")
147
+ .mockResolvedValue(undefined as never);
148
+ }
149
+
150
+ it("reconciles the created device", async () => {
151
+ silenceTheRestOfTheChain();
152
+
153
+ await (NetworkDeviceService as any).onCreateSuccess(
154
+ { createBy: { data: {}, props: {} }, carryForward: null },
155
+ deviceRow(),
156
+ );
157
+ await flushDetachedWork();
158
+
159
+ expect(reconcileDeviceMock).toHaveBeenCalledWith({
160
+ projectId: PROJECT_ID,
161
+ deviceId: DEVICE_ID,
162
+ });
163
+ });
164
+
165
+ /*
166
+ * ORDER MATTERS. A policy can be scoped by LABEL, and a discovery import
167
+ * creates a device with none — the label rules in this same chain are what
168
+ * put them on. Reconciling before them would evaluate the device against a
169
+ * scope it does not match yet, provision nothing, and leave it uncovered
170
+ * until the five-minute sweep noticed.
171
+ */
172
+ it("reconciles only after the label rules have run", async () => {
173
+ const order: Array<string> = [];
174
+
175
+ jest
176
+ .spyOn(NetworkDeviceLabelRuleEngineService, "applyRulesToNetworkDevice")
177
+ .mockImplementation(async (): Promise<void> => {
178
+ order.push("labels");
179
+ });
180
+ jest
181
+ .spyOn(NetworkDeviceOwnerRuleEngineService, "applyRulesToNetworkDevice")
182
+ .mockResolvedValue(undefined as never);
183
+ jest
184
+ .spyOn(NetworkDeviceService, "applySiteAssignmentRulesToDevice")
185
+ .mockImplementation(async (): Promise<void> => {
186
+ order.push("site");
187
+ });
188
+ reconcileDeviceMock.mockImplementation(async (): Promise<void> => {
189
+ order.push("policies");
190
+ });
191
+
192
+ await (NetworkDeviceService as any).onCreateSuccess(
193
+ { createBy: { data: {}, props: {} }, carryForward: null },
194
+ deviceRow(),
195
+ );
196
+ await flushDetachedWork();
197
+
198
+ expect(order).toEqual(["labels", "site", "policies"]);
199
+ });
200
+
201
+ /*
202
+ * Detached, so a policy that cannot provision — a deleted template, Redis
203
+ * down — must never turn into a failed device import.
204
+ */
205
+ it("does not fail the create when the engine throws", async () => {
206
+ silenceTheRestOfTheChain();
207
+ reconcileDeviceMock.mockRejectedValue(new Error("engine is unhappy"));
208
+
209
+ await expect(
210
+ (NetworkDeviceService as any).onCreateSuccess(
211
+ { createBy: { data: {}, props: {} }, carryForward: null },
212
+ deviceRow(),
213
+ ),
214
+ ).resolves.toBeDefined();
215
+ await flushDetachedWork();
216
+ });
217
+ });
218
+
219
+ describe("NetworkDeviceService.onUpdateSuccess reconciles the right writes", () => {
220
+ function runUpdateSuccess(
221
+ data: Record<string, unknown>,
222
+ updatedItemIds: Array<ObjectID>,
223
+ previousDevices: Array<NetworkDevice> = [deviceRow()],
224
+ ): Promise<unknown> {
225
+ return (NetworkDeviceService as any).onUpdateSuccess(
226
+ {
227
+ updateBy: { data: data, query: {}, props: { tenantId: PROJECT_ID } },
228
+ carryForward: { previousDevices: previousDevices },
229
+ },
230
+ updatedItemIds,
231
+ );
232
+ }
233
+
234
+ it.each([
235
+ ["siteId", { siteId: ObjectID.generate() }],
236
+ ["the site relation", { site: { _id: ObjectID.generate().toString() } }],
237
+ ["networkDeviceRoleId", { networkDeviceRoleId: ObjectID.generate() }],
238
+ ["labels", { labels: [] }],
239
+ ["isArchived", { isArchived: true }],
240
+ [
241
+ "monitoringMethod",
242
+ { monitoringMethod: NetworkDeviceMonitoringMethod.Monitor },
243
+ ],
244
+ ["probeId", { probeId: ObjectID.generate() }],
245
+ ])(
246
+ "reconciles when the write touches %s",
247
+ async (_name: string, data: Record<string, unknown>) => {
248
+ await runUpdateSuccess(data, [DEVICE_ID]);
249
+
250
+ expect(reconcileDeviceMock).toHaveBeenCalledWith({
251
+ projectId: PROJECT_ID,
252
+ deviceId: DEVICE_ID,
253
+ });
254
+ },
255
+ );
256
+
257
+ /*
258
+ * Every successful SNMP walk rewrites sysName and the poll columns. If
259
+ * those started a reconciliation, an 80,000-device fleet would run 80,000
260
+ * policy passes every five-minute cycle for no change at all.
261
+ */
262
+ it.each([
263
+ ["sysName", { sysName: "core-sw-1" }],
264
+ ["poll columns", { lastPolledAt: new Date(), isReachable: true }],
265
+ ["the name", { name: "Renamed" }],
266
+ ])(
267
+ "does not reconcile for a write that only touches %s",
268
+ async (_name: string, data: Record<string, unknown>) => {
269
+ await runUpdateSuccess(data, [DEVICE_ID]);
270
+
271
+ expect(reconcileDeviceMock).not.toHaveBeenCalled();
272
+ },
273
+ );
274
+
275
+ /*
276
+ * THE THRESHOLD. Five devices is a form save or a small bulk action and is
277
+ * worth doing inline, so the monitor is there by the next page load. Six is
278
+ * a bulk action whose size nobody bounded, and reconciling it inline is how
279
+ * a one-statement update becomes a request that never returns.
280
+ */
281
+ it("reconciles inline for up to five devices", async () => {
282
+ const deviceIds: Array<ObjectID> = [1, 2, 3, 4, 5].map((): ObjectID => {
283
+ return ObjectID.generate();
284
+ });
285
+
286
+ await runUpdateSuccess({ isArchived: true }, deviceIds, []);
287
+
288
+ expect(reconcileDeviceMock).toHaveBeenCalledTimes(5);
289
+ });
290
+
291
+ it("leaves a larger bulk write entirely to the sweep", async () => {
292
+ const deviceIds: Array<ObjectID> = [1, 2, 3, 4, 5, 6].map((): ObjectID => {
293
+ return ObjectID.generate();
294
+ });
295
+
296
+ await runUpdateSuccess({ isArchived: true }, deviceIds, []);
297
+
298
+ expect(reconcileDeviceMock).not.toHaveBeenCalled();
299
+ });
300
+
301
+ /*
302
+ * The project comes from the pre-write snapshot, not from props: a root
303
+ * caller (a worker, a data migration) has no tenant and its update can
304
+ * legitimately span projects, so using props.tenantId alone would
305
+ * reconcile a device against the wrong project's policies.
306
+ */
307
+ it("takes each device's project from the pre-write snapshot", async () => {
308
+ const foreignDevice: NetworkDevice = deviceRow({
309
+ projectId: OTHER_PROJECT_ID,
310
+ });
311
+
312
+ await (NetworkDeviceService as any).onUpdateSuccess(
313
+ {
314
+ updateBy: { data: { isArchived: true }, query: {}, props: {} },
315
+ carryForward: { previousDevices: [foreignDevice] },
316
+ },
317
+ [DEVICE_ID],
318
+ );
319
+
320
+ expect(reconcileDeviceMock).toHaveBeenCalledWith({
321
+ projectId: OTHER_PROJECT_ID,
322
+ deviceId: DEVICE_ID,
323
+ });
324
+ });
325
+
326
+ /*
327
+ * ...and a device the hook cannot attribute to any project is skipped
328
+ * rather than guessed at. The sweep starts from the policies and will
329
+ * reach it.
330
+ */
331
+ it("skips a device whose project it cannot determine", async () => {
332
+ await (NetworkDeviceService as any).onUpdateSuccess(
333
+ {
334
+ updateBy: { data: { isArchived: true }, query: {}, props: {} },
335
+ carryForward: { previousDevices: [] },
336
+ },
337
+ [DEVICE_ID],
338
+ );
339
+
340
+ expect(reconcileDeviceMock).not.toHaveBeenCalled();
341
+ });
342
+
343
+ it("does not fail the update when the engine throws", async () => {
344
+ reconcileDeviceMock.mockRejectedValue(new Error("engine is unhappy"));
345
+
346
+ await expect(
347
+ runUpdateSuccess({ isArchived: true }, [DEVICE_ID]),
348
+ ).resolves.toBeDefined();
349
+ });
350
+ });
351
+
352
+ describe("NetworkAlertPolicyService hands its own writes to the engine", () => {
353
+ function createdPolicy(): NetworkAlertPolicy {
354
+ const created: NetworkAlertPolicy = new NetworkAlertPolicy();
355
+ created.id = POLICY_ID;
356
+ created.projectId = PROJECT_ID;
357
+
358
+ return created;
359
+ }
360
+
361
+ it("syncs a newly created policy", async () => {
362
+ const created: NetworkAlertPolicy = createdPolicy();
363
+
364
+ await (NetworkAlertPolicyService as any).onCreateSuccess(
365
+ { createBy: { data: created, props: { tenantId: PROJECT_ID } } },
366
+ created,
367
+ );
368
+ await flushDetachedWork();
369
+
370
+ expect(syncPolicyMock).toHaveBeenCalledWith({
371
+ policyId: POLICY_ID,
372
+ /*
373
+ * A brand new policy has no monitors, so every monitor its first pass
374
+ * makes comes from the template it names — which is what
375
+ * templateSyncedAt claims.
376
+ */
377
+ stampTemplateSyncedOnCleanPass: true,
378
+ });
379
+ });
380
+
381
+ /*
382
+ * ...and the save does not WAIT for it. Provisioning a warehouse is
383
+ * hundreds of monitor creates; holding the operator's request open for that
384
+ * would time out. The engine here never finishes, and the hook still
385
+ * returns.
386
+ */
387
+ it("does not hold the save open while the engine provisions", async () => {
388
+ let releaseEngine: () => void = (): void => {
389
+ return undefined;
390
+ };
391
+
392
+ syncPolicyMock.mockImplementation((): Promise<null> => {
393
+ return new Promise<null>((resolve: (value: null) => void): void => {
394
+ releaseEngine = (): void => {
395
+ return resolve(null);
396
+ };
397
+ });
398
+ });
399
+
400
+ const created: NetworkAlertPolicy = createdPolicy();
401
+
402
+ await expect(
403
+ (NetworkAlertPolicyService as any).onCreateSuccess(
404
+ { createBy: { data: created, props: { tenantId: PROJECT_ID } } },
405
+ created,
406
+ ),
407
+ ).resolves.toBe(created);
408
+
409
+ releaseEngine();
410
+ });
411
+
412
+ it("does not fail the save when the engine throws", async () => {
413
+ syncPolicyMock.mockRejectedValue(new Error("engine is unhappy"));
414
+
415
+ const created: NetworkAlertPolicy = createdPolicy();
416
+
417
+ await expect(
418
+ (NetworkAlertPolicyService as any).onCreateSuccess(
419
+ { createBy: { data: created, props: { tenantId: PROJECT_ID } } },
420
+ created,
421
+ ),
422
+ ).resolves.toBe(created);
423
+ await flushDetachedWork();
424
+ });
425
+
426
+ function previousPolicy(
427
+ overrides: Partial<NetworkAlertPolicy> = {},
428
+ ): NetworkAlertPolicy {
429
+ const policy: NetworkAlertPolicy = new NetworkAlertPolicy();
430
+ policy.id = POLICY_ID;
431
+ policy.projectId = PROJECT_ID;
432
+ policy.isEnabled = true;
433
+ policy.monitorTemplateId = TEMPLATE_ID;
434
+ Object.assign(policy, overrides);
435
+
436
+ return policy;
437
+ }
438
+
439
+ async function runPolicyUpdateSuccess(
440
+ data: Record<string, unknown>,
441
+ previousPolicies: Array<NetworkAlertPolicy>,
442
+ ): Promise<void> {
443
+ await (NetworkAlertPolicyService as any).onUpdateSuccess(
444
+ {
445
+ updateBy: { data: data, query: {}, props: { tenantId: PROJECT_ID } },
446
+ carryForward: { previousPolicies: previousPolicies },
447
+ },
448
+ [POLICY_ID],
449
+ );
450
+ await flushDetachedWork();
451
+ }
452
+
453
+ it("does no engine work for a rename", async () => {
454
+ await runPolicyUpdateSuccess({ name: "New name" }, [previousPolicy()]);
455
+
456
+ expect(syncPolicyMock).not.toHaveBeenCalled();
457
+ expect(setPausedMock).not.toHaveBeenCalled();
458
+ });
459
+
460
+ it("syncs after a scope change", async () => {
461
+ await runPolicyUpdateSuccess({ scope: { siteIds: [] } }, [
462
+ previousPolicy(),
463
+ ]);
464
+
465
+ expect(syncPolicyMock).toHaveBeenCalledWith({
466
+ policyId: POLICY_ID,
467
+ stampTemplateSyncedOnCleanPass: false,
468
+ });
469
+ });
470
+
471
+ it("pauses the policy's monitors when it is really disabled", async () => {
472
+ await runPolicyUpdateSuccess({ isEnabled: false }, [previousPolicy()]);
473
+
474
+ expect(setPausedMock).toHaveBeenCalledWith({
475
+ projectId: PROJECT_ID,
476
+ policyId: POLICY_ID,
477
+ isPaused: true,
478
+ });
479
+ });
480
+
481
+ /*
482
+ * The settings form re-sends `isEnabled` on every save. Treating that as a
483
+ * transition would be one write per monitor every time somebody fixed a
484
+ * typo in the policy's description.
485
+ */
486
+ it("does not re-pause a policy that was already disabled", async () => {
487
+ await runPolicyUpdateSuccess({ isEnabled: false }, [
488
+ previousPolicy({ isEnabled: false }),
489
+ ]);
490
+
491
+ expect(setPausedMock).not.toHaveBeenCalled();
492
+ });
493
+
494
+ it("resumes the monitors when a disabled policy is enabled again", async () => {
495
+ await runPolicyUpdateSuccess({ isEnabled: true }, [
496
+ previousPolicy({ isEnabled: false }),
497
+ ]);
498
+
499
+ expect(setPausedMock).toHaveBeenCalledWith({
500
+ projectId: PROJECT_ID,
501
+ policyId: POLICY_ID,
502
+ isPaused: false,
503
+ });
504
+ expect(syncPolicyMock).toHaveBeenCalled();
505
+ });
506
+
507
+ /*
508
+ * Resume BEFORE the sync, so a monitor that was paused when the policy went
509
+ * off is running again by the time the sync counts the fleet as covered.
510
+ */
511
+ it("resumes before it syncs", async () => {
512
+ const order: Array<string> = [];
513
+ setPausedMock.mockImplementation(async (): Promise<number> => {
514
+ order.push("resume");
515
+
516
+ return 0;
517
+ });
518
+ syncPolicyMock.mockImplementation(async (): Promise<null> => {
519
+ order.push("sync");
520
+
521
+ return null;
522
+ });
523
+
524
+ await runPolicyUpdateSuccess({ isEnabled: true }, [
525
+ previousPolicy({ isEnabled: false }),
526
+ ]);
527
+
528
+ expect(order).toEqual(["resume", "sync"]);
529
+ });
530
+
531
+ it("asks for a template stamp only when the template really changed", async () => {
532
+ await runPolicyUpdateSuccess({ monitorTemplateId: ObjectID.generate() }, [
533
+ previousPolicy(),
534
+ ]);
535
+
536
+ expect(syncPolicyMock).toHaveBeenCalledWith({
537
+ policyId: POLICY_ID,
538
+ stampTemplateSyncedOnCleanPass: true,
539
+ });
540
+ });
541
+
542
+ /*
543
+ * Re-saving the SAME template has re-synced nothing. Stamping "Template
544
+ * Synced" for it would tell an operator their criteria edit had landed on
545
+ * the fleet when it had not.
546
+ */
547
+ it("does not ask for a template stamp when the same template is re-sent", async () => {
548
+ await runPolicyUpdateSuccess({ monitorTemplateId: TEMPLATE_ID }, [
549
+ previousPolicy(),
550
+ ]);
551
+
552
+ expect(syncPolicyMock).toHaveBeenCalledWith({
553
+ policyId: POLICY_ID,
554
+ stampTemplateSyncedOnCleanPass: false,
555
+ });
556
+ });
557
+ });
558
+
559
+ describe("deleting a policy removes its monitors first", () => {
560
+ it("deletes the monitors before the row, not after", async () => {
561
+ const policy: NetworkAlertPolicy = new NetworkAlertPolicy();
562
+ policy.id = POLICY_ID;
563
+ policy.projectId = PROJECT_ID;
564
+
565
+ jest
566
+ .spyOn(ModelPermission, "checkDeleteQueryPermission")
567
+ .mockImplementation(
568
+ async <TModel extends BaseModel>(
569
+ _modelType: { new (): TModel },
570
+ query: Query<TModel>,
571
+ ): Promise<Query<TModel>> => {
572
+ return query;
573
+ },
574
+ );
575
+ jest.spyOn(NetworkAlertPolicyService, "findBy").mockResolvedValue([policy]);
576
+
577
+ await (NetworkAlertPolicyService as any).onBeforeDelete({
578
+ query: { _id: POLICY_ID.toString() },
579
+ limit: 1,
580
+ skip: 0,
581
+ props: { tenantId: PROJECT_ID },
582
+ });
583
+
584
+ /*
585
+ * Already called by the time the hook returns — NOT detached. Deleting
586
+ * them afterwards would leave a window, and after a crash a permanent
587
+ * one, in which billable monitors exist whose owner is a soft-deleted
588
+ * row nothing looks at.
589
+ */
590
+ expect(deletePolicyMonitorsMock).toHaveBeenCalledWith({
591
+ projectId: PROJECT_ID,
592
+ policyId: POLICY_ID,
593
+ });
594
+ });
595
+
596
+ /*
597
+ * Only policies the caller may actually delete. The hook runs before
598
+ * DatabaseService permission-checks the query, so it re-applies the same
599
+ * check first; otherwise a bulk delete the permission layer will trim could
600
+ * still take another project's monitors with it on the way through.
601
+ */
602
+ it("cleans up only the rows the caller is authorized to delete", async () => {
603
+ const permissionSpy: SpyInstance<
604
+ typeof ModelPermission.checkDeleteQueryPermission
605
+ > = jest
606
+ .spyOn(ModelPermission, "checkDeleteQueryPermission")
607
+ .mockResolvedValue({ _id: POLICY_ID.toString() } as never);
608
+ const findSpy: SpyInstance<typeof NetworkAlertPolicyService.findBy> = jest
609
+ .spyOn(NetworkAlertPolicyService, "findBy")
610
+ .mockResolvedValue([]);
611
+
612
+ await (NetworkAlertPolicyService as any).onBeforeDelete({
613
+ query: { projectId: PROJECT_ID },
614
+ limit: 10,
615
+ skip: 0,
616
+ props: { tenantId: PROJECT_ID },
617
+ });
618
+
619
+ expect(permissionSpy).toHaveBeenCalled();
620
+ expect(findSpy).toHaveBeenCalledWith(
621
+ expect.objectContaining({
622
+ query: { _id: POLICY_ID.toString() },
623
+ }),
624
+ );
625
+ expect(deletePolicyMonitorsMock).not.toHaveBeenCalled();
626
+ });
627
+ });
628
+
629
+ /*
630
+ * The template delete guard. Both FKs pointing at MonitorTemplate are SET
631
+ * NULL, so without this the delete succeeds and the damage is silent: a
632
+ * policy loses its template and stops covering anything new, and an operator
633
+ * finds out when the switch they added last month turns out never to have
634
+ * been alerted on.
635
+ */
636
+ describe("MonitorTemplateService refuses to delete a template in use", () => {
637
+ function templateRow(): MonitorTemplate {
638
+ const template: MonitorTemplate = new MonitorTemplate();
639
+ template.id = TEMPLATE_ID;
640
+ template.projectId = PROJECT_ID;
641
+ template.templateName = "Reachability v1";
642
+
643
+ return template;
644
+ }
645
+
646
+ function runDelete(
647
+ props: DatabaseCommonInteractionProps = {
648
+ tenantId: PROJECT_ID,
649
+ },
650
+ ): Promise<unknown> {
651
+ return (MonitorTemplateService as any).onBeforeDelete({
652
+ query: { _id: TEMPLATE_ID.toString() },
653
+ limit: 1,
654
+ skip: 0,
655
+ props: props,
656
+ });
657
+ }
658
+
659
+ function policiesUsingTemplate(
660
+ names: Array<string>,
661
+ ): Array<NetworkAlertPolicy> {
662
+ return names.map((name: string): NetworkAlertPolicy => {
663
+ const policy: NetworkAlertPolicy = new NetworkAlertPolicy();
664
+ policy.id = ObjectID.generate();
665
+ policy.name = name;
666
+
667
+ return policy;
668
+ });
669
+ }
670
+
671
+ it("names the policies that stand in the way", async () => {
672
+ jest
673
+ .spyOn(MonitorTemplateService, "findBy")
674
+ .mockResolvedValue([templateRow()]);
675
+ jest
676
+ .spyOn(NetworkAlertPolicyService, "findBy")
677
+ .mockResolvedValue(policiesUsingTemplate(["Warehouse switches"]));
678
+ jest
679
+ .spyOn(NetworkDeviceAutoImportRuleService, "findBy")
680
+ .mockResolvedValue([]);
681
+
682
+ /*
683
+ * The NAME, not just a count: the operator has to find the policy to
684
+ * detach it, and "1 network alert policy" would send them hunting.
685
+ */
686
+ await expect(runDelete()).rejects.toThrow(
687
+ /Reachability v1 is used by 1 network alert policy \(Warehouse switches\)/,
688
+ );
689
+ });
690
+
691
+ it("counts and abbreviates when many policies use it", async () => {
692
+ jest
693
+ .spyOn(MonitorTemplateService, "findBy")
694
+ .mockResolvedValue([templateRow()]);
695
+ jest
696
+ .spyOn(NetworkAlertPolicyService, "findBy")
697
+ .mockResolvedValue(policiesUsingTemplate(["A", "B", "C", "D", "E"]));
698
+ jest
699
+ .spyOn(NetworkDeviceAutoImportRuleService, "findBy")
700
+ .mockResolvedValue([]);
701
+
702
+ await expect(runDelete()).rejects.toThrow(/A, B, C and 2 more/);
703
+ });
704
+
705
+ it("refuses for an auto-import rule too", async () => {
706
+ const rule: NetworkDeviceAutoImportRule = new NetworkDeviceAutoImportRule();
707
+ rule.id = ObjectID.generate();
708
+ rule.name = "Import warehouse switches";
709
+
710
+ jest
711
+ .spyOn(MonitorTemplateService, "findBy")
712
+ .mockResolvedValue([templateRow()]);
713
+ jest.spyOn(NetworkAlertPolicyService, "findBy").mockResolvedValue([]);
714
+ jest
715
+ .spyOn(NetworkDeviceAutoImportRuleService, "findBy")
716
+ .mockResolvedValue([rule]);
717
+
718
+ await expect(runDelete()).rejects.toThrow(BadDataException);
719
+ await expect(runDelete()).rejects.toThrow(/Import warehouse switches/);
720
+ });
721
+
722
+ it("allows the delete when nothing provisions from the template", async () => {
723
+ jest
724
+ .spyOn(MonitorTemplateService, "findBy")
725
+ .mockResolvedValue([templateRow()]);
726
+ jest.spyOn(NetworkAlertPolicyService, "findBy").mockResolvedValue([]);
727
+ jest
728
+ .spyOn(NetworkDeviceAutoImportRuleService, "findBy")
729
+ .mockResolvedValue([]);
730
+
731
+ await expect(runDelete()).resolves.toBeDefined();
732
+ });
733
+
734
+ /*
735
+ * The hook runs before DatabaseService permission-checks the query, so its
736
+ * root read is re-scoped to the caller's tenant by hand. Without that, the
737
+ * refusal message could name another project's policies.
738
+ */
739
+ it("reads the templates it is about to delete within the caller's tenant", async () => {
740
+ const findSpy: SpyInstance<typeof MonitorTemplateService.findBy> = jest
741
+ .spyOn(MonitorTemplateService, "findBy")
742
+ .mockResolvedValue([]);
743
+
744
+ await runDelete();
745
+
746
+ expect(findSpy).toHaveBeenCalledWith(
747
+ expect.objectContaining({
748
+ query: expect.objectContaining({ projectId: PROJECT_ID }),
749
+ }),
750
+ );
751
+ });
752
+ });