@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
@@ -20,25 +20,39 @@ import SnmpVendorTemplateUtil, {
20
20
  } from "../../../Types/Monitor/SnmpMonitor/SnmpVendorTemplate";
21
21
  import ObjectID from "../../../Types/ObjectID";
22
22
  import OneUptimeDate from "../../../Types/Date";
23
+ import { NetworkDeviceMonitoringMethodUtil } from "../../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
24
+ import { NetworkDevicePollMode } from "./NetworkDeviceHydrationUtil";
23
25
  import logger from "../Logger";
24
26
 
25
27
  /*
26
28
  * Keeps the NetworkDevice / NetworkInterface inventory in sync with each
27
- * device walk, then prunes the in-flight response down to MONITORED
29
+ * device poll, then prunes the in-flight response down to MONITORED
28
30
  * interfaces so criteria and metrics only consider ports the user cares
29
31
  * about. Inventory rows always reflect every walked interface; the
30
32
  * isMonitored flag is user-owned and never overwritten here.
31
33
  *
32
34
  * Called from the device polling pipeline (NetworkDeviceWalkUtil): the
33
- * device's assigned probe walks it on the device's own schedule, so this
34
- * runs for every registered device no Monitor required.
35
+ * device's assigned probe pings it on the device's own schedule - and walks
36
+ * it over SNMP as well when it has credentials - so this runs for every
37
+ * registered device, credentials or not, and no Monitor is required.
35
38
  */
