@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,992 @@
1
+ import { describe, expect, test } from "@jest/globals";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import OneUptimeDate from "../../../Types/Date";
5
+ import NetworkDeviceMonitoringMethod, {
6
+ NetworkDeviceMonitoringMethodUtil,
7
+ } from "../../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
8
+ import { NetworkTopologyNode } from "../../../Types/Monitor/SnmpMonitor/NetworkTopology";
9
+ import DeviceReachabilityUtil, {
10
+ NetworkDeviceReachability,
11
+ } from "../../../Utils/NetworkDevice/DeviceReachabilityUtil";
12
+ import {
13
+ DeviceHealthStateInput,
14
+ NetworkDeviceHealthState,
15
+ deviceHealthState,
16
+ } from "../../../Utils/NetworkDevice/DeviceHealthStateUtil";
17
+ import SiteStatusRollupUtil, {
18
+ DeviceHealthShare,
19
+ DeviceHealthState,
20
+ RollupStatusOption,
21
+ } from "../../../Utils/NetworkSite/SiteStatusRollupUtil";
22
+ import NetworkTopologyUtil, {
23
+ TopologyBuildResult,
24
+ TopologyDeviceInput,
25
+ } from "../../../Utils/Monitor/NetworkTopologyUtil";
26
+ import {
27
+ DeviceHealthGroup,
28
+ deviceHealthInputForGroup,
29
+ deviceRollupStateForGroup,
30
+ } from "../../../Server/Utils/NetworkDevice/DeviceHealthAggregation";
31
+
32
+ /*
33
+ * Issue #3562 — the monitoring method reaches every classifier, not only
34
+ * the device list.
35
+ *
36
+ * DeviceReachabilityUtil knows the two kinds of NetworkDevice: a
37
+ * PROBE-POLLED one (monitoringMethod "Probe", and equally NULL, "" or the
38
+ * retired "SNMP") is judged by the OUTCOME of its last poll — the probe
39
+ * pings it on its schedule and walks it over SNMP when credentials resolve,
40
+ * and either answering makes it reachable — while a MONITOR-BACKED one is
41
+ * judged ONLY by the status its bound Monitor stamped, and is Pending until
42
+ * one lands. The device list pill goes through that rule with
43
+ * `monitoringMethod` attached and gets the right answer.
44
+ *
45
+ * Three other surfaces build a DeviceReachabilityUtil input of their own —
46
+ * the site card's per-device health (DeviceHealthStateUtil), the site
47
+ * status rollup (SiteStatusRollupUtil) and the topology map
48
+ * (NetworkTopologyUtil) — and none of them used to say what kind of device
49
+ * it was passing. That was survivable while a monitor-backed row had NULL
50
+ * in every poll column, because the rule can only answer Pending for that.
51
+ * It stops being survivable the moment those columns hold anything else:
52
+ *
53
+ * - a device SWITCHED from probe polling to a bound monitor keeps its old
54
+ * lastSeenAt until the switch-over clears it, and `isReachable` NULL +
55
+ * lastSeenAt set is the one branch of the rule where staleness alone
56
+ * decides — so a months-old timestamp reads as Down on the site card
57
+ * while the pill under it reads Pending;
58
+ * - the server keeps `isReachable` on a monitor-backed device in step
59
+ * with its Monitor (true/false, NULL when nothing is bound), and a
60
+ * mirrored outcome beside a stamp that has not landed yet would read as
61
+ * a poll verdict.
62
+ *
63
+ * The field is load-bearing in the OTHER direction too, and that is the half
64
+ * ping-first polling added. A probe-polled device now always has a poll
65
+ * verdict of its own, and it can carry a stamped MonitorStatus at the same
66
+ * time: a Network Device monitor with an "interface down → Offline"
67
+ * criterion stamps one the moment a single port goes dark, and so does the
68
+ * SNMP walk failing on a switch that still answers ping. That stamp is
69
+ * INFORMATIONAL on such a device — its poll decides — because a stamp
70
+ * outranking the poll turned a site of answering devices red while every
71
+ * device row under it read Up.
72
+ *
73
+ * So the field is threaded through all three inputs, and through the
74
+ * bucket-to-input builders that feed two of them. What is pinned here:
75
+ *
76
+ * 1. the field is OPTIONAL, and a caller that omits it — or passes NULL,
77
+ * "SNMP", anything the parser reads as Probe — behaves exactly as
78
+ * before, legacy freshness branch included;
79
+ * 2. an unstamped monitor-backed device is "unknown" on the site card, is
80
+ * skipped by both rollup policies, and is drawn "unknown" on the map,
81
+ * whatever its leftover poll columns say;
82
+ * 3. a stamped monitor-backed device is judged by the stamp on every
83
+ * surface, the same way the pill judges it;
84
+ * 4. a stamped PROBE-POLLED device is judged by its poll on every surface,
85
+ * also the same way the pill judges it — the stamp does not enter;
86
+ * 5. the aggregation buckets carry the field into both classifier
87
+ * inputs, and the topology endpoint selects it, forwards it, and gates
88
+ * the stamp on it.
89
+ */
90
+
91
+ const NOW: Date = OneUptimeDate.fromString("2026-09-01T12:00:00.000Z");
92
+
93
+ function minutesAgo(minutes: number): Date {
94
+ return new Date(NOW.getTime() - minutes * 60 * 1000);
95
+ }
96
+
97
+ /** The poll columns every classifier reads, in their raw column shape. */
98
+ interface PollColumns {
99
+ isReachable: boolean | null;
100
+ lastPolledAt: Date | null;
101
+ lastSeenAt: Date | null;
102
+ pollingIntervalInMinutes: number;
103
+ }
104
+
105
+ /*
106
+ * What a device switched from probe polling to a bound monitor is left
107
+ * holding: no recorded outcome, and a last successful poll from long before
108
+ * the probe stopped asking. On the legacy branch of the shared rule (no
109
+ * outcome, but seen) staleness alone decides, so this reads as Down through
110
+ * any classifier that forgets to say what kind of device it is.
111
+ */
112
+ const STALE_LEFTOVERS: PollColumns = {
113
+ isReachable: null,
114
+ lastPolledAt: null,
115
+ lastSeenAt: minutesAgo(60 * 24 * 90),
116
+ pollingIntervalInMinutes: 5,
117
+ };
118
+
119
+ // The same leftovers still inside the window, where that branch says Up.
120
+ const FRESH_LEFTOVERS: PollColumns = {
121
+ isReachable: null,
122
+ lastPolledAt: null,
123
+ lastSeenAt: minutesAgo(2),
124
+ pollingIntervalInMinutes: 5,
125
+ };
126
+
127
+ const NEVER_POLLED: PollColumns = {
128
+ isReachable: null,
129
+ lastPolledAt: null,
130
+ lastSeenAt: null,
131
+ pollingIntervalInMinutes: 5,
132
+ };
133
+
134
+ const ANSWERED: PollColumns = {
135
+ isReachable: true,
136
+ lastPolledAt: minutesAgo(1),
137
+ lastSeenAt: minutesAgo(1),
138
+ pollingIntervalInMinutes: 5,
139
+ };
140
+
141
+ const FAILED: PollColumns = {
142
+ isReachable: false,
143
+ lastPolledAt: minutesAgo(1),
144
+ lastSeenAt: minutesAgo(600),
145
+ pollingIntervalInMinutes: 5,
146
+ };
147
+
148
+ // The real column value, so a renamed enum member fails here and not in prod.
149
+ const MONITOR: string = NetworkDeviceMonitoringMethod.Monitor;
150
+
151
+ // MonitorStatus priority is HIGHER = WORSE (seeded: Operational 1 ... Offline 3).
152
+ const OPERATIONAL: RollupStatusOption = {
153
+ monitorStatusId: "status-operational",
154
+ priority: 1,
155
+ };
156
+ const DEGRADED: RollupStatusOption = {
157
+ monitorStatusId: "status-degraded",
158
+ priority: 2,
159
+ };
160
+ const OFFLINE: RollupStatusOption = {
161
+ monitorStatusId: "status-offline",
162
+ priority: 3,
163
+ };
164
+
165
+ /*
166
+ * The ladder as each surface reads it. `isOffline` is the flag the site
167
+ * card and the map read (NetworkDeviceTopology.ts: `isOfflineState ? "down"
168
+ * : "up"`); `isOperational` is the one the percent-threshold share reads.
169
+ */
170
+ interface StampedRung {
171
+ name: string;
172
+ option: RollupStatusOption;
173
+ isOperational: boolean;
174
+ isOffline: boolean;
175
+ }
176
+
177
+ const RUNGS: Array<StampedRung> = [
178
+ {
179
+ name: "Operational",
180
+ option: OPERATIONAL,
181
+ isOperational: true,
182
+ isOffline: false,
183
+ },
184
+ {
185
+ name: "Degraded",
186
+ option: DEGRADED,
187
+ isOperational: false,
188
+ isOffline: false,
189
+ },
190
+ {
191
+ name: "Offline",
192
+ option: OFFLINE,
193
+ isOperational: false,
194
+ isOffline: true,
195
+ },
196
+ ];
197
+
198
+ function healthInput(
199
+ columns: PollColumns,
200
+ overrides?: Partial<DeviceHealthStateInput>,
201
+ ): DeviceHealthStateInput {
202
+ return { ...columns, ...overrides };
203
+ }
204
+
205
+ function rollupState(
206
+ columns: PollColumns,
207
+ overrides?: Partial<DeviceHealthState>,
208
+ ): DeviceHealthState {
209
+ return { ...columns, ...overrides };
210
+ }
211
+
212
+ // TopologyDeviceInput carries `undefined` where a column carries NULL.
213
+ function topologyInput(
214
+ columns: PollColumns,
215
+ overrides?: Partial<TopologyDeviceInput>,
216
+ ): TopologyDeviceInput {
217
+ return {
218
+ id: "device-1",
219
+ name: "device-1",
220
+ isReachable: columns.isReachable === null ? undefined : columns.isReachable,
221
+ lastPolledAt:
222
+ columns.lastPolledAt === null ? undefined : columns.lastPolledAt,
223
+ lastSeenAt: columns.lastSeenAt === null ? undefined : columns.lastSeenAt,
224
+ pollingIntervalInMinutes: columns.pollingIntervalInMinutes,
225
+ ...overrides,
226
+ };
227
+ }
228
+
229
+ function topologyStatus(device: TopologyDeviceInput): string {
230
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
231
+ [device],
232
+ NOW,
233
+ );
234
+ const node: NetworkTopologyNode | undefined = result.nodes.find(
235
+ (candidate: NetworkTopologyNode): boolean => {
236
+ return candidate.id === device.id;
237
+ },
238
+ );
239
+ expect(node).toBeDefined();
240
+ return node!.status;
241
+ }
242
+
243
+ function worst(deviceStates: Array<DeviceHealthState>): string | null {
244
+ return SiteStatusRollupUtil.worstStatus({
245
+ deviceStates: deviceStates,
246
+ operationalStatus: OPERATIONAL,
247
+ offlineStatus: OFFLINE,
248
+ now: NOW,
249
+ });
250
+ }
251
+
252
+ function share(deviceStates: Array<DeviceHealthState>): DeviceHealthShare {
253
+ return SiteStatusRollupUtil.deviceHealthShare({
254
+ deviceStates: deviceStates,
255
+ now: NOW,
256
+ });
257
+ }
258
+
259
+ const NOTHING_REPORTED: DeviceHealthShare = {
260
+ reportingDeviceCount: 0,
261
+ nonOperationalDeviceCount: 0,
262
+ nonOperationalPercent: 0,
263
+ };
264
+
265
+ const ONE_DOWN: DeviceHealthShare = {
266
+ reportingDeviceCount: 1,
267
+ nonOperationalDeviceCount: 1,
268
+ nonOperationalPercent: 100,
269
+ };
270
+
271
+ const ONE_UP: DeviceHealthShare = {
272
+ reportingDeviceCount: 1,
273
+ nonOperationalDeviceCount: 0,
274
+ nonOperationalPercent: 0,
275
+ };
276
+
277
+ /*
278
+ * The field is optional precisely so that nothing that does not pass it can
279
+ * change. Every caller written before it existed — and every test of those
280
+ * callers — must land on the same branch of the shared rule it always did,
281
+ * legacy freshness included.
282
+ */
283
+ describe("without a monitoring method nothing changes — the legacy path is pinned", () => {
284
+ test("stale leftovers read as down on every surface, as they always did", () => {
285
+ expect(deviceHealthState(healthInput(STALE_LEFTOVERS), NOW)).toBe("down");
286
+ expect(worst([rollupState(STALE_LEFTOVERS)])).toBe(OFFLINE.monitorStatusId);
287
+ expect(share([rollupState(STALE_LEFTOVERS)])).toEqual(ONE_DOWN);
288
+ expect(topologyStatus(topologyInput(STALE_LEFTOVERS))).toBe("down");
289
+ });
290
+
291
+ test("fresh leftovers read as up on every surface, as they always did", () => {
292
+ expect(deviceHealthState(healthInput(FRESH_LEFTOVERS), NOW)).toBe(
293
+ "healthy",
294
+ );
295
+ expect(worst([rollupState(FRESH_LEFTOVERS)])).toBe(
296
+ OPERATIONAL.monitorStatusId,
297
+ );
298
+ expect(share([rollupState(FRESH_LEFTOVERS)])).toEqual(ONE_UP);
299
+ expect(topologyStatus(topologyInput(FRESH_LEFTOVERS))).toBe("up");
300
+ });
301
+
302
+ /*
303
+ * Everything the parser reads as Probe has to land on the same path as an
304
+ * omitted value, or a row written before the column existed (NULL) would
305
+ * classify differently from one written after it ("SNMP"), or from one
306
+ * written today ("Probe").
307
+ */
308
+ test.each([null, "", "snmp", NetworkDeviceMonitoringMethod.Probe])(
309
+ "a monitoring method of %j is the poll rule, exactly as if omitted",
310
+ (monitoringMethod: string | null) => {
311
+ expect(
312
+ deviceHealthState(
313
+ healthInput(STALE_LEFTOVERS, { monitoringMethod: monitoringMethod }),
314
+ NOW,
315
+ ),
316
+ ).toBe("down");
317
+ expect(
318
+ worst([
319
+ rollupState(STALE_LEFTOVERS, { monitoringMethod: monitoringMethod }),
320
+ ]),
321
+ ).toBe(OFFLINE.monitorStatusId);
322
+ expect(
323
+ topologyStatus(
324
+ topologyInput(STALE_LEFTOVERS, {
325
+ monitoringMethod: monitoringMethod,
326
+ }),
327
+ ),
328
+ ).toBe("down");
329
+ },
330
+ );
331
+ });
332
+
333
+ describe("an unstamped monitor-backed device is Pending on every surface", () => {
334
+ test.each([
335
+ ["stale leftovers", STALE_LEFTOVERS],
336
+ ["fresh leftovers", FRESH_LEFTOVERS],
337
+ ["nothing at all", NEVER_POLLED],
338
+ ])("with %s in its poll columns", (_label: string, columns: PollColumns) => {
339
+ expect(
340
+ deviceHealthState(
341
+ healthInput(columns, { monitoringMethod: MONITOR }),
342
+ NOW,
343
+ ),
344
+ ).toBe("unknown");
345
+ expect(
346
+ worst([rollupState(columns, { monitoringMethod: MONITOR })]),
347
+ ).toBeNull();
348
+ expect(
349
+ share([rollupState(columns, { monitoringMethod: MONITOR })]),
350
+ ).toEqual(NOTHING_REPORTED);
351
+ expect(
352
+ topologyStatus(topologyInput(columns, { monitoringMethod: MONITOR })),
353
+ ).toBe("unknown");
354
+ });
355
+
356
+ /*
357
+ * The server keeps `isReachable` on a monitor-backed device in step with
358
+ * its Monitor, so a mirrored true/false can exist beside a stamp that has
359
+ * not landed yet. A mirror is not a verdict: only the stamp is — which is
360
+ * exactly what the pill says about the same row.
361
+ */
362
+ test.each([true, false])(
363
+ "with a mirrored isReachable of %s and no stamp yet",
364
+ (isReachable: boolean) => {
365
+ const columns: PollColumns = { ...ANSWERED, isReachable: isReachable };
366
+
367
+ expect(
368
+ deviceHealthState(
369
+ healthInput(columns, { monitoringMethod: MONITOR }),
370
+ NOW,
371
+ ),
372
+ ).toBe("unknown");
373
+ expect(
374
+ worst([rollupState(columns, { monitoringMethod: MONITOR })]),
375
+ ).toBeNull();
376
+ expect(
377
+ topologyStatus(topologyInput(columns, { monitoringMethod: MONITOR })),
378
+ ).toBe("unknown");
379
+ },
380
+ );
381
+
382
+ test("the column is parsed, not compared: any casing of the word is monitor-backed", () => {
383
+ for (const spelling of ["monitor", "MONITOR", " Monitor "]) {
384
+ expect(
385
+ deviceHealthState(
386
+ healthInput(STALE_LEFTOVERS, { monitoringMethod: spelling }),
387
+ NOW,
388
+ ),
389
+ ).toBe("unknown");
390
+ expect(
391
+ worst([rollupState(STALE_LEFTOVERS, { monitoringMethod: spelling })]),
392
+ ).toBeNull();
393
+ expect(
394
+ topologyStatus(
395
+ topologyInput(STALE_LEFTOVERS, { monitoringMethod: spelling }),
396
+ ),
397
+ ).toBe("unknown");
398
+ }
399
+ });
400
+
401
+ /*
402
+ * Skipped means skipped from BOTH sides of the share, the same treatment
403
+ * a never-polled probe-polled bucket gets. Four hundred devices awaiting
404
+ * their first monitor evaluation must not dilute the one switch that is
405
+ * genuinely dark beside them into a 0.25% blip...
406
+ */
407
+ test("a bucket of unstamped monitor-backed devices does not dilute a real outage", () => {
408
+ expect(
409
+ share([
410
+ rollupState(STALE_LEFTOVERS, {
411
+ monitoringMethod: MONITOR,
412
+ deviceCount: 400,
413
+ }),
414
+ rollupState(FAILED),
415
+ ]),
416
+ ).toEqual(ONE_DOWN);
417
+ });
418
+
419
+ test("...and cannot drag a healthy site down either", () => {
420
+ expect(
421
+ worst([
422
+ rollupState(STALE_LEFTOVERS, { monitoringMethod: MONITOR }),
423
+ rollupState(ANSWERED),
424
+ ]),
425
+ ).toBe(OPERATIONAL.monitorStatusId);
426
+ });
427
+ });
428
+
429
+ describe("a stamped monitor-backed device is judged by the stamp, everywhere", () => {
430
+ test.each(RUNGS)(
431
+ "$name: the site card reads the offline end of the ladder",
432
+ (rung: StampedRung) => {
433
+ expect(
434
+ deviceHealthState(
435
+ healthInput(STALE_LEFTOVERS, {
436
+ monitoringMethod: MONITOR,
437
+ monitorStatusIsOffline: rung.isOffline,
438
+ }),
439
+ NOW,
440
+ ),
441
+ ).toBe(rung.isOffline ? "down" : "healthy");
442
+ },
443
+ );
444
+
445
+ test.each(RUNGS)(
446
+ "$name: worst-of carries the stamp verbatim",
447
+ (rung: StampedRung) => {
448
+ expect(
449
+ worst([
450
+ rollupState(STALE_LEFTOVERS, {
451
+ monitoringMethod: MONITOR,
452
+ currentMonitorStatusId: rung.option.monitorStatusId,
453
+ monitorStatusPriority: rung.option.priority,
454
+ }),
455
+ ]),
456
+ ).toBe(rung.option.monitorStatusId);
457
+ },
458
+ );
459
+
460
+ test.each(RUNGS)(
461
+ "$name: the share reads the operational end of the ladder",
462
+ (rung: StampedRung) => {
463
+ expect(
464
+ share([
465
+ rollupState(STALE_LEFTOVERS, {
466
+ monitoringMethod: MONITOR,
467
+ currentMonitorStatusId: rung.option.monitorStatusId,
468
+ monitorStatusIsOperational: rung.isOperational,
469
+ }),
470
+ ]),
471
+ ).toEqual(rung.isOperational ? ONE_UP : ONE_DOWN);
472
+ },
473
+ );
474
+
475
+ test.each(RUNGS)("$name: the map draws the stamp", (rung: StampedRung) => {
476
+ expect(
477
+ topologyStatus(
478
+ topologyInput(STALE_LEFTOVERS, {
479
+ monitoringMethod: MONITOR,
480
+ monitorStatus: rung.isOffline ? "down" : "up",
481
+ }),
482
+ ),
483
+ ).toBe(rung.isOffline ? "down" : "up");
484
+ });
485
+
486
+ /*
487
+ * The rollup falls back to reachability when a stamped row cannot be
488
+ * resolved (a deleted status, or a lookup that missed). For a probe-polled
489
+ * device that fallback is a real poll verdict. For a monitor-backed one
490
+ * there is nothing underneath to fall back TO — and the pill, which
491
+ * resolves the same row, reads Pending for it — so it sits out the vote.
492
+ */
493
+ test("a stamp the rollup cannot resolve leaves a monitor-backed device out of the vote", () => {
494
+ const unresolved: DeviceHealthState = rollupState(STALE_LEFTOVERS, {
495
+ currentMonitorStatusId: "status-deleted",
496
+ });
497
+
498
+ expect(worst([{ ...unresolved, monitoringMethod: MONITOR }])).toBeNull();
499
+ expect(share([{ ...unresolved, monitoringMethod: MONITOR }])).toEqual(
500
+ NOTHING_REPORTED,
501
+ );
502
+ /*
503
+ * Whereas the probe-polled device beside it still has its poll to fall
504
+ * back to — and would have had one even if the row HAD resolved, since
505
+ * its stamp never votes.
506
+ */
507
+ expect(worst([unresolved])).toBe(OFFLINE.monitorStatusId);
508
+ });
509
+ });
510
+
511
+ /*
512
+ * The other precedence, and the half ping-first polling added (see the
513
+ * header). A probe-polled device carries a stamp and a poll at the same
514
+ * time, and the poll is the verdict on every surface.
515
+ *
516
+ * The concrete regression: an "interface down → Offline" criterion, or an
517
+ * SNMP walk failing on a credential rotation, stamps Offline on a switch
518
+ * that answers every ping. If any of these surfaces read that stamp, the
519
+ * site card and the topology node go red while the device's own row in the
520
+ * list — which reads `isReachable` — says Up, and an operator is sent to
521
+ * find an outage that is not there.
522
+ */
523
+ describe("a stamped probe-polled device is judged by its poll, everywhere", () => {
524
+ // Every spelling of "probe-polled" a real row can carry.
525
+ const PROBE_POLLED: Array<string | null | undefined> = [
526
+ NetworkDeviceMonitoringMethod.Probe,
527
+ "SNMP",
528
+ "",
529
+ null,
530
+ undefined,
531
+ ];
532
+
533
+ test.each(RUNGS)(
534
+ "$name: the site card reads the poll, not the rung",
535
+ (rung: StampedRung) => {
536
+ for (const monitoringMethod of PROBE_POLLED) {
537
+ expect(
538
+ deviceHealthState(
539
+ healthInput(ANSWERED, {
540
+ monitoringMethod: monitoringMethod,
541
+ monitorStatusIsOffline: rung.isOffline,
542
+ }),
543
+ NOW,
544
+ ),
545
+ ).toBe("healthy");
546
+ expect(
547
+ deviceHealthState(
548
+ healthInput(FAILED, {
549
+ monitoringMethod: monitoringMethod,
550
+ monitorStatusIsOffline: rung.isOffline,
551
+ }),
552
+ NOW,
553
+ ),
554
+ ).toBe("down");
555
+ }
556
+ },
557
+ );
558
+
559
+ test.each(RUNGS)(
560
+ "$name: worst-of maps the poll to the project's own rows, ignoring the stamp",
561
+ (rung: StampedRung) => {
562
+ expect(
563
+ worst([
564
+ rollupState(ANSWERED, {
565
+ currentMonitorStatusId: rung.option.monitorStatusId,
566
+ monitorStatusPriority: rung.option.priority,
567
+ }),
568
+ ]),
569
+ ).toBe(OPERATIONAL.monitorStatusId);
570
+ expect(
571
+ worst([
572
+ rollupState(FAILED, {
573
+ currentMonitorStatusId: rung.option.monitorStatusId,
574
+ monitorStatusPriority: rung.option.priority,
575
+ }),
576
+ ]),
577
+ ).toBe(OFFLINE.monitorStatusId);
578
+ },
579
+ );
580
+
581
+ test.each(RUNGS)(
582
+ "$name: the share counts the poll, so a stamped fleet that answers is 0% down",
583
+ (rung: StampedRung) => {
584
+ expect(
585
+ share([
586
+ rollupState(ANSWERED, {
587
+ currentMonitorStatusId: rung.option.monitorStatusId,
588
+ monitorStatusIsOperational: rung.isOperational,
589
+ deviceCount: 400,
590
+ }),
591
+ ]),
592
+ ).toEqual({
593
+ reportingDeviceCount: 400,
594
+ nonOperationalDeviceCount: 0,
595
+ nonOperationalPercent: 0,
596
+ });
597
+ },
598
+ );
599
+
600
+ /*
601
+ * The map's gate is one layer up. NetworkTopologyUtil takes a
602
+ * `monitorStatus` that is PRESENT as the verdict — by design, since the
603
+ * graph is handed nodes rather than rows — so the endpoint that builds
604
+ * those nodes is what withholds the stamp from a probe-polled device. The
605
+ * source assertion at the bottom of this file pins that gate; here we pin
606
+ * what the graph then draws, which is the poll.
607
+ */
608
+ test("the map draws the poll for a probe-polled device, the stamp having been withheld", () => {
609
+ expect(topologyStatus(topologyInput(ANSWERED))).toBe("up");
610
+ expect(topologyStatus(topologyInput(FAILED))).toBe("down");
611
+ });
612
+ });
613
+
614
+ /*
615
+ * The invariant all of the above serves, stated once over the whole
616
+ * matrix: for every row this change is about, the three surfaces answer
617
+ * what the device list pill answers. The pill IS DeviceReachabilityUtil
618
+ * with the same columns, so it is used as the oracle rather than a
619
+ * hand-written expectation per cell.
620
+ */
621
+ describe("the site card, the rollup and the map agree with the device list pill", () => {
622
+ interface MatrixCase {
623
+ label: string;
624
+ monitoringMethod: string | null | undefined;
625
+ monitorStatusIsOffline: boolean | undefined;
626
+ columns: PollColumns;
627
+ }
628
+
629
+ const METHODS: Array<string | null | undefined> = [
630
+ undefined,
631
+ null,
632
+ "SNMP",
633
+ MONITOR,
634
+ ];
635
+ const STAMPS: Array<boolean | undefined> = [undefined, false, true];
636
+ const COLUMN_SETS: Array<[string, PollColumns]> = [
637
+ ["stale leftovers", STALE_LEFTOVERS],
638
+ ["fresh leftovers", FRESH_LEFTOVERS],
639
+ ["never polled", NEVER_POLLED],
640
+ ["answered", ANSWERED],
641
+ ["failed", FAILED],
642
+ ];
643
+
644
+ const cases: Array<MatrixCase> = [];
645
+
646
+ /*
647
+ * The full product, stamped probe-polled devices included. They used to be
648
+ * excluded here on the grounds that the pill judged such a device by its
649
+ * poll while the classifiers judged it by its stamp — a real disagreement
650
+ * at the time, and the one ping-first polling closed. All four surfaces
651
+ * now read a probe-polled device by its poll, so the cell belongs in the
652
+ * matrix and is the strongest single check that they still agree.
653
+ */
654
+ for (const monitoringMethod of METHODS) {
655
+ for (const monitorStatusIsOffline of STAMPS) {
656
+ for (const [label, columns] of COLUMN_SETS) {
657
+ cases.push({
658
+ label: `${label} / method ${String(monitoringMethod)} / stamp ${String(monitorStatusIsOffline)}`,
659
+ monitoringMethod: monitoringMethod,
660
+ monitorStatusIsOffline: monitorStatusIsOffline,
661
+ columns: columns,
662
+ });
663
+ }
664
+ }
665
+ }
666
+
667
+ /*
668
+ * What the topology ENDPOINT hands the graph. NetworkTopologyUtil takes a
669
+ * present `monitorStatus` as the verdict outright, so the isMonitorBacked
670
+ * gate lives where the device row is mapped into a node — reproduced here
671
+ * so the map is compared against the graph it is actually given (the
672
+ * source assertions at the bottom of this file pin that the endpoint
673
+ * really applies it).
674
+ */
675
+ function stampForGraph(testCase: MatrixCase): "up" | "down" | undefined {
676
+ if (
677
+ testCase.monitorStatusIsOffline === undefined ||
678
+ !NetworkDeviceMonitoringMethodUtil.isMonitorBacked(
679
+ testCase.monitoringMethod,
680
+ )
681
+ ) {
682
+ return undefined;
683
+ }
684
+
685
+ return testCase.monitorStatusIsOffline ? "down" : "up";
686
+ }
687
+
688
+ function pill(testCase: MatrixCase): NetworkDeviceReachability {
689
+ return DeviceReachabilityUtil.getStatus(
690
+ {
691
+ ...testCase.columns,
692
+ monitoringMethod: testCase.monitoringMethod,
693
+ monitorStatusIsOffline: testCase.monitorStatusIsOffline,
694
+ },
695
+ NOW,
696
+ );
697
+ }
698
+
699
+ test("the matrix reaches every verdict the pill can give", () => {
700
+ const seen: Set<NetworkDeviceReachability> =
701
+ new Set<NetworkDeviceReachability>(cases.map(pill));
702
+
703
+ expect(Array.from(seen).sort()).toEqual(
704
+ [
705
+ NetworkDeviceReachability.Down,
706
+ NetworkDeviceReachability.Pending,
707
+ NetworkDeviceReachability.Up,
708
+ ].sort(),
709
+ );
710
+ });
711
+
712
+ test("the site card", () => {
713
+ const disagreements: Array<string> = [];
714
+
715
+ for (const testCase of cases) {
716
+ const verdict: NetworkDeviceReachability = pill(testCase);
717
+ const expected: NetworkDeviceHealthState =
718
+ verdict === NetworkDeviceReachability.Pending
719
+ ? "unknown"
720
+ : verdict === NetworkDeviceReachability.Up
721
+ ? "healthy"
722
+ : "down";
723
+
724
+ const actual: NetworkDeviceHealthState = deviceHealthState(
725
+ healthInput(testCase.columns, {
726
+ monitoringMethod: testCase.monitoringMethod,
727
+ monitorStatusIsOffline: testCase.monitorStatusIsOffline,
728
+ }),
729
+ NOW,
730
+ );
731
+
732
+ if (actual !== expected) {
733
+ disagreements.push(`${testCase.label}: pill=${verdict} card=${actual}`);
734
+ }
735
+ }
736
+
737
+ expect(disagreements).toEqual([]);
738
+ });
739
+
740
+ test("the worst-of rollup", () => {
741
+ const disagreements: Array<string> = [];
742
+
743
+ for (const testCase of cases) {
744
+ const verdict: NetworkDeviceReachability = pill(testCase);
745
+ const expected: string | null =
746
+ verdict === NetworkDeviceReachability.Pending
747
+ ? null
748
+ : verdict === NetworkDeviceReachability.Up
749
+ ? OPERATIONAL.monitorStatusId
750
+ : OFFLINE.monitorStatusId;
751
+
752
+ // A stamp reaches the rollup as the status row it resolved to.
753
+ const stamp: RollupStatusOption | undefined =
754
+ testCase.monitorStatusIsOffline === undefined
755
+ ? undefined
756
+ : testCase.monitorStatusIsOffline
757
+ ? OFFLINE
758
+ : OPERATIONAL;
759
+
760
+ const actual: string | null = worst([
761
+ rollupState(testCase.columns, {
762
+ monitoringMethod: testCase.monitoringMethod,
763
+ currentMonitorStatusId: stamp?.monitorStatusId,
764
+ monitorStatusPriority: stamp?.priority,
765
+ }),
766
+ ]);
767
+
768
+ if (actual !== expected) {
769
+ disagreements.push(
770
+ `${testCase.label}: pill=${verdict} rollup=${String(actual)}`,
771
+ );
772
+ }
773
+ }
774
+
775
+ expect(disagreements).toEqual([]);
776
+ });
777
+
778
+ test("the map", () => {
779
+ const disagreements: Array<string> = [];
780
+
781
+ for (const testCase of cases) {
782
+ const verdict: NetworkDeviceReachability = pill(testCase);
783
+ const expected: string =
784
+ verdict === NetworkDeviceReachability.Pending
785
+ ? "unknown"
786
+ : verdict === NetworkDeviceReachability.Up
787
+ ? "up"
788
+ : "down";
789
+
790
+ const actual: string = topologyStatus(
791
+ topologyInput(testCase.columns, {
792
+ monitoringMethod: testCase.monitoringMethod,
793
+ monitorStatus: stampForGraph(testCase),
794
+ }),
795
+ );
796
+
797
+ if (actual !== expected) {
798
+ disagreements.push(`${testCase.label}: pill=${verdict} map=${actual}`);
799
+ }
800
+ }
801
+
802
+ expect(disagreements).toEqual([]);
803
+ });
804
+ });
805
+
806
+ /*
807
+ * The site card and the rollup never see rows — they see buckets, grouped in
808
+ * SQL by the facts the classifiers read and turned back into classifier
809
+ * inputs by DeviceHealthAggregation. The method is one of those facts, so
810
+ * both builders have to carry it or the whole thread above is cut at the
811
+ * database.
812
+ */
813
+ describe("buckets carry the method into both classifier inputs", () => {
814
+ // An unstamped bucket of stale leftovers: the legacy branch, on purpose.
815
+ function bucket(overrides: Partial<DeviceHealthGroup>): DeviceHealthGroup {
816
+ return {
817
+ siteId: null,
818
+ monitorStatusId: null,
819
+ monitoringMethod: null,
820
+ isReachable: null,
821
+ hasBeenPolled: false,
822
+ hasBeenSeen: true,
823
+ isStale: true,
824
+ hasDownInterfaces: false,
825
+ deviceCount: 1,
826
+ interfacesDownTotal: 0,
827
+ ...overrides,
828
+ };
829
+ }
830
+
831
+ test.each([null, "SNMP", MONITOR])(
832
+ "deviceHealthInputForGroup emits %j verbatim",
833
+ (monitoringMethod: string | null) => {
834
+ expect(
835
+ deviceHealthInputForGroup({
836
+ group: bucket({ monitoringMethod: monitoringMethod }),
837
+ now: NOW,
838
+ }).monitoringMethod,
839
+ ).toBe(monitoringMethod);
840
+ },
841
+ );
842
+
843
+ test.each([null, "SNMP", MONITOR])(
844
+ "deviceRollupStateForGroup emits %j verbatim",
845
+ (monitoringMethod: string | null) => {
846
+ expect(
847
+ deviceRollupStateForGroup({
848
+ group: bucket({ monitoringMethod: monitoringMethod }),
849
+ now: NOW,
850
+ }).monitoringMethod,
851
+ ).toBe(monitoringMethod);
852
+ },
853
+ );
854
+
855
+ test("the same stale bucket is down as probe-polled and unknown as monitor-backed", () => {
856
+ const probePolled: DeviceHealthGroup = bucket({});
857
+ const monitorBacked: DeviceHealthGroup = bucket({
858
+ monitoringMethod: MONITOR,
859
+ });
860
+
861
+ expect(
862
+ deviceHealthState(
863
+ deviceHealthInputForGroup({ group: probePolled, now: NOW }),
864
+ NOW,
865
+ ),
866
+ ).toBe("down");
867
+ expect(
868
+ deviceHealthState(
869
+ deviceHealthInputForGroup({ group: monitorBacked, now: NOW }),
870
+ NOW,
871
+ ),
872
+ ).toBe("unknown");
873
+
874
+ expect(
875
+ worst([deviceRollupStateForGroup({ group: probePolled, now: NOW })]),
876
+ ).toBe(OFFLINE.monitorStatusId);
877
+ expect(
878
+ worst([deviceRollupStateForGroup({ group: monitorBacked, now: NOW })]),
879
+ ).toBeNull();
880
+ });
881
+ });
882
+
883
+ /*
884
+ * The map's endpoint is the one caller that maps device ROWS into
885
+ * TopologyDeviceInput by hand, so it has to select the column and copy it
886
+ * across — and neither omission would fail to compile or throw. It lives in
887
+ * App, which this suite cannot import, so it is asserted against the source
888
+ * the way App's own surface-invariant tests are. Whitespace is squashed
889
+ * first so prettier re-wrapping a line cannot turn this into a red herring.
890
+ */
891
+ describe("the topology endpoint selects the column and forwards it", () => {
892
+ const source: string = fs
893
+ .readFileSync(
894
+ path.join(
895
+ __dirname,
896
+ "..",
897
+ "..",
898
+ "..",
899
+ "..",
900
+ "App",
901
+ "FeatureSet",
902
+ "BaseAPI",
903
+ "API",
904
+ "NetworkDeviceTopology.ts",
905
+ ),
906
+ "utf8",
907
+ )
908
+ .replace(/\s+/g, " ");
909
+
910
+ /*
911
+ * The object literal enclosing the first occurrence of `needle`, found by
912
+ * brace matching outwards — so an assertion about "the device select" is
913
+ * made against that literal and not against the whole file.
914
+ */
915
+ function enclosingLiteral(needle: string): string {
916
+ const needleAt: number = source.indexOf(needle);
917
+ expect(needleAt).toBeGreaterThanOrEqual(0);
918
+
919
+ let start: number = -1;
920
+ let depth: number = 0;
921
+
922
+ for (let index: number = needleAt; index >= 0; index--) {
923
+ const character: string = source[index]!;
924
+
925
+ if (character === "}") {
926
+ depth++;
927
+ } else if (character === "{") {
928
+ if (depth === 0) {
929
+ start = index;
930
+ break;
931
+ }
932
+ depth--;
933
+ }
934
+ }
935
+
936
+ expect(start).toBeGreaterThanOrEqual(0);
937
+
938
+ depth = 0;
939
+
940
+ for (let index: number = start; index < source.length; index++) {
941
+ const character: string = source[index]!;
942
+
943
+ if (character === "{") {
944
+ depth++;
945
+ } else if (character === "}") {
946
+ depth--;
947
+ if (depth === 0) {
948
+ return source.slice(start, index + 1);
949
+ }
950
+ }
951
+ }
952
+
953
+ throw new Error(`Unbalanced literal around ${needle}`);
954
+ }
955
+
956
+ test("the device select asks for monitoringMethod beside the poll columns", () => {
957
+ const select: string = enclosingLiteral("isReachable: true,");
958
+
959
+ expect(select).toContain("monitoringMethod: true,");
960
+ // ...and still for the stamp, which is what the method qualifies.
961
+ expect(select).toContain("currentMonitorStatusId: true,");
962
+ });
963
+
964
+ test("the row is forwarded to the graph input with the method attached", () => {
965
+ const mapping: string = enclosingLiteral(
966
+ "isReachable: device.isReachable,",
967
+ );
968
+
969
+ expect(mapping).toContain("monitoringMethod: device.monitoringMethod,");
970
+ });
971
+
972
+ /*
973
+ * And the gate itself. NetworkTopologyUtil.deviceStatus returns a present
974
+ * `monitorStatus` outright — the graph is handed nodes, not rows, and has
975
+ * no business re-deciding what a node's status means — so the endpoint is
976
+ * the only place that can withhold a probe-polled device's stamp. Drop
977
+ * this condition and an "interface down → Offline" criterion paints every
978
+ * answering switch on the map red while its row in the device list reads
979
+ * Up: a silent, compiling, non-throwing regression, which is why it is
980
+ * asserted against the source.
981
+ */
982
+ test("the stamp reaches the graph only for a monitor-backed device", () => {
983
+ const mapping: string = enclosingLiteral(
984
+ "isReachable: device.isReachable,",
985
+ );
986
+
987
+ expect(mapping).toContain("monitorStatus:");
988
+ expect(mapping).toContain(
989
+ "NetworkDeviceMonitoringMethodUtil.isMonitorBacked( device.monitoringMethod, )",
990
+ );
991
+ });
992
+ });