@oneuptime/common 12.0.31 → 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 (747) hide show
  1. package/Models/AnalyticsModels/Span.ts +14 -0
  2. package/Models/DatabaseModels/AlertState.ts +0 -2
  3. package/Models/DatabaseModels/Domain.ts +1 -1
  4. package/Models/DatabaseModels/EnterpriseLicense.ts +56 -0
  5. package/Models/DatabaseModels/Incident.ts +1 -1
  6. package/Models/DatabaseModels/IncidentTemplate.ts +1 -1
  7. package/Models/DatabaseModels/Index.ts +12 -0
  8. package/Models/DatabaseModels/MetricType.ts +0 -2
  9. package/Models/DatabaseModels/Monitor.ts +76 -0
  10. package/Models/DatabaseModels/MonitorStatusTimeline.ts +0 -2
  11. package/Models/DatabaseModels/MonitorTest.ts +0 -2
  12. package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
  13. package/Models/DatabaseModels/NetworkDevice.ts +297 -3
  14. package/Models/DatabaseModels/NetworkDeviceOidTemplate.ts +3 -1
  15. package/Models/DatabaseModels/NetworkDeviceRole.ts +648 -0
  16. package/Models/DatabaseModels/NetworkSite.ts +201 -2
  17. package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
  18. package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
  19. package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -1
  20. package/Models/DatabaseModels/ScheduledMaintenanceTemplate.ts +1 -1
  21. package/Models/DatabaseModels/StatusPageAnnouncement.ts +0 -2
  22. package/Models/DatabaseModels/StatusPageAnnouncementTemplate.ts +0 -2
  23. package/Models/DatabaseModels/StatusPagePrivateUser.ts +0 -2
  24. package/Models/DatabaseModels/StatusPageResource.ts +0 -2
  25. package/Models/DatabaseModels/StatusPageSubscriber.ts +0 -2
  26. package/Models/DatabaseModels/TelemetryException.ts +119 -0
  27. package/Models/DatabaseModels/UserNotificationEmailRollupBatch.ts +334 -0
  28. package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +370 -0
  29. package/Models/DatabaseModels/UserNotificationEmailRollupSetting.ts +282 -0
  30. package/Server/API/EnterpriseLicenseAPI.ts +391 -64
  31. package/Server/API/LlmProviderAPI.ts +137 -22
  32. package/Server/EnvironmentConfig.ts +14 -0
  33. package/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.ts +55 -0
  34. package/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.ts +72 -0
  35. package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.ts +31 -0
  36. package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.ts +124 -0
  37. package/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.ts +132 -0
  38. package/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.ts +79 -0
  39. package/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.ts +191 -0
  40. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +14 -0
  41. package/Server/Infrastructure/QueueWorker.ts +38 -8
  42. package/Server/Middleware/BearerTokenAuthorization.ts +12 -0
  43. package/Server/Middleware/ProjectAuthorization.ts +11 -0
  44. package/Server/Middleware/SCIMAuthorization.ts +12 -0
  45. package/Server/Middleware/TelemetryIngest.ts +11 -0
  46. package/Server/Services/AIBillingService.ts +101 -27
  47. package/Server/Services/DatabaseService.ts +39 -9
  48. package/Server/Services/EnterpriseLicenseInstanceService.ts +197 -0
  49. package/Server/Services/EnterpriseLicenseService.ts +55 -0
  50. package/Server/Services/Index.ts +12 -0
  51. package/Server/Services/MonitorService.ts +143 -21
  52. package/Server/Services/MonitorStatusTimelineService.ts +150 -8
  53. package/Server/Services/MonitorTemplateService.ts +217 -1
  54. package/Server/Services/NetworkAlertPolicyEngineService.ts +2159 -0
  55. package/Server/Services/NetworkAlertPolicyService.ts +944 -0
  56. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +9 -10
  57. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +60 -15
  58. package/Server/Services/NetworkDeviceRoleService.ts +90 -0
  59. package/Server/Services/NetworkDeviceService.ts +1032 -73
  60. package/Server/Services/NetworkSiteService.ts +1502 -129
  61. package/Server/Services/NetworkSiteTypeService.ts +1216 -0
  62. package/Server/Services/NetworkSnmpCredentialProfileService.ts +238 -0
  63. package/Server/Services/NotificationService.ts +118 -28
  64. package/Server/Services/ProjectService.ts +186 -44
  65. package/Server/Services/StatusPagePrivateUserService.ts +103 -3
  66. package/Server/Services/UserNotificationEmailRollupBatchService.ts +78 -0
  67. package/Server/Services/UserNotificationEmailRollupItemService.ts +79 -0
  68. package/Server/Services/UserNotificationEmailRollupSettingService.ts +113 -0
  69. package/Server/Services/UserNotificationSettingService.ts +62 -31
  70. package/Server/Services/UserService.ts +95 -0
  71. package/Server/Types/Database/QueryHelper.ts +2 -2
  72. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +14 -3
  73. package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +10 -0
  74. package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +10 -0
  75. package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +62 -1
  76. package/Server/Utils/AI/Toolbox/AlertTools.ts +15 -1
  77. package/Server/Utils/Billing/BillingFailureNoticeThrottle.ts +80 -0
  78. package/Server/Utils/DataSource/HttpFetch.ts +9 -2
  79. package/Server/Utils/EmailRollup/EmailRollupConstants.ts +98 -0
  80. package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +872 -0
  81. package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +781 -0
  82. package/Server/Utils/EmailRollup/EmailRollupWriter.ts +368 -0
  83. package/Server/Utils/LLM/LLMService.ts +78 -0
  84. package/Server/Utils/LogRedaction.ts +8 -0
  85. package/Server/Utils/Logger.ts +79 -1
  86. package/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.ts +190 -0
  87. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +9 -2
  88. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +61 -1
  89. package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +14 -0
  90. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +49 -0
  91. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +255 -4
  92. package/Server/Utils/Monitor/MonitorMetricUtil.ts +41 -0
  93. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +43 -0
  94. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +499 -19
  95. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +66 -10
  96. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +238 -44
  97. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +146 -39
  98. package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +31 -18
  99. package/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.ts +213 -0
  100. package/Server/Utils/OutboundUserAgent.ts +152 -0
  101. package/Server/Utils/StartServer.ts +51 -19
  102. package/Server/Utils/Telemetry/CaptureSpan.ts +32 -8
  103. package/Server/Utils/Telemetry/ErrorClassResolver.ts +120 -0
  104. package/Server/Utils/Telemetry/SpanUtil.ts +33 -0
  105. package/Server/Utils/Telemetry.ts +198 -51
  106. package/Server/Views/Partials/SensitiveUrlToken.ejs +140 -0
  107. package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +158 -27
  108. package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
  109. package/Tests/App/Dashboard/DashboardChartWidgetZoom.test.tsx +35 -8
  110. package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +107 -3
  111. package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
  112. package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -0
  113. package/Tests/App/Dashboard/DashboardWideChartZoom.test.tsx +401 -0
  114. package/Tests/App/Dashboard/DeviceStatusHero.test.tsx +588 -0
  115. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +18 -9
  116. package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +632 -0
  117. package/Tests/App/Dashboard/MonitorRecommendationCreateProgress.test.tsx +682 -0
  118. package/Tests/App/Dashboard/MonitorTemplateColumnAndFacet.test.tsx +318 -0
  119. package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +4 -2
  120. package/Tests/App/Dashboard/NetworkDeviceBulkDelete.test.tsx +357 -0
  121. package/Tests/App/Dashboard/NetworkDeviceCreateFormMonitorBinding.test.tsx +676 -0
  122. package/Tests/App/Dashboard/NetworkDeviceCreateFormPingMonitor.test.tsx +791 -0
  123. package/Tests/App/Dashboard/NetworkDeviceCreateFormProbeAndSnmp.test.tsx +833 -0
  124. package/Tests/App/Dashboard/NetworkDeviceCriteriaFilter.test.ts +161 -0
  125. package/Tests/App/Dashboard/NetworkDeviceSettingsMonitoringSection.test.tsx +458 -0
  126. package/Tests/App/Dashboard/NetworkSideMenu.test.tsx +626 -0
  127. package/Tests/App/Dashboard/PingMonitorProvisioning.test.ts +368 -0
  128. package/Tests/App/Dashboard/RecommendationCard.test.tsx +796 -0
  129. package/Tests/App/Dashboard/RecommendationToolbar.test.tsx +519 -0
  130. package/Tests/App/Dashboard/RecommendationsList.test.tsx +661 -0
  131. package/Tests/App/Dashboard/SideMenuHarness.tsx +11 -3
  132. package/Tests/App/Dashboard/UseBulkCreatePingMonitors.test.tsx +899 -0
  133. package/Tests/App/Dashboard/UseBulkSnmpCredentialProfileActions.test.tsx +732 -0
  134. package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +256 -0
  135. package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +11 -1
  136. package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +9 -4
  137. package/Tests/Models/DatabaseModels/ModelRegistryInvariants.test.ts +115 -41
  138. package/Tests/Models/NetworkSiteHierarchy.test.ts +41 -4
  139. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +951 -7
  140. package/Tests/Server/API/LlmProviderConnectionTest.test.ts +522 -0
  141. package/Tests/Server/Infrastructure/Postgres/NetworkDeviceRoleTableMigration.test.ts +476 -0
  142. package/Tests/Server/Infrastructure/Postgres/NetworkSnmpCredentialProfilesAndAlertPoliciesMigration.test.ts +854 -0
  143. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +18 -0
  144. package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +535 -0
  145. package/Tests/Server/Services/AIChatPrivacyPin.test.ts +560 -0
  146. package/Tests/Server/Services/BillingRechargeOwnerEmailGuards.test.ts +783 -0
  147. package/Tests/Server/Services/DatabaseServiceGenerateSlug.test.ts +215 -0
  148. package/Tests/Server/Services/EnterpriseLicenseInstanceServiceDeletionUsage.test.ts +707 -0
  149. package/Tests/Server/Services/EnterpriseLicenseServiceUsageAggregationLock.test.ts +329 -0
  150. package/Tests/Server/Services/MonitorServiceDeleteNetworkDeviceCleanup.test.ts +294 -0
  151. package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +802 -0
  152. package/Tests/Server/Services/MonitorStatusTimelineService.test.ts +72 -2
  153. package/Tests/Server/Services/NetworkAlertPolicyEngineHooks.test.ts +752 -0
  154. package/Tests/Server/Services/NetworkAlertPolicyEngineService.test.ts +1849 -0
  155. package/Tests/Server/Services/NetworkAlertPolicyModel.test.ts +1793 -0
  156. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +47 -4
  157. package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +97 -12
  158. package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +148 -3
  159. package/Tests/Server/Services/NetworkDeviceMonitorBindingUpdateGuard.test.ts +514 -0
  160. package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +447 -58
  161. package/Tests/Server/Services/NetworkDeviceMonitoringMethodTransition.test.ts +739 -0
  162. package/Tests/Server/Services/NetworkDevicePollingTenancy.test.ts +501 -0
  163. package/Tests/Server/Services/NetworkDeviceRoleModel.test.ts +672 -0
  164. package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +1 -1
  165. package/Tests/Server/Services/NetworkDeviceSiteDefaultProbe.test.ts +432 -0
  166. package/Tests/Server/Services/NetworkSiteMonitoringDefaults.test.ts +498 -0
  167. package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +337 -55
  168. package/Tests/Server/Services/NetworkSiteService.test.ts +1868 -131
  169. package/Tests/Server/Services/NetworkSiteTypeService.test.ts +1109 -0
  170. package/Tests/Server/Services/NetworkSnmpCredentialProfileModel.test.ts +926 -0
  171. package/Tests/Server/Services/NetworkSnmpCredentialProfileService.test.ts +796 -0
  172. package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +67 -4
  173. package/Tests/Server/Services/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -0
  174. package/Tests/Server/Services/ScheduledMaintenanceSubscriberEndTime.test.ts +369 -0
  175. package/Tests/Server/Services/StatusPagePrivateUserEmailChangePasswordResetExpiry.test.ts +269 -0
  176. package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +472 -0
  177. package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +569 -0
  178. package/Tests/Server/Services/UserNotificationEmailRollupSettingModel.test.ts +314 -0
  179. package/Tests/Server/Services/UserNotificationEmailRollupSettingService.test.ts +409 -0
  180. package/Tests/Server/Services/UserNotificationSettingMonitorDefaults.test.ts +248 -0
  181. package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +856 -0
  182. package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +145 -3
  183. package/Tests/Server/Types/Database/Permissions/DashboardAccessPermission.test.ts +321 -0
  184. package/Tests/Server/Types/Database/QueryHelperOperators.test.ts +17 -0
  185. package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +124 -0
  186. package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +208 -0
  187. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +235 -0
  188. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +253 -0
  189. package/Tests/Server/Utils/BasicCron.test.ts +283 -0
  190. package/Tests/Server/Utils/Captcha.test.ts +422 -0
  191. package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +96 -2
  192. package/Tests/Server/Utils/Database/MigrationFailureLog.test.ts +466 -0
  193. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1096 -0
  194. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerClaim.test.ts +466 -0
  195. package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +1428 -0
  196. package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +752 -0
  197. package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +864 -0
  198. package/Tests/Server/Utils/IncomingCallPhoneNumber.test.ts +174 -0
  199. package/Tests/Server/Utils/LoggerFaultDemotion.test.ts +346 -0
  200. package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +633 -0
  201. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +196 -0
  202. package/Tests/Server/Utils/Monitor/DatabaseMetricWrite.test.ts +367 -0
  203. package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +100 -0
  204. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +5 -0
  205. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +512 -31
  206. package/Tests/Server/Utils/Monitor/NetworkDeviceMetricUtil.test.ts +252 -0
  207. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +479 -42
  208. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +351 -5
  209. package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +136 -12
  210. package/Tests/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.test.ts +306 -0
  211. package/Tests/Server/Utils/OutboundUserAgent.test.ts +266 -0
  212. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClientUserAgent.test.ts +141 -0
  213. package/Tests/Server/Utils/Telemetry/ErrorClassResolver.test.ts +298 -0
  214. package/Tests/Server/Utils/Telemetry.test.ts +456 -66
  215. package/Tests/Types/Monitor/DatabaseMetricCatalog.test.ts +388 -0
  216. package/Tests/Types/Monitor/MonitorStepDatabaseMonitor.test.ts +243 -0
  217. package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
  218. package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
  219. package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +16 -7
  220. package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +60 -0
  221. package/Tests/Types/NetworkDevice/DefaultNetworkDeviceRole.test.ts +417 -0
  222. package/Tests/Types/NetworkDevice/NetworkAlertPolicyScope.test.ts +655 -0
  223. package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +115 -26
  224. package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +39 -0
  225. package/Tests/Types/NotificationSetting/NotificationEmailRollupPolicy.test.ts +299 -0
  226. package/Tests/Types/Telemetry/ErrorClass.test.ts +483 -0
  227. package/Tests/UI/Components/BasicRadioButtons.test.tsx +336 -0
  228. package/Tests/UI/Components/Charts/ChartClickDoubleClickDisambiguation.test.tsx +221 -0
  229. package/Tests/UI/Components/Charts/ChartDoubleClickReset.test.tsx +220 -0
  230. package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +751 -0
  231. package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +475 -43
  232. package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +89 -0
  233. package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +15 -0
  234. package/Tests/UI/Components/NavBarCommandKGating.test.tsx +103 -8
  235. package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
  236. package/Tests/UI/Components/SideMenuItem.test.tsx +256 -4
  237. package/Tests/UI/Components/SideMenuSection.test.tsx +310 -0
  238. package/Tests/UI/Components/SideOverSubmitState.test.tsx +335 -0
  239. package/Tests/UI/Utils/PageScrollLock.test.tsx +377 -0
  240. package/Tests/UI/Utils/PermissionGate.test.ts +78 -0
  241. package/Tests/UI/Utils/SensitiveUrlToken.test.ts +140 -0
  242. package/Tests/UI/Utils/TableColumnsToCsv.test.ts +30 -0
  243. package/Tests/UI/Utils/UseDashboardTimeRangeZoom.test.tsx +187 -0
  244. package/Tests/Utils/Dashboard/DashboardResourceListSharedArgs.test.ts +302 -0
  245. package/Tests/Utils/Dashboard/DashboardTimeRangeZoom.test.ts +242 -0
  246. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +69 -0
  247. package/Tests/Utils/EnterpriseLicenseSync.test.ts +7 -1
  248. package/Tests/Utils/EnterpriseLicenseUsage.test.ts +433 -2
  249. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +280 -1
  250. package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
  251. package/Tests/Utils/Monitor/NetworkDeviceRoleCatalog.test.ts +981 -0
  252. package/Tests/Utils/Monitor/NetworkTopologyRoleCatalog.test.ts +865 -0
  253. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +38 -0
  254. package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +284 -23
  255. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +177 -0
  256. package/Tests/Utils/NetworkDevice/DeviceRoleKeyUtil.test.ts +538 -0
  257. package/Tests/Utils/NetworkDevice/MonitoringMethodThreadedClassifiers.test.ts +992 -0
  258. package/Tests/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.test.ts +427 -0
  259. package/Tests/Utils/NetworkDevice/ReachabilityStampConsistency.test.ts +185 -0
  260. package/Tests/Utils/NetworkDevice/SnmpCredentialUtil.test.ts +268 -0
  261. package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +55 -5
  262. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +98 -21
  263. package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +98 -20
  264. package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +8 -7
  265. package/Tests/Utils/NetworkDiscovery/PingMonitorBuilderForAddress.test.ts +274 -0
  266. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +230 -51
  267. package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +209 -0
  268. package/Tests/Utils/Slo/SloEvaluation.test.ts +171 -0
  269. package/Tests/Utils/Slug.test.ts +61 -1
  270. package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +145 -0
  271. package/Tests/jest.setup.ts +19 -0
  272. package/Types/AI/ExceptionAIClassification.ts +10 -24
  273. package/Types/Email/EmailTemplateType.ts +2 -0
  274. package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +5 -0
  275. package/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.ts +13 -0
  276. package/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.ts +6 -0
  277. package/Types/Exception/ApiException.ts +10 -0
  278. package/Types/Exception/BadDataException.ts +11 -0
  279. package/Types/Exception/BadRequestException.ts +11 -0
  280. package/Types/Exception/Exception.ts +65 -0
  281. package/Types/Exception/ForbiddenException.ts +10 -0
  282. package/Types/Exception/NotAuthenticatedException.ts +10 -0
  283. package/Types/Exception/NotAuthorizedException.ts +10 -0
  284. package/Types/Exception/NotFoundException.ts +11 -0
  285. package/Types/Exception/PayloadTooLargeException.ts +11 -0
  286. package/Types/Exception/PaymentRequiredException.ts +10 -0
  287. package/Types/Exception/ServiceUnavailableException.ts +10 -0
  288. package/Types/Exception/SsoAuthorizationException.ts +10 -0
  289. package/Types/Exception/TenantNotFoundException.ts +11 -0
  290. package/Types/Exception/TimeoutException.ts +10 -0
  291. package/Types/Exception/TooManyRequestsException.ts +10 -0
  292. package/Types/Exception/UnableToReachServer.ts +10 -0
  293. package/Types/Exception/WebsiteRequestException.ts +10 -0
  294. package/Types/Monitor/CriteriaFilter.ts +60 -2
  295. package/Types/Monitor/DatabaseMetricCatalog.ts +693 -0
  296. package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +83 -0
  297. package/Types/Monitor/MonitorCriteriaInstance.ts +76 -0
  298. package/Types/Monitor/MonitorMetricType.ts +71 -0
  299. package/Types/Monitor/MonitorStep.ts +76 -0
  300. package/Types/Monitor/MonitorStepDatabaseMonitor.ts +171 -0
  301. package/Types/Monitor/MonitorStepSqlMonitor.ts +2 -20
  302. package/Types/Monitor/MonitorType.ts +47 -1
  303. package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +22 -1
  304. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +61 -0
  305. package/Types/Monitor/SqlConnectionConfig.ts +31 -0
  306. package/Types/NetworkDevice/DefaultNetworkDeviceRole.ts +145 -0
  307. package/Types/NetworkDevice/NetworkAlertPolicyScope.ts +343 -0
  308. package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +42 -22
  309. package/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.ts +30 -0
  310. package/Types/NotificationSetting/NotificationEmailRollupCategory.ts +255 -0
  311. package/Types/NotificationSetting/NotificationEmailRollupPolicy.ts +104 -0
  312. package/Types/Permission.ts +135 -0
  313. package/Types/Probe/ProbeMonitorResponse.ts +16 -0
  314. package/Types/Telemetry/ErrorClass.ts +274 -0
  315. package/Types/Telemetry/UnitOfWork.ts +59 -0
  316. package/UI/Components/Charts/Area/AreaChart.tsx +7 -0
  317. package/UI/Components/Charts/Bar/BarChart.tsx +6 -0
  318. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +9 -1
  319. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +97 -35
  320. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +14 -0
  321. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +97 -35
  322. package/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.ts +13 -0
  323. package/UI/Components/Charts/Line/LineChart.tsx +7 -0
  324. package/UI/Components/CommandPalette/CommandPalette.tsx +2 -8
  325. package/UI/Components/EditionLabel/EditionLabel.tsx +4 -0
  326. package/UI/Components/Modal/Modal.tsx +2 -8
  327. package/UI/Components/ModelTable/BaseModelTable.tsx +50 -15
  328. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
  329. package/UI/Components/Navbar/NavBar.tsx +62 -13
  330. package/UI/Components/Navbar/NavBarMenuModal.tsx +7 -2
  331. package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
  332. package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
  333. package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +2 -0
  334. package/UI/Components/SideMenu/SideMenu.tsx +135 -7
  335. package/UI/Components/SideMenu/SideMenuItem.tsx +80 -85
  336. package/UI/Components/SideMenu/SideMenuSection.tsx +69 -25
  337. package/UI/Components/SideOver/SideOver.tsx +21 -20
  338. package/UI/Utils/PageScrollLock.ts +79 -3
  339. package/UI/Utils/PermissionGate.ts +61 -0
  340. package/UI/Utils/SensitiveUrlToken.ts +112 -0
  341. package/UI/Utils/TestLLMProvider.ts +11 -0
  342. package/UI/Utils/UseDashboardTimeRangeZoom.ts +77 -0
  343. package/Utils/Dashboard/DashboardTimeRangeZoom.ts +118 -0
  344. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +16 -0
  345. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +191 -11
  346. package/Utils/Monitor/MonitorMetricType.ts +153 -1
  347. package/Utils/Monitor/NetworkDeviceRoleCatalog.ts +232 -0
  348. package/Utils/Monitor/NetworkDeviceRoleUtil.ts +2 -1
  349. package/Utils/Monitor/NetworkTopologyUtil.ts +139 -36
  350. package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
  351. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
  352. package/Utils/NetworkDevice/DeviceRoleKeyUtil.ts +137 -0
  353. package/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.ts +247 -0
  354. package/Utils/NetworkDevice/SnmpCredentialUtil.ts +68 -0
  355. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +15 -7
  356. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +52 -17
  357. package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +55 -23
  358. package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +115 -13
  359. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +66 -20
  360. package/Utils/NetworkSite/TypeHierarchyUtil.ts +313 -0
  361. package/Utils/Rules/RulePatternMatchUtil.ts +1 -1
  362. package/Utils/Slug.ts +34 -1
  363. package/build/dist/Models/AnalyticsModels/Span.js +14 -0
  364. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  365. package/build/dist/Models/DatabaseModels/AlertState.js +0 -2
  366. package/build/dist/Models/DatabaseModels/AlertState.js.map +1 -1
  367. package/build/dist/Models/DatabaseModels/Domain.js +1 -1
  368. package/build/dist/Models/DatabaseModels/Domain.js.map +1 -1
  369. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +59 -0
  370. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
  371. package/build/dist/Models/DatabaseModels/Incident.js +1 -1
  372. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  373. package/build/dist/Models/DatabaseModels/IncidentTemplate.js +1 -1
  374. package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
  375. package/build/dist/Models/DatabaseModels/Index.js +12 -0
  376. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  377. package/build/dist/Models/DatabaseModels/MetricType.js +0 -2
  378. package/build/dist/Models/DatabaseModels/MetricType.js.map +1 -1
  379. package/build/dist/Models/DatabaseModels/Monitor.js +75 -0
  380. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  381. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js +0 -2
  382. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
  383. package/build/dist/Models/DatabaseModels/MonitorTest.js +0 -2
  384. package/build/dist/Models/DatabaseModels/MonitorTest.js.map +1 -1
  385. package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js +713 -0
  386. package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js.map +1 -0
  387. package/build/dist/Models/DatabaseModels/NetworkDevice.js +304 -4
  388. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  389. package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js +3 -1
  390. package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js.map +1 -1
  391. package/build/dist/Models/DatabaseModels/NetworkDeviceRole.js +677 -0
  392. package/build/dist/Models/DatabaseModels/NetworkDeviceRole.js.map +1 -0
  393. package/build/dist/Models/DatabaseModels/NetworkSite.js +200 -2
  394. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
  395. package/build/dist/Models/DatabaseModels/NetworkSiteType.js +102 -3
  396. package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -1
  397. package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js +878 -0
  398. package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js.map +1 -0
  399. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -1
  400. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  401. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js +1 -1
  402. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js.map +1 -1
  403. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +0 -2
  404. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
  405. package/build/dist/Models/DatabaseModels/StatusPageAnnouncementTemplate.js +0 -2
  406. package/build/dist/Models/DatabaseModels/StatusPageAnnouncementTemplate.js.map +1 -1
  407. package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js +0 -2
  408. package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js.map +1 -1
  409. package/build/dist/Models/DatabaseModels/StatusPageResource.js +0 -2
  410. package/build/dist/Models/DatabaseModels/StatusPageResource.js.map +1 -1
  411. package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +0 -2
  412. package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
  413. package/build/dist/Models/DatabaseModels/TelemetryException.js +123 -0
  414. package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
  415. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js +363 -0
  416. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js.map +1 -0
  417. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +402 -0
  418. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -0
  419. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js +296 -0
  420. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js.map +1 -0
  421. package/build/dist/Server/API/EnterpriseLicenseAPI.js +273 -60
  422. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
  423. package/build/dist/Server/API/LlmProviderAPI.js +108 -13
  424. package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
  425. package/build/dist/Server/EnvironmentConfig.js +12 -0
  426. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  427. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js +24 -0
  428. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js.map +1 -0
  429. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.js +39 -0
  430. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.js.map +1 -0
  431. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js +16 -0
  432. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js.map +1 -0
  433. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js +111 -0
  434. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js.map +1 -0
  435. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js +77 -0
  436. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js.map +1 -0
  437. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js +50 -0
  438. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js.map +1 -0
  439. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js +83 -0
  440. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js.map +1 -0
  441. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +14 -0
  442. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  443. package/build/dist/Server/Infrastructure/QueueWorker.js +33 -5
  444. package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
  445. package/build/dist/Server/Middleware/BearerTokenAuthorization.js +12 -0
  446. package/build/dist/Server/Middleware/BearerTokenAuthorization.js.map +1 -1
  447. package/build/dist/Server/Middleware/ProjectAuthorization.js +11 -0
  448. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  449. package/build/dist/Server/Middleware/SCIMAuthorization.js +12 -0
  450. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +1 -1
  451. package/build/dist/Server/Middleware/TelemetryIngest.js +11 -0
  452. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  453. package/build/dist/Server/Services/AIBillingService.js +70 -16
  454. package/build/dist/Server/Services/AIBillingService.js.map +1 -1
  455. package/build/dist/Server/Services/DatabaseService.js +31 -5
  456. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  457. package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js +167 -0
  458. package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js.map +1 -1
  459. package/build/dist/Server/Services/EnterpriseLicenseService.js +39 -0
  460. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  461. package/build/dist/Server/Services/Index.js +12 -0
  462. package/build/dist/Server/Services/Index.js.map +1 -1
  463. package/build/dist/Server/Services/MonitorService.js +119 -21
  464. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  465. package/build/dist/Server/Services/MonitorStatusTimelineService.js +127 -8
  466. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  467. package/build/dist/Server/Services/MonitorTemplateService.js +162 -0
  468. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  469. package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js +1683 -0
  470. package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js.map +1 -0
  471. package/build/dist/Server/Services/NetworkAlertPolicyService.js +732 -0
  472. package/build/dist/Server/Services/NetworkAlertPolicyService.js.map +1 -0
  473. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +10 -9
  474. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  475. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +54 -11
  476. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
  477. package/build/dist/Server/Services/NetworkDeviceRoleService.js +70 -0
  478. package/build/dist/Server/Services/NetworkDeviceRoleService.js.map +1 -0
  479. package/build/dist/Server/Services/NetworkDeviceService.js +841 -70
  480. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  481. package/build/dist/Server/Services/NetworkSiteService.js +1145 -107
  482. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  483. package/build/dist/Server/Services/NetworkSiteTypeService.js +863 -0
  484. package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
  485. package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js +217 -0
  486. package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js.map +1 -0
  487. package/build/dist/Server/Services/NotificationService.js +80 -17
  488. package/build/dist/Server/Services/NotificationService.js.map +1 -1
  489. package/build/dist/Server/Services/ProjectService.js +131 -30
  490. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  491. package/build/dist/Server/Services/StatusPagePrivateUserService.js +92 -2
  492. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  493. package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js +76 -0
  494. package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js.map +1 -0
  495. package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js +77 -0
  496. package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js.map +1 -0
  497. package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js +111 -0
  498. package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js.map +1 -0
  499. package/build/dist/Server/Services/UserNotificationSettingService.js +46 -21
  500. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  501. package/build/dist/Server/Services/UserService.js +90 -0
  502. package/build/dist/Server/Services/UserService.js.map +1 -1
  503. package/build/dist/Server/Types/Database/QueryHelper.js +1 -1
  504. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  505. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +14 -3
  506. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
  507. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +10 -0
  508. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
  509. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +10 -0
  510. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
  511. package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +54 -1
  512. package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -1
  513. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +18 -4
  514. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
  515. package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js +59 -0
  516. package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js.map +1 -0
  517. package/build/dist/Server/Utils/DataSource/HttpFetch.js +2 -1
  518. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
  519. package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js +91 -0
  520. package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -0
  521. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +691 -0
  522. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -0
  523. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +497 -0
  524. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -0
  525. package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +257 -0
  526. package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -0
  527. package/build/dist/Server/Utils/LLM/LLMService.js +64 -1
  528. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  529. package/build/dist/Server/Utils/LogRedaction.js +8 -0
  530. package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
  531. package/build/dist/Server/Utils/Logger.js +63 -1
  532. package/build/dist/Server/Utils/Logger.js.map +1 -1
  533. package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js +141 -0
  534. package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js.map +1 -0
  535. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  536. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  537. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +51 -1
  538. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  539. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +7 -0
  540. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
  541. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +37 -0
  542. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  543. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +158 -6
  544. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  545. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
  546. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  547. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +32 -0
  548. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  549. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +330 -21
  550. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  551. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +55 -10
  552. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
  553. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +178 -49
  554. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
  555. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +119 -29
  556. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  557. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +30 -17
  558. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -1
  559. package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js +158 -0
  560. package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js.map +1 -0
  561. package/build/dist/Server/Utils/OutboundUserAgent.js +123 -0
  562. package/build/dist/Server/Utils/OutboundUserAgent.js.map +1 -0
  563. package/build/dist/Server/Utils/StartServer.js +38 -14
  564. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  565. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +28 -8
  566. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
  567. package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js +95 -0
  568. package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js.map +1 -0
  569. package/build/dist/Server/Utils/Telemetry/SpanUtil.js +29 -0
  570. package/build/dist/Server/Utils/Telemetry/SpanUtil.js.map +1 -1
  571. package/build/dist/Server/Utils/Telemetry.js +162 -46
  572. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  573. package/build/dist/Types/AI/ExceptionAIClassification.js +10 -24
  574. package/build/dist/Types/AI/ExceptionAIClassification.js.map +1 -1
  575. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  576. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  577. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js +2 -0
  578. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js.map +1 -0
  579. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js +7 -0
  580. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js.map +1 -0
  581. package/build/dist/Types/Exception/ApiException.js +9 -0
  582. package/build/dist/Types/Exception/ApiException.js.map +1 -1
  583. package/build/dist/Types/Exception/BadDataException.js +10 -0
  584. package/build/dist/Types/Exception/BadDataException.js.map +1 -1
  585. package/build/dist/Types/Exception/BadRequestException.js +10 -0
  586. package/build/dist/Types/Exception/BadRequestException.js.map +1 -1
  587. package/build/dist/Types/Exception/Exception.js +56 -0
  588. package/build/dist/Types/Exception/Exception.js.map +1 -1
  589. package/build/dist/Types/Exception/ForbiddenException.js +9 -0
  590. package/build/dist/Types/Exception/ForbiddenException.js.map +1 -1
  591. package/build/dist/Types/Exception/NotAuthenticatedException.js +9 -0
  592. package/build/dist/Types/Exception/NotAuthenticatedException.js.map +1 -1
  593. package/build/dist/Types/Exception/NotAuthorizedException.js +9 -0
  594. package/build/dist/Types/Exception/NotAuthorizedException.js.map +1 -1
  595. package/build/dist/Types/Exception/NotFoundException.js +10 -0
  596. package/build/dist/Types/Exception/NotFoundException.js.map +1 -1
  597. package/build/dist/Types/Exception/PayloadTooLargeException.js +10 -0
  598. package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -1
  599. package/build/dist/Types/Exception/PaymentRequiredException.js +9 -0
  600. package/build/dist/Types/Exception/PaymentRequiredException.js.map +1 -1
  601. package/build/dist/Types/Exception/ServiceUnavailableException.js +9 -0
  602. package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -1
  603. package/build/dist/Types/Exception/SsoAuthorizationException.js +9 -0
  604. package/build/dist/Types/Exception/SsoAuthorizationException.js.map +1 -1
  605. package/build/dist/Types/Exception/TenantNotFoundException.js +10 -0
  606. package/build/dist/Types/Exception/TenantNotFoundException.js.map +1 -1
  607. package/build/dist/Types/Exception/TimeoutException.js +9 -0
  608. package/build/dist/Types/Exception/TimeoutException.js.map +1 -1
  609. package/build/dist/Types/Exception/TooManyRequestsException.js +9 -0
  610. package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -1
  611. package/build/dist/Types/Exception/UnableToReachServer.js +9 -0
  612. package/build/dist/Types/Exception/UnableToReachServer.js.map +1 -1
  613. package/build/dist/Types/Exception/WebsiteRequestException.js +9 -0
  614. package/build/dist/Types/Exception/WebsiteRequestException.js.map +1 -1
  615. package/build/dist/Types/Monitor/CriteriaFilter.js +45 -2
  616. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  617. package/build/dist/Types/Monitor/DatabaseMetricCatalog.js +594 -0
  618. package/build/dist/Types/Monitor/DatabaseMetricCatalog.js.map +1 -0
  619. package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js +21 -0
  620. package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js.map +1 -0
  621. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +70 -0
  622. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  623. package/build/dist/Types/Monitor/MonitorMetricType.js +61 -0
  624. package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
  625. package/build/dist/Types/Monitor/MonitorStep.js +54 -0
  626. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  627. package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js +122 -0
  628. package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js.map +1 -0
  629. package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -1
  630. package/build/dist/Types/Monitor/MonitorType.js +45 -1
  631. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  632. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +21 -1
  633. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
  634. package/build/dist/Types/Monitor/SqlConnectionConfig.js +2 -0
  635. package/build/dist/Types/Monitor/SqlConnectionConfig.js.map +1 -0
  636. package/build/dist/Types/NetworkDevice/DefaultNetworkDeviceRole.js +105 -0
  637. package/build/dist/Types/NetworkDevice/DefaultNetworkDeviceRole.js.map +1 -0
  638. package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js +172 -0
  639. package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js.map +1 -0
  640. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +40 -22
  641. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -1
  642. package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js +26 -0
  643. package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js.map +1 -0
  644. package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js +186 -0
  645. package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js.map +1 -0
  646. package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js +87 -0
  647. package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js.map +1 -0
  648. package/build/dist/Types/Permission.js +120 -0
  649. package/build/dist/Types/Permission.js.map +1 -1
  650. package/build/dist/Types/Telemetry/ErrorClass.js +216 -0
  651. package/build/dist/Types/Telemetry/ErrorClass.js.map +1 -0
  652. package/build/dist/Types/Telemetry/UnitOfWork.js +59 -0
  653. package/build/dist/Types/Telemetry/UnitOfWork.js.map +1 -0
  654. package/build/dist/UI/Components/Charts/Area/AreaChart.js +1 -1
  655. package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
  656. package/build/dist/UI/Components/Charts/Bar/BarChart.js +1 -1
  657. package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
  658. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +6 -1
  659. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  660. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +79 -31
  661. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  662. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +7 -1
  663. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  664. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +79 -31
  665. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  666. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js +14 -0
  667. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js.map +1 -0
  668. package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
  669. package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
  670. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +2 -7
  671. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
  672. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +3 -0
  673. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  674. package/build/dist/UI/Components/Modal/Modal.js +2 -7
  675. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  676. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +39 -13
  677. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  678. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +39 -0
  679. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  680. package/build/dist/UI/Components/Navbar/NavBar.js +44 -9
  681. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  682. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +2 -2
  683. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  684. package/build/dist/UI/Components/ProgressBar/ProgressBar.js +12 -1
  685. package/build/dist/UI/Components/ProgressBar/ProgressBar.js.map +1 -1
  686. package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +6 -6
  687. package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
  688. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +1 -1
  689. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
  690. package/build/dist/UI/Components/SideMenu/SideMenu.js +76 -11
  691. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  692. package/build/dist/UI/Components/SideMenu/SideMenuItem.js +50 -54
  693. package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
  694. package/build/dist/UI/Components/SideMenu/SideMenuSection.js +32 -9
  695. package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
  696. package/build/dist/UI/Components/SideOver/SideOver.js +5 -20
  697. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  698. package/build/dist/UI/Utils/PageScrollLock.js +31 -3
  699. package/build/dist/UI/Utils/PageScrollLock.js.map +1 -1
  700. package/build/dist/UI/Utils/PermissionGate.js +42 -1
  701. package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
  702. package/build/dist/UI/Utils/SensitiveUrlToken.js +97 -0
  703. package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -0
  704. package/build/dist/UI/Utils/TestLLMProvider.js +4 -5
  705. package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -1
  706. package/build/dist/UI/Utils/UseDashboardTimeRangeZoom.js +42 -0
  707. package/build/dist/UI/Utils/UseDashboardTimeRangeZoom.js.map +1 -0
  708. package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js +74 -0
  709. package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js.map +1 -0
  710. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +15 -0
  711. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -1
  712. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +111 -9
  713. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  714. package/build/dist/Utils/Monitor/MonitorMetricType.js +109 -1
  715. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  716. package/build/dist/Utils/Monitor/NetworkDeviceRoleCatalog.js +126 -0
  717. package/build/dist/Utils/Monitor/NetworkDeviceRoleCatalog.js.map +1 -0
  718. package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js +2 -1
  719. package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js.map +1 -1
  720. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +75 -35
  721. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  722. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +27 -7
  723. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
  724. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +7 -5
  725. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
  726. package/build/dist/Utils/NetworkDevice/DeviceRoleKeyUtil.js +114 -0
  727. package/build/dist/Utils/NetworkDevice/DeviceRoleKeyUtil.js.map +1 -0
  728. package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js +180 -0
  729. package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js.map +1 -0
  730. package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js +12 -0
  731. package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js.map +1 -0
  732. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +15 -5
  733. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
  734. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +44 -15
  735. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
  736. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +52 -23
  737. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -1
  738. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +85 -13
  739. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -1
  740. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +30 -15
  741. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
  742. package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +191 -0
  743. package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -0
  744. package/build/dist/Utils/Rules/RulePatternMatchUtil.js +1 -1
  745. package/build/dist/Utils/Slug.js +31 -1
  746. package/build/dist/Utils/Slug.js.map +1 -1
  747. package/package.json +2 -2
