@oneuptime/common 12.0.30 → 12.0.32

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 (645) hide show
  1. package/Models/AnalyticsModels/SecurityEvent.ts +48 -16
  2. package/Models/AnalyticsModels/ThreatIntelIndicator.ts +10 -5
  3. package/Models/DatabaseModels/AlertSeverity.ts +44 -0
  4. package/Models/DatabaseModels/AlertState.ts +0 -2
  5. package/Models/DatabaseModels/DetectionRule.ts +16 -5
  6. package/Models/DatabaseModels/Domain.ts +1 -1
  7. package/Models/DatabaseModels/GoogleSecOpsConnection.ts +14 -5
  8. package/Models/DatabaseModels/Incident.ts +1 -1
  9. package/Models/DatabaseModels/IncidentSeverity.ts +44 -0
  10. package/Models/DatabaseModels/IncidentTemplate.ts +1 -1
  11. package/Models/DatabaseModels/Index.ts +4 -0
  12. package/Models/DatabaseModels/MetricType.ts +0 -2
  13. package/Models/DatabaseModels/MonitorStatusTimeline.ts +0 -2
  14. package/Models/DatabaseModels/MonitorTest.ts +0 -2
  15. package/Models/DatabaseModels/NetworkDevice.ts +234 -5
  16. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +88 -0
  17. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +22 -0
  18. package/Models/DatabaseModels/NetworkDeviceOidTemplate.ts +501 -0
  19. package/Models/DatabaseModels/NetworkDeviceRole.ts +648 -0
  20. package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -1
  21. package/Models/DatabaseModels/ScheduledMaintenanceTemplate.ts +1 -1
  22. package/Models/DatabaseModels/StatusPageAnnouncement.ts +0 -2
  23. package/Models/DatabaseModels/StatusPageAnnouncementTemplate.ts +0 -2
  24. package/Models/DatabaseModels/StatusPagePrivateUser.ts +0 -2
  25. package/Models/DatabaseModels/StatusPageResource.ts +0 -2
  26. package/Models/DatabaseModels/StatusPageSubscriber.ts +0 -2
  27. package/Models/DatabaseModels/ThreatIntelFeed.ts +16 -5
  28. package/Server/API/GlobalConfigAPI.ts +362 -183
  29. package/Server/API/TelemetryAPI.ts +42 -4
  30. package/Server/EnvironmentConfig.ts +112 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.ts +59 -0
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.ts +25 -0
  33. package/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.ts +72 -0
  34. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  35. package/Server/Middleware/MultipartFormData.ts +118 -32
  36. package/Server/Services/AlertEpisodeLabelRuleEngineService.ts +9 -1
  37. package/Server/Services/AlertEpisodeOnCallRuleEngineService.ts +9 -1
  38. package/Server/Services/AlertEpisodeOwnerRuleEngineService.ts +9 -1
  39. package/Server/Services/AlertEpisodePrivacyRuleEngineService.ts +9 -1
  40. package/Server/Services/AlertGroupingEngineService.ts +9 -1
  41. package/Server/Services/AlertLabelRuleEngineService.ts +9 -1
  42. package/Server/Services/AlertOnCallRuleEngineService.ts +9 -1
  43. package/Server/Services/AlertOwnerRuleEngineService.ts +9 -1
  44. package/Server/Services/AlertPrivacyRuleEngineService.ts +9 -1
  45. package/Server/Services/AlertReminderRuleService.ts +9 -1
  46. package/Server/Services/AutoRemediationRuleEngineService.ts +9 -1
  47. package/Server/Services/CephClusterLabelRuleEngineService.ts +9 -1
  48. package/Server/Services/CephClusterOwnerRuleEngineService.ts +9 -1
  49. package/Server/Services/CloudResourceLabelRuleEngineService.ts +9 -1
  50. package/Server/Services/CloudResourceOwnerRuleEngineService.ts +9 -1
  51. package/Server/Services/DashboardLabelRuleEngineService.ts +9 -1
  52. package/Server/Services/DashboardOwnerRuleEngineService.ts +9 -1
  53. package/Server/Services/DatabaseService.ts +39 -9
  54. package/Server/Services/DockerHostLabelRuleEngineService.ts +9 -1
  55. package/Server/Services/DockerHostOwnerRuleEngineService.ts +9 -1
  56. package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +9 -1
  57. package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +9 -1
  58. package/Server/Services/HostLabelRuleEngineService.ts +9 -1
  59. package/Server/Services/HostOwnerRuleEngineService.ts +9 -1
  60. package/Server/Services/IncidentEpisodeLabelRuleEngineService.ts +9 -1
  61. package/Server/Services/IncidentEpisodeOnCallRuleEngineService.ts +9 -1
  62. package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +9 -1
  63. package/Server/Services/IncidentEpisodePrivacyRuleEngineService.ts +9 -1
  64. package/Server/Services/IncidentGroupingEngineService.ts +9 -1
  65. package/Server/Services/IncidentLabelRuleEngineService.ts +9 -1
  66. package/Server/Services/IncidentOnCallRuleEngineService.ts +9 -1
  67. package/Server/Services/IncidentOwnerRuleEngineService.ts +9 -1
  68. package/Server/Services/IncidentPrivacyRuleEngineService.ts +9 -1
  69. package/Server/Services/IncidentReminderRuleService.ts +9 -1
  70. package/Server/Services/IncidentSlaRuleService.ts +9 -1
  71. package/Server/Services/IncomingCallPolicyLabelRuleEngineService.ts +9 -1
  72. package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +9 -1
  73. package/Server/Services/Index.ts +4 -0
  74. package/Server/Services/IoTFleetLabelRuleEngineService.ts +9 -1
  75. package/Server/Services/IoTFleetOwnerRuleEngineService.ts +9 -1
  76. package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +9 -1
  77. package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +9 -1
  78. package/Server/Services/KubernetesResourceService.ts +5 -1
  79. package/Server/Services/MonitorLabelRuleEngineService.ts +9 -1
  80. package/Server/Services/MonitorOwnerRuleEngineService.ts +9 -1
  81. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +35 -0
  82. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +96 -0
  83. package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +9 -1
  84. package/Server/Services/NetworkDeviceOidTemplateService.ts +201 -0
  85. package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +9 -1
  86. package/Server/Services/NetworkDeviceRoleService.ts +90 -0
  87. package/Server/Services/NetworkDeviceService.ts +209 -1
  88. package/Server/Services/OnCallDutyPolicyLabelRuleEngineService.ts +9 -1
  89. package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +9 -1
  90. package/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.ts +9 -1
  91. package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +9 -1
  92. package/Server/Services/PodmanHostLabelRuleEngineService.ts +9 -1
  93. package/Server/Services/PodmanHostOwnerRuleEngineService.ts +9 -1
  94. package/Server/Services/ProjectService.ts +85 -0
  95. package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +9 -1
  96. package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +9 -1
  97. package/Server/Services/RumApplicationLabelRuleEngineService.ts +9 -1
  98. package/Server/Services/RumApplicationOwnerRuleEngineService.ts +9 -1
  99. package/Server/Services/RunbookLabelRuleEngineService.ts +9 -1
  100. package/Server/Services/RunbookOwnerRuleEngineService.ts +9 -1
  101. package/Server/Services/RunbookRuleEngineService.ts +9 -1
  102. package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +9 -1
  103. package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +9 -1
  104. package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +9 -1
  105. package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +9 -1
  106. package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +9 -1
  107. package/Server/Services/ServiceLabelRuleEngineService.ts +9 -1
  108. package/Server/Services/ServiceOwnerRuleEngineService.ts +9 -1
  109. package/Server/Services/StatusPageLabelRuleEngineService.ts +9 -1
  110. package/Server/Services/StatusPageMonitorRuleEngineService.ts +7 -0
  111. package/Server/Services/StatusPageOwnerRuleEngineService.ts +9 -1
  112. package/Server/Services/TelemetrySourceMapService.ts +266 -23
  113. package/Server/Services/UserNotificationSettingService.ts +0 -6
  114. package/Server/Services/UserService.ts +27 -0
  115. package/Server/Services/WorkflowLabelRuleEngineService.ts +9 -1
  116. package/Server/Services/WorkflowOwnerRuleEngineService.ts +9 -1
  117. package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +186 -0
  118. package/Server/Utils/Monitor/CapturedMetricAttributeUtil.ts +245 -0
  119. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +21 -2
  120. package/Server/Utils/Monitor/MonitorMetricUtil.ts +55 -21
  121. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +32 -0
  122. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +15 -2
  123. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +18 -1
  124. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +10 -0
  125. package/Server/Utils/Monitor/SeriesResourceLabels.ts +34 -0
  126. package/Server/Utils/Rules/RuleEngineRuleRead.ts +48 -0
  127. package/Server/Utils/Telemetry/ExceptionSanitizer.ts +14 -1
  128. package/Server/Utils/Telemetry/LogExceptionExtractor.ts +14 -2
  129. package/Server/Utils/Telemetry/SourceMapResolver.ts +16 -5
  130. package/Server/Utils/Telemetry/StackTraceParser.ts +399 -0
  131. package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +31 -1
  132. package/Tests/App/Dashboard/DashboardChartWidgetZoom.test.tsx +35 -8
  133. package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +107 -3
  134. package/Tests/App/Dashboard/DashboardWideChartZoom.test.tsx +401 -0
  135. package/Tests/App/Dashboard/EventOverlayHook.test.tsx +125 -0
  136. package/Tests/App/Dashboard/HeaderImageAssets.test.tsx +93 -0
  137. package/Tests/App/Dashboard/MonitorTemplateColumnAndFacet.test.tsx +318 -0
  138. package/Tests/App/Dashboard/NetworkDeviceBulkDelete.test.tsx +357 -0
  139. package/Tests/App/Dashboard/NetworkSideMenu.test.tsx +590 -0
  140. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +3 -3
  141. package/Tests/App/Dashboard/SideMenuHarness.tsx +11 -3
  142. package/Tests/App/Dashboard/UserElementEmail.test.tsx +12 -4
  143. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +1 -1
  144. package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +14 -0
  145. package/Tests/Models/DatabaseModels/ModelRegistryInvariants.test.ts +543 -0
  146. package/Tests/Models/SecurityDomainAccessControl.test.ts +429 -0
  147. package/Tests/Server/API/GlobalConfigLicense.test.ts +657 -0
  148. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +84 -6
  149. package/Tests/Server/API/TelemetryResolveStackTraceAPI.test.ts +805 -0
  150. package/Tests/Server/Infrastructure/Postgres/AddOnCallCalendarFeedsMigration.test.ts +32 -7
  151. package/Tests/Server/Infrastructure/Postgres/NetworkDeviceRoleTableMigration.test.ts +476 -0
  152. package/Tests/Server/Middleware/IdentityRateLimit.test.ts +1144 -0
  153. package/Tests/Server/Middleware/MultipartFormData.test.ts +618 -3
  154. package/Tests/Server/Services/DatabaseServiceGenerateSlug.test.ts +215 -0
  155. package/Tests/Server/Services/MonitorLabelRuleEngineScale.test.ts +520 -0
  156. package/Tests/Server/Services/NetworkDeviceOidTemplateService.test.ts +332 -0
  157. package/Tests/Server/Services/NetworkDeviceOidTemplateWriteGuards.test.ts +409 -0
  158. package/Tests/Server/Services/NetworkDeviceRoleModel.test.ts +672 -0
  159. package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +1 -1
  160. package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +67 -4
  161. package/Tests/Server/Services/RuleEngineRuleFetchLimit.test.ts +239 -0
  162. package/Tests/Server/Services/ScheduledMaintenanceSubscriberEndTime.test.ts +369 -0
  163. package/Tests/Server/Services/TelemetrySourceMapService.test.ts +1210 -2
  164. package/Tests/Server/Services/UserNotificationSettingMonitorDefaults.test.ts +248 -0
  165. package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +43 -2
  166. package/Tests/Server/Services/UserServiceSeatLimit.test.ts +182 -0
  167. package/Tests/Server/Types/AnalyticsDatabase/SecurityEventModelPermission.test.ts +255 -0
  168. package/Tests/Server/Types/Database/Permissions/ReadBlockPermission.test.ts +212 -0
  169. package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +413 -0
  170. package/Tests/Server/Utils/BasicCron.test.ts +283 -0
  171. package/Tests/Server/Utils/CodeRepository.test.ts +689 -0
  172. package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +495 -0
  173. package/Tests/Server/Utils/ExceptionSanitizer.test.ts +77 -0
  174. package/Tests/Server/Utils/IncomingCallPhoneNumber.test.ts +174 -0
  175. package/Tests/Server/Utils/Monitor/CapturedMetricAttributeUtil.test.ts +284 -0
  176. package/Tests/Server/Utils/Monitor/MonitorCustomMetricAttributes.test.ts +503 -0
  177. package/Tests/Server/Utils/Monitor/MonitorTemplatePrototypePollution.test.ts +106 -0
  178. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkLogWritePath.test.ts +33 -4
  179. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +14 -4
  180. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +44 -0
  181. package/Tests/Server/Utils/OpenAPISpec.test.ts +536 -0
  182. package/Tests/Server/Utils/Rules/RuleEngineRuleRead.test.ts +115 -0
  183. package/Tests/Server/Utils/StackTraceParser.test.ts +610 -0
  184. package/Tests/Server/Utils/Telemetry/LogExceptionExtractor.test.ts +0 -0
  185. package/Tests/Server/Utils/Telemetry/SourceMapLimits.test.ts +656 -0
  186. package/Tests/Server/Utils/Telemetry/SourceMapResolver.test.ts +100 -0
  187. package/Tests/Types/Monitor/SnmpMonitor/SnmpOidListUtil.test.ts +454 -0
  188. package/Tests/Types/NetworkDevice/DefaultNetworkDeviceRole.test.ts +417 -0
  189. package/Tests/Types/SecurityRolePermissions.test.ts +193 -0
  190. package/Tests/UI/Components/Charts/AnnotationLayout.test.ts +773 -0
  191. package/Tests/UI/Components/Charts/ChartAnnotationRail.test.tsx +789 -0
  192. package/Tests/UI/Components/Charts/ChartBucketIdentity.test.ts +254 -0
  193. package/Tests/UI/Components/Charts/ChartClickDoubleClickDisambiguation.test.tsx +221 -0
  194. package/Tests/UI/Components/Charts/ChartDoubleClickReset.test.tsx +220 -0
  195. package/Tests/UI/Components/Charts/TimeAnnotation.test.ts +471 -0
  196. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +405 -0
  197. package/Tests/UI/Components/ErrorMessageRefreshControl.test.tsx +83 -0
  198. package/Tests/UI/Components/MarkdownConverters.test.ts +686 -0
  199. package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +751 -0
  200. package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +475 -43
  201. package/Tests/UI/Components/ModelTable/BaseModelTableDeleteAndEmptyStates.test.tsx +341 -0
  202. package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +89 -0
  203. package/Tests/UI/Components/NavBarCommandKGating.test.tsx +103 -8
  204. package/Tests/UI/Components/OrderedStatesList.test.tsx +5 -5
  205. package/Tests/UI/Components/PendingProjectInvitations.test.tsx +1 -1
  206. package/Tests/UI/Components/SideMenuItem.test.tsx +30 -0
  207. package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +195 -0
  208. package/Tests/UI/Components/XAxis.test.ts +270 -5
  209. package/Tests/UI/Components/XAxisDaylightSaving.test.ts +113 -0
  210. package/Tests/UI/Styles/ChartFocusRing.test.ts +153 -0
  211. package/Tests/UI/Styles/ChartFocusRingCoverage.test.tsx +377 -0
  212. package/Tests/UI/Styles/ThemeStylesheet.ts +162 -0
  213. package/Tests/UI/Utils/TableColumnsToCsv.test.ts +30 -0
  214. package/Tests/UI/Utils/UseDashboardTimeRangeZoom.test.tsx +187 -0
  215. package/Tests/Utils/Dashboard/DashboardResourceListSharedArgs.test.ts +302 -0
  216. package/Tests/Utils/Dashboard/DashboardTimeRangeZoom.test.ts +242 -0
  217. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +507 -0
  218. package/Tests/Utils/Monitor/NetworkDeviceRoleCatalog.test.ts +981 -0
  219. package/Tests/Utils/Monitor/NetworkTopologyRoleCatalog.test.ts +865 -0
  220. package/Tests/Utils/NetworkDevice/DeviceRoleKeyUtil.test.ts +538 -0
  221. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +951 -1
  222. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +238 -0
  223. package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +1056 -0
  224. package/Tests/Utils/NetworkDiscovery/ReverseDnsNameUtil.test.ts +882 -0
  225. package/Tests/Utils/Slo/SloEvaluation.test.ts +171 -0
  226. package/Tests/Utils/Slug.test.ts +61 -1
  227. package/Tests/jest.setup.ts +19 -0
  228. package/Types/Date.ts +39 -0
  229. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +61 -0
  230. package/Types/Monitor/SnmpMonitor/SnmpOidListUtil.ts +333 -0
  231. package/Types/NetworkDevice/DefaultNetworkDeviceRole.ts +145 -0
  232. package/Types/Permission.ts +141 -0
  233. package/Types/Rum/SessionReplay.ts +21 -0
  234. package/Types/Telemetry/SourceMap.ts +8 -0
  235. package/UI/Components/Charts/Area/AreaChart.tsx +7 -0
  236. package/UI/Components/Charts/Bar/BarChart.tsx +6 -0
  237. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +9 -1
  238. package/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.tsx +176 -0
  239. package/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.ts +745 -0
  240. package/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.tsx +576 -0
  241. package/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.tsx +204 -0
  242. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +554 -545
  243. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +337 -371
  244. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +549 -540
  245. package/UI/Components/Charts/ChartLibrary/Types/FormattedReferenceRegion.ts +7 -3
  246. package/UI/Components/Charts/ChartLibrary/Types/FormattedTimeReferenceLine.ts +14 -3
  247. package/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.ts +13 -0
  248. package/UI/Components/Charts/Line/LineChart.tsx +7 -0
  249. package/UI/Components/Charts/Types/ChartEventKind.ts +13 -0
  250. package/UI/Components/Charts/Types/ReferenceRegionProps.ts +6 -0
  251. package/UI/Components/Charts/Types/TimeReferenceLineProps.ts +20 -3
  252. package/UI/Components/Charts/Utils/TimeAnnotation.ts +69 -35
  253. package/UI/Components/Charts/Utils/XAxis.ts +125 -18
  254. package/UI/Components/EditionLabel/EditionLabel.tsx +280 -26
  255. package/UI/Components/ErrorMessage/ErrorMessage.tsx +21 -10
  256. package/UI/Components/Feed/FeedItem.tsx +4 -5
  257. package/UI/Components/Header/HeaderIconDropdownButton.tsx +1 -2
  258. package/UI/Components/Header/UserProfile/UserProfile.tsx +1 -2
  259. package/UI/Components/Image/Image.tsx +20 -3
  260. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  261. package/UI/Components/MemberRoleAssignment/MemberRoleAssignment.tsx +1 -2
  262. package/UI/Components/ModelTable/BaseModelTable.tsx +200 -39
  263. package/UI/Components/Navbar/NavBar.tsx +62 -13
  264. package/UI/Components/Navbar/NavBarMenuModal.tsx +7 -2
  265. package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +2 -0
  266. package/UI/Components/SideMenu/SideMenu.tsx +12 -2
  267. package/UI/Components/SideMenu/SideMenuItem.tsx +4 -1
  268. package/UI/Components/SideMenu/SideMenuSection.tsx +14 -2
  269. package/UI/Components/Table/TableHeader.tsx +64 -48
  270. package/UI/Components/Table/TableRow.tsx +13 -3
  271. package/UI/Styles/Theme.css +38 -0
  272. package/UI/Utils/UseDashboardTimeRangeZoom.ts +77 -0
  273. package/Utils/Dashboard/DashboardTimeRangeZoom.ts +118 -0
  274. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +271 -0
  275. package/Utils/Monitor/NetworkDeviceRoleCatalog.ts +232 -0
  276. package/Utils/Monitor/NetworkDeviceRoleUtil.ts +2 -1
  277. package/Utils/Monitor/NetworkTopologyUtil.ts +116 -33
  278. package/Utils/NetworkDevice/DeviceRoleKeyUtil.ts +137 -0
  279. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +6 -0
  280. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +141 -10
  281. package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +55 -3
  282. package/Utils/NetworkDiscovery/ReverseDnsNameUtil.ts +151 -0
  283. package/Utils/Rules/RuleEngineLimits.ts +32 -0
  284. package/Utils/Rules/RulePatternMatchUtil.ts +1 -1
  285. package/Utils/Slug.ts +34 -1
  286. package/build/dist/Models/AnalyticsModels/SecurityEvent.js +48 -16
  287. package/build/dist/Models/AnalyticsModels/SecurityEvent.js.map +1 -1
  288. package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js +10 -5
  289. package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js.map +1 -1
  290. package/build/dist/Models/DatabaseModels/AlertSeverity.js +46 -1
  291. package/build/dist/Models/DatabaseModels/AlertSeverity.js.map +1 -1
  292. package/build/dist/Models/DatabaseModels/AlertState.js +0 -2
  293. package/build/dist/Models/DatabaseModels/AlertState.js.map +1 -1
  294. package/build/dist/Models/DatabaseModels/DetectionRule.js +16 -5
  295. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  296. package/build/dist/Models/DatabaseModels/Domain.js +1 -1
  297. package/build/dist/Models/DatabaseModels/Domain.js.map +1 -1
  298. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +14 -5
  299. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +1 -1
  300. package/build/dist/Models/DatabaseModels/Incident.js +1 -1
  301. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  302. package/build/dist/Models/DatabaseModels/IncidentSeverity.js +46 -1
  303. package/build/dist/Models/DatabaseModels/IncidentSeverity.js.map +1 -1
  304. package/build/dist/Models/DatabaseModels/IncidentTemplate.js +1 -1
  305. package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
  306. package/build/dist/Models/DatabaseModels/Index.js +4 -0
  307. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  308. package/build/dist/Models/DatabaseModels/MetricType.js +0 -2
  309. package/build/dist/Models/DatabaseModels/MetricType.js.map +1 -1
  310. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js +0 -2
  311. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
  312. package/build/dist/Models/DatabaseModels/MonitorTest.js +0 -2
  313. package/build/dist/Models/DatabaseModels/MonitorTest.js.map +1 -1
  314. package/build/dist/Models/DatabaseModels/NetworkDevice.js +239 -6
  315. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  316. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +88 -0
  317. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
  318. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  319. package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js +521 -0
  320. package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js.map +1 -0
  321. package/build/dist/Models/DatabaseModels/NetworkDeviceRole.js +677 -0
  322. package/build/dist/Models/DatabaseModels/NetworkDeviceRole.js.map +1 -0
  323. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -1
  324. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  325. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js +1 -1
  326. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js.map +1 -1
  327. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +0 -2
  328. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
  329. package/build/dist/Models/DatabaseModels/StatusPageAnnouncementTemplate.js +0 -2
  330. package/build/dist/Models/DatabaseModels/StatusPageAnnouncementTemplate.js.map +1 -1
  331. package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js +0 -2
  332. package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js.map +1 -1
  333. package/build/dist/Models/DatabaseModels/StatusPageResource.js +0 -2
  334. package/build/dist/Models/DatabaseModels/StatusPageResource.js.map +1 -1
  335. package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +0 -2
  336. package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
  337. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +16 -5
  338. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js.map +1 -1
  339. package/build/dist/Server/API/GlobalConfigAPI.js +293 -176
  340. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  341. package/build/dist/Server/API/TelemetryAPI.js +31 -3
  342. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  343. package/build/dist/Server/EnvironmentConfig.js +83 -0
  344. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  345. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.js +26 -0
  346. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.js.map +1 -0
  347. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.js +14 -0
  348. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.js.map +1 -0
  349. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.js +39 -0
  350. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.js.map +1 -0
  351. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  352. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  353. package/build/dist/Server/Middleware/MultipartFormData.js +93 -28
  354. package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
  355. package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js +8 -1
  356. package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js.map +1 -1
  357. package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js +8 -1
  358. package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js.map +1 -1
  359. package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js +8 -1
  360. package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js.map +1 -1
  361. package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js +8 -1
  362. package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js.map +1 -1
  363. package/build/dist/Server/Services/AlertGroupingEngineService.js +8 -1
  364. package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
  365. package/build/dist/Server/Services/AlertLabelRuleEngineService.js +8 -1
  366. package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
  367. package/build/dist/Server/Services/AlertOnCallRuleEngineService.js +8 -1
  368. package/build/dist/Server/Services/AlertOnCallRuleEngineService.js.map +1 -1
  369. package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +8 -1
  370. package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
  371. package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js +8 -1
  372. package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js.map +1 -1
  373. package/build/dist/Server/Services/AlertReminderRuleService.js +8 -1
  374. package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
  375. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +8 -1
  376. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
  377. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +8 -1
  378. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
  379. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +8 -1
  380. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
  381. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +8 -1
  382. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
  383. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +8 -1
  384. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
  385. package/build/dist/Server/Services/DashboardLabelRuleEngineService.js +8 -1
  386. package/build/dist/Server/Services/DashboardLabelRuleEngineService.js.map +1 -1
  387. package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +8 -1
  388. package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
  389. package/build/dist/Server/Services/DatabaseService.js +31 -5
  390. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  391. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +8 -1
  392. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
  393. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +8 -1
  394. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
  395. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +8 -1
  396. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
  397. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +8 -1
  398. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
  399. package/build/dist/Server/Services/HostLabelRuleEngineService.js +8 -1
  400. package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
  401. package/build/dist/Server/Services/HostOwnerRuleEngineService.js +8 -1
  402. package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
  403. package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js +8 -1
  404. package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js.map +1 -1
  405. package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js +8 -1
  406. package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js.map +1 -1
  407. package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +8 -1
  408. package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
  409. package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js +8 -1
  410. package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js.map +1 -1
  411. package/build/dist/Server/Services/IncidentGroupingEngineService.js +8 -1
  412. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  413. package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +8 -1
  414. package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
  415. package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js +8 -1
  416. package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js.map +1 -1
  417. package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +8 -1
  418. package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
  419. package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js +8 -1
  420. package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js.map +1 -1
  421. package/build/dist/Server/Services/IncidentReminderRuleService.js +8 -1
  422. package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
  423. package/build/dist/Server/Services/IncidentSlaRuleService.js +8 -1
  424. package/build/dist/Server/Services/IncidentSlaRuleService.js.map +1 -1
  425. package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js +8 -1
  426. package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js.map +1 -1
  427. package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +8 -1
  428. package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
  429. package/build/dist/Server/Services/Index.js +4 -0
  430. package/build/dist/Server/Services/Index.js.map +1 -1
  431. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +8 -1
  432. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -1
  433. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +8 -1
  434. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
  435. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +8 -1
  436. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
  437. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +8 -1
  438. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
  439. package/build/dist/Server/Services/KubernetesResourceService.js +5 -1
  440. package/build/dist/Server/Services/KubernetesResourceService.js.map +1 -1
  441. package/build/dist/Server/Services/MonitorLabelRuleEngineService.js +8 -1
  442. package/build/dist/Server/Services/MonitorLabelRuleEngineService.js.map +1 -1
  443. package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js +8 -1
  444. package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js.map +1 -1
  445. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +30 -21
  446. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  447. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +64 -0
  448. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
  449. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +8 -1
  450. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
  451. package/build/dist/Server/Services/NetworkDeviceOidTemplateService.js +180 -0
  452. package/build/dist/Server/Services/NetworkDeviceOidTemplateService.js.map +1 -0
  453. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +8 -1
  454. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
  455. package/build/dist/Server/Services/NetworkDeviceRoleService.js +70 -0
  456. package/build/dist/Server/Services/NetworkDeviceRoleService.js.map +1 -0
  457. package/build/dist/Server/Services/NetworkDeviceService.js +154 -1
  458. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  459. package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js +8 -1
  460. package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js.map +1 -1
  461. package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +8 -1
  462. package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
  463. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js +8 -1
  464. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js.map +1 -1
  465. package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +8 -1
  466. package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
  467. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +8 -1
  468. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
  469. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +8 -1
  470. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
  471. package/build/dist/Server/Services/ProjectService.js +65 -0
  472. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  473. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +8 -1
  474. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
  475. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +8 -1
  476. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
  477. package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +8 -1
  478. package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -1
  479. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +8 -1
  480. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
  481. package/build/dist/Server/Services/RunbookLabelRuleEngineService.js +8 -1
  482. package/build/dist/Server/Services/RunbookLabelRuleEngineService.js.map +1 -1
  483. package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +8 -1
  484. package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
  485. package/build/dist/Server/Services/RunbookRuleEngineService.js +8 -1
  486. package/build/dist/Server/Services/RunbookRuleEngineService.js.map +1 -1
  487. package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +8 -1
  488. package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
  489. package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +8 -1
  490. package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
  491. package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +8 -1
  492. package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
  493. package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +8 -1
  494. package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -1
  495. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +8 -1
  496. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
  497. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +8 -1
  498. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
  499. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +8 -1
  500. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
  501. package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js +8 -1
  502. package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js.map +1 -1
  503. package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js +6 -0
  504. package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js.map +1 -1
  505. package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js +8 -1
  506. package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js.map +1 -1
  507. package/build/dist/Server/Services/TelemetrySourceMapService.js +213 -19
  508. package/build/dist/Server/Services/TelemetrySourceMapService.js.map +1 -1
  509. package/build/dist/Server/Services/UserNotificationSettingService.js +0 -1
  510. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  511. package/build/dist/Server/Services/UserService.js +25 -0
  512. package/build/dist/Server/Services/UserService.js.map +1 -1
  513. package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js +8 -1
  514. package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js.map +1 -1
  515. package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +8 -1
  516. package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
  517. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +145 -0
  518. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +1 -0
  519. package/build/dist/Server/Utils/Monitor/CapturedMetricAttributeUtil.js +201 -0
  520. package/build/dist/Server/Utils/Monitor/CapturedMetricAttributeUtil.js.map +1 -0
  521. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +19 -2
  522. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  523. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +42 -23
  524. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  525. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +29 -0
  526. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  527. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +11 -2
  528. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
  529. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +16 -1
  530. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
  531. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +10 -0
  532. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  533. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +33 -0
  534. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  535. package/build/dist/Server/Utils/Rules/RuleEngineRuleRead.js +37 -0
  536. package/build/dist/Server/Utils/Rules/RuleEngineRuleRead.js.map +1 -0
  537. package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js +12 -1
  538. package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js.map +1 -1
  539. package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js +14 -2
  540. package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js.map +1 -1
  541. package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js +15 -5
  542. package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js.map +1 -1
  543. package/build/dist/Server/Utils/Telemetry/StackTraceParser.js +307 -0
  544. package/build/dist/Server/Utils/Telemetry/StackTraceParser.js.map +1 -1
  545. package/build/dist/Types/Date.js +27 -0
  546. package/build/dist/Types/Date.js.map +1 -1
  547. package/build/dist/Types/Monitor/SnmpMonitor/SnmpOidListUtil.js +253 -0
  548. package/build/dist/Types/Monitor/SnmpMonitor/SnmpOidListUtil.js.map +1 -0
  549. package/build/dist/Types/NetworkDevice/DefaultNetworkDeviceRole.js +105 -0
  550. package/build/dist/Types/NetworkDevice/DefaultNetworkDeviceRole.js.map +1 -0
  551. package/build/dist/Types/Permission.js +126 -0
  552. package/build/dist/Types/Permission.js.map +1 -1
  553. package/build/dist/Types/Rum/SessionReplay.js +19 -0
  554. package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
  555. package/build/dist/UI/Components/Charts/Area/AreaChart.js +1 -1
  556. package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
  557. package/build/dist/UI/Components/Charts/Bar/BarChart.js +1 -1
  558. package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
  559. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +6 -1
  560. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  561. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.js +83 -0
  562. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.js.map +1 -0
  563. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.js +531 -0
  564. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.js.map +1 -0
  565. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.js +264 -0
  566. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.js.map +1 -0
  567. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.js +122 -0
  568. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.js.map +1 -0
  569. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +262 -234
  570. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  571. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +146 -153
  572. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  573. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +261 -233
  574. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  575. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js +14 -0
  576. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js.map +1 -0
  577. package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
  578. package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
  579. package/build/dist/UI/Components/Charts/Types/ChartEventKind.js +14 -0
  580. package/build/dist/UI/Components/Charts/Types/ChartEventKind.js.map +1 -0
  581. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js +57 -28
  582. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js.map +1 -1
  583. package/build/dist/UI/Components/Charts/Utils/XAxis.js +103 -17
  584. package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
  585. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +198 -23
  586. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  587. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +15 -5
  588. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
  589. package/build/dist/UI/Components/Feed/FeedItem.js +4 -5
  590. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  591. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -2
  592. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
  593. package/build/dist/UI/Components/Header/UserProfile/UserProfile.js.map +1 -1
  594. package/build/dist/UI/Components/Image/Image.js +6 -1
  595. package/build/dist/UI/Components/Image/Image.js.map +1 -1
  596. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  597. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  598. package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js +1 -2
  599. package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js.map +1 -1
  600. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +143 -36
  601. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  602. package/build/dist/UI/Components/Navbar/NavBar.js +44 -9
  603. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  604. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +2 -2
  605. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  606. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +1 -1
  607. package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
  608. package/build/dist/UI/Components/SideMenu/SideMenu.js +9 -6
  609. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  610. package/build/dist/UI/Components/SideMenu/SideMenuItem.js +1 -1
  611. package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
  612. package/build/dist/UI/Components/SideMenu/SideMenuSection.js +7 -2
  613. package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
  614. package/build/dist/UI/Components/Table/TableHeader.js +20 -22
  615. package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
  616. package/build/dist/UI/Components/Table/TableRow.js +13 -4
  617. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  618. package/build/dist/UI/Utils/UseDashboardTimeRangeZoom.js +42 -0
  619. package/build/dist/UI/Utils/UseDashboardTimeRangeZoom.js.map +1 -0
  620. package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js +74 -0
  621. package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js.map +1 -0
  622. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +153 -0
  623. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -0
  624. package/build/dist/Utils/Monitor/NetworkDeviceRoleCatalog.js +126 -0
  625. package/build/dist/Utils/Monitor/NetworkDeviceRoleCatalog.js.map +1 -0
  626. package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js +2 -1
  627. package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js.map +1 -1
  628. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +67 -32
  629. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  630. package/build/dist/Utils/NetworkDevice/DeviceRoleKeyUtil.js +114 -0
  631. package/build/dist/Utils/NetworkDevice/DeviceRoleKeyUtil.js.map +1 -0
  632. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
  633. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +127 -7
  634. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
  635. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +50 -3
  636. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
  637. package/build/dist/Utils/NetworkDiscovery/ReverseDnsNameUtil.js +132 -0
  638. package/build/dist/Utils/NetworkDiscovery/ReverseDnsNameUtil.js.map +1 -0
  639. package/build/dist/Utils/Rules/RuleEngineLimits.js +31 -0
  640. package/build/dist/Utils/Rules/RuleEngineLimits.js.map +1 -0
  641. package/build/dist/Utils/Rules/RulePatternMatchUtil.js +1 -1
  642. package/build/dist/Utils/Slug.js +31 -1
  643. package/build/dist/Utils/Slug.js.map +1 -1
  644. package/jest.config.json +1 -0
  645. package/package.json +2 -2
