@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
@@ -9,11 +9,13 @@ import NetworkDeviceMonitoringMethod from "../../../Types/NetworkDevice/NetworkD
9
9
  import ObjectID from "../../../Types/ObjectID";
10
10
  import UpdateBy from "../../../Server/Types/Database/UpdateBy";
11
11
  import { OnUpdate } from "../../../Server/Types/Database/Hooks";
12
- import { afterEach, describe, expect, it } from "@jest/globals";
12
+ import { afterEach, beforeEach, describe, expect, it } from "@jest/globals";
13
13
 
14
14
  /*
15
15
  * Contract under test — OneUptime/oneuptime#3392, "a correctly bound
16
- * ping-only device is stuck on Pending".
16
+ * ping-only device is stuck on Pending", and its second half: the device
17
+ * list's summary tiles and Status facet still said "Pending" for such a
18
+ * device after the pill said Up.
17
19
  *
18
20
  * A monitor-backed NetworkDevice is never polled: no probe, no
19
21
  * credentials, no walk. Its ONLY source of health is the Monitor bound to
@@ -28,15 +30,27 @@ import { afterEach, describe, expect, it } from "@jest/globals";
28
30
  * down. On a healthy device that is never, which is why the reporter's
29
31
  * phone stayed on "Pending" while it answered every ping.
30
32
  *
33
+ * The tiles and the facet are a separate surface with a separate rule:
34
+ * they count and filter in SQL over `isReachable` alone, because they
35
+ * cannot walk the stamp's ladder per row. So the stamp alone left them
36
+ * wrong, and the server now keeps `isReachable` on a monitor-backed device
37
+ * in step with the monitor — `!isOfflineState`, NULL when nothing is bound
38
+ * — in the same write as the stamp.
39
+ *
31
40
  * What is pinned here:
32
41
  *
33
42
  * - binding stamps the monitor's CURRENT status immediately, on create
34
43
  * and on update, rather than waiting for its next change,
35
- * - the site chain is recomputed when the stamp moves, and only then,
36
- * - unbinding (or switching the device back to SNMP) clears the stamp,
37
- * so a ping monitor's verdict cannot outlive the binding,
38
- * - an SNMP device's stamp which comes from the Network Device monitor
39
- * watching its walk, not from this column is never touched,
44
+ * - `isReachable` is written with it, from the OFFLINE end of the
45
+ * ladder, and both go in ONE write,
46
+ * - the site chain is recomputed when either moves, and only then,
47
+ * - unbinding clears both; switching the device back to Probe clears the
48
+ * stamp, the mirrored `isReachable` and the SNMP walk's pair, and
49
+ * leaves all of them to the next poll,
50
+ * - a Probe device's stamp — which comes from the Network Device monitor
51
+ * watching its polls, not from this column — is never touched, and in
52
+ * particular a form re-sending "Probe" on a Probe device is not a
53
+ * transition,
40
54
  * - the monitor lookup is scoped to the device's own project,
41
55
  * - and a failure in any of it never escapes into the device update.
42
56
  */
