@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
@@ -1,4 +1,5 @@
1
1
  import NetworkTopology, {
2
+ NetworkTopologyDeviceRole,
2
3
  NetworkTopologyEdge,
3
4
  NetworkTopologyEdgeEndpoint,
4
5
  NetworkTopologyLinkProtocol,
@@ -13,6 +14,13 @@ import {
13
14
  classifyEndpointRole,
14
15
  resolveDeviceRole,
15
16
  } from "./NetworkDeviceRoleUtil";
17
+ import {
18
+ TopologyDeviceRoleInput,
19
+ applyRoleStamp,
20
+ buildDeviceRoleIndex,
21
+ roleKeyForNode,
22
+ stampForRoleKey,
23
+ } from "./NetworkDeviceRoleCatalog";
16
24
  import DeviceReachabilityUtil, {
17
25
  NetworkDeviceReachability,
18
26
  } from "../NetworkDevice/DeviceReachabilityUtil";
@@ -34,6 +42,21 @@ export interface TopologyDeviceInput {
34
42
  lastPolledAt?: Date | undefined;
35
43
  lastSeenAt?: Date | undefined;
36
44
  pollingIntervalInMinutes?: number | undefined;
45
+ /*
46
+ * How this device's health is established. NULL, empty and anything
47
+ * unrecognised read as Probe — see NetworkDeviceMonitoringMethodUtil.parse,
48
+ * which is why an omitted value keeps every existing caller on the poll
49
+ * rule unchanged.
50
+ *
51
+ * Read only when `monitorStatus` below is absent, and load-bearing there:
52
+ * a monitor-backed device (monitoringMethod "Monitor") with nothing
53
+ * stamped yet is drawn "unknown", which is what the device list says
54
+ * about it too. Without this the poll columns above would decide — and on
55
+ * a device switched over from SNMP they hold the last thing a probe found
56
+ * before it stopped asking, so a months-old lastSeenAt would draw the node
57
+ * red while its row in the device list reads Pending.
58
+ */
59
+ monitoringMethod?: string | null | undefined;
37
60
  interfacesUp?: number | undefined;
38
61
  interfacesDown?: number | undefined;
39
62
  vendor?: string | undefined;
@@ -45,11 +68,18 @@ export interface TopologyDeviceInput {
45
68
  sysDescr?: string | undefined;
46
69
  sysObjectId?: string | undefined;
47
70
  /*
48
- * The operator's own answer to what this device is, when they gave one.
49
- * Outranks the classifier below, because it is the only statement about
50
- * the role that is not an inference — and on a device nothing walks it
51
- * is the ONLY statement available at all, the classifier having nothing
52
- * but a hostname to go on.
71
+ * The KEY of the role the operator assigned this device, when they
72
+ * assigned one. Outranks the classifier below, because it is the only
73
+ * statement about the role that is not an inference — and on a device
74
+ * nothing walks it is the ONLY statement available at all, the classifier
75
+ * having nothing but a hostname to go on.
76
+ *
77
+ * A key, not a name: roles are per-project rows an operator can rename, so
78
+ * the caller reads it off the assigned row (NetworkDevice.networkDeviceRole)
79
+ * rather than passing a label. It may be a key outside the built-in twelve
80
+ * — a role the project invented — in which case `role` on the node falls
81
+ * back to the classifier and the node's roleKey/roleLabel/roleShape carry
82
+ * the configured answer instead. See buildTopology's deviceRoles argument.
53
83
  */
54
84
  deviceRole?: string | undefined;
55
85
  /*
@@ -329,9 +359,19 @@ export default class NetworkTopologyUtil {
329
359
  endpoints: Array<TopologyEndpointInput> = [],
330
360
  manualLinks: Array<TopologyManualLinkInput> = [],
331
361
  suppressedNodeKeys: ReadonlySet<string> = new Set<string>(),
362
+ deviceRoles: ReadonlyArray<TopologyDeviceRoleInput> = [],
332
363
  ): TopologyBuildResult {
333
364
  const nodes: Array<NetworkTopologyNode> = [];
334
365
 
366
+ /*
367
+ * The project's configured roles, indexed by key. Passing none is a
368
+ * supported case - the nodes then carry no role stamp and every consumer
369
+ * falls back to the built-in labels, shapes and core set, which is exactly
370
+ * the map drawn before roles were configurable.
371
+ */
372
+ const roleIndex: Map<string, TopologyDeviceRoleInput> =
373
+ buildDeviceRoleIndex(deviceRoles);
374
+
335
375
  /*
336
376
  * Index managed devices by every identifier a neighbor entry could
337
377
  * reference. A key TWO devices both claim is deleted rather than
@@ -384,26 +424,47 @@ export default class NetworkTopologyUtil {
384
424
  device.id,
385
425
  device.isNeighborDiscoveryEnabled,
386
426
  );
387
- nodes.push({
388
- id: device.id,
389
- name: device.name,
390
- isManaged: true,
391
- kind: "device",
392
- role: resolveDeviceRole(device.deviceRole, {
427
+ const deviceRole: NetworkTopologyDeviceRole = resolveDeviceRole(
428
+ device.deviceRole,
429
+ {
393
430
  sysDescr: device.sysDescr,
394
431
  sysObjectId: device.sysObjectId,
395
432
  vendor: device.vendor,
396
433
  deviceModel: device.deviceModel,
397
434
  name: device.name,
398
435
  sysName: device.sysName || device.hostname,
399
- }),
436
+ },
437
+ );
438
+
439
+ const deviceNode: NetworkTopologyNode = {
440
+ id: device.id,
441
+ name: device.name,
442
+ isManaged: true,
443
+ kind: "device",
444
+ role: deviceRole,
400
445
  status: NetworkTopologyUtil.deviceStatus(device, now),
401
446
  interfacesUp: device.interfacesUp,
402
447
  interfacesDown: device.interfacesDown,
403
448
  sysName: device.sysName,
404
449
  vendor: device.vendor,
405
450
  deviceModel: device.deviceModel,
406
- });
451
+ };
452
+
453
+ /*
454
+ * The configured role, when the project has one for this key. The
455
+ * assignment is looked up ahead of the classifier's answer, so a device
456
+ * an operator gave a CUSTOM role ("PoS Terminal") is drawn as that role
457
+ * even though `role` above can only ever be one of the built-in twelve.
458
+ */
459
+ applyRoleStamp(
460
+ deviceNode,
461
+ stampForRoleKey(
462
+ roleKeyForNode(device.deviceRole, deviceRole),
463
+ roleIndex,
464
+ ),
465
+ );
466
+
467
+ nodes.push(deviceNode);
407
468
  }
408
469
 
409
470
  const edgeByKey: Map<string, NetworkTopologyEdge> = new Map();
@@ -465,7 +526,11 @@ export default class NetworkTopologyUtil {
465
526
  NetworkTopologyUtil.propagateMatchesAcrossPeerGroups(resolvedClaims);
466
527
 
467
528
  const peerNodeIdByClaim: Map<ResolvedClaim, string> =
468
- NetworkTopologyUtil.buildUnmanagedPeerNodes(settledClaims, nodes);
529
+ NetworkTopologyUtil.buildUnmanagedPeerNodes(
530
+ settledClaims,
531
+ nodes,
532
+ roleIndex,
533
+ );
469
534
 
470
535
  for (const resolved of settledClaims) {
471
536
  const device: TopologyDeviceInput = resolved.device;
@@ -780,16 +845,18 @@ export default class NetworkTopologyUtil {
780
845
  endpoint.vendor ||
781
846
  endpoint.ipAddress ||
782
847
  endpoint.macAddress;
783
- nodes.push({
848
+ const endpointRole: NetworkTopologyDeviceRole = classifyEndpointRole({
849
+ classification: endpoint.classification,
850
+ vendor: endpoint.vendor,
851
+ name: endpointName,
852
+ });
853
+
854
+ const endpointNode: NetworkTopologyNode = {
784
855
  id: nodeId,
785
856
  name: endpointName,
786
857
  isManaged: false,
787
858
  kind: "endpoint",
788
- role: classifyEndpointRole({
789
- classification: endpoint.classification,
790
- vendor: endpoint.vendor,
791
- name: endpointName,
792
- }),
859
+ role: endpointRole,
793
860
  status: NetworkTopologyUtil.statusFromLastSeen(
794
861
  endpoint.lastSeenAt,
795
862
  now,
@@ -799,7 +866,21 @@ export default class NetworkTopologyUtil {
799
866
  ipAddress: endpoint.ipAddress,
800
867
  classification: endpoint.classification,
801
868
  vlanId: endpoint.vlanId,
802
- });
869
+ };
870
+
871
+ /*
872
+ * Endpoints are stamped too, so a project that renamed "IP phone" sees
873
+ * the new name on the handsets its switches learned. It cannot change
874
+ * where they sit: the layouts put every endpoint in its switch's group
875
+ * box before they ever look at a role, so isCoreLayerRole is inert here
876
+ * by construction rather than by omission.
877
+ */
878
+ applyRoleStamp(
879
+ endpointNode,
880
+ stampForRoleKey(roleKeyForNode(undefined, endpointRole), roleIndex),
881
+ );
882
+
883
+ nodes.push(endpointNode);
803
884
 
804
885
  // Port label + interface state on the switch end, when identifiable.
805
886
  let switchInterface: TopologyInterfaceInput | undefined = undefined;
@@ -1264,6 +1345,10 @@ export default class NetworkTopologyUtil {
1264
1345
  private static buildUnmanagedPeerNodes(
1265
1346
  resolvedClaims: Array<ResolvedClaim>,
1266
1347
  nodes: Array<NetworkTopologyNode>,
1348
+ roleIndex: Map<string, TopologyDeviceRoleInput> = new Map<
1349
+ string,
1350
+ TopologyDeviceRoleInput
1351
+ >(),
1267
1352
  ): Map<ResolvedClaim, string> {
1268
1353
  const unmanagedClaims: Array<ResolvedClaim> = resolvedClaims.filter(
1269
1354
  (resolved: ResolvedClaim) => {
@@ -1359,21 +1444,22 @@ export default class NetworkTopologyUtil {
1359
1444
  usedNodeIds.add(nodeId);
1360
1445
 
1361
1446
  const unmanagedName: string = displayName || "Unknown device";
1362
- nodes.push({
1447
+ /*
1448
+ * Classified from the whole group rather than from whichever
1449
+ * report happened to be first: the platform string is usually the
1450
+ * only real evidence about a peer, and it may well arrive on the
1451
+ * second report of it.
1452
+ */
1453
+ const unmanagedRole: NetworkTopologyDeviceRole = classifyDeviceRole({
1454
+ platform: platform,
1455
+ name: unmanagedName,
1456
+ });
1457
+ const unmanagedNode: NetworkTopologyNode = {
1363
1458
  id: nodeId,
1364
1459
  name: unmanagedName,
1365
1460
  isManaged: false,
1366
1461
  kind: "unmanaged",
1367
- /*
1368
- * Classified from the whole group rather than from whichever
1369
- * report happened to be first: the platform string is usually the
1370
- * only real evidence about a peer, and it may well arrive on the
1371
- * second report of it.
1372
- */
1373
- role: classifyDeviceRole({
1374
- platform: platform,
1375
- name: unmanagedName,
1376
- }),
1462
+ role: unmanagedRole,
1377
1463
  status: "unknown",
1378
1464
  deviceModel: platform,
1379
1465
  /*
@@ -1383,7 +1469,19 @@ export default class NetworkTopologyUtil {
1383
1469
  * they can only look at.
1384
1470
  */
1385
1471
  ipAddress: ipAddress,
1386
- });
1472
+ };
1473
+
1474
+ /*
1475
+ * Stamped for the adopt-a-neighbour flow above all: isSnmpWalkableRole
1476
+ * is what decides whether adopting this peer opens on SNMP polling or on
1477
+ * a monitor, and a peer is exactly the node an operator adopts.
1478
+ */
1479
+ applyRoleStamp(
1480
+ unmanagedNode,
1481
+ stampForRoleKey(roleKeyForNode(undefined, unmanagedRole), roleIndex),
1482
+ );
1483
+
1484
+ nodes.push(unmanagedNode);
1387
1485
 
1388
1486
  for (const resolved of groupClaims) {
1389
1487
  nodeIdByClaim.set(resolved, nodeId);
@@ -1571,9 +1669,13 @@ export default class NetworkTopologyUtil {
1571
1669
 
1572
1670
  /*
1573
1671
  * The shared reachability rule (DeviceReachabilityUtil), mapped onto the
1574
- * graph's three node states. "Pending" — never polled is the graph's
1575
- * "unknown", which is what keeps a device nothing walks from being drawn
1576
- * as a failure.
1672
+ * graph's three node states. "Pending" — never polled, or monitor-backed
1673
+ * with nothing reported yet is the graph's "unknown", which is what
1674
+ * keeps a device nothing walks from being drawn as a failure.
1675
+ *
1676
+ * Only reached with no stamped status (deviceStatus took every stamped
1677
+ * one), so the monitoring method is the one fact left that tells the rule
1678
+ * whether the poll columns are evidence or leftovers.
1577
1679
  */
1578
1680
  private static statusFromPoll(
1579
1681
  device: TopologyDeviceInput,
@@ -1585,6 +1687,7 @@ export default class NetworkTopologyUtil {
1585
1687
  lastPolledAt: device.lastPolledAt,
1586
1688
  lastSeenAt: device.lastSeenAt,
1587
1689
  pollingIntervalInMinutes: device.pollingIntervalInMinutes,
1690
+ monitoringMethod: device.monitoringMethod,
1588
1691
  },
1589
1692
  now,
1590
1693
  );
@@ -1,6 +1,7 @@
1
1
  import DeviceReachabilityUtil, {
2
2
  NetworkDeviceReachability,
3
3
  } from "./DeviceReachabilityUtil";
4
+ import { NetworkDeviceMonitoringMethodUtil } from "../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
4
5
 
5
6
  /*
6
7
  * The one place that decides how healthy a single NetworkDevice is, and how
@@ -15,10 +16,12 @@ import DeviceReachabilityUtil, {
15
16
  *
16
17
  * So the rule moves here, and both halves read it:
17
18
  *
18
- * status — a monitor-stamped status wins outright; otherwise the shared
19
- * reachability rule (the OUTCOME of the last poll, never its
20
- * age) decides, and a device nothing has ever polled is
21
- * `unknown` rather than a failure.
19
+ * status — for a MONITOR-BACKED device the stamped monitor status is the
20
+ * verdict; for a probe-polled device the shared reachability
21
+ * rule (the OUTCOME of the last poll, never its age) decides and
22
+ * the stamp is informational only (see the input docs); a device
23
+ * nothing has ever polled — or a monitor-backed device nothing
24
+ * has yet reported on — is `unknown` rather than a failure.
22
25
  * degraded — an up device with dark ports. A switch that answers every
23
26
  * poll while three of its interfaces are down is not down, but
24
27
  * it is exactly what somebody is looking for.
@@ -55,9 +58,18 @@ export type NetworkDeviceHealthState =
55
58
  * The columns the classifier reads. Every caller selects exactly these.
56
59
  *
57
60
  * `monitorStatusIsOffline` is the OFFLINE end of the device's stamped
58
- * MonitorStatus row — `undefined` when no monitor backs the device (the
59
- * ordinary case for an SNMP-walked switch), which is what sends the
60
- * decision down to reachability.
61
+ * MonitorStatus row — `undefined` when nothing has stamped one, which is
62
+ * what sends the decision down to reachability.
63
+ *
64
+ * It is CONSULTED ONLY FOR A MONITOR-BACKED DEVICE (monitoringMethod
65
+ * "Monitor"). A probe-polled device can carry a stamp too — a Network
66
+ * Device monitor watching its walk writes one, and an "interface down →
67
+ * Offline" criterion will happily stamp Offline on a switch that answers
68
+ * every ping — but its health source is the poll: `isReachable` is what its
69
+ * pill, the summary tiles and the Status chip all read, and a classifier
70
+ * that let the stamp outrank it would colour the site card and the map red
71
+ * over a device whose own row reads Up. So for a probe-polled device the
72
+ * stamp stays informational and reachability decides.
61
73
  *
62
74
  * The offline end and not the operational end, because MonitorStatus is a
63
75
  * ladder rather than a pair: the seeded rows run Operational (1) ...
@@ -74,6 +86,24 @@ export interface DeviceHealthStateInput {
74
86
  lastPolledAt?: Date | string | null | undefined;
75
87
  lastSeenAt?: Date | string | null | undefined;
76
88
  pollingIntervalInMinutes?: number | null | undefined;
89
+ /*
90
+ * How this device's health is established. NULL, empty and anything
91
+ * unrecognised read as Probe — see NetworkDeviceMonitoringMethodUtil.parse,
92
+ * which is why an omitted value keeps every existing caller on the poll
93
+ * rule unchanged.
94
+ *
95
+ * Load-bearing twice. It decides whether `monitorStatusIsOffline` above is
96
+ * read at all (only for a monitor-backed device). And when a monitor-backed
97
+ * device has NO stamped status to read — nothing bound yet, or bound and
98
+ * never evaluated — the shared rule answers Pending ("unknown" here)
99
+ * rather than falling through to the poll columns, which on such a device
100
+ * are either NULL or, worse, the last thing a probe found before it
101
+ * stopped asking: a device switched from Probe to Monitor keeps its old
102
+ * lastSeenAt until the switch-over clears it, and a caller that dropped
103
+ * this field would let that months-old timestamp call the device "down" on
104
+ * the site card while its own row in the device list reads Pending.
105
+ */
106
+ monitoringMethod?: string | null | undefined;
77
107
  interfacesDown?: number | null | undefined;
78
108
  }
79
109
 
@@ -96,11 +126,13 @@ export interface DeviceHealthCounts {
96
126
  /**
97
127
  * The state of one device.
98
128
  *
99
- * Order is load-bearing. A stamped monitor status is the operator's own
100
- * system of record and beats everything; then hard-down beats everything
101
- * else, because a device that does not answer has interface counts that
102
- * are by definition stale; then and only for a device known to be up —
103
- * dark ports make it degraded.
129
+ * Order is load-bearing. On a monitor-backed device the stamped monitor
130
+ * status is the operator's own system of record and beats everything; on a
131
+ * probe-polled one the poll's outcome does (the stamp is informational
132
+ * see the input docs); then hard-down beats everything else, because a
133
+ * device that does not answer has interface counts that are by definition
134
+ * stale; then — and only for a device known to be up — dark ports make it
135
+ * degraded.
104
136
  *
105
137
  * Note what this means for a device stamped "Degraded": the ladder does not
106
138
  * call it offline, so it is up, and it lands in "degraded" only if it also
@@ -119,9 +151,19 @@ export function deviceHealthState(
119
151
 
120
152
  let isUp: boolean;
121
153
 
154
+ /*
155
+ * The stamp is read for a monitor-backed device and nothing else. The
156
+ * shared reachability rule below applies the same gate, so the two
157
+ * branches cannot be reached with different ideas of what kind of device
158
+ * this is.
159
+ */
160
+ const isMonitorBacked: boolean =
161
+ NetworkDeviceMonitoringMethodUtil.isMonitorBacked(device.monitoringMethod);
162
+
122
163
  if (
123
- device.monitorStatusIsOffline === true ||
124
- device.monitorStatusIsOffline === false
164
+ isMonitorBacked &&
165
+ (device.monitorStatusIsOffline === true ||
166
+ device.monitorStatusIsOffline === false)
125
167
  ) {
126
168
  // Anything the ladder does not call OFFLINE is up. See the input docs.
127
169
  isUp = !device.monitorStatusIsOffline;
@@ -133,6 +175,15 @@ export function deviceHealthState(
133
175
  lastPolledAt: device.lastPolledAt,
134
176
  lastSeenAt: device.lastSeenAt,
135
177
  pollingIntervalInMinutes: device.pollingIntervalInMinutes,
178
+ /*
179
+ * Carried so the shared rule knows whether the poll columns above
180
+ * mean anything. A monitor-backed device only reaches this branch
181
+ * with NO stamped status (the one above took every stamped one),
182
+ * so for it this is exactly the "Pending" case — see the input
183
+ * docs. A probe-polled device always reaches it, stamp or no
184
+ * stamp, and is judged by its poll.
185
+ */
186
+ monitoringMethod: device.monitoringMethod,
136
187
  },
137
188
  now,
138
189
  );
@@ -1,5 +1,6 @@
1
1
  import OneUptimeDate from "../../Types/Date";
2
2
  import { NetworkDeviceMonitoringMethodUtil } from "../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
3
+ import ObjectID from "../../Types/ObjectID";
3
4
 
4
5
  /*
5
6
  * The one place that decides whether a NetworkDevice is reachable.
@@ -21,13 +22,15 @@ import { NetworkDeviceMonitoringMethodUtil } from "../../Types/NetworkDevice/Net
21
22
  * window.
22
23
  *
23
24
  * So reachability is now the OUTCOME of the most recent poll —
24
- * NetworkDevice.isReachable, stamped by the walk pipeline on every ingested
25
- * walk and freshness is only a backstop for "the polling pipeline itself
26
- * stopped", measured generously against the device's own interval.
25
+ * NetworkDevice.isReachable, stamped by the poll pipeline on every ingested
26
+ * poll (a ping, plus the SNMP walk on a device that has credentials; the
27
+ * device is reachable when either answers) and freshness is only a
28
+ * backstop for "the polling pipeline itself stopped", measured generously
29
+ * against the device's own interval.
27
30
  *
28
31
  * All of which is about a device that gets POLLED. A monitor-backed device
29
- * (monitoringMethod "Monitor") is never polled at all: no probe, no
30
- * credentials, no walk. Every poll column on such a row is NULL forever, so
32
+ * (monitoringMethod "Monitor") is never polled at all: no probe, no ping,
33
+ * no walk. Every poll column on such a row is NULL forever, so
31
34
  * the rule above can only ever answer "Pending" for it — which is
32
35
  * OneUptime/oneuptime#3392, a correctly bound ping-only device stuck on
33
36
  * Pending. Its health comes from the Monitor bound to it, stamped onto
@@ -69,12 +72,13 @@ export const DEVICE_MIN_STALE_WINDOW_IN_MINUTES: number = 60;
69
72
  // The columns this util reads. Every caller selects exactly these.
70
73
  export interface DeviceReachabilityInput {
71
74
  /*
72
- * Outcome of the most recent poll: true = the device answered, false = the
73
- * probe could not reach it, null/undefined = never polled, or a row
74
- * written before this column existed.
75
+ * Outcome of the most recent poll: true = the device answered (ping, or
76
+ * the SNMP walk either is enough), false = the probe could not reach it
77
+ * by any means, null/undefined = never polled, or a row written before
78
+ * this column existed.
75
79
  */
76
80
  isReachable?: boolean | null | undefined;
77
- // When the probe last ATTEMPTED a walk, whatever the outcome.
81
+ // When the probe last ATTEMPTED a poll, whatever the outcome.
78
82
  lastPolledAt?: Date | string | null | undefined;
79
83
  // When the device last ANSWERED one.
80
84
  lastSeenAt?: Date | string | null | undefined;
@@ -82,7 +86,7 @@ export interface DeviceReachabilityInput {
82
86
  pollingIntervalInMinutes?: number | null | undefined;
83
87
  /*
84
88
  * How this device's health is established. NULL, empty and anything
85
- * unrecognised read as SNMP — see NetworkDeviceMonitoringMethodUtil.parse,
89
+ * unrecognised read as Probe — see NetworkDeviceMonitoringMethodUtil.parse,
86
90
  * which is why an omitted value keeps every existing caller on the poll
87
91
  * rule unchanged.
88
92
  */
@@ -102,6 +106,31 @@ export interface DeviceReachabilityInput {
102
106
  * way for the same reason.
103
107
  */
104
108
  monitorStatusIsOffline?: boolean | null | undefined;
109
+
110
+ /*
111
+ * QUALIFIER inputs. None of the four below moves the Up / Down / Pending
112
+ * verdict — the rule above is deliberately decided by `isReachable` alone,
113
+ * so the pill, the summary tiles and the Status chip (all SQL over that one
114
+ * column) can never disagree. They ride on the same input so a surface can
115
+ * hand its whole row over once and put the second, explanatory pill
116
+ * ("SNMP failing", "No probe") beside the verdict; see the predicates in
117
+ * the dashboard's DeviceStatusUtil.
118
+ *
119
+ * `isSnmpReachable`: the outcome of the last SNMP WALK, separate from the
120
+ * ping — false is a device that answers ping but not SNMP (credentials, or
121
+ * SNMP disabled on the box), NULL is "no walk was attempted": no usable
122
+ * credentials, or never polled.
123
+ */
124
+ isSnmpReachable?: boolean | null | undefined;
125
+ // When the last SUCCESSFUL walk completed; only moves on a success.
126
+ lastSnmpSeenAt?: Date | string | null | undefined;
127
+ /*
128
+ * Which probe polls the device, and whether it is allowed to. A probe-polled
129
+ * device with no probe, or with polling switched off, can never be polled
130
+ * and is Pending for as long as that stays true.
131
+ */
132
+ probeId?: ObjectID | string | null | undefined;
133
+ isPollingEnabled?: boolean | null | undefined;
105
134
  }
106
135
 
107
136
  export interface DeviceReachabilityResult {
@@ -119,10 +148,10 @@ export interface DeviceReachabilityResult {
119
148
  // Latest of lastPolledAt / lastSeenAt; null when neither is set.
120
149
  lastContactAt: Date | null;
121
150
  /*
122
- * True when this verdict came from the bound Monitor rather than from an
123
- * SNMP poll. Carried so a surface can word its pill and its tooltip for
124
- * what actually decided the answer — "the last SNMP poll reached this
125
- * device" is a lie on a device nothing polls.
151
+ * True when this verdict came from the bound Monitor rather than from a
152
+ * probe's poll. Carried so a surface can word its pill and its tooltip for
153
+ * what actually decided the answer — "the last poll reached this device"
154
+ * is a lie on a device nothing polls.
126
155
  */
127
156
  isMonitorBacked: boolean;
128
157
  }
@@ -0,0 +1,137 @@
1
+ /*
2
+ * Turns a device role's NAME into its stable KEY.
3
+ *
4
+ * Device roles are per-project rows an operator can rename at will, which is
5
+ * exactly why nothing may identify one by its name. The key is what does the
6
+ * identifying: it is what the SNMP classifier's answer is matched against,
7
+ * what a topology payload carries, and what survives the role being renamed.
8
+ *
9
+ * The shape is lowerCamelCase, because the eleven built-in roles seeded into
10
+ * every project already use it ("wirelessAccessPoint", "loadBalancer") and a
11
+ * key derived from the name "Wireless AP" must be able to look like one of
12
+ * them. Anything that is not a letter or a digit is a word boundary, so
13
+ * "PoS Terminal", "pos-terminal" and "POS terminal!" all derive "posTerminal"
14
+ * - near-duplicates collapse rather than multiplying.
15
+ *
16
+ * Pure and dependency-free: the service derives keys with it on the server and
17
+ * the tests exercise it directly.
18
+ */
19
+
20
+ // Keys are stored in a ShortText column; nothing sensible is this long.
21
+ const MAX_KEY_LENGTH: number = 100;
22
+
23
+ /*
24
+ * A name of nothing but punctuation ("---") has no letters to build a key
25
+ * from. Rather than returning an empty string - which would fail the column's
26
+ * NOT NULL and surface as a database error - it falls back to this, and the
27
+ * caller's uniqueness suffixing turns the second one into "role2".
28
+ */
29
+ export const FALLBACK_DEVICE_ROLE_KEY: string = "role";
30
+
31
+ export type DeriveDeviceRoleKeyFunction = (name: string) => string;
32
+
33
+ /**
34
+ * The key for a role named `name`. Deterministic and case-insensitive over
35
+ * word separators: it is safe to call twice and get the same answer.
36
+ */
37
+ export const deriveDeviceRoleKey: DeriveDeviceRoleKeyFunction = (
38
+ name: string,
39
+ ): string => {
40
+ const words: Array<string> = (name || "")
41
+ .split(/[^a-zA-Z0-9]+/)
42
+ .filter((word: string) => {
43
+ return word.length > 0;
44
+ });
45
+
46
+ if (words.length === 0) {
47
+ return FALLBACK_DEVICE_ROLE_KEY;
48
+ }
49
+
50
+ /*
51
+ * A ONE-WORD name is only re-cased at its first letter. A MULTI-word name
52
+ * has its first word lowercased whole, and every later word capitalised at
53
+ * the front with its interior left alone.
54
+ *
55
+ * Both halves are load-bearing, and for different reasons.
56
+ *
57
+ * Lowercasing the head of a multi-word name is what makes the key readable.
58
+ * Re-casing only its first letter turns "PoS Terminal" into "poSTerminal"
59
+ * and "IP phone" into "iPPhone", and this key is a column an operator reads
60
+ * on the settings page. Later words keep their interior for the opposite
61
+ * reason: "Wireless AP" should read as "wirelessAP" and "SD-WAN Edge" as
62
+ * "sdWANEdge", because those acronyms are the boundaries a reader navigates
63
+ * by.
64
+ *
65
+ * Leaving a one-word name alone is what makes every derived key a FIXED
66
+ * POINT of this function. A derived key is always a single run of letters
67
+ * and digits, so re-deriving it takes this branch and returns it unchanged -
68
+ * "wirelessAccessPoint" stays "wirelessAccessPoint", and a key that is
69
+ * accidentally fed back in as a name cannot silently move a role's identity.
70
+ * It is also honest: a name with no word boundaries has no boundaries to
71
+ * normalise.
72
+ */
73
+ const key: string =
74
+ words.length === 1
75
+ ? words[0]!.charAt(0).toLowerCase() + words[0]!.slice(1)
76
+ : words
77
+ .map((word: string, index: number): string => {
78
+ if (index === 0) {
79
+ return word.toLowerCase();
80
+ }
81
+ return word.charAt(0).toUpperCase() + word.slice(1);
82
+ })
83
+ .join("");
84
+
85
+ /*
86
+ * A key starting with a digit ("5gRouter") is still a fine identifier here -
87
+ * it is a lookup key, not a JavaScript name - so only the length is capped.
88
+ */
89
+ return key.slice(0, MAX_KEY_LENGTH);
90
+ };
91
+
92
+ export type BuildUniqueDeviceRoleKeyFunction = (
93
+ name: string,
94
+ takenKeys: ReadonlySet<string>,
95
+ ) => string;
96
+
97
+ /**
98
+ * The key for a role named `name` that no other role in the project holds.
99
+ *
100
+ * Two differently-named roles can derive the same key ("PoS Terminal" and
101
+ * "pos_terminal" both give "posTerminal"), and the column is unique per
102
+ * project, so the second one has to move. It gets a numeric suffix rather than
103
+ * a random one so the result stays readable and stable for a given project
104
+ * state - "posTerminal2", not "posTerminal-f3a9".
105
+ *
106
+ * Comparison is case-insensitive because that is how the key is matched when
107
+ * a role is looked up; two keys differing only in case would collide there.
108
+ */
109
+ export const buildUniqueDeviceRoleKey: BuildUniqueDeviceRoleKeyFunction = (
110
+ name: string,
111
+ takenKeys: ReadonlySet<string>,
112
+ ): string => {
113
+ const taken: Set<string> = new Set<string>();
114
+ for (const key of takenKeys) {
115
+ taken.add(key.trim().toLowerCase());
116
+ }
117
+
118
+ const base: string = deriveDeviceRoleKey(name);
119
+
120
+ if (!taken.has(base.toLowerCase())) {
121
+ return base;
122
+ }
123
+
124
+ /*
125
+ * Bounded so a pathological project cannot spin here. Past the bound the
126
+ * caller gets the base key back and the database's unique constraint
127
+ * rejects the create - a loud, correct failure rather than a hang.
128
+ */
129
+ for (let suffix: number = 2; suffix < 1000; suffix++) {
130
+ const candidate: string = `${base}${suffix}`;
131
+ if (!taken.has(candidate.toLowerCase())) {
132
+ return candidate;
133
+ }
134
+ }
135
+
136
+ return base;
137
+ };