@@ -0,0 +1,802 @@
1
+ /*
2
+ * Contract under test: WHERE a monitor status change is bridged to the
3
+ * network-site rollup engine (NetworkSiteService.onMonitorStatusChanged),
4
+ * which is what stamps a bound NetworkDevice's currentMonitorStatusId and
5
+ * isReachable and refreshes its site chain.
6
+ *
7
+ * The pre-existing bug: the only call to that bridge lived inside
8
+ * MonitorService.changeMonitorStatus. A PROBE result never goes through
9
+ * changeMonitorStatus - it goes MonitorResource ->
10
+ * MonitorStatusTimelineService.create -> onCreateSuccess ->
11
+ * MonitorService.updateOneBy({ currentMonitorStatusId }) with ROOT props,
12
+ * and MonitorService.onUpdateSuccess only calls changeMonitorStatus when
13
+ * props.tenantId is set. So a ping monitor going down moved the monitor's
14
+ * status and left every device bound to it exactly where it was; devices
15
+ * only ever moved on manual, incident and maintenance status changes.
16
+ *
17
+ * What is pinned here:
18
+ *
19
+ * - MonitorStatusTimelineService.create bridges a NEW CURRENT row (no
20
+ * endsAt) exactly once, with root props and no tenantId - the probe
21
+ * path's exact shape - and does not bridge a row that is already closed
22
+ * (an endsAt: a backfilled historical row that is not the current
23
+ * status). It bridges AFTER super.create has resolved and the
24
+ * per-monitor mutex has been released: the bridge stamps every bound
25
+ * device and recomputes each site chain (alerts, workspace
26
+ * notifications), and holding the lock across that would refuse
27
+ * concurrent status writes for the monitor past the semaphore's
28
+ * acquire timeout,
29
+ * - onCreateSuccess (which runs UNDER that mutex) writes the monitor's
30
+ * currentMonitorStatusId and does NOT call the bridge itself,
31
+ * - onDeleteSuccess bridges the SURVIVING latest status after a row is
32
+ * deleted,
33
+ * - MonitorService.refreshMonitorCurrentStatus bridges only when it
34
+ * actually moved the id,
35
+ * - changeMonitorStatus no longer calls the bridge itself: its timeline
36
+ * create reaches MonitorStatusTimelineService.create's bridge, so
37
+ * keeping both stamped every device twice,
38
+ * - a bridge that throws never fails the status write it follows.
39
+ *
40
+ * Everything below the service boundary is spied - no database. Semaphore is
41
+ * mocked at the module boundary (as MonitorStatusTimelineService.test.ts
42
+ * does) so create() can run its lock -> super.create -> release -> bridge
43
+ * sequence without Redis.
44
+ */
45
+
46
+ const lockMock: jest.Mock = jest.fn();
47
+ const releaseMock: jest.Mock = jest.fn();
48
+
49
+ jest.mock("../../../Server/Infrastructure/Semaphore", () => {
50
+ return {
51
+ __esModule: true,
52
+ default: {
53
+ lock: (...args: Array<unknown>) => {
54
+ return lockMock(...args);
55
+ },
56
+ release: (...args: Array<unknown>) => {
57
+ return releaseMock(...args);
58
+ },
59
+ },
60
+ };
61
+ });
62
+
63
+ import MonitorStatusTimelineService from "../../../Server/Services/MonitorStatusTimelineService";
64
+ import DatabaseService from "../../../Server/Services/DatabaseService";
65
+ import MonitorService from "../../../Server/Services/MonitorService";
66
+ import NetworkSiteService from "../../../Server/Services/NetworkSiteService";
67
+ import logger from "../../../Server/Utils/Logger";
68
+ import MonitorStatusTimeline from "../../../Models/DatabaseModels/MonitorStatusTimeline";
69
+ import Monitor from "../../../Models/DatabaseModels/Monitor";
70
+ import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
71
+ import ObjectID from "../../../Types/ObjectID";
72
+ import DeleteBy from "../../../Server/Types/Database/DeleteBy";
73
+ import { OnCreate, OnDelete } from "../../../Server/Types/Database/Hooks";
74
+ import fs from "fs";
75
+ import path from "path";
76
+ import { afterEach, beforeEach, describe, expect, it } from "@jest/globals";
77
+
78
+ const PROJECT_ID: ObjectID = new ObjectID(
79
+ "22222222-2222-4222-8222-222222222222",
80
+ );
81
+ const MONITOR_ID: ObjectID = new ObjectID(
82
+ "44444444-4444-4444-8444-444444444444",
83
+ );
84
+ const ROW_ID: ObjectID = new ObjectID("11111111-1111-4111-8111-111111111111");
85
+ const OPERATIONAL_STATUS_ID: ObjectID = new ObjectID(
86
+ "55555555-5555-4555-8555-555555555555",
87
+ );
88
+ const OFFLINE_STATUS_ID: ObjectID = new ObjectID(
89
+ "66666666-6666-4666-8666-666666666666",
90
+ );
91
+
92
+ // The probe path's props: root, and deliberately NO tenantId.
93
+ const ROOT_PROPS: DatabaseCommonInteractionProps = {
94
+ isRoot: true,
95
+ };
96
+
97
+ function fakeTimelineRow(data: {
98
+ monitorStatusId: ObjectID;
99
+ projectId?: ObjectID | undefined;
100
+ endsAt?: Date | undefined;
101
+ }): MonitorStatusTimeline {
102
+ const row: MonitorStatusTimeline = new MonitorStatusTimeline();
103
+ row.id = ROW_ID;
104
+ row.monitorId = MONITOR_ID;
105
+ row.monitorStatusId = data.monitorStatusId;
106
+ row.startsAt = new Date("2026-08-01T00:00:00.000Z");
107
+ if (data.projectId) {
108
+ row.projectId = data.projectId;
109
+ }
110
+ if (data.endsAt) {
111
+ row.endsAt = data.endsAt;
112
+ }
113
+ return row;
114
+ }
115
+
116
+ function mockBridge(): jest.SpyInstance {
117
+ return jest
118
+ .spyOn(NetworkSiteService, "onMonitorStatusChanged")
119
+ .mockResolvedValue(undefined as never);
120
+ }
121
+
122
+ function mockMonitorStatusWrite(): jest.SpyInstance {
123
+ return jest.spyOn(MonitorService, "updateOneBy").mockResolvedValue(1);
124
+ }
125
+
126
+ /*
127
+ * Drives the hook exactly as DatabaseService.create does after the INSERT:
128
+ * with the saved row and the createBy that produced it. A first-status
129
+ * carryForward (no predecessor, no successor) keeps the predecessor
130
+ * bookkeeping out of the way - it is not what is under test here.
131
+ */
132
+ async function runOnCreateSuccess(data: {
133
+ createdItem: MonitorStatusTimeline;
134
+ createByData?: MonitorStatusTimeline | undefined;
135
+ props?: DatabaseCommonInteractionProps | undefined;
136
+ }): Promise<MonitorStatusTimeline> {
137
+ const onCreate: OnCreate<MonitorStatusTimeline> = {
138
+ createBy: {
139
+ data: data.createByData || data.createdItem,
140
+ props: data.props || ROOT_PROPS,
141
+ },
142
+ carryForward: {
143
+ statusTimelineBeforeThisStatus: null,
144
+ statusTimelineAfterThisStatus: null,
145
+ },
146
+ };
147
+
148
+ return await (MonitorStatusTimelineService as any).onCreateSuccess(
149
+ onCreate,
150
+ data.createdItem,
151
+ );
152
+ }
153
+
154
+ /*
155
+ * Drives create() exactly as the probe path does - root props, no tenantId -
156
+ * with super.create (DatabaseService.prototype.create: hooks, validation, the
157
+ * INSERT) stubbed to resolve the saved row, and the feed item (DB lookups +
158
+ * Slack/Teams HTTP) stubbed. What is left running is exactly what create()
159
+ * owns: lock -> super.create -> release -> bridge -> feed item.
160
+ */
161
+ async function runCreate(data: {
162
+ createdItem: MonitorStatusTimeline;
163
+ createByData?: MonitorStatusTimeline | undefined;
164
+ props?: DatabaseCommonInteractionProps | undefined;
165
+ }): Promise<MonitorStatusTimeline> {
166
+ return await MonitorStatusTimelineService.create({
167
+ data: data.createByData || data.createdItem,
168
+ props: data.props || ROOT_PROPS,
169
+ });
170
+ }
171
+
172
+ function expectBridgedOnceWith(
173
+ bridgeSpy: jest.SpyInstance,
174
+ expected: { projectId: ObjectID; monitorStatusId: ObjectID },
175
+ ): void {
176
+ expect(bridgeSpy).toHaveBeenCalledTimes(1);
177
+
178
+ const args: any = bridgeSpy.mock.calls[0]![0];
179
+
180
+ expect(args.projectId.toString()).toBe(expected.projectId.toString());
181
+ expect(
182
+ args.monitorIds.map((id: ObjectID) => {
183
+ return id.toString();
184
+ }),
185
+ ).toEqual([MONITOR_ID.toString()]);
186
+ expect(args.monitorStatusId.toString()).toBe(
187
+ expected.monitorStatusId.toString(),
188
+ );
189
+ }
190
+
191
+ describe("MonitorStatusTimelineService.create - the probe path bridge", () => {
192
+ let superCreateSpy: jest.SpyInstance;
193
+ let feedItemSpy: jest.SpyInstance;
194
+
195
+ // a unique object standing in for the redis-semaphore mutex.
196
+ const fakeMutex: { id: string } = { id: "fake-mutex" };
197
+
198
+ beforeEach(() => {
199
+ lockMock.mockReset();
200
+ releaseMock.mockReset();
201
+
202
+ lockMock.mockResolvedValue(fakeMutex);
203
+ releaseMock.mockResolvedValue(undefined);
204
+
205
+ superCreateSpy = jest.spyOn(DatabaseService.prototype, "create");
206
+
207
+ feedItemSpy = jest
208
+ .spyOn(
209
+ MonitorStatusTimelineService as unknown as {
210
+ createStatusChangeFeedItem: () => Promise<void>;
211
+ },
212
+ "createStatusChangeFeedItem",
213
+ )
214
+ .mockResolvedValue(undefined);
215
+ });
216
+
217
+ afterEach(() => {
218
+ jest.restoreAllMocks();
219
+ });
220
+
221
+ /*
222
+ * super.create resolves the saved row. Its hooks (onBeforeCreate /
223
+ * onCreateSuccess) do not run here - they are DatabaseService.create's
224
+ * responsibility and are pinned separately below.
225
+ */
226
+ function stubSuperCreate(createdItem: MonitorStatusTimeline): void {
227
+ superCreateSpy.mockResolvedValue(createdItem);
228
+ }
229
+
230
+ it("bridges a new current row exactly once with root props and no tenantId", async () => {
231
+ const bridge: jest.SpyInstance = mockBridge();
232
+
233
+ const createdItem: MonitorStatusTimeline = fakeTimelineRow({
234
+ monitorStatusId: OFFLINE_STATUS_ID,
235
+ projectId: PROJECT_ID,
236
+ });
237
+ stubSuperCreate(createdItem);
238
+
239
+ const result: MonitorStatusTimeline = await runCreate({
240
+ createdItem: createdItem,
241
+ });
242
+
243
+ expect(result).toBe(createdItem);
244
+
245
+ /*
246
+ * The probe path's exact shape: root, no tenantId. The create went
247
+ * through the locked path (a monitorId is set), and the bridge fired
248
+ * off the row that was written - not off anything tenant-gated.
249
+ */
250
+ const createArgs: any = superCreateSpy.mock.calls[0]![0];
251
+ expect(createArgs.props.isRoot).toBe(true);
252
+ expect(createArgs.props.tenantId).toBeUndefined();
253
+ expect(lockMock).toHaveBeenCalledTimes(1);
254
+ expect(releaseMock).toHaveBeenCalledTimes(1);
255
+
256
+ expectBridgedOnceWith(bridge, {
257
+ projectId: PROJECT_ID,
258
+ monitorStatusId: OFFLINE_STATUS_ID,
259
+ });
260
+ });
261
+
262
+ it("bridges AFTER super.create has resolved and the mutex is released, and before the feed item", async () => {
263
+ const bridge: jest.SpyInstance = mockBridge();
264
+
265
+ stubSuperCreate(
266
+ fakeTimelineRow({
267
+ monitorStatusId: OFFLINE_STATUS_ID,
268
+ projectId: PROJECT_ID,
269
+ }),
270
+ );
271
+
272
+ await runCreate({
273
+ createdItem: fakeTimelineRow({
274
+ monitorStatusId: OFFLINE_STATUS_ID,
275
+ projectId: PROJECT_ID,
276
+ }),
277
+ });
278
+
279
+ /*
280
+ * super.create -> release -> bridge -> feed item.
281
+ *
282
+ * After super.create: the timeline row and (in onCreateSuccess) the
283
+ * monitor's currentMonitorStatusId are written, and
284
+ * NetworkDeviceService.refreshStampedMonitorStatus (and anything else
285
+ * the rollup reads) derives from Monitor.currentMonitorStatusId, so the
286
+ * bridge must observe the new value, not the old one.
287
+ *
288
+ * After release: the bridge stamps every bound device and recomputes
289
+ * each site chain (alerts, workspace notifications). Under the lock,
290
+ * one slow rollup would make a concurrent status write for the same
291
+ * monitor be REFUSED past the semaphore's acquire timeout.
292
+ *
293
+ * Before the feed item: a device stamp must not wait on Slack/Teams.
294
+ */
295
+ expect(superCreateSpy.mock.invocationCallOrder[0]!).toBeLessThan(
296
+ releaseMock.mock.invocationCallOrder[0]!,
297
+ );
298
+ expect(releaseMock.mock.invocationCallOrder[0]!).toBeLessThan(
299
+ bridge.mock.invocationCallOrder[0]!,
300
+ );
301
+ expect(bridge.mock.invocationCallOrder[0]!).toBeLessThan(
302
+ feedItemSpy.mock.invocationCallOrder[0]!,
303
+ );
304
+ });
305
+
306
+ it("does not bridge a row that is already closed (endsAt set)", async () => {
307
+ const bridge: jest.SpyInstance = mockBridge();
308
+
309
+ const createdItem: MonitorStatusTimeline = fakeTimelineRow({
310
+ monitorStatusId: OFFLINE_STATUS_ID,
311
+ projectId: PROJECT_ID,
312
+ endsAt: new Date("2026-08-01T01:00:00.000Z"),
313
+ });
314
+ stubSuperCreate(createdItem);
315
+
316
+ await runCreate({ createdItem: createdItem });
317
+
318
+ // A closed row is history, not the current status: nothing moves.
319
+ expect(bridge).not.toHaveBeenCalled();
320
+ // The lock was still taken and released around the write itself.
321
+ expect(releaseMock).toHaveBeenCalledTimes(1);
322
+ });
323
+
324
+ it("does not bridge when super.create throws", async () => {
325
+ const bridge: jest.SpyInstance = mockBridge();
326
+ superCreateSpy.mockRejectedValue(new Error("insert failed"));
327
+
328
+ await expect(
329
+ runCreate({
330
+ createdItem: fakeTimelineRow({
331
+ monitorStatusId: OFFLINE_STATUS_ID,
332
+ projectId: PROJECT_ID,
333
+ }),
334
+ }),
335
+ ).rejects.toThrow("insert failed");
336
+
337
+ // No row, no status change, nothing to stamp - but the lock is released.
338
+ expect(bridge).not.toHaveBeenCalled();
339
+ expect(releaseMock).toHaveBeenCalledTimes(1);
340
+ });
341
+
342
+ it("falls back to the createBy data when the saved row carries no projectId", async () => {
343
+ const bridge: jest.SpyInstance = mockBridge();
344
+
345
+ const createdItem: MonitorStatusTimeline = fakeTimelineRow({
346
+ monitorStatusId: OFFLINE_STATUS_ID,
347
+ projectId: undefined,
348
+ });
349
+ const createByData: MonitorStatusTimeline = fakeTimelineRow({
350
+ monitorStatusId: OFFLINE_STATUS_ID,
351
+ projectId: PROJECT_ID,
352
+ });
353
+ stubSuperCreate(createdItem);
354
+
355
+ await runCreate({
356
+ createdItem: createdItem,
357
+ createByData: createByData,
358
+ });
359
+
360
+ expectBridgedOnceWith(bridge, {
361
+ projectId: PROJECT_ID,
362
+ monitorStatusId: OFFLINE_STATUS_ID,
363
+ });
364
+ });
365
+
366
+ it("falls back to props.tenantId when neither the row nor the data has a projectId", async () => {
367
+ const bridge: jest.SpyInstance = mockBridge();
368
+
369
+ const createdItem: MonitorStatusTimeline = fakeTimelineRow({
370
+ monitorStatusId: OFFLINE_STATUS_ID,
371
+ projectId: undefined,
372
+ });
373
+ stubSuperCreate(createdItem);
374
+
375
+ await runCreate({
376
+ createdItem: createdItem,
377
+ props: {
378
+ isRoot: true,
379
+ tenantId: PROJECT_ID,
380
+ },
381
+ });
382
+
383
+ expectBridgedOnceWith(bridge, {
384
+ projectId: PROJECT_ID,
385
+ monitorStatusId: OFFLINE_STATUS_ID,
386
+ });
387
+ });
388
+
389
+ it("skips the bridge, with a warning, when no projectId can be resolved at all", async () => {
390
+ const bridge: jest.SpyInstance = mockBridge();
391
+ const warn: jest.SpyInstance = jest
392
+ .spyOn(logger, "warn")
393
+ .mockImplementation(() => {
394
+ return undefined;
395
+ });
396
+
397
+ const createdItem: MonitorStatusTimeline = fakeTimelineRow({
398
+ monitorStatusId: OFFLINE_STATUS_ID,
399
+ projectId: undefined,
400
+ });
401
+ stubSuperCreate(createdItem);
402
+
403
+ const result: MonitorStatusTimeline = await runCreate({
404
+ createdItem: createdItem,
405
+ });
406
+
407
+ expect(result).toBe(createdItem);
408
+ expect(bridge).not.toHaveBeenCalled();
409
+ expect(warn).toHaveBeenCalledTimes(1);
410
+ });
411
+
412
+ it("a bridge that throws does not fail the timeline create", async () => {
413
+ jest
414
+ .spyOn(NetworkSiteService, "onMonitorStatusChanged")
415
+ .mockRejectedValue(new Error("rollup exploded") as never);
416
+ const error: jest.SpyInstance = jest
417
+ .spyOn(logger, "error")
418
+ .mockImplementation(() => {
419
+ return undefined;
420
+ });
421
+
422
+ const createdItem: MonitorStatusTimeline = fakeTimelineRow({
423
+ monitorStatusId: OFFLINE_STATUS_ID,
424
+ projectId: PROJECT_ID,
425
+ });
426
+ stubSuperCreate(createdItem);
427
+
428
+ /*
429
+ * The timeline row and the monitor's current status are already
430
+ * written by the time the bridge runs; a rollup failure surfacing here
431
+ * would turn a persisted status change into a failed probe ingest.
432
+ */
433
+ await expect(runCreate({ createdItem: createdItem })).resolves.toBe(
434
+ createdItem,
435
+ );
436
+
437
+ expect(error).toHaveBeenCalledTimes(1);
438
+ expect(String(error.mock.calls[0]![0])).toContain("rollup exploded");
439
+
440
+ // The failed bridge did not stop the feed item either.
441
+ expect(feedItemSpy).toHaveBeenCalledTimes(1);
442
+ });
443
+ });
444
+
445
+ describe("MonitorStatusTimelineService.onCreateSuccess - writes the monitor, never bridges", () => {
446
+ afterEach(() => {
447
+ jest.restoreAllMocks();
448
+ });
449
+
450
+ it("writes the monitor's current status with the caller's props and leaves the bridge to create()", async () => {
451
+ const monitorWrite: jest.SpyInstance = mockMonitorStatusWrite();
452
+ const bridge: jest.SpyInstance = mockBridge();
453
+
454
+ const createdItem: MonitorStatusTimeline = fakeTimelineRow({
455
+ monitorStatusId: OFFLINE_STATUS_ID,
456
+ projectId: PROJECT_ID,
457
+ });
458
+
459
+ await expect(
460
+ runOnCreateSuccess({ createdItem: createdItem }),
461
+ ).resolves.toBe(createdItem);
462
+
463
+ /*
464
+ * The monitor's current status is written with the caller's props -
465
+ * root, no tenantId - which is precisely the write that never reaches
466
+ * MonitorService.onUpdateSuccess's tenant-gated changeMonitorStatus.
467
+ */
468
+ expect(monitorWrite).toHaveBeenCalledTimes(1);
469
+ const writeArgs: any = monitorWrite.mock.calls[0]![0];
470
+ expect(writeArgs.data.currentMonitorStatusId.toString()).toBe(
471
+ OFFLINE_STATUS_ID.toString(),
472
+ );
473
+ expect(writeArgs.props.isRoot).toBe(true);
474
+ expect(writeArgs.props.tenantId).toBeUndefined();
475
+
476
+ /*
477
+ * This hook runs while create() still holds the per-monitor mutex, so
478
+ * the bridge (device stamps, site rollups, alerts, notifications) must
479
+ * NOT run from here: create() runs it right after the release. A bridge
480
+ * call from this hook would put it back under the lock.
481
+ */
482
+ expect(bridge).not.toHaveBeenCalled();
483
+ });
484
+
485
+ it("does not write the monitor for a row that is already closed (endsAt set)", async () => {
486
+ const monitorWrite: jest.SpyInstance = mockMonitorStatusWrite();
487
+ const bridge: jest.SpyInstance = mockBridge();
488
+
489
+ await runOnCreateSuccess({
490
+ createdItem: fakeTimelineRow({
491
+ monitorStatusId: OFFLINE_STATUS_ID,
492
+ projectId: PROJECT_ID,
493
+ endsAt: new Date("2026-08-01T01:00:00.000Z"),
494
+ }),
495
+ });
496
+
497
+ // A closed row is history, not the current status: nothing moves.
498
+ expect(monitorWrite).not.toHaveBeenCalled();
499
+ expect(bridge).not.toHaveBeenCalled();
500
+ });
501
+ });
502
+
503
+ describe("MonitorStatusTimelineService.onDeleteSuccess - bridging the surviving status", () => {
504
+ afterEach(() => {
505
+ jest.restoreAllMocks();
506
+ });
507
+
508
+ function runOnDeleteSuccess(
509
+ carryForward: ObjectID | null,
510
+ ): Promise<OnDelete<MonitorStatusTimeline>> {
511
+ const onDelete: OnDelete<MonitorStatusTimeline> = {
512
+ deleteBy: {
513
+ query: {
514
+ _id: ROW_ID.toString(),
515
+ },
516
+ props: ROOT_PROPS,
517
+ } as DeleteBy<MonitorStatusTimeline>,
518
+ carryForward: carryForward,
519
+ };
520
+
521
+ return (MonitorStatusTimelineService as any).onDeleteSuccess(onDelete, [
522
+ ROW_ID,
523
+ ]);
524
+ }
525
+
526
+ it("bridges to the surviving latest status, selecting its projectId to do so", async () => {
527
+ const findLatest: jest.SpyInstance = jest
528
+ .spyOn(MonitorStatusTimelineService, "findOneBy")
529
+ .mockResolvedValue(
530
+ fakeTimelineRow({
531
+ monitorStatusId: OPERATIONAL_STATUS_ID,
532
+ projectId: PROJECT_ID,
533
+ }),
534
+ );
535
+ const monitorWrite: jest.SpyInstance = mockMonitorStatusWrite();
536
+ const bridge: jest.SpyInstance = mockBridge();
537
+
538
+ await runOnDeleteSuccess(MONITOR_ID);
539
+
540
+ // The projectId for the bridge comes off the row already being read.
541
+ expect(findLatest).toHaveBeenCalledTimes(1);
542
+ const findArgs: any = findLatest.mock.calls[0]![0];
543
+ expect(findArgs.select.projectId).toBe(true);
544
+ expect(findArgs.select.monitorStatusId).toBe(true);
545
+
546
+ expect(monitorWrite).toHaveBeenCalledTimes(1);
547
+ expect(
548
+ monitorWrite.mock.calls[0]![0].data.currentMonitorStatusId.toString(),
549
+ ).toBe(OPERATIONAL_STATUS_ID.toString());
550
+
551
+ expectBridgedOnceWith(bridge, {
552
+ projectId: PROJECT_ID,
553
+ monitorStatusId: OPERATIONAL_STATUS_ID,
554
+ });
555
+ expect(monitorWrite.mock.invocationCallOrder[0]!).toBeLessThan(
556
+ bridge.mock.invocationCallOrder[0]!,
557
+ );
558
+ });
559
+
560
+ it("does not bridge when no status survives for the monitor", async () => {
561
+ jest
562
+ .spyOn(MonitorStatusTimelineService, "findOneBy")
563
+ .mockResolvedValue(null);
564
+ const monitorWrite: jest.SpyInstance = mockMonitorStatusWrite();
565
+ const bridge: jest.SpyInstance = mockBridge();
566
+
567
+ await runOnDeleteSuccess(MONITOR_ID);
568
+
569
+ expect(monitorWrite).not.toHaveBeenCalled();
570
+ expect(bridge).not.toHaveBeenCalled();
571
+ });
572
+
573
+ it("does nothing without a monitorId carryForward", async () => {
574
+ const findLatest: jest.SpyInstance = jest.spyOn(
575
+ MonitorStatusTimelineService,
576
+ "findOneBy",
577
+ );
578
+ const bridge: jest.SpyInstance = mockBridge();
579
+
580
+ await runOnDeleteSuccess(null);
581
+
582
+ expect(findLatest).not.toHaveBeenCalled();
583
+ expect(bridge).not.toHaveBeenCalled();
584
+ });
585
+
586
+ it("a bridge that throws does not fail the delete", async () => {
587
+ jest.spyOn(MonitorStatusTimelineService, "findOneBy").mockResolvedValue(
588
+ fakeTimelineRow({
589
+ monitorStatusId: OPERATIONAL_STATUS_ID,
590
+ projectId: PROJECT_ID,
591
+ }),
592
+ );
593
+ mockMonitorStatusWrite();
594
+ jest
595
+ .spyOn(NetworkSiteService, "onMonitorStatusChanged")
596
+ .mockRejectedValue(new Error("rollup exploded") as never);
597
+ jest.spyOn(logger, "error").mockImplementation(() => {
598
+ return undefined;
599
+ });
600
+
601
+ await expect(runOnDeleteSuccess(MONITOR_ID)).resolves.toBeDefined();
602
+ });
603
+ });
604
+
605
+ describe("MonitorService.refreshMonitorCurrentStatus - bridging a repaired status", () => {
606
+ afterEach(() => {
607
+ jest.restoreAllMocks();
608
+ });
609
+
610
+ function fakeMonitor(currentMonitorStatusId: ObjectID | undefined): Monitor {
611
+ return {
612
+ id: MONITOR_ID,
613
+ _id: MONITOR_ID.toString(),
614
+ projectId: PROJECT_ID,
615
+ currentMonitorStatusId: currentMonitorStatusId,
616
+ } as unknown as Monitor;
617
+ }
618
+
619
+ it("bridges when the current status id actually changed", async () => {
620
+ const findMonitor: jest.SpyInstance = jest
621
+ .spyOn(MonitorService, "findOneById")
622
+ .mockResolvedValue(fakeMonitor(OPERATIONAL_STATUS_ID));
623
+ jest.spyOn(MonitorStatusTimelineService, "findOneBy").mockResolvedValue(
624
+ fakeTimelineRow({
625
+ monitorStatusId: OFFLINE_STATUS_ID,
626
+ projectId: PROJECT_ID,
627
+ }),
628
+ );
629
+ const monitorWrite: jest.SpyInstance = jest
630
+ .spyOn(MonitorService, "updateOneById")
631
+ .mockResolvedValue(1);
632
+ const bridge: jest.SpyInstance = mockBridge();
633
+
634
+ await MonitorService.refreshMonitorCurrentStatus(MONITOR_ID);
635
+
636
+ // The monitor read has to carry projectId or there is nothing to bridge with.
637
+ expect(findMonitor.mock.calls[0]![0].select.projectId).toBe(true);
638
+
639
+ expect(monitorWrite).toHaveBeenCalledTimes(1);
640
+ expect(
641
+ monitorWrite.mock.calls[0]![0].data.currentMonitorStatusId.toString(),
642
+ ).toBe(OFFLINE_STATUS_ID.toString());
643
+
644
+ expectBridgedOnceWith(bridge, {
645
+ projectId: PROJECT_ID,
646
+ monitorStatusId: OFFLINE_STATUS_ID,
647
+ });
648
+ expect(monitorWrite.mock.invocationCallOrder[0]!).toBeLessThan(
649
+ bridge.mock.invocationCallOrder[0]!,
650
+ );
651
+ });
652
+
653
+ it("neither writes nor bridges when the id is already in sync", async () => {
654
+ jest
655
+ .spyOn(MonitorService, "findOneById")
656
+ .mockResolvedValue(fakeMonitor(OFFLINE_STATUS_ID));
657
+ jest.spyOn(MonitorStatusTimelineService, "findOneBy").mockResolvedValue(
658
+ fakeTimelineRow({
659
+ monitorStatusId: OFFLINE_STATUS_ID,
660
+ projectId: PROJECT_ID,
661
+ }),
662
+ );
663
+ const monitorWrite: jest.SpyInstance = jest.spyOn(
664
+ MonitorService,
665
+ "updateOneById",
666
+ );
667
+ const bridge: jest.SpyInstance = mockBridge();
668
+
669
+ await MonitorService.refreshMonitorCurrentStatus(MONITOR_ID);
670
+
671
+ /*
672
+ * An unchanged status must not churn every site rollup above the
673
+ * device on each repair pass.
674
+ */
675
+ expect(monitorWrite).not.toHaveBeenCalled();
676
+ expect(bridge).not.toHaveBeenCalled();
677
+ });
678
+
679
+ it("falls back to the timeline row's projectId when the monitor read has none", async () => {
680
+ jest.spyOn(MonitorService, "findOneById").mockResolvedValue({
681
+ id: MONITOR_ID,
682
+ _id: MONITOR_ID.toString(),
683
+ currentMonitorStatusId: OPERATIONAL_STATUS_ID,
684
+ } as unknown as Monitor);
685
+ jest.spyOn(MonitorStatusTimelineService, "findOneBy").mockResolvedValue(
686
+ fakeTimelineRow({
687
+ monitorStatusId: OFFLINE_STATUS_ID,
688
+ projectId: PROJECT_ID,
689
+ }),
690
+ );
691
+ jest.spyOn(MonitorService, "updateOneById").mockResolvedValue(1);
692
+ const bridge: jest.SpyInstance = mockBridge();
693
+
694
+ await MonitorService.refreshMonitorCurrentStatus(MONITOR_ID);
695
+
696
+ expectBridgedOnceWith(bridge, {
697
+ projectId: PROJECT_ID,
698
+ monitorStatusId: OFFLINE_STATUS_ID,
699
+ });
700
+ });
701
+
702
+ it("a bridge that throws does not fail the repair", async () => {
703
+ jest
704
+ .spyOn(MonitorService, "findOneById")
705
+ .mockResolvedValue(fakeMonitor(OPERATIONAL_STATUS_ID));
706
+ jest.spyOn(MonitorStatusTimelineService, "findOneBy").mockResolvedValue(
707
+ fakeTimelineRow({
708
+ monitorStatusId: OFFLINE_STATUS_ID,
709
+ projectId: PROJECT_ID,
710
+ }),
711
+ );
712
+ jest.spyOn(MonitorService, "updateOneById").mockResolvedValue(1);
713
+ jest
714
+ .spyOn(NetworkSiteService, "onMonitorStatusChanged")
715
+ .mockRejectedValue(new Error("rollup exploded") as never);
716
+ jest.spyOn(logger, "error").mockImplementation(() => {
717
+ return undefined;
718
+ });
719
+
720
+ await expect(
721
+ MonitorService.refreshMonitorCurrentStatus(MONITOR_ID),
722
+ ).resolves.toBeUndefined();
723
+ });
724
+ });
725
+
726
+ describe("MonitorService.changeMonitorStatus - no longer bridges directly", () => {
727
+ afterEach(() => {
728
+ jest.restoreAllMocks();
729
+ });
730
+
731
+ it("creates the timeline row and leaves the bridge to MonitorStatusTimelineService.create", async () => {
732
+ jest
733
+ .spyOn(MonitorStatusTimelineService, "findOneBy")
734
+ .mockResolvedValue(null);
735
+ /*
736
+ * The timeline create is stubbed, so MonitorStatusTimelineService.create
737
+ * (the one place the bridge now lives on the create path, after its
738
+ * mutex is released) does not run. If changeMonitorStatus still called
739
+ * the bridge itself, it would show up here.
740
+ */
741
+ const createTimeline: jest.SpyInstance = jest
742
+ .spyOn(MonitorStatusTimelineService, "create")
743
+ .mockResolvedValue(
744
+ fakeTimelineRow({
745
+ monitorStatusId: OFFLINE_STATUS_ID,
746
+ projectId: PROJECT_ID,
747
+ }),
748
+ );
749
+ const bridge: jest.SpyInstance = mockBridge();
750
+
751
+ await MonitorService.changeMonitorStatus(
752
+ PROJECT_ID,
753
+ [MONITOR_ID],
754
+ OFFLINE_STATUS_ID,
755
+ false,
756
+ "manual change",
757
+ undefined,
758
+ ROOT_PROPS,
759
+ );
760
+
761
+ expect(createTimeline).toHaveBeenCalledTimes(1);
762
+ expect(
763
+ createTimeline.mock.calls[0]![0].data.monitorStatusId.toString(),
764
+ ).toBe(OFFLINE_STATUS_ID.toString());
765
+ expect(bridge).not.toHaveBeenCalled();
766
+ });
767
+
768
+ it("the bridge call is gone from the changeMonitorStatus source", () => {
769
+ const source: string = fs.readFileSync(
770
+ path.join(__dirname, "../../../Server/Services/MonitorService.ts"),
771
+ "utf8",
772
+ );
773
+
774
+ const bodyStart: number = source.indexOf(
775
+ "public async changeMonitorStatus(",
776
+ );
777
+ const bodyEnd: number = source.indexOf(
778
+ "private async createStatusTimelineWithRetry(",
779
+ );
780
+
781
+ expect(bodyStart).toBeGreaterThan(-1);
782
+ expect(bodyEnd).toBeGreaterThan(bodyStart);
783
+
784
+ const changeMonitorStatusBody: string = source.slice(bodyStart, bodyEnd);
785
+
786
+ expect(changeMonitorStatusBody).not.toContain(
787
+ "NetworkSiteService.onMonitorStatusChanged",
788
+ );
789
+
790
+ /*
791
+ * The ONLY direct call left in MonitorService is the one in
792
+ * refreshMonitorCurrentStatus, whose updateOneById does not go through
793
+ * a timeline create and so cannot be bridged from
794
+ * MonitorStatusTimelineService.create.
795
+ */
796
+ const callSites: number = source.split(
797
+ "NetworkSiteService.onMonitorStatusChanged(",
798
+ ).length;
799
+
800
+ expect(callSites - 1).toBe(1);
801
+ });
802
+ });