@@ -63,6 +77,9 @@ const OPERATIONAL_STATUS_ID: ObjectID = new ObjectID(
63
77
  const OFFLINE_STATUS_ID: ObjectID = new ObjectID(
64
78
  "66666666-6666-4666-8666-666666666666",
65
79
  );
80
+ const DEGRADED_STATUS_ID: ObjectID = new ObjectID(
81
+ "77777777-7777-4777-8777-777777777777",
82
+ );
66
83
 
67
84
  function fakeDevice(overrides: Record<string, unknown>): NetworkDevice {
68
85
  return {
@@ -73,11 +90,29 @@ function fakeDevice(overrides: Record<string, unknown>): NetworkDevice {
73
90
  } as unknown as NetworkDevice;
74
91
  }
75
92
 
76
- function fakeMonitor(currentMonitorStatusId: ObjectID | undefined): Monitor {
93
+ /*
94
+ * The monitor as refreshStampedMonitorStatus selects it: the stamp id plus
95
+ * the OFFLINE flag of the status row behind it. `isOfflineState` defaults
96
+ * from the id so the common cases read naturally; the Degraded case sets
97
+ * it explicitly, because that rung is the one where the two flags of the
98
+ * ladder disagree.
99
+ */
100
+ function fakeMonitor(
101
+ currentMonitorStatusId: ObjectID | undefined,
102
+ isOfflineState?: boolean,
103
+ ): Monitor {
104
+ const offline: boolean =
105
+ isOfflineState === undefined
106
+ ? currentMonitorStatusId?.toString() === OFFLINE_STATUS_ID.toString()
107
+ : isOfflineState;
108
+
77
109
  return {
78
110
  id: MONITOR_ID,
79
111
  _id: MONITOR_ID.toString(),
80
112
  currentMonitorStatusId: currentMonitorStatusId,
113
+ currentMonitorStatus: currentMonitorStatusId
114
+ ? { isOfflineState: offline }
115
+ : undefined,
81
116
  } as unknown as Monitor;
82
117
  }
83
118
 
@@ -120,7 +155,8 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
120
155
 
121
156
  /*
122
157
  * The fix, stated once: the device in the issue, bound to a Ping monitor
123
- * that is Operational and has been for weeks.
158
+ * that is Operational and has been for weeks. Both columns land, in one
159
+ * write.
124
160
  */
125
161
  it("stamps the bound monitor's current status onto a monitor-backed device", async () => {
126
162
  const { update } = mockDeviceAndMonitor({
@@ -143,14 +179,20 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
143
179
  expect(args.data.currentMonitorStatusId.toString()).toBe(
144
180
  OPERATIONAL_STATUS_ID.toString(),
145
181
  );
182
+ expect(args.data.isReachable).toBe(true);
183
+ expect(Object.keys(args.data).sort()).toEqual([
184
+ "currentMonitorStatusId",
185
+ "isReachable",
186
+ ]);
146
187
  });
147
188
 
148
- it("stamps an offline monitor just the same, so the device reads Down", async () => {
189
+ it("stamps an offline monitor just the same, so the device reads Down everywhere", async () => {
149
190
  const { update } = mockDeviceAndMonitor({
150
191
  device: fakeDevice({
151
192
  monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
152
193
  monitorId: MONITOR_ID,
153
194
  currentMonitorStatusId: OPERATIONAL_STATUS_ID,
195
+ isReachable: true,
154
196
  }),
155
197
  monitor: fakeMonitor(OFFLINE_STATUS_ID),
156
198
  });
@@ -160,9 +202,39 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
160
202
  clearWhenNotMonitorBacked: false,
161
203
  });
162
204
 
163
- expect(
164
- update.mock.calls[0]![0].data.currentMonitorStatusId.toString(),
165
- ).toBe(OFFLINE_STATUS_ID.toString());
205
+ const data: any = update.mock.calls[0]![0].data;
206
+ expect(data.currentMonitorStatusId.toString()).toBe(
207
+ OFFLINE_STATUS_ID.toString(),
208
+ );
209
+ expect(data.isReachable).toBe(false);
210
+ });
211
+
212
+ /*
213
+ * MonitorStatus is a ladder, not a pair: a "Degraded" row is neither
214
+ * operational nor offline. DeviceReachabilityUtil reads only the offline
215
+ * end for the pill, so the value stamped here has to be derived from the
216
+ * same end — reading the operational flag would paint a degraded device
217
+ * red in the tiles and green in the pill.
218
+ */
219
+ it("stamps a Degraded monitor as reachable, matching the pill's rule", async () => {
220
+ const { update } = mockDeviceAndMonitor({
221
+ device: fakeDevice({
222
+ monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
223
+ monitorId: MONITOR_ID,
224
+ }),
225
+ monitor: fakeMonitor(DEGRADED_STATUS_ID, false),
226
+ });
227
+
228
+ await NetworkDeviceService.refreshStampedMonitorStatus({
229
+ deviceId: DEVICE_ID,
230
+ clearWhenNotMonitorBacked: false,
231
+ });
232
+
233
+ const data: any = update.mock.calls[0]![0].data;
234
+ expect(data.currentMonitorStatusId.toString()).toBe(
235
+ DEGRADED_STATUS_ID.toString(),
236
+ );
237
+ expect(data.isReachable).toBe(true);
166
238
  });
167
239
 
168
240
  /*
@@ -209,17 +281,19 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
209
281
 
210
282
  /*
211
283
  * Idempotence is what makes this safe to call from every save and from
212
- * the upgrade backfill: re-deriving a stamp that already agrees must
213
- * cost nothing and, more importantly, must not churn the site rollups of
214
- * a whole estate on every unrelated device edit.
284
+ * the upgrade backfill: re-deriving a row that already agrees must cost
285
+ * nothing and, more importantly, must not churn the site rollups of a
286
+ * whole estate on every unrelated device edit. "Agrees" is both
287
+ * columns, not just the stamp.
215
288
  */
216
- it("writes nothing when the stamp already agrees", async () => {
289
+ it("writes nothing when the stamp and isReachable already agree", async () => {
217
290
  const { update, rollup } = mockDeviceAndMonitor({
218
291
  device: fakeDevice({
219
292
  monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
220
293
  monitorId: MONITOR_ID,
221
294
  siteId: SITE_ID,
222
295
  currentMonitorStatusId: OPERATIONAL_STATUS_ID,
296
+ isReachable: true,
223
297
  }),
224
298
  monitor: fakeMonitor(OPERATIONAL_STATUS_ID),
225
299
  });
@@ -233,16 +307,49 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
233
307
  expect(rollup).not.toHaveBeenCalled();
234
308
  });
235
309
 
310
+ /*
311
+ * The row every pre-upgrade monitor-backed device is in: the stamp was
312
+ * put there by a status change, but nothing ever wrote isReachable, so
313
+ * the tiles still count it as Pending. A stamp that agrees is not a
314
+ * reason to skip the write.
315
+ */
316
+ it("writes both when the stamp agrees but isReachable is stale", async () => {
317
+ const { update, rollup } = mockDeviceAndMonitor({
318
+ device: fakeDevice({
319
+ monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
320
+ monitorId: MONITOR_ID,
321
+ siteId: SITE_ID,
322
+ currentMonitorStatusId: OPERATIONAL_STATUS_ID,
323
+ isReachable: undefined,
324
+ }),
325
+ monitor: fakeMonitor(OPERATIONAL_STATUS_ID),
326
+ });
327
+
328
+ await NetworkDeviceService.refreshStampedMonitorStatus({
329
+ deviceId: DEVICE_ID,
330
+ clearWhenNotMonitorBacked: false,
331
+ });
332
+
333
+ expect(update).toHaveBeenCalledTimes(1);
334
+ const data: any = update.mock.calls[0]![0].data;
335
+ expect(data.currentMonitorStatusId.toString()).toBe(
336
+ OPERATIONAL_STATUS_ID.toString(),
337
+ );
338
+ expect(data.isReachable).toBe(true);
339
+ expect(rollup).toHaveBeenCalledTimes(1);
340
+ });
341
+
236
342
  /*
237
343
  * Discovery import creates ping-only hosts with no monitor on purpose —
238
344
  * a subnet sweep has nothing to bind them to yet. "Pending" is the true
239
345
  * answer for those, so nothing is invented for them.
240
346
  */
241
- it("leaves an already-empty stamp alone when no monitor is bound", async () => {
347
+ it("leaves an already-empty row alone when no monitor is bound", async () => {
242
348
  const { update, findMonitor } = mockDeviceAndMonitor({
243
349
  device: fakeDevice({
244
350
  monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
245
351
  monitorId: undefined,
352
+ isReachable: undefined,
246
353
  }),
247
354
  });
248
355
 
@@ -257,14 +364,15 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
257
364
 
258
365
  /*
259
366
  * ...and the same device once its monitor is unbound. The old verdict
260
- * must not survive the binding that produced it.
367
+ * must not survive the binding that produced it — on either column.
261
368
  */
262
- it("clears the stamp when the monitor is unbound", async () => {
369
+ it("clears the stamp and isReachable when the monitor is unbound", async () => {
263
370
  const { update } = mockDeviceAndMonitor({
264
371
  device: fakeDevice({
265
372
  monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
266
373
  monitorId: undefined,
267
374
  currentMonitorStatusId: OPERATIONAL_STATUS_ID,
375
+ isReachable: true,
268
376
  }),
269
377
  });
270
378
 
@@ -274,19 +382,50 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
274
382
  });
275
383
 
276
384
  expect(update).toHaveBeenCalledTimes(1);
277
- expect(update.mock.calls[0]![0].data.currentMonitorStatusId).toBeNull();
385
+ expect(update.mock.calls[0]![0].data).toEqual({
386
+ currentMonitorStatusId: null,
387
+ isReachable: null,
388
+ });
389
+ });
390
+
391
+ /*
392
+ * An unbound device whose stamp is already empty but whose isReachable
393
+ * is not: a device switched over from probe polling before the transition started
394
+ * clearing poll residue. The stale `true` would keep it in the "Up" tile.
395
+ */
396
+ it("nulls a stale isReachable on an unbound device even when the stamp is already empty", async () => {
397
+ const { update } = mockDeviceAndMonitor({
398
+ device: fakeDevice({
399
+ monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
400
+ monitorId: undefined,
401
+ currentMonitorStatusId: undefined,
402
+ isReachable: true,
403
+ }),
404
+ });
405
+
406
+ await NetworkDeviceService.refreshStampedMonitorStatus({
407
+ deviceId: DEVICE_ID,
408
+ clearWhenNotMonitorBacked: false,
409
+ });
410
+
411
+ expect(update).toHaveBeenCalledTimes(1);
412
+ expect(update.mock.calls[0]![0].data).toEqual({
413
+ currentMonitorStatusId: null,
414
+ isReachable: null,
415
+ });
278
416
  });
279
417
 
280
418
  /*
281
419
  * A bound monitor that has somehow never had a status is the same case:
282
420
  * there is nothing to adopt, and a stale stamp is worse than none.
283
421
  */
284
- it("clears the stamp when the bound monitor has no status of its own", async () => {
422
+ it("clears both when the bound monitor has no status of its own", async () => {
285
423
  const { update } = mockDeviceAndMonitor({
286
424
  device: fakeDevice({
287
425
  monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
288
426
  monitorId: MONITOR_ID,
289
427
  currentMonitorStatusId: OPERATIONAL_STATUS_ID,
428
+ isReachable: true,
290
429
  }),
291
430
  monitor: fakeMonitor(undefined),
292
431
  });
@@ -296,15 +435,19 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
296
435
  clearWhenNotMonitorBacked: false,
297
436
  });
298
437
 
299
- expect(update.mock.calls[0]![0].data.currentMonitorStatusId).toBeNull();
438
+ expect(update.mock.calls[0]![0].data).toEqual({
439
+ currentMonitorStatusId: null,
440
+ isReachable: null,
441
+ });
300
442
  });
301
443
 
302
- it("clears the stamp when the bound monitor is gone", async () => {
444
+ it("clears both when the bound monitor is gone", async () => {
303
445
  const { update } = mockDeviceAndMonitor({
304
446
  device: fakeDevice({
305
447
  monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
306
448
  monitorId: MONITOR_ID,
307
449
  currentMonitorStatusId: OPERATIONAL_STATUS_ID,
450
+ isReachable: true,
308
451
  }),
309
452
  monitor: null,
310
453
  });
@@ -314,12 +457,15 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
314
457
  clearWhenNotMonitorBacked: false,
315
458
  });
316
459
 
317
- expect(update.mock.calls[0]![0].data.currentMonitorStatusId).toBeNull();
460
+ expect(update.mock.calls[0]![0].data).toEqual({
461
+ currentMonitorStatusId: null,
462
+ isReachable: null,
463
+ });
318
464
  });
319
465
 
320
466
  /*
321
467
  * The monitorId FK only requires the Monitor row to exist, not that it
322
- * belongs to the device's project — the same hole the create/update
468
+ * belongs to the device's project — the same hole the create and update
323
469
  * guards close. Reading it back through a project-scoped query is what
324
470
  * stops another tenant's status being stamped here.
325
471
  */
@@ -344,17 +490,43 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
344
490
  });
345
491
 
346
492
  /*
347
- * An SNMP device's stamp comes from the Network Device monitor watching
348
- * its walk, and that binding lives in the monitor's step data rather
493
+ * The offline flag lives on the MonitorStatus row, not on the monitor.
494
+ * A select that dropped the relation would read `undefined` for every
495
+ * monitor and stamp every device reachable.
496
+ */
497
+ it("selects the offline flag of the monitor's status row", async () => {
498
+ const { findMonitor } = mockDeviceAndMonitor({
499
+ device: fakeDevice({
500
+ monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
501
+ monitorId: MONITOR_ID,
502
+ }),
503
+ monitor: fakeMonitor(OPERATIONAL_STATUS_ID),
504
+ });
505
+
506
+ await NetworkDeviceService.refreshStampedMonitorStatus({
507
+ deviceId: DEVICE_ID,
508
+ clearWhenNotMonitorBacked: false,
509
+ });
510
+
511
+ const select: any = findMonitor.mock.calls[0]![0].select;
512
+ expect(select.currentMonitorStatusId).toBe(true);
513
+ expect(select.currentMonitorStatus).toEqual({ isOfflineState: true });
514
+ });
515
+
516
+ /*
517
+ * A Probe device's stamp comes from the Network Device monitor watching
518
+ * its polls, and that binding lives in the monitor's step data rather
349
519
  * than in this column. Re-deriving it from `monitorId` would wipe a
350
- * legitimate status the walk pipeline put there.
520
+ * legitimate status the poll pipeline put there — and its isReachable
521
+ * is the poll's own verdict.
351
522
  */
352
- it("does not touch an SNMP device by default", async () => {
523
+ it("does not touch a Probe device by default", async () => {
353
524
  const { update, findMonitor } = mockDeviceAndMonitor({
354
525
  device: fakeDevice({
355
- monitoringMethod: NetworkDeviceMonitoringMethod.Snmp,
526
+ monitoringMethod: NetworkDeviceMonitoringMethod.Probe,
356
527
  monitorId: MONITOR_ID,
357
528
  currentMonitorStatusId: OPERATIONAL_STATUS_ID,
529
+ isReachable: true,
358
530
  }),
359
531
  monitor: fakeMonitor(OFFLINE_STATUS_ID),
360
532
  });
@@ -370,9 +542,9 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
370
542
 
371
543
  /*
372
544
  * A device created before the column existed holds NULL, which reads as
373
- * SNMP — and must behave as one.
545
+ * Probe — and must behave as one.
374
546
  */
375
- it("treats a device with no monitoring method as SNMP", async () => {
547
+ it("treats a device with no monitoring method as Probe", async () => {
376
548
  const { update } = mockDeviceAndMonitor({
377
549
  device: fakeDevice({
378
550
  monitoringMethod: undefined,
@@ -391,19 +563,28 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
391
563
  });
392
564
 
393
565
  /*
394
- * The one write that DOES clear an SNMP device: the one that just moved
395
- * it off monitor-backed. The ping monitor's verdict outliving the
566
+ * The one write that DOES clear a Probe device: the one that just moved
567
+ * it off monitor-backed. The bound monitor's verdict outliving the
396
568
  * binding matters because a stamped status beats reachability in
397
569
  * DeviceHealthStateUtil — it would keep deciding the site rollup of a
398
- * device that is now being walked.
570
+ * device that is now being polled.
571
+ *
572
+ * And the mirrored `isReachable` goes with it. While the device was
573
+ * monitor-backed that column could only ever be the bound monitor's
574
+ * mirror (the poll's value was NULLed on the way in, and the poll never
575
+ * writes a monitor-backed row), so leaving it would make the device read
576
+ * "Down — the last poll could not reach it" on every surface from a
577
+ * verdict no poll ever produced. NULL is Pending until the first poll.
578
+ * The SNMP walk's pair is NULLed in the same write — see below.
399
579
  */
400
- it("clears the stamp when a device is switched back to SNMP", async () => {
401
- const { update, rollup } = mockDeviceAndMonitor({
580
+ it("clears the stamp and the mirrored isReachable when a device is switched back to Probe", async () => {
581
+ const { update, rollup, findMonitor } = mockDeviceAndMonitor({
402
582
  device: fakeDevice({
403
- monitoringMethod: NetworkDeviceMonitoringMethod.Snmp,
583
+ monitoringMethod: NetworkDeviceMonitoringMethod.Probe,
404
584
  monitorId: MONITOR_ID,
405
585
  siteId: SITE_ID,
406
586
  currentMonitorStatusId: OPERATIONAL_STATUS_ID,
587
+ isReachable: true,
407
588
  }),
408
589
  monitor: fakeMonitor(OPERATIONAL_STATUS_ID),
409
590
  });
@@ -413,11 +594,117 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
413
594
  clearWhenNotMonitorBacked: true,
414
595
  });
415
596
 
597
+ expect(findMonitor).not.toHaveBeenCalled();
416
598
  expect(update).toHaveBeenCalledTimes(1);
417
- expect(update.mock.calls[0]![0].data.currentMonitorStatusId).toBeNull();
599
+ expect(update.mock.calls[0]![0].data).toEqual({
600
+ currentMonitorStatusId: null,
601
+ isReachable: null,
602
+ isSnmpReachable: null,
603
+ lastSnmpSeenAt: null,
604
+ });
418
605
  expect(rollup).toHaveBeenCalledTimes(1);
419
606
  });
420
607
 
608
+ /*
609
+ * The mirror can outlive the stamp on its own — the monitor was deleted
610
+ * (stamp cleared) while isReachable stayed — and it is just as wrong.
611
+ */
612
+ it("clears a mirrored isReachable even when the stamp is already gone", async () => {
613
+ const { update, rollup } = mockDeviceAndMonitor({
614
+ device: fakeDevice({
615
+ monitoringMethod: NetworkDeviceMonitoringMethod.Probe,
616
+ monitorId: undefined,
617
+ siteId: SITE_ID,
618
+ currentMonitorStatusId: undefined,
619
+ isReachable: false,
620
+ }),
621
+ });
622
+
623
+ await NetworkDeviceService.refreshStampedMonitorStatus({
624
+ deviceId: DEVICE_ID,
625
+ clearWhenNotMonitorBacked: true,
626
+ });
627
+
628
+ expect(update).toHaveBeenCalledTimes(1);
629
+ expect(update.mock.calls[0]![0].data).toEqual({
630
+ currentMonitorStatusId: null,
631
+ isReachable: null,
632
+ isSnmpReachable: null,
633
+ lastSnmpSeenAt: null,
634
+ });
635
+ expect(rollup).toHaveBeenCalledTimes(1);
636
+ });
637
+
638
+ /*
639
+ * The SNMP walk's pair is residue of the same kind: nothing walked the
640
+ * device while it was monitor-backed, so whatever those two columns hold
641
+ * predates the binding, and a device switched back to Probe starts clean
642
+ * — its first poll decides whether SNMP answers. A failed walk (`false`)
643
+ * is a verdict, so it counts as something to clear; only NULL is "no
644
+ * walk".
645
+ */
646
+ it.each([
647
+ ["a failed walk", { isSnmpReachable: false }],
648
+ ["a successful walk", { isSnmpReachable: true }],
649
+ [
650
+ "a last successful walk time",
651
+ { lastSnmpSeenAt: new Date("2026-08-01T00:00:00.000Z") },
652
+ ],
653
+ ])(
654
+ "clears the SNMP walk's residue (%s) when a device is switched back to Probe, even with no stamp and no mirror",
655
+ async (_label: string, residue: Record<string, unknown>) => {
656
+ const { update, rollup } = mockDeviceAndMonitor({
657
+ device: fakeDevice({
658
+ monitoringMethod: NetworkDeviceMonitoringMethod.Probe,
659
+ siteId: SITE_ID,
660
+ currentMonitorStatusId: undefined,
661
+ isReachable: undefined,
662
+ ...residue,
663
+ }),
664
+ });
665
+
666
+ await NetworkDeviceService.refreshStampedMonitorStatus({
667
+ deviceId: DEVICE_ID,
668
+ clearWhenNotMonitorBacked: true,
669
+ });
670
+
671
+ expect(update).toHaveBeenCalledTimes(1);
672
+ expect(update.mock.calls[0]![0].data).toEqual({
673
+ currentMonitorStatusId: null,
674
+ isReachable: null,
675
+ isSnmpReachable: null,
676
+ lastSnmpSeenAt: null,
677
+ });
678
+ expect(rollup).toHaveBeenCalledTimes(1);
679
+ },
680
+ );
681
+
682
+ /*
683
+ * ...and a Probe device with nothing stamped, no mirrored verdict and no
684
+ * walk residue has nothing to clear. A null-over-null write would still
685
+ * recompute the site chain for nothing.
686
+ */
687
+ it("writes nothing when asked to clear a Probe device that has no stamp, no mirror and no walk residue", async () => {
688
+ const { update, rollup } = mockDeviceAndMonitor({
689
+ device: fakeDevice({
690
+ monitoringMethod: NetworkDeviceMonitoringMethod.Probe,
691
+ siteId: SITE_ID,
692
+ currentMonitorStatusId: undefined,
693
+ isReachable: undefined,
694
+ isSnmpReachable: undefined,
695
+ lastSnmpSeenAt: undefined,
696
+ }),
697
+ });
698
+
699
+ await NetworkDeviceService.refreshStampedMonitorStatus({
700
+ deviceId: DEVICE_ID,
701
+ clearWhenNotMonitorBacked: true,
702
+ });
703
+
704
+ expect(update).not.toHaveBeenCalled();
705
+ expect(rollup).not.toHaveBeenCalled();
706
+ });
707
+
421
708
  it("does nothing for a device the update never actually matched", async () => {
422
709
  const { update } = mockDeviceAndMonitor({ device: null });
423
710
 
@@ -449,8 +736,10 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
449
736
  /*
450
737
  * The columns the method reads. A select that drops one of them makes
451
738
  * this silently wrong rather than loudly broken — a missing
452
- * `monitoringMethod` reads as SNMP and skips every monitor-backed
453
- * device, which is the bug all over again.
739
+ * `monitoringMethod` reads as Probe and skips every monitor-backed
740
+ * device, which is the bug all over again, and a missing `isReachable`
741
+ * reads as "never written" and rewrites every device on every save. The
742
+ * SNMP pair is read only to decide whether the clear has anything to do.
454
743
  */
455
744
  it("selects every column its decision depends on", async () => {
456
745
  const findDevice: jest.SpyInstance = jest
@@ -466,6 +755,9 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
466
755
  expect(select.monitoringMethod).toBe(true);
467
756
  expect(select.monitorId).toBe(true);
468
757
  expect(select.currentMonitorStatusId).toBe(true);
758
+ expect(select.isReachable).toBe(true);
759
+ expect(select.isSnmpReachable).toBe(true);
760
+ expect(select.lastSnmpSeenAt).toBe(true);
469
761
  expect(select.projectId).toBe(true);
470
762
  expect(select.siteId).toBe(true);
471
763
  });
@@ -477,8 +769,27 @@ describe("NetworkDeviceService.refreshStampedMonitorStatus", () => {
477
769
  * `monitor` RELATION together; server-side callers write the `monitorId`
478
770
  * COLUMN. Both spellings have to fire, or the fix reaches only half the
479
771
  * writes (OneUptime/oneuptime#2940 is the same lesson for sites).
772
+ *
773
+ * Whether the re-stamp may CLEAR is decided from what onBeforeUpdate
774
+ * recorded about each device's previous method (carryForward), never from
775
+ * the payload alone: the form re-sends monitoringMethod on every save, so
776
+ * "the payload says Probe" used to wipe the stamp of every Probe device that
777
+ * was ever saved.
480
778
  */
481
779
  describe("NetworkDeviceService.onUpdateSuccess re-stamps a changed binding", () => {
780
+ let residueWrite: jest.SpyInstance;
781
+
782
+ beforeEach(() => {
783
+ /*
784
+ * The Probe -> Monitor transition clears poll residue through this
785
+ * seam, and the Monitor -> Probe transition restores polling through
786
+ * it; mocked so no case here reaches a database.
787
+ */
788
+ residueWrite = jest
789
+ .spyOn(NetworkDeviceService, "updateColumnsByIdWithoutHooks")
790
+ .mockResolvedValue(undefined as never);
791
+ });
792
+
482
793
  afterEach(() => {
483
794
  jest.restoreAllMocks();
484
795
  });
@@ -486,6 +797,7 @@ describe("NetworkDeviceService.onUpdateSuccess re-stamps a changed binding", ()
486
797
  function runOnUpdateSuccess(
487
798
  data: Record<string, unknown>,
488
799
  updatedItemIds: Array<ObjectID> = [DEVICE_ID],
800
+ carryForward: unknown = null,
489
801
  ): Promise<OnUpdate<NetworkDevice>> {
490
802
  const onUpdate: OnUpdate<NetworkDevice> = {
491
803
  updateBy: {
@@ -493,7 +805,7 @@ describe("NetworkDeviceService.onUpdateSuccess re-stamps a changed binding", ()
493
805
  data: data,
494
806
  props: { isRoot: true },
495
807
  } as unknown as UpdateBy<NetworkDevice>,
496
- carryForward: null,
808
+ carryForward: carryForward,
497
809
  };
498
810
 
499
811
  return (NetworkDeviceService as any).onUpdateSuccess(
@@ -502,6 +814,16 @@ describe("NetworkDeviceService.onUpdateSuccess re-stamps a changed binding", ()
502
814
  );
503
815
  }
504
816
 
817
+ // What onBeforeUpdate hands over on a method write.
818
+ function methodCarryForward(
819
+ wasMonitorBackedByDeviceId: Record<string, boolean>,
820
+ ): unknown {
821
+ return {
822
+ previousDevices: [],
823
+ wasMonitorBackedByDeviceId: wasMonitorBackedByDeviceId,
824
+ };
825
+ }
826
+
505
827
  it("re-stamps when the monitoring method is written", async () => {
506
828
  const refresh: jest.SpyInstance = jest
507
829
  .spyOn(NetworkDeviceService, "refreshStampedMonitorStatus")
@@ -539,29 +861,93 @@ describe("NetworkDeviceService.onUpdateSuccess re-stamps a changed binding", ()
539
861
 
540
862
  /*
541
863
  * The exact save from the issue: Monitoring Method and Monitor set in one
542
- * submit, which is how the Device Details card posts them.
864
+ * submit, on a device that was Probe until now. Nothing to clear — the
865
+ * device is arriving at monitor-backed, not leaving it — and its poll
866
+ * residue goes before the re-stamp so the monitor's verdict is what
867
+ * lands.
543
868
  */
544
869
  it("re-stamps the reported save, which writes both at once", async () => {
545
870
  const refresh: jest.SpyInstance = jest
546
871
  .spyOn(NetworkDeviceService, "refreshStampedMonitorStatus")
547
872
  .mockResolvedValue(undefined as never);
548
873
 
549
- await runOnUpdateSuccess({
550
- monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
551
- monitor: { _id: MONITOR_ID.toString() },
552
- deviceRole: "IP phone",
553
- });
874
+ await runOnUpdateSuccess(
875
+ {
876
+ monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
877
+ monitor: { _id: MONITOR_ID.toString() },
878
+ deviceRole: "IP phone",
879
+ },
880
+ [DEVICE_ID],
881
+ methodCarryForward({ [DEVICE_ID.toString()]: false }),
882
+ );
554
883
 
555
884
  expect(refresh).toHaveBeenCalledTimes(1);
885
+ expect(refresh.mock.calls[0]![0].clearWhenNotMonitorBacked).toBe(false);
886
+ expect(residueWrite).toHaveBeenCalledTimes(1);
887
+ expect(residueWrite.mock.invocationCallOrder[0]).toBeLessThan(
888
+ refresh.mock.invocationCallOrder[0]!,
889
+ );
890
+ });
891
+
892
+ /*
893
+ * THE regression. The Settings form re-sends monitoringMethod on every
894
+ * save, so a Probe device saved with a new name arrives here with
895
+ * "Probe" in the payload. Before carryForward existed that was read as a
896
+ * transition and the stamp its Network Device monitor had put there was
897
+ * wiped on every save.
898
+ */
899
+ it("does not ask to clear when a Probe device is re-saved as Probe", async () => {
900
+ const refresh: jest.SpyInstance = jest
901
+ .spyOn(NetworkDeviceService, "refreshStampedMonitorStatus")
902
+ .mockResolvedValue(undefined as never);
903
+
904
+ await runOnUpdateSuccess(
905
+ {
906
+ monitoringMethod: NetworkDeviceMonitoringMethod.Probe,
907
+ name: "core-sw-01",
908
+ },
909
+ [DEVICE_ID],
910
+ methodCarryForward({ [DEVICE_ID.toString()]: false }),
911
+ );
912
+
913
+ expect(refresh).toHaveBeenCalledTimes(1);
914
+ expect(refresh.mock.calls[0]![0].clearWhenNotMonitorBacked).toBe(false);
915
+ expect(residueWrite).not.toHaveBeenCalled();
916
+ });
917
+
918
+ /*
919
+ * The one write that may clear: the device WAS monitor-backed and the
920
+ * payload moves it off. Only the previous method can say so.
921
+ */
922
+ it("asks to clear on a real Monitor -> Probe transition", async () => {
923
+ const refresh: jest.SpyInstance = jest
924
+ .spyOn(NetworkDeviceService, "refreshStampedMonitorStatus")
925
+ .mockResolvedValue(undefined as never);
926
+
927
+ await runOnUpdateSuccess(
928
+ { monitoringMethod: NetworkDeviceMonitoringMethod.Probe },
929
+ [DEVICE_ID],
930
+ methodCarryForward({ [DEVICE_ID.toString()]: true }),
931
+ );
932
+
556
933
  expect(refresh.mock.calls[0]![0].clearWhenNotMonitorBacked).toBe(true);
934
+ /*
935
+ * The only root write this direction makes is the polling restore
936
+ * (pinned in NetworkDeviceMonitoringMethodTransition.test); never a
937
+ * residue reset, which is the other direction's.
938
+ */
939
+ expect(
940
+ residueWrite.mock.calls.filter((call: Array<any>) => {
941
+ return "lastSeenAt" in call[0].data;
942
+ }),
943
+ ).toHaveLength(0);
557
944
  });
558
945
 
559
946
  /*
560
- * A method write is the only thing allowed to clear an SNMP device's
561
- * stamp, because it is the only write that can have just moved the
562
- * device off monitor-backed. Binding alone must not.
947
+ * A binding-only write cannot be a transition, whatever the device's
948
+ * method: there is no previous method to compare and nothing to clear.
563
949
  */
564
- it("only asks to clear on a method write", async () => {
950
+ it("only ever asks to clear on a method write", async () => {
565
951
  const refresh: jest.SpyInstance = jest
566
952
  .spyOn(NetworkDeviceService, "refreshStampedMonitorStatus")
567
953
  .mockResolvedValue(undefined as never);
@@ -569,6 +955,7 @@ describe("NetworkDeviceService.onUpdateSuccess re-stamps a changed binding", ()
569
955
  await runOnUpdateSuccess({ monitorId: MONITOR_ID });
570
956
 
571
957
  expect(refresh.mock.calls[0]![0].clearWhenNotMonitorBacked).toBe(false);
958
+ expect(residueWrite).not.toHaveBeenCalled();
572
959
  });
573
960
 
574
961
  it("re-stamps every device a bulk update touched", async () => {
@@ -605,6 +992,7 @@ describe("NetworkDeviceService.onUpdateSuccess re-stamps a changed binding", ()
605
992
  );
606
993
 
607
994
  expect(refresh).not.toHaveBeenCalled();
995
+ expect(residueWrite).not.toHaveBeenCalled();
608
996
  });
609
997
 
610
998
  /*
@@ -621,6 +1009,7 @@ describe("NetworkDeviceService.onUpdateSuccess re-stamps a changed binding", ()
621
1009
  await runOnUpdateSuccess({ sysName: "un0661voipcp01", interfacesDown: 2 });
622
1010
 
623
1011
  expect(refresh).not.toHaveBeenCalled();
1012
+ expect(residueWrite).not.toHaveBeenCalled();
624
1013
  });
625
1014
 
626
1015
  /*
@@ -668,8 +1057,8 @@ describe("NetworkDeviceService.onUpdateSuccess re-stamps a changed binding", ()
668
1057
 
669
1058
  /*
670
1059
  * The create side. A device can arrive monitor-backed and already bound —
671
- * the "Add Device" form asks for the monitor in the same submit, and the
672
- * discovery review screen imports ping-only hosts in bulk — so waiting for
1060
+ * the API and Terraform can post the method and the monitor in one body —
1061
+ * so waiting for
673
1062
  * a later edit to stamp it would leave a freshly created device on
674
1063
  * "Pending" for exactly the same reason the reported one was.
675
1064
  *
@@ -748,18 +1137,18 @@ describe("NetworkDeviceService.onCreateSuccess stamps a device created bound", (
748
1137
  });
749
1138
 
750
1139
  /*
751
- * Every SNMP device ever created goes through this hook, including a
1140
+ * Every Probe device ever created goes through this hook, including a
752
1141
  * whole subnet at a time on discovery import. None of them has anything
753
1142
  * to stamp, so none of them pays for a device read and a monitor read.
754
1143
  */
755
- it("does not touch an SNMP device", async () => {
1144
+ it("does not touch a Probe device", async () => {
756
1145
  mockRuleChain();
757
1146
  const refresh: jest.SpyInstance = jest
758
1147
  .spyOn(NetworkDeviceService, "refreshStampedMonitorStatus")
759
1148
  .mockResolvedValue(undefined as never);
760
1149
 
761
1150
  await runOnCreateSuccess(
762
- fakeDevice({ monitoringMethod: NetworkDeviceMonitoringMethod.Snmp }),
1151
+ fakeDevice({ monitoringMethod: NetworkDeviceMonitoringMethod.Probe }),
763
1152
  );
764
1153
 
765
1154
  expect(refresh).not.toHaveBeenCalled();