36
39
  export default class NetworkInventoryUtil {
37
40
  public static async updateFromWalk(data: {
38
41
  projectId: ObjectID;
39
42
  deviceId: ObjectID;
43
+ /*
44
+ * The SNMP walk, when one ran (success or failure). Undefined on a
45
+ * ping-only poll - never a synthesized failure.
46
+ */
40
47
  snmpResponse: SnmpMonitorResponse | undefined;
48
+ // Device reachability: answered ping OR the walk succeeded.
41
49
  isOnline: boolean | undefined;
50
+ /*
51
+ * How the probe polled. Absent from callers that predate ping-first
52
+ * polling (the ingest processor stamps "snmp" for an old probe's walk),
53
+ * and read as "snmp" when absent.
54
+ */
55
+ pollMode?: NetworkDevicePollMode | undefined;
42
56
  }): Promise<void> {
43
57
  const deviceId: ObjectID = data.deviceId;
44
58
 
@@ -61,6 +75,8 @@ export default class NetworkInventoryUtil {
61
75
  autoApplyVendorHealthTemplate: true,
62
76
  snmpOids: true,
63
77
  oidTemplateId: true,
78
+ // For the monitor-backed guard on the poll columns below.
79
+ monitoringMethod: true,
64
80
  },
65
81
  props: {
66
82
  isRoot: true,
@@ -71,27 +87,70 @@ export default class NetworkInventoryUtil {
71
87
  return;
72
88
  }
73
89
 
74
- const walkedInterfaces: Array<SnmpInterface> =
75
- data.snmpResponse?.interfaces || [];
76
- const systemInfo: SnmpSystemInfo | undefined =
77
- data.snmpResponse?.systemInfo;
78
- const entityInfo: SnmpEntityInfo | undefined =
79
- data.snmpResponse?.entityInfo;
80
- const lldpNeighbors: Array<LldpNeighbor> | undefined =
81
- data.snmpResponse?.lldpNeighbors;
82
- const cdpNeighbors: Array<CdpNeighbor> | undefined =
83
- data.snmpResponse?.cdpNeighbors;
84
- const arpEntries: Array<ArpEntry> | undefined =
85
- data.snmpResponse?.arpEntries;
86
- const fdbEntries: Array<FdbEntry> | undefined =
87
- data.snmpResponse?.fdbEntries;
90
+ /*
91
+ * A monitor-backed device (monitoringMethod "Monitor") is never meant to
92
+ * be walked: nothing polls it and its bound Monitor's status owns
93
+ * isReachable. But claimDevicesForPolling only excludes such rows at
94
+ * CLAIM time, so a device claimed as SNMP and switched to Monitor before
95
+ * its walk result arrived still lands here. Writing the poll verdict
96
+ * then would overwrite the monitor's reachability with the last thing a
97
+ * probe found before it stopped asking, and the two would fight on the
98
+ * device list until the next status change. The poll and interface-count
99
+ * columns are therefore withheld for such a row; everything else the
100
+ * walk learned (system group, vendor, neighbors, interfaces, endpoints)
101
+ * is still recorded, because it is inventory rather than health.
102
+ */
103
+ const isMonitorBacked: boolean =
104
+ NetworkDeviceMonitoringMethodUtil.isMonitorBacked(
105
+ ownedDevice.monitoringMethod,
106
+ );
107
+
108
+ if (isMonitorBacked) {
109
+ logger.warn(
110
+ `Network device ${deviceId.toString()} is monitor-backed (monitoringMethod "Monitor") but a poll result arrived for it - most likely it was switched off probe polling while a poll was in flight. Its bound monitor owns reachability, so lastPolledAt, isReachable, lastSeenAt, isSnmpReachable, lastSnmpSeenAt and the interface counts from this poll are not written.`,
111
+ );
112
+ }
113
+
114
+ const pollMode: NetworkDevicePollMode = data.pollMode ?? "snmp";
115
+
116
+ /*
117
+ * Did a walk run, and did it succeed? Two separate questions, because a
118
+ * ping-only poll runs no walk at all and must not read as a failed one:
119
+ * the walk columns below go NULL for it, not false.
120
+ *
121
+ * A walk where the probe could not open the SNMP session reports
122
+ * isOnline === false; treat anything else (success, or a walk that
123
+ * reports no verdict at all) as succeeded - the same convention
124
+ * isDeviceReachable uses further down.
125
+ */
126
+ const walkRan: boolean = data.snmpResponse !== undefined;
127
+ const walkSucceeded: boolean =
128
+ data.snmpResponse !== undefined && data.snmpResponse.isOnline !== false;
129
+
130
+ /*
131
+ * Inventory comes ONLY from a successful walk. A failed walk carries no
132
+ * system group, no neighbours and no interfaces, and reading whatever a
133
+ * malformed failure did carry would let it clear the LLDP snapshot or
134
+ * rewrite sysName off a session that never really opened.
135
+ */
136
+ const walk: SnmpMonitorResponse | undefined = walkSucceeded
137
+ ? data.snmpResponse
138
+ : undefined;
139
+
140
+ const walkedInterfaces: Array<SnmpInterface> = walk?.interfaces || [];
141
+ const systemInfo: SnmpSystemInfo | undefined = walk?.systemInfo;
142
+ const entityInfo: SnmpEntityInfo | undefined = walk?.entityInfo;
143
+ const lldpNeighbors: Array<LldpNeighbor> | undefined = walk?.lldpNeighbors;
144
+ const cdpNeighbors: Array<CdpNeighbor> | undefined = walk?.cdpNeighbors;
145
+ const arpEntries: Array<ArpEntry> | undefined = walk?.arpEntries;
146
+ const fdbEntries: Array<FdbEntry> | undefined = walk?.fdbEntries;
88
147
 
89
148
  const now: Date = OneUptimeDate.getCurrentDate();
90
149
 
91
150
  /*
92
- * A poll where the probe could not reach the device reports
93
- * isOnline === false; treat anything else (reachable, or a walk that
94
- * reports no reachability at all) as answered.
151
+ * A poll where the probe could not reach the device (no ping answer AND
152
+ * no walk) reports isOnline === false; treat anything else (reachable,
153
+ * or a poll that reports no reachability at all) as answered.
95
154
  */
96
155
  const isDeviceReachable: boolean = data.isOnline !== false;
97
156
 
@@ -115,12 +174,39 @@ export default class NetworkInventoryUtil {
115
174
  * lastSeenAt - when the device last ANSWERED. Only moves on a
116
175
  * successful walk, so it stays honest as "last
117
176
  * contact" and never paints a dead device green.
177
+ *
178
+ * Under ping-first polling the three answer for the DEVICE - "did it
179
+ * answer ping or SNMP" - which is what the status pill shows. The
180
+ * walk gets its own pair:
181
+ *
182
+ * isSnmpReachable - the verdict of the last WALK: true/false when
183
+ * one ran, NULL when none did (a ping-only poll)
184
+ * or the device was never polled. NULL is the
185
+ * whole point: a credential-less device is not
186
+ * "SNMP down", it is "not walked".
187
+ * lastSnmpSeenAt - when the walk last SUCCEEDED. Only moves on a
188
+ * good walk, like lastSeenAt for the device.
189
+ *
190
+ * An old probe (no pollMode) only ever walked, and the processor
191
+ * stamps its walk verdict as the device verdict, so both columns
192
+ * carry the same value for it - never NULL for a credentialed device.
193
+ *
194
+ * None of the five is written for a monitor-backed device - see the
195
+ * guard above the try.
118
196
  */
119
- deviceUpdate["lastPolledAt"] = now;
120
- deviceUpdate["isReachable"] = isDeviceReachable;
197
+ if (!isMonitorBacked) {
198
+ deviceUpdate["lastPolledAt"] = now;
199
+ deviceUpdate["isReachable"] = isDeviceReachable;
200
+
201
+ if (isDeviceReachable) {
202
+ deviceUpdate["lastSeenAt"] = now;
203
+ }
121
204
 
122
- if (isDeviceReachable) {
123
- deviceUpdate["lastSeenAt"] = now;
205
+ deviceUpdate["isSnmpReachable"] = walkRan ? walkSucceeded : null;
206
+
207
+ if (walkSucceeded) {
208
+ deviceUpdate["lastSnmpSeenAt"] = now;
209
+ }
124
210
  }
125
211
 
126
212
  if (systemInfo?.sysDescr) {
@@ -232,24 +318,45 @@ export default class NetworkInventoryUtil {
232
318
  deviceUpdate["cdpNeighbors"] = cdpNeighbors.slice(0, 256);
233
319
  }
234
320
 
235
- if (walkedInterfaces.length > 0) {
236
- deviceUpdate["interfacesTotal"] = walkedInterfaces.length;
237
- deviceUpdate["interfacesUp"] = walkedInterfaces.filter(
238
- (walked: SnmpInterface) => {
239
- return walked.isAdministrativelyUp && walked.isOperationallyUp;
240
- },
241
- ).length;
242
- deviceUpdate["interfacesDown"] = walkedInterfaces.filter(
243
- (walked: SnmpInterface) => {
244
- return walked.isAdministrativelyUp && !walked.isOperationallyUp;
245
- },
246
- ).length;
321
+ /*
322
+ * The cached interface counts are health columns too (the device list
323
+ * and the site overview read interfacesDown), so a monitor-backed
324
+ * device keeps them out for the same reason as the poll columns.
325
+ *
326
+ * On a ping-only poll they go NULL rather than staying put: a device
327
+ * whose credentials were removed would otherwise keep showing the
328
+ * interface counts of its last walk indefinitely, and the list would
329
+ * read "3 interfaces down" on a device nothing is walking any more.
330
+ * A failed walk in snmp mode, by contrast, leaves them alone - the
331
+ * last good counts are the best estimate until the next good walk,
332
+ * exactly as the lastWalkLog baseline is kept across failed polls.
333
+ */
334
+ if (!isMonitorBacked) {
335
+ if (pollMode === "ping") {
336
+ deviceUpdate["interfacesTotal"] = null;
337
+ deviceUpdate["interfacesUp"] = null;
338
+ deviceUpdate["interfacesDown"] = null;
339
+ } else if (walkedInterfaces.length > 0) {
340
+ deviceUpdate["interfacesTotal"] = walkedInterfaces.length;
341
+ deviceUpdate["interfacesUp"] = walkedInterfaces.filter(
342
+ (walked: SnmpInterface) => {
343
+ return walked.isAdministrativelyUp && walked.isOperationallyUp;
344
+ },
345
+ ).length;
346
+ deviceUpdate["interfacesDown"] = walkedInterfaces.filter(
347
+ (walked: SnmpInterface) => {
348
+ return walked.isAdministrativelyUp && !walked.isOperationallyUp;
349
+ },
350
+ ).length;
351
+ }
247
352
  }
248
353
 
249
354
  /*
250
- * Always non-empty now: even a walk that reached nothing has to
251
- * record that we tried, or the staleness backstop cannot tell a
252
- * failing device from an unpolled one.
355
+ * Always non-empty for a probe-polled device: even a poll that
356
+ * reached nothing has to record that we tried, or the staleness
357
+ * backstop cannot tell a failing device from an unpolled one. Only
358
+ * the monitor-backed case above can leave it empty, and then there
359
+ * is genuinely nothing to write.
253
360
  */
254
361
  if (Object.keys(deviceUpdate).length > 0) {
255
362
  await NetworkDeviceService.updateOneById({
@@ -27,12 +27,12 @@ import { DeviceHealthState } from "../../../Utils/NetworkSite/SiteStatusRollupUt
27
27
  *
28
28
  * So the rule does not move. What moves is the DATA REDUCTION.
29
29
  *
30
- * `deviceHealthState` is a pure function of six facts about a row, and five of
31
- * them are already booleans or three-state flags. Group the table by those
32
- * facts in SQL and 80,000 rows collapse into at most a few per site — one
33
- * bucket per distinct combination that actually occurs. Then hand each bucket
34
- * back to the REAL classifier once and multiply its verdict by the bucket's
35
- * count.
30
+ * `deviceHealthState` is a pure function of seven facts about a row, and six
31
+ * of them are already booleans, three-state flags or a column that only ever
32
+ * holds two values. Group the table by those facts in SQL and 80,000 rows
33
+ * collapse into at most a few per site one bucket per distinct combination
34
+ * that actually occurs. Then hand each bucket back to the REAL classifier
35
+ * once and multiply its verdict by the bucket's count.
36
36
  *
37
37
  * One rule, one implementation, and the wire carries buckets instead of rows.
38
38
  *
@@ -121,20 +121,26 @@ const DEVICE_HEALTH_DISCRIMINATOR_COLUMNS: Array<AggregateColumn> = [
121
121
  * The column only ever holds a handful of distinct values, so the raw form
122
122
  * costs nothing in bucket count.
123
123
  *
124
- * Note carefully WHO reads it: `deviceHealthState` never receives it (it is
125
- * not part of `DeviceHealthStateInput`, and `deviceHealthInputForGroup` does
126
- * not emit it), so the per-site health rollups are indifferent to it. Its
127
- * one consumer is the Overview's fleet tally, which re-attaches it and calls
128
- * `DeviceReachabilityUtil` directly and a tally that dropped it would
129
- * report every ping-only device as Pending forever (issue #3392, one level
130
- * up).
124
+ * Every consumer of a bucket reads it. `deviceHealthInputForGroup` and
125
+ * `deviceRollupStateForGroup` carry it into the classifier inputs, where
126
+ * the shared reachability rule uses it to decide whether the poll facts
127
+ * beside it mean anything. On a monitor-backed device they do not: its
128
+ * `isReachable` mirrors the bound monitor (NULL when nothing is bound) and
129
+ * its `lastSeenAt` is whatever a probe last found before it stopped asking
130
+ * — so an unstamped monitor-backed bucket has to classify as "unknown",
131
+ * not as whatever those leftovers happen to say, or the site card and the
132
+ * device list under it describe two different networks. The Overview's
133
+ * fleet tally reads it for the same reason one level up (issue #3392: a
134
+ * tally that dropped it reported every ping-only device as Pending
135
+ * forever).
131
136
  *
132
- * It therefore costs the rollup path a discriminator it does not use. On a
133
- * real fleet that costs nothing, because `monitoringMethod` is almost
137
+ * Dropping it from the group keys would therefore not be a harmless
138
+ * simplification: a bucket that mixed probe-polled and monitor-backed devices with
139
+ * the same poll facts would classify all of them by the poll rule. On a
140
+ * real fleet it also costs nothing, because `monitoringMethod` is almost
134
141
  * perfectly correlated with whether the device carries a stamped monitor
135
142
  * status — which is already a group key — so it splits no bucket that
136
- * `currentMonitorStatusId` had not split anyway. Keeping one discriminator
137
- * set is worth more than saving that.
143
+ * `currentMonitorStatusId` had not split anyway.
138
144
  */
139
145
  {
140
146
  expression: column("monitoringMethod"),
@@ -270,7 +276,7 @@ export interface DeviceHealthGroup {
270
276
  monitorStatusId: string | null;
271
277
  /*
272
278
  * Null for rows written before the column existed, which
273
- * `NetworkDeviceMonitoringMethodUtil.parse` reads as SNMP.
279
+ * `NetworkDeviceMonitoringMethodUtil.parse` reads as Probe.
274
280
  */
275
281
  monitoringMethod: string | null;
276
282
  isReachable: boolean | null;
@@ -373,6 +379,11 @@ export function deviceHealthInputForGroup(data: {
373
379
  * the synthetic dates above are placed relative to.
374
380
  */
375
381
  pollingIntervalInMinutes: undefined,
382
+ /*
383
+ * Carried verbatim — the classifier parses it, and NULL reads as Probe
384
+ * there. See the discriminator column for why a bucket cannot drop it.
385
+ */
386
+ monitoringMethod: group.monitoringMethod,
376
387
  interfacesDown: group.hasDownInterfaces ? 1 : 0,
377
388
  };
378
389
  }
@@ -422,6 +433,8 @@ export function deviceRollupStateForGroup(data: {
422
433
  lastSeenAt: group.hasBeenSeen ? contactAt : null,
423
434
  // See deviceHealthInputForGroup — staleness is already applied.
424
435
  pollingIntervalInMinutes: undefined,
436
+ // ...and for why this rides along with the poll facts it qualifies.
437
+ monitoringMethod: group.monitoringMethod,
425
438
  deviceCount: group.deviceCount,
426
439
  };
427
440
  }
@@ -0,0 +1,213 @@
1
+ import Semaphore, { SemaphoreMutex } from "../../Infrastructure/Semaphore";
2
+ import logger from "../../Utils/Logger";
3
+ import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
4
+ import BadDataException from "../../../Types/Exception/BadDataException";
5
+ import ServerException from "../../../Types/Exception/ServerException";
6
+ import ObjectID from "../../../Types/ObjectID";
7
+
8
+ export const NETWORK_SITE_HIERARCHY_LOCK_NAMESPACE: string =
9
+ "NetworkSiteHierarchy";
10
+
11
+ export const NETWORK_SITE_HIERARCHY_LOCK_ERROR_MESSAGE: string =
12
+ "Could not acquire the Network Site hierarchy lock. Please try again.";
13
+
14
+ export const NETWORK_SITE_HIERARCHY_ROOT_SCOPE_ERROR_MESSAGE: string =
15
+ "Root Network Site hierarchy mutations must be scoped to a project or a closed set of row IDs.";
16
+
17
+ const LOCK_TIMEOUT_IN_MILLISECONDS: number = 30_000;
18
+ const ACQUIRE_TIMEOUT_IN_MILLISECONDS: number = 15_000;
19
+ const RETRY_INTERVAL_IN_MILLISECONDS: number = 100;
20
+
21
+ interface AcquiredMutex {
22
+ projectId: string;
23
+ mutex: SemaphoreMutex;
24
+ }
25
+
26
+ /*
27
+ * NetworkSite and NetworkSiteType jointly define one invariant: concrete
28
+ * parent-site edges must agree with the configured parent-type graph. Their
29
+ * service hooks validate that invariant before DatabaseService persists the
30
+ * write, so two concurrent requests must not validate the same old snapshot.
31
+ *
32
+ * This distributed, project-keyed critical section is intentionally owned by
33
+ * the public service methods rather than a before hook. DatabaseService can
34
+ * still fail after a before hook returns; a redis-semaphore mutex acquired in
35
+ * the hook would then never reach a success hook and would keep refreshing
36
+ * forever. runExclusive's finally releases every mutex on every write path.
37
+ */
38
+ export default class NetworkSiteHierarchyLock {
39
+ public static getExplicitProjectIds(
40
+ query: Record<string, unknown>,
41
+ ): Array<ObjectID | string> {
42
+ for (const key of ["projectId", "project"]) {
43
+ const value: unknown = query[key];
44
+
45
+ if (this.isExactId(value)) {
46
+ return [value];
47
+ }
48
+ }
49
+
50
+ return [];
51
+ }
52
+
53
+ /*
54
+ * Resolving an arbitrary root query and locking the projects it happens to
55
+ * match is not safe: another create can enter that query's limit/skip window
56
+ * before DatabaseService executes it. A permission-enforced tenant scope,
57
+ * a literal project scope, and explicit ID sets are closed; no new row can
58
+ * silently introduce an unlocked project.
59
+ */
60
+ public static assertSafeRootMutationScope(data: {
61
+ query: Record<string, unknown>;
62
+ props: DatabaseCommonInteractionProps;
63
+ tenantScopeIsClosed?: boolean;
64
+ }): void {
65
+ if (this.isSafeRootMutationScope(data)) {
66
+ return;
67
+ }
68
+
69
+ throw new BadDataException(NETWORK_SITE_HIERARCHY_ROOT_SCOPE_ERROR_MESSAGE);
70
+ }
71
+
72
+ public static isSafeRootMutationScope(data: {
73
+ query: Record<string, unknown>;
74
+ props: DatabaseCommonInteractionProps;
75
+ tenantScopeIsClosed?: boolean;
76
+ }): boolean {
77
+ if (!data.props.isRoot && !data.props.isMasterAdmin) {
78
+ return true;
79
+ }
80
+
81
+ /*
82
+ * DeletePermission retains an explicit tenantId even for a root caller,
83
+ * so it is a closed project scope for deletes. UpdatePermission does not:
84
+ * a root update keeps the caller's raw query. Callers must opt in only
85
+ * when their permission path actually applies the tenant predicate.
86
+ */
87
+ if (
88
+ data.tenantScopeIsClosed &&
89
+ data.props.tenantId &&
90
+ !data.props.isMultiTenantRequest
91
+ ) {
92
+ return true;
93
+ }
94
+
95
+ const hasExactProjectScope: boolean = ["projectId", "project"].some(
96
+ (key: string): boolean => {
97
+ return this.isExactId(data.query[key]);
98
+ },
99
+ );
100
+ const hasExplicitRowIdScope: boolean = this.isExplicitIdSet(
101
+ data.query["_id"],
102
+ );
103
+
104
+ if (hasExactProjectScope || hasExplicitRowIdScope) {
105
+ return true;
106
+ }
107
+
108
+ return false;
109
+ }
110
+
111
+ /*
112
+ * QueryHelper predicates are TypeORM FindOperator objects. Even when one
113
+ * happens to be backed by a fixed value today, accepting an arbitrary raw
114
+ * predicate here would let a later row enter the pre-read/write window in
115
+ * a project for which no mutex was acquired. Only literal UUIDs are a
116
+ * stable project scope; literal row-ID arrays are a stable closed set.
117
+ */
118
+ private static isExactId(value: unknown): value is ObjectID | string {
119
+ if (value instanceof ObjectID) {
120
+ return ObjectID.isValidUUID(value.toString());
121
+ }
122
+
123
+ return typeof value === "string" && ObjectID.isValidUUID(value.trim());
124
+ }
125
+
126
+ private static isExplicitIdSet(value: unknown): boolean {
127
+ if (this.isExactId(value)) {
128
+ return true;
129
+ }
130
+
131
+ return (
132
+ Array.isArray(value) &&
133
+ value.every((candidate: unknown): boolean => {
134
+ return this.isExactId(candidate);
135
+ })
136
+ );
137
+ }
138
+
139
+ public static async runExclusive<TResult>(data: {
140
+ projectIds: Array<ObjectID | string>;
141
+ operation: () => Promise<TResult>;
142
+ }): Promise<TResult> {
143
+ const projectIds: Array<string> = [
144
+ ...new Set<string>(
145
+ data.projectIds
146
+ .map((projectId: ObjectID | string): string => {
147
+ return projectId.toString().trim().toLowerCase();
148
+ })
149
+ .filter((projectId: string): boolean => {
150
+ return Boolean(projectId);
151
+ }),
152
+ ),
153
+ ].sort((left: string, right: string): number => {
154
+ return left.localeCompare(right);
155
+ });
156
+
157
+ /*
158
+ * A mutation that matched no rows has no project whose hierarchy it can
159
+ * change. Let DatabaseService preserve its normal zero-row/permission
160
+ * semantics without taking an unrelated global lock.
161
+ */
162
+ if (projectIds.length === 0) {
163
+ return await data.operation();
164
+ }
165
+
166
+ const acquiredMutexes: Array<AcquiredMutex> = [];
167
+
168
+ try {
169
+ for (const projectId of projectIds) {
170
+ const mutex: SemaphoreMutex = await Semaphore.lock({
171
+ key: projectId,
172
+ namespace: NETWORK_SITE_HIERARCHY_LOCK_NAMESPACE,
173
+ lockTimeout: LOCK_TIMEOUT_IN_MILLISECONDS,
174
+ acquireTimeout: ACQUIRE_TIMEOUT_IN_MILLISECONDS,
175
+ retryInterval: RETRY_INTERVAL_IN_MILLISECONDS,
176
+ });
177
+
178
+ acquiredMutexes.push({ projectId, mutex });
179
+ }
180
+ } catch (error) {
181
+ await this.releaseAll(acquiredMutexes);
182
+ logger.error(error);
183
+ throw new ServerException(NETWORK_SITE_HIERARCHY_LOCK_ERROR_MESSAGE);
184
+ }
185
+
186
+ try {
187
+ return await data.operation();
188
+ } finally {
189
+ await this.releaseAll(acquiredMutexes);
190
+ }
191
+ }
192
+
193
+ /*
194
+ * Release in reverse acquisition order. This mirrors ordinary lock-stack
195
+ * discipline and, together with sorted acquisition, prevents bulk writes
196
+ * spanning the same projects from deadlocking each other.
197
+ *
198
+ * Semaphore.release stops the mutex refresh timer before talking to Redis.
199
+ * A Redis failure is therefore logged but must not replace the mutation's
200
+ * real result/error; the lock key will expire at lockTimeout.
201
+ */
202
+ private static async releaseAll(
203
+ acquiredMutexes: Array<AcquiredMutex>,
204
+ ): Promise<void> {
205
+ for (const acquired of [...acquiredMutexes].reverse()) {
206
+ try {
207
+ await Semaphore.release(acquired.mutex);
208
+ } catch (error) {
209
+ logger.error(error, { projectId: acquired.projectId });
210
+ }
211
+ }
212
+ }
213
+ }