@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,739 @@
1
+ import { Service as NetworkDeviceServiceType } from "../../../Server/Services/NetworkDeviceService";
2
+ import UpdateBy from "../../../Server/Types/Database/UpdateBy";
3
+ import { OnUpdate } from "../../../Server/Types/Database/Hooks";
4
+ import NetworkDevice from "../../../Models/DatabaseModels/NetworkDevice";
5
+ import NetworkDeviceMonitoringMethod from "../../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
6
+ import ObjectID from "../../../Types/ObjectID";
7
+ import { beforeEach, describe, expect, test } from "@jest/globals";
8
+
9
+ /*
10
+ * WHAT THIS FILE IS DEFENDING
11
+ *
12
+ * A NetworkDevice's monitoring method can move in two directions, and each
13
+ * direction has a consequence the payload alone cannot express:
14
+ *
15
+ * Probe -> Monitor The device stops being polled. The last thing its
16
+ * probe found — lastSeenAt, lastPolledAt, isReachable,
17
+ * the SNMP walk's verdict and last success, the
18
+ * interface counts — is now residue on a device nothing
19
+ * polls, and left in place it keeps feeding the legacy
20
+ * staleness rule (DeviceReachabilityUtil judges a row
21
+ * with lastSeenAt and no isReachable by freshness) and
22
+ * the network summary's "degraded" query (isReachable
23
+ * true AND interfacesDown > 0).
24
+ *
25
+ * Monitor -> Probe The bound monitor's stamped verdict must not outlive
26
+ * the binding: DeviceHealthStateUtil lets a stamp beat
27
+ * reachability, so a stale one would keep deciding the
28
+ * site rollup of a device that is now polled. And the
29
+ * polling that arriving at Monitor switched off has to
30
+ * come back on, or the device sits on "Pending" under a
31
+ * method whose whole point is that the probe polls it.
32
+ *
33
+ * The trap is that "the payload writes monitoringMethod" is NOT "the
34
+ * method changed". The Settings form re-sends the method on every save, so
35
+ * before onBeforeUpdate started recording the OLD method, every save of a
36
+ * Probe device was treated as a Monitor -> Probe transition and wiped the
37
+ * stamp its Network Device monitor had put there. So what is pinned here:
38
+ *
39
+ * 1. onBeforeUpdate snapshots each matched device's previous method into
40
+ * carryForward, WITHOUT clobbering the previousDevices snapshot the
41
+ * site maintenance already relies on;
42
+ * 2. onUpdateSuccess asks to clear the stamp ONLY for a device that was
43
+ * monitor-backed and no longer is;
44
+ * 3. the Probe -> Monitor transition clears the poll residue, as a root
45
+ * write, BEFORE the re-stamp — and NOT on the caller's own payload,
46
+ * because those columns are updatable by fewer roles than
47
+ * monitoringMethod is and the column-permission check runs on the
48
+ * payload after the hook. Only isPollingEnabled rides the payload,
49
+ * and its permissions match monitoringMethod's;
50
+ * 4. the Monitor -> Probe transition restores polling — isPollingEnabled
51
+ * on, nextPollAt now — as a root write, per device that actually left
52
+ * monitor-backed and never from the payload (a bulk "Probe" also
53
+ * matches devices that already were Probe, one of which may have
54
+ * polling off on purpose), and never over a payload that says
55
+ * isPollingEnabled: false in the same write. No probe is required for
56
+ * it: the forms require one, the API and Terraform may assign it later.
57
+ */
58
+
59
+ const PROJECT_ID: ObjectID = new ObjectID(
60
+ "11111111-1111-4111-8111-111111111111",
61
+ );
62
+ const PROBE_DEVICE_ID: ObjectID = new ObjectID(
63
+ "22222222-2222-4222-8222-222222222222",
64
+ );
65
+ const MONITOR_BACKED_DEVICE_ID: ObjectID = new ObjectID(
66
+ "33333333-3333-4333-8333-333333333333",
67
+ );
68
+ const UNRECORDED_DEVICE_ID: ObjectID = new ObjectID(
69
+ "44444444-4444-4444-8444-444444444444",
70
+ );
71
+
72
+ const RESIDUE_COLUMNS: Array<string> = [
73
+ "lastSeenAt",
74
+ "lastPolledAt",
75
+ "isReachable",
76
+ "isSnmpReachable",
77
+ "lastSnmpSeenAt",
78
+ "interfacesUp",
79
+ "interfacesDown",
80
+ ];
81
+
82
+ type DeviceServiceInternals = {
83
+ onBeforeUpdate: (
84
+ updateBy: UpdateBy<NetworkDevice>,
85
+ ) => Promise<OnUpdate<NetworkDevice>>;
86
+ onUpdateSuccess: (
87
+ onUpdate: OnUpdate<NetworkDevice>,
88
+ updatedItemIds: Array<ObjectID>,
89
+ ) => Promise<OnUpdate<NetworkDevice>>;
90
+ };
91
+
92
+ function buildDeviceService(): {
93
+ service: NetworkDeviceServiceType;
94
+ internals: DeviceServiceInternals;
95
+ } {
96
+ const service: NetworkDeviceServiceType = new NetworkDeviceServiceType();
97
+ return {
98
+ service,
99
+ internals: service as unknown as DeviceServiceInternals,
100
+ };
101
+ }
102
+
103
+ function deviceWithMethod(
104
+ deviceId: ObjectID,
105
+ monitoringMethod: string | undefined,
106
+ ): NetworkDevice {
107
+ const device: NetworkDevice = new NetworkDevice(deviceId);
108
+ device.projectId = PROJECT_ID;
109
+ if (monitoringMethod !== undefined) {
110
+ device.monitoringMethod = monitoringMethod;
111
+ }
112
+ return device;
113
+ }
114
+
115
+ function methodUpdate(
116
+ data: Record<string, unknown>,
117
+ query: Record<string, unknown> = {},
118
+ ): UpdateBy<NetworkDevice> {
119
+ return {
120
+ query: query,
121
+ data: data,
122
+ props: { isRoot: true },
123
+ } as unknown as UpdateBy<NetworkDevice>;
124
+ }
125
+
126
+ describe("onBeforeUpdate on a monitoring method write", () => {
127
+ beforeEach(() => {
128
+ jest.restoreAllMocks();
129
+ });
130
+
131
+ test("switching to Monitor turns polling off on the same payload", async () => {
132
+ const { service, internals } = buildDeviceService();
133
+
134
+ jest
135
+ .spyOn(service, "findBy")
136
+ .mockResolvedValue([
137
+ deviceWithMethod(PROBE_DEVICE_ID, NetworkDeviceMonitoringMethod.Probe),
138
+ ] as never);
139
+
140
+ const result: OnUpdate<NetworkDevice> = await internals.onBeforeUpdate(
141
+ methodUpdate({ monitoringMethod: NetworkDeviceMonitoringMethod.Monitor }),
142
+ );
143
+
144
+ expect(result.updateBy.data.isPollingEnabled).toBe(false);
145
+ });
146
+
147
+ /*
148
+ * The residue columns are deliberately NOT put on the payload. Column
149
+ * permissions are checked on the payload AFTER this hook, and a project
150
+ * member may update monitoringMethod but not isReachable — so nulling
151
+ * them here would turn that member's legitimate switch into a permission
152
+ * failure. onUpdateSuccess clears them as root instead (below).
153
+ */
154
+ test("does not put the poll residue columns on the caller's payload", async () => {
155
+ const { service, internals } = buildDeviceService();
156
+
157
+ jest
158
+ .spyOn(service, "findBy")
159
+ .mockResolvedValue([
160
+ deviceWithMethod(PROBE_DEVICE_ID, NetworkDeviceMonitoringMethod.Probe),
161
+ ] as never);
162
+
163
+ const result: OnUpdate<NetworkDevice> = await internals.onBeforeUpdate(
164
+ methodUpdate({ monitoringMethod: NetworkDeviceMonitoringMethod.Monitor }),
165
+ );
166
+
167
+ for (const column of RESIDUE_COLUMNS) {
168
+ expect(column in result.updateBy.data).toBe(false);
169
+ }
170
+ });
171
+
172
+ /*
173
+ * The snapshot. Only the previous method can tell onUpdateSuccess whether
174
+ * anything actually transitioned, so every matched device's old method is
175
+ * recorded — including a NULL one, which reads as Probe.
176
+ */
177
+ test("records which matched devices were monitor-backed before the write", async () => {
178
+ const { service, internals } = buildDeviceService();
179
+
180
+ jest
181
+ .spyOn(service, "findBy")
182
+ .mockResolvedValue([
183
+ deviceWithMethod(PROBE_DEVICE_ID, NetworkDeviceMonitoringMethod.Probe),
184
+ deviceWithMethod(
185
+ MONITOR_BACKED_DEVICE_ID,
186
+ NetworkDeviceMonitoringMethod.Monitor,
187
+ ),
188
+ deviceWithMethod(UNRECORDED_DEVICE_ID, undefined),
189
+ ] as never);
190
+
191
+ const result: OnUpdate<NetworkDevice> = await internals.onBeforeUpdate(
192
+ methodUpdate({ monitoringMethod: NetworkDeviceMonitoringMethod.Probe }),
193
+ );
194
+
195
+ expect(result.carryForward.wasMonitorBackedByDeviceId).toEqual({
196
+ [PROBE_DEVICE_ID.toString()]: false,
197
+ [MONITOR_BACKED_DEVICE_ID.toString()]: true,
198
+ [UNRECORDED_DEVICE_ID.toString()]: false,
199
+ });
200
+ });
201
+
202
+ /*
203
+ * The site maintenance reads carryForward.previousDevices; a method write
204
+ * that also moves the site must hand over BOTH, not one at the expense
205
+ * of the other.
206
+ */
207
+ test("keeps the previousDevices snapshot alongside the method snapshot", async () => {
208
+ const { service, internals } = buildDeviceService();
209
+
210
+ jest
211
+ .spyOn(service, "findBy")
212
+ .mockResolvedValue([
213
+ deviceWithMethod(PROBE_DEVICE_ID, NetworkDeviceMonitoringMethod.Probe),
214
+ ] as never);
215
+
216
+ const result: OnUpdate<NetworkDevice> = await internals.onBeforeUpdate(
217
+ methodUpdate({
218
+ monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
219
+ name: "phone-01",
220
+ }),
221
+ );
222
+
223
+ expect(result.carryForward.previousDevices).toHaveLength(1);
224
+ expect(result.carryForward.wasMonitorBackedByDeviceId).toEqual({
225
+ [PROBE_DEVICE_ID.toString()]: false,
226
+ });
227
+ });
228
+
229
+ test("reads the old method with a single snapshot query", async () => {
230
+ const { service, internals } = buildDeviceService();
231
+
232
+ const findBySpy: jest.SpyInstance = jest
233
+ .spyOn(service, "findBy")
234
+ .mockResolvedValue([
235
+ deviceWithMethod(PROBE_DEVICE_ID, NetworkDeviceMonitoringMethod.Probe),
236
+ ] as never);
237
+
238
+ await internals.onBeforeUpdate(
239
+ methodUpdate({
240
+ monitoringMethod: NetworkDeviceMonitoringMethod.Monitor,
241
+ name: "phone-01",
242
+ }),
243
+ );
244
+
245
+ expect(findBySpy).toHaveBeenCalledTimes(1);
246
+ const select: Record<string, unknown> = findBySpy.mock.calls[0]![0]
247
+ .select as unknown as Record<string, unknown>;
248
+ expect(select["monitoringMethod"]).toBe(true);
249
+ expect(select["_id"]).toBe(true);
250
+ expect(findBySpy.mock.calls[0]![0].props.isRoot).toBe(true);
251
+ });
252
+
253
+ /*
254
+ * A write that does not carry the method cannot be a transition, and must
255
+ * not pay for the snapshot on its account — the probe's poll writes device
256
+ * columns through this hook on every poll of every device.
257
+ */
258
+ test("records nothing about the method on a write that does not carry it", async () => {
259
+ const { service, internals } = buildDeviceService();
260
+
261
+ const findBySpy: jest.SpyInstance = jest.spyOn(service, "findBy");
262
+
263
+ const result: OnUpdate<NetworkDevice> = await internals.onBeforeUpdate(
264
+ methodUpdate({ interfacesDown: 2, lastSeenAt: new Date() }),
265
+ );
266
+
267
+ expect(findBySpy).not.toHaveBeenCalled();
268
+ expect(result.carryForward).toBeNull();
269
+ });
270
+
271
+ test("still snapshots when the payload re-sends the method with nothing else", async () => {
272
+ const { service, internals } = buildDeviceService();
273
+
274
+ jest
275
+ .spyOn(service, "findBy")
276
+ .mockResolvedValue([
277
+ deviceWithMethod(
278
+ MONITOR_BACKED_DEVICE_ID,
279
+ NetworkDeviceMonitoringMethod.Monitor,
280
+ ),
281
+ ] as never);
282
+
283
+ const result: OnUpdate<NetworkDevice> = await internals.onBeforeUpdate(
284
+ methodUpdate({ monitoringMethod: NetworkDeviceMonitoringMethod.Probe }),
285
+ );
286
+
287
+ expect(result.carryForward.wasMonitorBackedByDeviceId).toEqual({
288
+ [MONITOR_BACKED_DEVICE_ID.toString()]: true,
289
+ });
290
+ });
291
+
292
+ /*
293
+ * The polling guard shares the snapshot now. It has to keep refusing
294
+ * "turn polling on" for a monitor-backed device — and keep allowing it
295
+ * when the same write moves the device back to Probe.
296
+ */
297
+ test("still refuses turning polling on for a monitor-backed device", async () => {
298
+ const { service, internals } = buildDeviceService();
299
+
300
+ jest
301
+ .spyOn(service, "findBy")
302
+ .mockResolvedValue([
303
+ deviceWithMethod(
304
+ MONITOR_BACKED_DEVICE_ID,
305
+ NetworkDeviceMonitoringMethod.Monitor,
306
+ ),
307
+ ] as never);
308
+
309
+ await expect(
310
+ internals.onBeforeUpdate(methodUpdate({ isPollingEnabled: true })),
311
+ ).rejects.toThrow(/nothing to poll/);
312
+ });
313
+
314
+ // The refusal names the way out, and the way out is the Probe method.
315
+ test("tells the caller to switch the method to Probe first", async () => {
316
+ const { service, internals } = buildDeviceService();
317
+
318
+ jest
319
+ .spyOn(service, "findBy")
320
+ .mockResolvedValue([
321
+ deviceWithMethod(
322
+ MONITOR_BACKED_DEVICE_ID,
323
+ NetworkDeviceMonitoringMethod.Monitor,
324
+ ),
325
+ ] as never);
326
+
327
+ await expect(
328
+ internals.onBeforeUpdate(methodUpdate({ isPollingEnabled: true })),
329
+ ).rejects.toThrow(/Switch its monitoring method to Probe first/);
330
+ });
331
+
332
+ test("allows turning polling on in the write that moves the device back to Probe", async () => {
333
+ const { service, internals } = buildDeviceService();
334
+
335
+ jest
336
+ .spyOn(service, "findBy")
337
+ .mockResolvedValue([
338
+ deviceWithMethod(
339
+ MONITOR_BACKED_DEVICE_ID,
340
+ NetworkDeviceMonitoringMethod.Monitor,
341
+ ),
342
+ ] as never);
343
+
344
+ await expect(
345
+ internals.onBeforeUpdate(
346
+ methodUpdate({
347
+ isPollingEnabled: true,
348
+ monitoringMethod: NetworkDeviceMonitoringMethod.Probe,
349
+ }),
350
+ ),
351
+ ).resolves.toBeDefined();
352
+ });
353
+
354
+ /*
355
+ * The polling restore is NOT put on the payload either, for a different
356
+ * reason than the residue: the payload is shared by every matched row,
357
+ * and a bulk "Probe" also matches devices that already were Probe — one
358
+ * of which may have polling off on purpose. Only onUpdateSuccess, with
359
+ * the per-device snapshot, can tell which rows actually transitioned.
360
+ */
361
+ test("does not put the polling restore on the caller's payload when moving to Probe", async () => {
362
+ const { service, internals } = buildDeviceService();
363
+
364
+ jest
365
+ .spyOn(service, "findBy")
366
+ .mockResolvedValue([
367
+ deviceWithMethod(
368
+ MONITOR_BACKED_DEVICE_ID,
369
+ NetworkDeviceMonitoringMethod.Monitor,
370
+ ),
371
+ ] as never);
372
+
373
+ const result: OnUpdate<NetworkDevice> = await internals.onBeforeUpdate(
374
+ methodUpdate({ monitoringMethod: NetworkDeviceMonitoringMethod.Probe }),
375
+ );
376
+
377
+ expect("isPollingEnabled" in result.updateBy.data).toBe(false);
378
+ expect("nextPollAt" in result.updateBy.data).toBe(false);
379
+ });
380
+ });
381
+
382
+ describe("onUpdateSuccess acts on the transition, not on the payload", () => {
383
+ let refresh: jest.SpyInstance;
384
+ let rootWrite: jest.SpyInstance;
385
+ let internals: DeviceServiceInternals;
386
+
387
+ beforeEach(() => {
388
+ jest.restoreAllMocks();
389
+ const built: {
390
+ service: NetworkDeviceServiceType;
391
+ internals: DeviceServiceInternals;
392
+ } = buildDeviceService();
393
+ internals = built.internals;
394
+ refresh = jest
395
+ .spyOn(built.service, "refreshStampedMonitorStatus")
396
+ .mockResolvedValue(undefined as never);
397
+ rootWrite = jest
398
+ .spyOn(built.service, "updateColumnsByIdWithoutHooks")
399
+ .mockResolvedValue(undefined as never);
400
+ });
401
+
402
+ function run(
403
+ data: Record<string, unknown>,
404
+ wasMonitorBackedByDeviceId: Record<string, boolean> | undefined,
405
+ updatedItemIds: Array<ObjectID>,
406
+ ): Promise<OnUpdate<NetworkDevice>> {
407
+ return internals.onUpdateSuccess(
408
+ {
409
+ updateBy: methodUpdate(data),
410
+ carryForward: {
411
+ previousDevices: [],
412
+ wasMonitorBackedByDeviceId: wasMonitorBackedByDeviceId,
413
+ },
414
+ },
415
+ updatedItemIds,
416
+ );
417
+ }
418
+
419
+ type RootWrite = { id: ObjectID; data: Record<string, unknown> };
420
+
421
+ function rootWrites(): Array<RootWrite> {
422
+ return rootWrite.mock.calls.map((callArgs: Array<unknown>) => {
423
+ return callArgs[0] as RootWrite;
424
+ });
425
+ }
426
+
427
+ /*
428
+ * The residue reset and the polling restore go through the same seam;
429
+ * they are told apart by shape, which is also what pins that neither
430
+ * ever carries the other's columns.
431
+ */
432
+ function residueResets(): Array<RootWrite> {
433
+ return rootWrites().filter((write: RootWrite) => {
434
+ return "lastSeenAt" in write.data;
435
+ });
436
+ }
437
+
438
+ function pollingRestores(): Array<RootWrite> {
439
+ return rootWrites().filter((write: RootWrite) => {
440
+ return "isPollingEnabled" in write.data;
441
+ });
442
+ }
443
+
444
+ function clearFlagFor(deviceId: ObjectID): boolean | undefined {
445
+ const call: Array<unknown> | undefined = refresh.mock.calls.find(
446
+ (callArgs: Array<unknown>) => {
447
+ return (
448
+ (callArgs[0] as { deviceId: ObjectID }).deviceId.toString() ===
449
+ deviceId.toString()
450
+ );
451
+ },
452
+ );
453
+
454
+ return (call?.[0] as { clearWhenNotMonitorBacked: boolean } | undefined)
455
+ ?.clearWhenNotMonitorBacked;
456
+ }
457
+
458
+ /*
459
+ * One bulk write of "Probe" over a mixed set: the device that WAS
460
+ * monitor-backed gets its stamp cleared and its polling restored; the one
461
+ * that already was Probe — the Settings-form re-save — gets neither.
462
+ */
463
+ test("asks to clear only for the rows that actually left monitor-backed", async () => {
464
+ await run(
465
+ { monitoringMethod: NetworkDeviceMonitoringMethod.Probe },
466
+ {
467
+ [PROBE_DEVICE_ID.toString()]: false,
468
+ [MONITOR_BACKED_DEVICE_ID.toString()]: true,
469
+ },
470
+ [PROBE_DEVICE_ID, MONITOR_BACKED_DEVICE_ID],
471
+ );
472
+
473
+ expect(refresh).toHaveBeenCalledTimes(2);
474
+ expect(clearFlagFor(PROBE_DEVICE_ID)).toBe(false);
475
+ expect(clearFlagFor(MONITOR_BACKED_DEVICE_ID)).toBe(true);
476
+ expect(residueResets()).toHaveLength(0);
477
+ expect(
478
+ pollingRestores().map((write: RootWrite) => {
479
+ return write.id.toString();
480
+ }),
481
+ ).toEqual([MONITOR_BACKED_DEVICE_ID.toString()]);
482
+ });
483
+
484
+ test("never asks to clear when the write arrives at Monitor", async () => {
485
+ await run(
486
+ { monitoringMethod: NetworkDeviceMonitoringMethod.Monitor },
487
+ {
488
+ [PROBE_DEVICE_ID.toString()]: false,
489
+ [MONITOR_BACKED_DEVICE_ID.toString()]: true,
490
+ },
491
+ [PROBE_DEVICE_ID, MONITOR_BACKED_DEVICE_ID],
492
+ );
493
+
494
+ expect(clearFlagFor(PROBE_DEVICE_ID)).toBe(false);
495
+ expect(clearFlagFor(MONITOR_BACKED_DEVICE_ID)).toBe(false);
496
+ });
497
+
498
+ /*
499
+ * Probe -> Monitor: the seven residue columns go, as one root write, and
500
+ * before the re-stamp — so a device bound in the same save ends up with
501
+ * its monitor's verdict rather than the walk's last one.
502
+ */
503
+ test("clears the poll residue of a device arriving at Monitor, before re-stamping it", async () => {
504
+ await run(
505
+ { monitoringMethod: NetworkDeviceMonitoringMethod.Monitor },
506
+ { [PROBE_DEVICE_ID.toString()]: false },
507
+ [PROBE_DEVICE_ID],
508
+ );
509
+
510
+ expect(rootWrite).toHaveBeenCalledTimes(1);
511
+ const write: { id: ObjectID; data: Record<string, unknown> } = rootWrite
512
+ .mock.calls[0]![0] as unknown as {
513
+ id: ObjectID;
514
+ data: Record<string, unknown>;
515
+ };
516
+ expect(write.id.toString()).toBe(PROBE_DEVICE_ID.toString());
517
+ expect(Object.keys(write.data).sort()).toEqual([...RESIDUE_COLUMNS].sort());
518
+ for (const column of RESIDUE_COLUMNS) {
519
+ expect(write.data[column]).toBeNull();
520
+ }
521
+
522
+ expect(rootWrite.mock.invocationCallOrder[0]).toBeLessThan(
523
+ refresh.mock.invocationCallOrder[0]!,
524
+ );
525
+ });
526
+
527
+ /*
528
+ * A monitor-backed device re-saved as Monitor has no residue to clear —
529
+ * the transition that made it monitor-backed already did — and must not
530
+ * be rewritten on every save.
531
+ */
532
+ test("does not rewrite residue on a device that already was monitor-backed", async () => {
533
+ await run(
534
+ { monitoringMethod: NetworkDeviceMonitoringMethod.Monitor },
535
+ { [MONITOR_BACKED_DEVICE_ID.toString()]: true },
536
+ [MONITOR_BACKED_DEVICE_ID],
537
+ );
538
+
539
+ expect(rootWrite).not.toHaveBeenCalled();
540
+ expect(refresh).toHaveBeenCalledTimes(1);
541
+ });
542
+
543
+ /*
544
+ * A device the snapshot did not record: "unknown" must err on the side of
545
+ * clearing residue (the write is idempotent) and NOT on the side of
546
+ * clearing a stamp (which needs evidence the device was monitor-backed).
547
+ */
548
+ test("treats a device missing from the snapshot as safe to reset but not to clear", async () => {
549
+ await run({ monitoringMethod: NetworkDeviceMonitoringMethod.Monitor }, {}, [
550
+ UNRECORDED_DEVICE_ID,
551
+ ]);
552
+ expect(rootWrite).toHaveBeenCalledTimes(1);
553
+
554
+ rootWrite.mockClear();
555
+ refresh.mockClear();
556
+
557
+ await run({ monitoringMethod: NetworkDeviceMonitoringMethod.Probe }, {}, [
558
+ UNRECORDED_DEVICE_ID,
559
+ ]);
560
+ expect(clearFlagFor(UNRECORDED_DEVICE_ID)).toBe(false);
561
+ expect(rootWrite).not.toHaveBeenCalled();
562
+ });
563
+
564
+ test("a binding-only write is never a transition", async () => {
565
+ await internals.onUpdateSuccess(
566
+ {
567
+ updateBy: methodUpdate({ monitorId: ObjectID.generate() }),
568
+ carryForward: null,
569
+ },
570
+ [MONITOR_BACKED_DEVICE_ID],
571
+ );
572
+
573
+ expect(clearFlagFor(MONITOR_BACKED_DEVICE_ID)).toBe(false);
574
+ expect(rootWrite).not.toHaveBeenCalled();
575
+ });
576
+
577
+ /*
578
+ * The residue reset is bookkeeping after a committed write; it must not
579
+ * cost the device its re-stamp, nor the caller their save.
580
+ */
581
+ test("still re-stamps, and still resolves, when the residue reset fails", async () => {
582
+ rootWrite.mockRejectedValue(new Error("reset exploded") as never);
583
+
584
+ await expect(
585
+ run(
586
+ { monitoringMethod: NetworkDeviceMonitoringMethod.Monitor },
587
+ { [PROBE_DEVICE_ID.toString()]: false },
588
+ [PROBE_DEVICE_ID],
589
+ ),
590
+ ).resolves.toBeDefined();
591
+
592
+ expect(refresh).toHaveBeenCalledTimes(1);
593
+ });
594
+
595
+ /*
596
+ * Monitor -> Probe: arriving at Monitor switched polling off, so leaving
597
+ * it switches polling back on — and makes the device due NOW, rather than
598
+ * at whatever moment its last claim (months ago, or never) left behind.
599
+ * Exactly those two columns, as one root write: nothing else about the
600
+ * device is this transition's to decide, and no probe is required.
601
+ */
602
+ test("restores polling, due now, on a device that left monitor-backed", async () => {
603
+ const before: number = Date.now();
604
+
605
+ await run(
606
+ { monitoringMethod: NetworkDeviceMonitoringMethod.Probe },
607
+ { [MONITOR_BACKED_DEVICE_ID.toString()]: true },
608
+ [MONITOR_BACKED_DEVICE_ID],
609
+ );
610
+
611
+ const restores: Array<RootWrite> = pollingRestores();
612
+ expect(restores).toHaveLength(1);
613
+ expect(restores[0]!.id.toString()).toBe(
614
+ MONITOR_BACKED_DEVICE_ID.toString(),
615
+ );
616
+ expect(Object.keys(restores[0]!.data).sort()).toEqual([
617
+ "isPollingEnabled",
618
+ "nextPollAt",
619
+ ]);
620
+ expect(restores[0]!.data["isPollingEnabled"]).toBe(true);
621
+
622
+ const nextPollAt: Date = restores[0]!.data["nextPollAt"] as Date;
623
+ expect(nextPollAt).toBeInstanceOf(Date);
624
+ expect(nextPollAt.getTime()).toBeGreaterThanOrEqual(before);
625
+ expect(nextPollAt.getTime()).toBeLessThanOrEqual(Date.now());
626
+
627
+ expect(residueResets()).toHaveLength(0);
628
+ expect(clearFlagFor(MONITOR_BACKED_DEVICE_ID)).toBe(true);
629
+ });
630
+
631
+ /*
632
+ * The payload alone must never decide it: a bulk "Probe" over devices
633
+ * that already were Probe is the Settings-form re-save, and one of them
634
+ * may have polling off on purpose.
635
+ */
636
+ test("does not restore polling on a device that already was Probe", async () => {
637
+ await run(
638
+ { monitoringMethod: NetworkDeviceMonitoringMethod.Probe },
639
+ { [PROBE_DEVICE_ID.toString()]: false },
640
+ [PROBE_DEVICE_ID],
641
+ );
642
+
643
+ expect(rootWrite).not.toHaveBeenCalled();
644
+ });
645
+
646
+ /*
647
+ * "Unknown" errs on the side of not writing here: restoring polling is a
648
+ * change of behaviour, and it needs evidence the device was monitor-backed
649
+ * — the opposite of the residue reset, which is idempotent and safe.
650
+ */
651
+ test("does not restore polling on a device the snapshot did not record", async () => {
652
+ await run({ monitoringMethod: NetworkDeviceMonitoringMethod.Probe }, {}, [
653
+ UNRECORDED_DEVICE_ID,
654
+ ]);
655
+
656
+ expect(rootWrite).not.toHaveBeenCalled();
657
+ });
658
+
659
+ test("does not restore polling when the write arrives at Monitor", async () => {
660
+ await run(
661
+ { monitoringMethod: NetworkDeviceMonitoringMethod.Monitor },
662
+ { [MONITOR_BACKED_DEVICE_ID.toString()]: true },
663
+ [MONITOR_BACKED_DEVICE_ID],
664
+ );
665
+
666
+ expect(pollingRestores()).toHaveLength(0);
667
+ });
668
+
669
+ /*
670
+ * The caller's own word wins when it says the opposite: a payload that
671
+ * writes isPollingEnabled: false beside the method wants a Probe device
672
+ * that is not polled yet (a bulk switch whose probe is assigned in a
673
+ * second step, say), and the server must not argue with it.
674
+ */
675
+ test("does not restore polling when the payload turns it off in the same write", async () => {
676
+ await run(
677
+ {
678
+ monitoringMethod: NetworkDeviceMonitoringMethod.Probe,
679
+ isPollingEnabled: false,
680
+ },
681
+ { [MONITOR_BACKED_DEVICE_ID.toString()]: true },
682
+ [MONITOR_BACKED_DEVICE_ID],
683
+ );
684
+
685
+ expect(rootWrite).not.toHaveBeenCalled();
686
+ // The stamp still goes: that half is not the payload's to keep.
687
+ expect(clearFlagFor(MONITOR_BACKED_DEVICE_ID)).toBe(true);
688
+ });
689
+
690
+ /*
691
+ * ...but a payload that asks for polling itself still gets the "due now":
692
+ * the flag alone would leave nextPollAt wherever the last claim put it.
693
+ */
694
+ test("still makes the device due now when the payload turns polling on itself", async () => {
695
+ await run(
696
+ {
697
+ monitoringMethod: NetworkDeviceMonitoringMethod.Probe,
698
+ isPollingEnabled: true,
699
+ },
700
+ { [MONITOR_BACKED_DEVICE_ID.toString()]: true },
701
+ [MONITOR_BACKED_DEVICE_ID],
702
+ );
703
+
704
+ expect(pollingRestores()).toHaveLength(1);
705
+ expect(pollingRestores()[0]!.data["nextPollAt"]).toBeInstanceOf(Date);
706
+ });
707
+
708
+ test("restores polling before the re-stamp clears the old verdict", async () => {
709
+ await run(
710
+ { monitoringMethod: NetworkDeviceMonitoringMethod.Probe },
711
+ { [MONITOR_BACKED_DEVICE_ID.toString()]: true },
712
+ [MONITOR_BACKED_DEVICE_ID],
713
+ );
714
+
715
+ expect(rootWrite.mock.invocationCallOrder[0]).toBeLessThan(
716
+ refresh.mock.invocationCallOrder[0]!,
717
+ );
718
+ });
719
+
720
+ /*
721
+ * Bookkeeping after a committed write, like the residue reset: a failed
722
+ * restore must not cost the device its re-stamp, nor the caller their
723
+ * save. The operator can turn polling on from Settings.
724
+ */
725
+ test("still re-stamps, and still resolves, when the polling restore fails", async () => {
726
+ rootWrite.mockRejectedValue(new Error("restore exploded") as never);
727
+
728
+ await expect(
729
+ run(
730
+ { monitoringMethod: NetworkDeviceMonitoringMethod.Probe },
731
+ { [MONITOR_BACKED_DEVICE_ID.toString()]: true },
732
+ [MONITOR_BACKED_DEVICE_ID],
733
+ ),
734
+ ).resolves.toBeDefined();
735
+
736
+ expect(refresh).toHaveBeenCalledTimes(1);
737
+ expect(clearFlagFor(MONITOR_BACKED_DEVICE_ID)).toBe(true);
738
+ });
739
+ });