@@ -0,0 +1,865 @@
1
+ import NetworkTopologyUtil, {
2
+ TopologyBuildResult,
3
+ TopologyDeviceInput,
4
+ TopologyEndpointInput,
5
+ } from "../../../Utils/Monitor/NetworkTopologyUtil";
6
+ import { TopologyDeviceRoleInput } from "../../../Utils/Monitor/NetworkDeviceRoleCatalog";
7
+ import { NetworkTopologyNode } from "../../../Types/Monitor/SnmpMonitor/NetworkTopology";
8
+ import DEFAULT_NETWORK_DEVICE_ROLES, {
9
+ DefaultNetworkDeviceRole,
10
+ } from "../../../Types/NetworkDevice/DefaultNetworkDeviceRole";
11
+
12
+ /*
13
+ * Device roles are rows now (NetworkDeviceRole), one set per project, and the
14
+ * client is deliberately NOT handed the table to look things up in. Instead
15
+ * buildTopology stamps the project's answers — label, silhouette, "is this a
16
+ * core device", "is this worth walking with SNMP" — onto each node as it
17
+ * builds it, so the shape module, the three layouts, the legend and the adopt
18
+ * flow all keep their existing pure signatures.
19
+ *
20
+ * NetworkDeviceRoleCatalog's units are tested on their own; this file is the
21
+ * wiring: what actually lands on a node once a real graph has been built.
22
+ *
23
+ * The load-bearing invariant, and the reason most of the first block exists:
24
+ * every stamped field is ADDITIVE and OPTIONAL. A project with no roles
25
+ * configured, a caller that predates the parameter, and a payload serialised
26
+ * before the table existed must all produce exactly the nodes they produced
27
+ * before — which means the fields have to be ABSENT, not present-and-undefined,
28
+ * because "absent means fall back to the built-in" is the contract every
29
+ * consumer downstream reads.
30
+ */
31
+ describe("NetworkTopologyUtil.buildTopology — the project's configured device roles", () => {
32
+ const now: Date = new Date("2026-07-22T12:00:00Z");
33
+ const fresh: Date = new Date("2026-07-22T11:55:00Z");
34
+
35
+ // Every field the role catalogue is allowed to put on a node.
36
+ const ROLE_STAMP_FIELDS: ReadonlyArray<string> = [
37
+ "roleId",
38
+ "roleKey",
39
+ "roleLabel",
40
+ "roleShape",
41
+ "isCoreLayerRole",
42
+ "isSnmpWalkableRole",
43
+ ];
44
+
45
+ const makeDevice: (
46
+ id: string,
47
+ name: string,
48
+ overrides?: Partial<TopologyDeviceInput>,
49
+ ) => TopologyDeviceInput = (
50
+ id: string,
51
+ name: string,
52
+ overrides?: Partial<TopologyDeviceInput>,
53
+ ): TopologyDeviceInput => {
54
+ return {
55
+ id,
56
+ name,
57
+ lastSeenAt: fresh,
58
+ ...overrides,
59
+ };
60
+ };
61
+
62
+ const nodeById: (
63
+ result: TopologyBuildResult,
64
+ id: string,
65
+ ) => NetworkTopologyNode | undefined = (
66
+ result: TopologyBuildResult,
67
+ id: string,
68
+ ): NetworkTopologyNode | undefined => {
69
+ return result.nodes.find((node: NetworkTopologyNode) => {
70
+ return node.id === id;
71
+ });
72
+ };
73
+
74
+ /*
75
+ * Absence, not `undefined`. A consumer that checks with `in`, or a payload
76
+ * that goes through JSON, cannot tell the two apart afterwards — and a node
77
+ * carrying `roleShape: undefined` would still be a node whose author claimed
78
+ * to know something about its shape.
79
+ */
80
+ const expectNoRoleStamp: (node: NetworkTopologyNode) => void = (
81
+ node: NetworkTopologyNode,
82
+ ): void => {
83
+ for (const field of ROLE_STAMP_FIELDS) {
84
+ expect(node).not.toHaveProperty(field);
85
+ }
86
+ };
87
+
88
+ /*
89
+ * The eleven roles seeded into every project, in the shape the API hands
90
+ * buildTopology. Built from the shared defaults rather than retyped, so a
91
+ * change to what a fresh project starts with cannot pass here and fail in
92
+ * production.
93
+ */
94
+ const seededRoles: () => Array<TopologyDeviceRoleInput> =
95
+ (): Array<TopologyDeviceRoleInput> => {
96
+ return DEFAULT_NETWORK_DEVICE_ROLES.map(
97
+ (role: DefaultNetworkDeviceRole): TopologyDeviceRoleInput => {
98
+ return {
99
+ id: `role-${role.key}`,
100
+ key: role.key,
101
+ name: role.name,
102
+ topologyShape: role.topologyShape,
103
+ isCoreLayer: role.isCoreLayer,
104
+ isSnmpWalkable: role.isSnmpWalkable,
105
+ };
106
+ },
107
+ );
108
+ };
109
+
110
+ // The seeded set with one row edited, which is what "renaming a role" is.
111
+ const seededRolesWith: (
112
+ key: string,
113
+ patch: Partial<TopologyDeviceRoleInput>,
114
+ ) => Array<TopologyDeviceRoleInput> = (
115
+ key: string,
116
+ patch: Partial<TopologyDeviceRoleInput>,
117
+ ): Array<TopologyDeviceRoleInput> => {
118
+ return seededRoles().map(
119
+ (role: TopologyDeviceRoleInput): TopologyDeviceRoleInput => {
120
+ return role.key === key ? { ...role, ...patch } : role;
121
+ },
122
+ );
123
+ };
124
+
125
+ /*
126
+ * One small estate that exercises all three node kinds at once: a managed
127
+ * device the classifier can place, one it cannot, a CDP peer nobody manages,
128
+ * and two ARP/FDB endpoints. Reused so the "before" and "after" pictures are
129
+ * the same graph.
130
+ */
131
+ const estateDevices: () => Array<TopologyDeviceInput> =
132
+ (): Array<TopologyDeviceInput> => {
133
+ return [
134
+ makeDevice("d-router", "core-rtr-1", {
135
+ sysName: "core-rtr-1",
136
+ deviceModel: "ISR4331/K9",
137
+ }),
138
+ makeDevice("d-switch", "access-1", {
139
+ sysName: "access-1",
140
+ sysDescr: "Cisco IOS Software, Catalyst 9300-48P",
141
+ cdpNeighbors: [
142
+ {
143
+ localInterfaceIndex: 1,
144
+ remoteDeviceId: "ap-lobby",
145
+ remotePlatform: "cisco AIR-CAP3702I-A-K9",
146
+ },
147
+ ],
148
+ }),
149
+ // Nothing walks this one and its name says nothing: honestly "unknown".
150
+ makeDevice("d-blank", "device-42"),
151
+ ];
152
+ };
153
+
154
+ const estateEndpoints: () => Array<TopologyEndpointInput> =
155
+ (): Array<TopologyEndpointInput> => {
156
+ return [
157
+ {
158
+ id: "ep-phone",
159
+ macAddress: "aa:bb:cc:dd:ee:01",
160
+ classification: "VoIP handset",
161
+ attachedNetworkDeviceId: "d-switch",
162
+ lastSeenAt: fresh,
163
+ },
164
+ {
165
+ id: "ep-plain",
166
+ macAddress: "aa:bb:cc:dd:ee:02",
167
+ attachedNetworkDeviceId: "d-switch",
168
+ lastSeenAt: fresh,
169
+ },
170
+ ];
171
+ };
172
+
173
+ describe("a project that has configured nothing", () => {
174
+ it("stamps no role fields at all when the catalogue argument is omitted", () => {
175
+ /*
176
+ * The compatibility case that matters most: this is every caller written
177
+ * before the parameter existed, and every project whose backfill has not
178
+ * run yet. The node must come out byte-identical to the one built before
179
+ * roles were configurable, which means `role` intact and not one of the
180
+ * six new fields present.
181
+ */
182
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
183
+ estateDevices(),
184
+ now,
185
+ [],
186
+ estateEndpoints(),
187
+ );
188
+
189
+ expect(nodeById(result, "d-router")!.role).toBe("router");
190
+ expect(nodeById(result, "d-switch")!.role).toBe("switch");
191
+ expect(nodeById(result, "d-blank")!.role).toBe("unknown");
192
+ expect(nodeById(result, "unmanaged:ap-lobby")!.role).toBe(
193
+ "wirelessAccessPoint",
194
+ );
195
+ expect(nodeById(result, "endpoint:ep-phone")!.role).toBe("phone");
196
+ expect(nodeById(result, "endpoint:ep-plain")!.role).toBe("host");
197
+
198
+ for (const node of result.nodes) {
199
+ expectNoRoleStamp(node);
200
+ }
201
+ });
202
+
203
+ it("treats an empty catalogue exactly as it treats no catalogue", () => {
204
+ /*
205
+ * A project that deleted every role is not a project asking for blank
206
+ * nodes — it is a project with nothing to say, which is the same thing
207
+ * the omitted argument says. Compared whole rather than field by field
208
+ * so a future field cannot be added to one path and not the other.
209
+ */
210
+ const omitted: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
211
+ estateDevices(),
212
+ now,
213
+ [],
214
+ estateEndpoints(),
215
+ );
216
+ const empty: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
217
+ estateDevices(),
218
+ now,
219
+ [],
220
+ estateEndpoints(),
221
+ [],
222
+ new Set<string>(),
223
+ [],
224
+ );
225
+
226
+ expect(empty.nodes).toStrictEqual(omitted.nodes);
227
+ });
228
+
229
+ it("stamps nothing from rows that carry no usable key", () => {
230
+ /*
231
+ * A key is what a row is FOUND by, so a row without one cannot be found
232
+ * — and must not be silently applied to everything either. Blank keys
233
+ * are what a half-written import leaves behind.
234
+ */
235
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
236
+ estateDevices(),
237
+ now,
238
+ [],
239
+ [],
240
+ [],
241
+ new Set<string>(),
242
+ [
243
+ { id: "role-a", key: "", name: "Nameless" },
244
+ { id: "role-b", key: " ", name: "Whitespace" },
245
+ ],
246
+ );
247
+
248
+ expect(nodeById(result, "d-router")!.role).toBe("router");
249
+ for (const node of result.nodes) {
250
+ expectNoRoleStamp(node);
251
+ }
252
+ });
253
+ });
254
+
255
+ describe("a role the classifier chose, drawn the way the project configured it", () => {
256
+ it("relabels a device the operator never touched when its role is renamed", () => {
257
+ /*
258
+ * The whole point of keying on the classifier's answer. Nobody has ever
259
+ * opened this router's settings — the role came from its model string —
260
+ * and renaming the "router" row still has to reach it, because otherwise
261
+ * a rename only ever applies to devices somebody edited by hand.
262
+ */
263
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
264
+ estateDevices(),
265
+ now,
266
+ [],
267
+ [],
268
+ [],
269
+ new Set<string>(),
270
+ seededRolesWith("router", {
271
+ name: "Edge Router",
272
+ topologyShape: "hexagon",
273
+ }),
274
+ );
275
+
276
+ const router: NetworkTopologyNode = nodeById(result, "d-router")!;
277
+ // The classifier's vocabulary is untouched — only the presentation moved.
278
+ expect(router.role).toBe("router");
279
+ expect(router.roleKey).toBe("router");
280
+ expect(router.roleLabel).toBe("Edge Router");
281
+ expect(router.roleShape).toBe("hexagon");
282
+ expect(router.isCoreLayerRole).toBe(true);
283
+ expect(router.isSnmpWalkableRole).toBe(true);
284
+ // So a form can preselect the row the map is already showing.
285
+ expect(router.roleId).toBe("role-router");
286
+ });
287
+
288
+ it("carries a role that was turned OFF the core layer through as false", () => {
289
+ /*
290
+ * The tiered and radial layouts read isCoreLayerRole BEFORE `role`, so
291
+ * `false` is a real instruction — "draw routers with the access kit" —
292
+ * and not the absence of one. If a false were dropped as falsy the node
293
+ * would silently fall back to the built-in core set and the layout would
294
+ * ignore what the project configured.
295
+ */
296
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
297
+ estateDevices(),
298
+ now,
299
+ [],
300
+ [],
301
+ [],
302
+ new Set<string>(),
303
+ seededRolesWith("router", { isCoreLayer: false }),
304
+ );
305
+
306
+ const router: NetworkTopologyNode = nodeById(result, "d-router")!;
307
+ expect(router.isCoreLayerRole).toBe(false);
308
+ expect(router).toHaveProperty("isCoreLayerRole");
309
+ });
310
+
311
+ it("omits the flags a row does not state rather than inventing them", () => {
312
+ /*
313
+ * A row that says nothing about the core layer is not a row saying "not
314
+ * core". Absent has to stay absent so the client falls back to the
315
+ * built-in answer for `role`, which is the pre-feature behaviour.
316
+ */
317
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
318
+ estateDevices(),
319
+ now,
320
+ [],
321
+ [],
322
+ [],
323
+ new Set<string>(),
324
+ [{ key: "router", name: "Edge Router" }],
325
+ );
326
+
327
+ const router: NetworkTopologyNode = nodeById(result, "d-router")!;
328
+ expect(router.roleKey).toBe("router");
329
+ expect(router.roleLabel).toBe("Edge Router");
330
+ expect(router).not.toHaveProperty("isCoreLayerRole");
331
+ expect(router).not.toHaveProperty("isSnmpWalkableRole");
332
+ expect(router).not.toHaveProperty("roleShape");
333
+ // No row id to preselect, because this catalogue carried none.
334
+ expect(router).not.toHaveProperty("roleId");
335
+ });
336
+
337
+ it("drops a silhouette the renderer has no geometry for", () => {
338
+ /*
339
+ * topologyShape is free text — adding a shape must not need a migration
340
+ * — so a value the renderer cannot draw is dropped and the node falls
341
+ * back to the built-in shape for its role. Passing it through would hand
342
+ * the renderer a shape with no path and draw nothing at all.
343
+ */
344
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
345
+ estateDevices(),
346
+ now,
347
+ [],
348
+ [],
349
+ [],
350
+ new Set<string>(),
351
+ seededRolesWith("router", { topologyShape: "sparkle" }),
352
+ );
353
+
354
+ const router: NetworkTopologyNode = nodeById(result, "d-router")!;
355
+ // The rest of the row still applies; only the unusable field is dropped.
356
+ expect(router.roleLabel).toBe("Router");
357
+ expect(router).not.toHaveProperty("roleShape");
358
+ });
359
+
360
+ it("stamps the catalogue's own spelling of a key so the legend groups once", () => {
361
+ /*
362
+ * The legend groups by roleKey. A device that got its key from the
363
+ * classifier ("switch") and one an operator assigned ("switch") must
364
+ * therefore land on the SAME string, or one estate's switches split into
365
+ * two legend entries that read identically.
366
+ */
367
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
368
+ [
369
+ makeDevice("d1", "access-1", {
370
+ sysDescr: "Cisco IOS Software, Catalyst 9300-48P",
371
+ }),
372
+ makeDevice("d2", "ping-only-9", { deviceRole: "switch" }),
373
+ ],
374
+ now,
375
+ [],
376
+ [],
377
+ [],
378
+ new Set<string>(),
379
+ [
380
+ {
381
+ id: "role-switch",
382
+ key: "Switch",
383
+ name: "Access Switch",
384
+ topologyShape: "rounded-square",
385
+ },
386
+ ],
387
+ );
388
+
389
+ expect(nodeById(result, "d1")!.roleKey).toBe("Switch");
390
+ expect(nodeById(result, "d2")!.roleKey).toBe("Switch");
391
+ expect(nodeById(result, "d1")!.roleLabel).toBe("Access Switch");
392
+ expect(nodeById(result, "d2")!.roleLabel).toBe("Access Switch");
393
+ });
394
+
395
+ it("gives a node the classifier declined to place no stamp at all", () => {
396
+ /*
397
+ * "unknown" is the classifier saying it has no answer, not a role, and
398
+ * no project has a row for it — offering one would mean "stop
399
+ * classifying this device forever". A neutral node is the honest
400
+ * drawing, so nothing is stamped even with a full catalogue loaded.
401
+ */
402
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
403
+ estateDevices(),
404
+ now,
405
+ [],
406
+ [],
407
+ [],
408
+ new Set<string>(),
409
+ seededRoles(),
410
+ );
411
+
412
+ const blank: NetworkTopologyNode = nodeById(result, "d-blank")!;
413
+ expect(blank.role).toBe("unknown");
414
+ expectNoRoleStamp(blank);
415
+ // The devices around it were stamped, so this is a decision, not a miss.
416
+ expect(nodeById(result, "d-router")!.roleKey).toBe("router");
417
+ });
418
+ });
419
+
420
+ describe("a role the operator assigned to a device", () => {
421
+ it("stamps the assigned built-in role, over anything the evidence said", () => {
422
+ /*
423
+ * The assignment is the only statement about the role that is not an
424
+ * inference, so it decides both halves: the built-in `role` AND which
425
+ * configured row the node is drawn from. The classifier would answer
426
+ * "switch" here off the Catalyst model string.
427
+ */
428
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
429
+ [
430
+ makeDevice("d1", "dmz-1", {
431
+ sysDescr: "Cisco IOS Software, Catalyst 9300-48P",
432
+ deviceRole: "firewall",
433
+ }),
434
+ ],
435
+ now,
436
+ [],
437
+ [],
438
+ [],
439
+ new Set<string>(),
440
+ seededRolesWith("firewall", { name: "Perimeter Firewall" }),
441
+ );
442
+
443
+ const node: NetworkTopologyNode = nodeById(result, "d1")!;
444
+ expect(node.role).toBe("firewall");
445
+ expect(node.roleKey).toBe("firewall");
446
+ // From the row, not from the built-in DEVICE_ROLE_LABELS map.
447
+ expect(node.roleLabel).toBe("Perimeter Firewall");
448
+ expect(node.roleShape).toBe("diamond");
449
+ expect(node.isCoreLayerRole).toBe(true);
450
+ });
451
+
452
+ it("draws a device as its CUSTOM role while `role` keeps the built-in answer", () => {
453
+ /*
454
+ * A custom role has no place in NetworkTopologyDeviceRole and never can
455
+ * — that union is the vocabulary the SNMP classifier speaks, and it
456
+ * cannot invent a project's own roles. So the two fields deliberately
457
+ * disagree here: `role` stays whatever the evidence supports (this box
458
+ * reports a Linux kernel, so "server"), and every field a human reads —
459
+ * label, silhouette, tier — comes from the PoS Terminal row.
460
+ *
461
+ * Leaving `role` alone is not an oversight. It is what any consumer that
462
+ * still speaks only the built-in union falls back to, and blanking it to
463
+ * "unknown" would downgrade those consumers rather than extend them.
464
+ */
465
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
466
+ [
467
+ makeDevice("d-pos", "lane-4-till", {
468
+ sysDescr: "Linux 5.10.0 x86_64",
469
+ deviceRole: "posTerminal",
470
+ }),
471
+ ],
472
+ now,
473
+ [],
474
+ [],
475
+ [],
476
+ new Set<string>(),
477
+ [
478
+ ...seededRoles(),
479
+ {
480
+ id: "role-pos",
481
+ key: "posTerminal",
482
+ name: "PoS Terminal",
483
+ topologyShape: "hexagon",
484
+ isCoreLayer: false,
485
+ isSnmpWalkable: false,
486
+ },
487
+ ],
488
+ );
489
+
490
+ const node: NetworkTopologyNode = nodeById(result, "d-pos")!;
491
+ expect(node.role).toBe("server");
492
+ expect(node.roleKey).toBe("posTerminal");
493
+ expect(node.roleLabel).toBe("PoS Terminal");
494
+ expect(node.roleShape).toBe("hexagon");
495
+ expect(node.isCoreLayerRole).toBe(false);
496
+ expect(node.isSnmpWalkableRole).toBe(false);
497
+ expect(node.roleId).toBe("role-pos");
498
+ });
499
+
500
+ it("matches an assigned key case- and whitespace-insensitively", () => {
501
+ /*
502
+ * The stored value is a ShortText column: what lands in it depends on
503
+ * which form, import or API call wrote it. A role that only applied when
504
+ * the key was typed in exactly the row's camelCase spelling would be a
505
+ * trap, and the same leniency parseDeviceRoleOverride already applies to
506
+ * the built-in half has to apply to the configured half.
507
+ */
508
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
509
+ [
510
+ makeDevice("d1", "a", { deviceRole: " SWITCH " }),
511
+ makeDevice("d2", "b", { deviceRole: "POSTERMINAL" }),
512
+ makeDevice("d3", "c", { deviceRole: " posTerminal " }),
513
+ makeDevice("d4", "d", { deviceRole: "wirelessaccesspoint" }),
514
+ ],
515
+ now,
516
+ [],
517
+ [],
518
+ [],
519
+ new Set<string>(),
520
+ [
521
+ ...seededRoles(),
522
+ {
523
+ id: "role-pos",
524
+ key: "posTerminal",
525
+ name: "PoS Terminal",
526
+ topologyShape: "hexagon",
527
+ },
528
+ ],
529
+ );
530
+
531
+ expect(nodeById(result, "d1")!.roleKey).toBe("switch");
532
+ expect(nodeById(result, "d1")!.roleLabel).toBe("Switch");
533
+ // Both spellings of the custom key reach the one row.
534
+ expect(nodeById(result, "d2")!.roleKey).toBe("posTerminal");
535
+ expect(nodeById(result, "d3")!.roleKey).toBe("posTerminal");
536
+ expect(nodeById(result, "d4")!.roleKey).toBe("wirelessAccessPoint");
537
+ expect(nodeById(result, "d4")!.roleLabel).toBe("Wireless AP");
538
+ });
539
+
540
+ it("stamps nothing when the assigned key matches no row in the catalogue", () => {
541
+ /*
542
+ * The role the device was assigned has since been deleted, or the row
543
+ * belongs to a project this device was moved out of. There is nothing to
544
+ * draw it as, so it falls all the way back to the built-in behaviour —
545
+ * and NOT to the classifier's row, because the assignment is still the
546
+ * operator's statement about what this box is and using "firewall"'s
547
+ * label for a device somebody called an SD-WAN edge would be a lie.
548
+ */
549
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
550
+ [
551
+ makeDevice("d1", "edge-1", {
552
+ sysDescr: "FortiGate-60F v7.2.5",
553
+ deviceRole: "sdWanEdge",
554
+ }),
555
+ ],
556
+ now,
557
+ [],
558
+ [],
559
+ [],
560
+ new Set<string>(),
561
+ seededRoles(),
562
+ );
563
+
564
+ const node: NetworkTopologyNode = nodeById(result, "d1")!;
565
+ // The classifier still gets to answer, exactly as it did before.
566
+ expect(node.role).toBe("firewall");
567
+ expectNoRoleStamp(node);
568
+ });
569
+
570
+ it("stamps nothing when the project deleted the row the classifier chose", () => {
571
+ /*
572
+ * The permanent case, not a transient one: a project may delete a seeded
573
+ * role the classifier can still produce. An empty stamp on those nodes
574
+ * is what makes them draw the pre-feature map instead of erroring or
575
+ * borrowing another role's shape.
576
+ */
577
+ const withoutCameras: Array<TopologyDeviceRoleInput> =
578
+ seededRoles().filter((role: TopologyDeviceRoleInput) => {
579
+ return role.key !== "camera";
580
+ });
581
+
582
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
583
+ [
584
+ makeDevice("d1", "lobby-cam", {
585
+ deviceModel: "Hikvision DS-2CD2143G0",
586
+ }),
587
+ makeDevice("d2", "access-1", {
588
+ sysDescr: "Cisco IOS Software, Catalyst 9300-48P",
589
+ }),
590
+ ],
591
+ now,
592
+ [],
593
+ [],
594
+ [],
595
+ new Set<string>(),
596
+ withoutCameras,
597
+ );
598
+
599
+ expect(nodeById(result, "d1")!.role).toBe("camera");
600
+ expectNoRoleStamp(nodeById(result, "d1")!);
601
+ // Its neighbour, whose row survives, is unaffected.
602
+ expect(nodeById(result, "d2")!.roleKey).toBe("switch");
603
+ });
604
+ });
605
+
606
+ describe("nodes nobody manages", () => {
607
+ it("stamps an unmanaged CDP peer from the classifier's answer", () => {
608
+ /*
609
+ * A peer is exactly the node an operator adopts, and the adopt flow
610
+ * reads isSnmpWalkableRole to decide whether the modal opens on SNMP
611
+ * polling or on a plain monitor. Without the stamp that decision falls
612
+ * back to a hardcoded set, which is what made a project's own roles
613
+ * unable to influence it.
614
+ */
615
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
616
+ [
617
+ makeDevice("d1", "access-1", {
618
+ sysName: "access-1",
619
+ cdpNeighbors: [
620
+ {
621
+ localInterfaceIndex: 1,
622
+ remoteDeviceId: "ap-lobby",
623
+ remotePlatform: "cisco AIR-CAP3702I-A-K9",
624
+ },
625
+ {
626
+ localInterfaceIndex: 2,
627
+ remoteDeviceId: "handset-3f",
628
+ remotePlatform: "Cisco IP Phone 7961",
629
+ },
630
+ ],
631
+ }),
632
+ ],
633
+ now,
634
+ [],
635
+ [],
636
+ [],
637
+ new Set<string>(),
638
+ seededRolesWith("wirelessAccessPoint", { name: "Access Point" }),
639
+ );
640
+
641
+ const ap: NetworkTopologyNode = nodeById(result, "unmanaged:ap-lobby")!;
642
+ expect(ap.role).toBe("wirelessAccessPoint");
643
+ expect(ap.roleKey).toBe("wirelessAccessPoint");
644
+ expect(ap.roleLabel).toBe("Access Point");
645
+ expect(ap.roleShape).toBe("triangle");
646
+ // Walkable: adopting this one should open on SNMP.
647
+ expect(ap.isSnmpWalkableRole).toBe(true);
648
+
649
+ const phone: NetworkTopologyNode = nodeById(
650
+ result,
651
+ "unmanaged:handset-3f",
652
+ )!;
653
+ expect(phone.roleKey).toBe("phone");
654
+ // Not walkable: adopting a handset should open on a monitor instead.
655
+ expect(phone.isSnmpWalkableRole).toBe(false);
656
+ });
657
+
658
+ it("leaves an unmanaged peer nothing said anything about unstamped", () => {
659
+ /*
660
+ * Most peers come back "unknown" and should: a name and nothing else is
661
+ * not evidence. Those nodes keep drawing neutral, catalogue or no
662
+ * catalogue.
663
+ */
664
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
665
+ [
666
+ makeDevice("d1", "access-1", {
667
+ sysName: "access-1",
668
+ lldpNeighbors: [
669
+ { localInterfaceIndex: 3, remoteSysName: "prod-node-7" },
670
+ ],
671
+ }),
672
+ ],
673
+ now,
674
+ [],
675
+ [],
676
+ [],
677
+ new Set<string>(),
678
+ seededRoles(),
679
+ );
680
+
681
+ const peer: NetworkTopologyNode = nodeById(
682
+ result,
683
+ "unmanaged:prod-node-7",
684
+ )!;
685
+ expect(peer.role).toBe("unknown");
686
+ expectNoRoleStamp(peer);
687
+ });
688
+
689
+ it("stamps discovered endpoints, so a renamed handset role reaches them", () => {
690
+ /*
691
+ * Endpoints are learned from ARP/FDB and never assigned a role by hand,
692
+ * so the classifier's answer is all there is — and a project that
693
+ * renamed "IP phone" expects to see the new word on its handsets, which
694
+ * are the most numerous thing on the map.
695
+ */
696
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
697
+ estateDevices(),
698
+ now,
699
+ [],
700
+ estateEndpoints(),
701
+ [],
702
+ new Set<string>(),
703
+ seededRolesWith("phone", { name: "Desk Handset" }),
704
+ );
705
+
706
+ const handset: NetworkTopologyNode = nodeById(
707
+ result,
708
+ "endpoint:ep-phone",
709
+ )!;
710
+ expect(handset.role).toBe("phone");
711
+ expect(handset.roleKey).toBe("phone");
712
+ expect(handset.roleLabel).toBe("Desk Handset");
713
+ expect(handset.roleShape).toBe("rect");
714
+
715
+ // An endpoint nothing was said about is still a host, and still stamped.
716
+ const plain: NetworkTopologyNode = nodeById(result, "endpoint:ep-plain")!;
717
+ expect(plain.role).toBe("host");
718
+ expect(plain.roleKey).toBe("host");
719
+ expect(plain.roleLabel).toBe("Host");
720
+ });
721
+
722
+ it("keeps a stamp off the endpoints of a project with no host row", () => {
723
+ /*
724
+ * Same fallback as everywhere else, checked on the node kind that never
725
+ * has an assignment to fall back FROM. Endpoints are capped and numerous,
726
+ * so a missing row must be cheap and silent, not an error per node.
727
+ */
728
+ const withoutHosts: Array<TopologyDeviceRoleInput> = seededRoles().filter(
729
+ (role: TopologyDeviceRoleInput) => {
730
+ return role.key !== "host";
731
+ },
732
+ );
733
+
734
+ const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
735
+ estateDevices(),
736
+ now,
737
+ [],
738
+ estateEndpoints(),
739
+ [],
740
+ new Set<string>(),
741
+ withoutHosts,
742
+ );
743
+
744
+ expectNoRoleStamp(nodeById(result, "endpoint:ep-plain")!);
745
+ // The handset beside it, whose row survives, is still stamped.
746
+ expect(nodeById(result, "endpoint:ep-phone")!.roleKey).toBe("phone");
747
+ });
748
+ });
749
+
750
+ describe("the stamp is deterministic", () => {
751
+ it("produces identical role fields on two builds of the same input", () => {
752
+ /*
753
+ * The map is rebuilt on every poll and on every page load. A role field
754
+ * that varied between builds would make nodes change shape, tier or
755
+ * legend group under an operator watching the same screen.
756
+ */
757
+ const roles: Array<TopologyDeviceRoleInput> = seededRolesWith("router", {
758
+ name: "Edge Router",
759
+ });
760
+
761
+ const first: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
762
+ estateDevices(),
763
+ now,
764
+ [],
765
+ estateEndpoints(),
766
+ [],
767
+ new Set<string>(),
768
+ roles,
769
+ );
770
+ const second: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
771
+ estateDevices(),
772
+ now,
773
+ [],
774
+ estateEndpoints(),
775
+ [],
776
+ new Set<string>(),
777
+ roles,
778
+ );
779
+
780
+ expect(second.nodes).toStrictEqual(first.nodes);
781
+ });
782
+
783
+ it("ignores the order the catalogue rows arrive in", () => {
784
+ /*
785
+ * Rows come off a query ordered by the settings page's `order` column,
786
+ * and an operator may reorder that list at any time. Reordering the
787
+ * legend must not change a single thing about how a node is drawn.
788
+ */
789
+ const roles: Array<TopologyDeviceRoleInput> = seededRoles();
790
+
791
+ const forward: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
792
+ estateDevices(),
793
+ now,
794
+ [],
795
+ estateEndpoints(),
796
+ [],
797
+ new Set<string>(),
798
+ roles,
799
+ );
800
+ const reversed: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
801
+ estateDevices(),
802
+ now,
803
+ [],
804
+ estateEndpoints(),
805
+ [],
806
+ new Set<string>(),
807
+ [...roles].reverse(),
808
+ );
809
+
810
+ expect(reversed.nodes).toStrictEqual(forward.nodes);
811
+ });
812
+
813
+ it("resolves each device's stamp independently of the device query order", () => {
814
+ const roles: Array<TopologyDeviceRoleInput> = seededRoles();
815
+ const devices: Array<TopologyDeviceInput> = estateDevices();
816
+
817
+ const forward: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
818
+ devices,
819
+ now,
820
+ [],
821
+ [],
822
+ [],
823
+ new Set<string>(),
824
+ roles,
825
+ );
826
+ const reversed: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
827
+ [...devices].reverse(),
828
+ now,
829
+ [],
830
+ [],
831
+ [],
832
+ new Set<string>(),
833
+ roles,
834
+ );
835
+
836
+ for (const deviceId of ["d-router", "d-switch", "d-blank"]) {
837
+ expect(nodeById(reversed, deviceId)).toStrictEqual(
838
+ nodeById(forward, deviceId),
839
+ );
840
+ }
841
+ });
842
+
843
+ it("does not modify the catalogue it was handed", () => {
844
+ /*
845
+ * The API loads the project's roles once and may reuse the array. A
846
+ * builder that wrote back into it would corrupt the next build in the
847
+ * same request.
848
+ */
849
+ const roles: Array<TopologyDeviceRoleInput> = seededRoles();
850
+ const before: string = JSON.stringify(roles);
851
+
852
+ NetworkTopologyUtil.buildTopology(
853
+ estateDevices(),
854
+ now,
855
+ [],
856
+ estateEndpoints(),
857
+ [],
858
+ new Set<string>(),
859
+ roles,
860
+ );
861
+
862
+ expect(JSON.stringify(roles)).toBe(before);
863
+ });
864
+ });
865
+ });