@oneuptime/common 11.6.1 → 11.7.0

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 (420) hide show
  1. package/Models/AnalyticsModels/Index.ts +4 -0
  2. package/Models/AnalyticsModels/KubernetesCostAllocation.ts +842 -0
  3. package/Models/AnalyticsModels/NetworkFlow.ts +54 -0
  4. package/Models/AnalyticsModels/SloHistory.ts +243 -0
  5. package/Models/DatabaseModels/Index.ts +20 -0
  6. package/Models/DatabaseModels/NetworkDevice.ts +453 -6
  7. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +7 -6
  8. package/Models/DatabaseModels/NetworkEndpoint.ts +753 -0
  9. package/Models/DatabaseModels/NetworkSite.ts +1155 -0
  10. package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +517 -0
  11. package/Models/DatabaseModels/NetworkSiteLink.ts +611 -0
  12. package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +520 -0
  13. package/Models/DatabaseModels/NetworkSiteType.ts +499 -0
  14. package/Models/DatabaseModels/ServiceLevelObjective.ts +1115 -0
  15. package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +762 -0
  16. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +444 -0
  17. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +443 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.ts +359 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.ts +48 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.ts +65 -0
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.ts +88 -0
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.ts +391 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1785066759532-MigrationName.ts +30 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
  25. package/Server/Services/AnalyticsDatabaseService.ts +25 -9
  26. package/Server/Services/Index.ts +24 -0
  27. package/Server/Services/KubernetesCostAllocationService.ts +14 -0
  28. package/Server/Services/MetricService.ts +21 -2
  29. package/Server/Services/MonitorService.ts +22 -0
  30. package/Server/Services/NetworkDeviceService.ts +438 -2
  31. package/Server/Services/NetworkEndpointService.ts +414 -0
  32. package/Server/Services/NetworkSiteAssignmentRuleService.ts +98 -0
  33. package/Server/Services/NetworkSiteLinkService.ts +10 -0
  34. package/Server/Services/NetworkSiteService.ts +1254 -0
  35. package/Server/Services/NetworkSiteStatusTimelineService.ts +10 -0
  36. package/Server/Services/NetworkSiteTypeService.ts +10 -0
  37. package/Server/Services/ProjectService.ts +122 -2
  38. package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +457 -0
  39. package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +10 -0
  40. package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +10 -0
  41. package/Server/Services/ServiceLevelObjectiveService.ts +685 -0
  42. package/Server/Services/SloHistoryService.ts +101 -0
  43. package/Server/Services/UserNotificationSettingService.ts +37 -0
  44. package/Server/Types/AnalyticsDatabase/AggregateBy.ts +9 -0
  45. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +15 -0
  46. package/Server/Utils/AnalyticsDatabase/Statement.ts +39 -3
  47. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +87 -48
  48. package/Server/Utils/Memory.ts +9 -1
  49. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +190 -12
  50. package/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
  51. package/Server/Utils/Monitor/DnsResolutionCache.ts +129 -0
  52. package/Server/Utils/Monitor/MonitorResource.ts +4 -30
  53. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +214 -39
  54. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +343 -0
  55. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +251 -0
  56. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +176 -142
  57. package/Server/Utils/Monitor/OuiLookupUtil.ts +49 -0
  58. package/Server/Utils/Monitor/SnmpInterfaceRateUtil.ts +17 -13
  59. package/Server/Utils/WhatsAppTemplateUtil.ts +7 -3
  60. package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +135 -0
  61. package/Tests/Models/NetworkSiteHierarchy.test.ts +134 -0
  62. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +239 -0
  63. package/Tests/Server/Services/KubernetesCostAllocationAggregate.test.ts +338 -0
  64. package/Tests/Server/Services/MetricServiceAggregate.test.ts +142 -0
  65. package/Tests/Server/Services/NetworkDeviceSiteAssignment.test.ts +484 -0
  66. package/Tests/Server/Services/NetworkEndpointServiceUpsert.test.ts +686 -0
  67. package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +185 -0
  68. package/Tests/Server/Services/NetworkSiteService.test.ts +1354 -0
  69. package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +1313 -0
  70. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +1988 -0
  71. package/Tests/Server/Utils/AnalyticsDatabase/Statement.test.ts +22 -0
  72. package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +404 -0
  73. package/Tests/Server/Utils/Encryption.test.ts +70 -0
  74. package/Tests/Server/Utils/FileAttachmentMarkdownUtil.test.ts +225 -0
  75. package/Tests/Server/Utils/JsonWebToken.test.ts +175 -0
  76. package/Tests/Server/Utils/LocalFile.test.ts +258 -0
  77. package/Tests/Server/Utils/Memory.test.ts +213 -0
  78. package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +30 -0
  79. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +385 -0
  80. package/Tests/Server/Utils/Monitor/DnsResolutionCache.test.ts +194 -0
  81. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +155 -0
  82. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +600 -0
  83. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +151 -124
  84. package/Tests/Server/Utils/Monitor/SnmpInterfaceRateUtil.test.ts +496 -0
  85. package/Tests/Server/Utils/MonitorCriteriaDataExtractor.test.ts +175 -0
  86. package/Tests/Server/Utils/MonitorCriteriaMessageFormatter.test.ts +282 -0
  87. package/Tests/Server/Utils/OuiLookupUtil.test.ts +59 -0
  88. package/Tests/Server/Utils/SeriesResourceLabels.test.ts +117 -0
  89. package/Tests/Server/Utils/StackTraceParser.test.ts +370 -0
  90. package/Tests/Server/Utils/Stream.test.ts +87 -0
  91. package/Tests/Server/Utils/ValidateGlobalProviderProjectTeams.test.ts +221 -0
  92. package/Tests/Server/Utils/WhatsAppTemplateUtil.test.ts +199 -0
  93. package/Tests/Types/Database/CompareOperatorWireSerialization.test.ts +33 -0
  94. package/Tests/Types/Email.test.ts +198 -0
  95. package/Tests/Types/Kubernetes/KubernetesObjectParser.test.ts +177 -0
  96. package/Tests/Types/Log/LogQueryToFilter.test.ts +111 -0
  97. package/Tests/Types/Monitor/MonitorCriteria.test.ts +155 -0
  98. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +465 -0
  99. package/Tests/Types/Monitor/MonitorStep.test.ts +183 -0
  100. package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +141 -1
  101. package/Tests/Types/Monitor/MonitorSteps.test.ts +183 -0
  102. package/Tests/Types/Monitor/MonitorType.test.ts +59 -1
  103. package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +97 -0
  104. package/Tests/Types/Monitor/SnmpEndpointDiscovery.test.ts +151 -0
  105. package/Tests/Types/Monitor/SnmpVendorTemplate.test.ts +110 -6
  106. package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +129 -0
  107. package/Tests/Types/SerializableObjectDictionary.test.ts +166 -0
  108. package/Tests/Types/Time/RangeStartAndEndDateTime.test.ts +98 -0
  109. package/Tests/Types/WebsiteRequest.test.ts +230 -0
  110. package/Tests/UI/Components/EntityFilterRoundTrip.test.tsx +103 -0
  111. package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +612 -0
  112. package/Tests/UI/Components/ModelTable/FilterDataToQuery.test.ts +275 -0
  113. package/Tests/UI/Utils/LogExport.test.ts +159 -0
  114. package/Tests/UI/Utils/Navigation.test.ts +183 -0
  115. package/Tests/UI/Utils/TableFilterUrlState.test.ts +539 -0
  116. package/Tests/UI/Utils/TableViewUrlState.test.ts +272 -0
  117. package/Tests/Utils/Base64.test.ts +51 -0
  118. package/Tests/Utils/Boolean.test.ts +76 -0
  119. package/Tests/Utils/Crypto.test.ts +48 -0
  120. package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +259 -0
  121. package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +162 -0
  122. package/Tests/Utils/Enum.test.ts +54 -0
  123. package/Tests/Utils/IpCanonicalUtil.test.ts +85 -0
  124. package/Tests/Utils/Memory.test.ts +44 -0
  125. package/Tests/Utils/Metrics/MetricSeriesFingerprint.test.ts +160 -0
  126. package/Tests/Utils/Monitor/EndpointAttachmentUtil.test.ts +836 -0
  127. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +218 -0
  128. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +447 -0
  129. package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +440 -0
  130. package/Tests/Utils/NetworkSite/MaterializedPathUtil.test.ts +205 -0
  131. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +221 -0
  132. package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +283 -0
  133. package/Tests/Utils/ObjectUtil.test.ts +30 -0
  134. package/Tests/Utils/Slo/SloBurnRateRuleState.test.ts +124 -0
  135. package/Tests/Utils/Slo/SloDuration.test.ts +148 -0
  136. package/Tests/Utils/Slo/SloHealth.test.ts +334 -0
  137. package/Tests/Utils/Slo/SloStatusColor.test.ts +89 -0
  138. package/Tests/Utils/Slo/SloUtil.test.ts +1980 -0
  139. package/Tests/Utils/Slo/SloWidgetFormat.test.ts +605 -0
  140. package/Tests/Utils/TechStack.test.ts +50 -0
  141. package/Tests/Utils/Traces/CriticalPath.test.ts +178 -0
  142. package/Types/AnalyticsDatabase/AnalyticsTableName.ts +10 -0
  143. package/Types/BaseDatabase/EqualTo.ts +9 -1
  144. package/Types/BaseDatabase/EqualToOrNull.ts +9 -1
  145. package/Types/BaseDatabase/NotEqual.ts +9 -1
  146. package/Types/Dashboard/DashboardComponentType.ts +1 -0
  147. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
  148. package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +42 -0
  149. package/Types/Dashboard/DashboardTemplates.ts +214 -0
  150. package/Types/Email/EmailTemplateType.ts +2 -0
  151. package/Types/Kubernetes/KubernetesCostIngest.ts +79 -0
  152. package/Types/Monitor/CriteriaFilter.ts +9 -0
  153. package/Types/Monitor/MonitorStep.ts +5 -8
  154. package/Types/Monitor/MonitorStepNetworkDeviceMonitor.ts +27 -5
  155. package/Types/Monitor/MonitorType.ts +15 -5
  156. package/Types/Monitor/SnmpMonitor/ArpEntry.ts +14 -0
  157. package/Types/Monitor/SnmpMonitor/FdbEntry.ts +18 -0
  158. package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +10 -3
  159. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +31 -5
  160. package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +12 -0
  161. package/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.ts +231 -3
  162. package/Types/NetworkSite/DefaultNetworkSiteType.ts +20 -0
  163. package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
  164. package/Types/Permission.ts +449 -0
  165. package/Types/ServiceLevelObjective/SliType.ts +6 -0
  166. package/Types/ServiceLevelObjective/SloMultiMonitorMode.ts +6 -0
  167. package/Types/ServiceLevelObjective/SloStatus.ts +9 -0
  168. package/Types/ServiceLevelObjective/SloWindowType.ts +6 -0
  169. package/Types/Telemetry/ServiceType.ts +1 -0
  170. package/UI/Components/Filters/EntityFilter.tsx +16 -0
  171. package/UI/Components/Filters/FilterViewer.tsx +22 -5
  172. package/UI/Components/List/List.tsx +8 -0
  173. package/UI/Components/ModelTable/BaseModelTable.tsx +309 -106
  174. package/UI/Components/ModelTable/FilterDataToQuery.ts +172 -0
  175. package/UI/Components/Navbar/NavBar.tsx +16 -2
  176. package/UI/Components/Navbar/NavBarMenuModal.tsx +3 -3
  177. package/UI/Utils/Navigation.ts +10 -0
  178. package/UI/Utils/TableFilterUrlState.ts +204 -17
  179. package/UI/Utils/TableViewUrlState.ts +165 -0
  180. package/Utils/Dashboard/Components/DashboardSloComponent.ts +114 -0
  181. package/Utils/Dashboard/Components/Index.ts +7 -0
  182. package/Utils/IpCanonicalUtil.ts +134 -0
  183. package/Utils/Monitor/EndpointAttachmentUtil.ts +508 -0
  184. package/Utils/Monitor/NetworkTopologyUtil.ts +157 -5
  185. package/Utils/NetworkSite/CidrMatchUtil.ts +296 -0
  186. package/Utils/NetworkSite/MaterializedPathUtil.ts +115 -0
  187. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +97 -0
  188. package/Utils/NetworkSite/SiteUptimeUtil.ts +111 -0
  189. package/Utils/Slo/SloBurnRateRuleState.ts +91 -0
  190. package/Utils/Slo/SloDuration.ts +165 -0
  191. package/Utils/Slo/SloEvaluation.ts +22 -0
  192. package/Utils/Slo/SloHealth.ts +302 -0
  193. package/Utils/Slo/SloStatusColor.ts +54 -0
  194. package/Utils/Slo/SloUtil.ts +637 -0
  195. package/Utils/Slo/SloWidgetFormat.ts +383 -0
  196. package/build/dist/Models/AnalyticsModels/Index.js +4 -0
  197. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  198. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +713 -0
  199. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -0
  200. package/build/dist/Models/AnalyticsModels/NetworkFlow.js +44 -0
  201. package/build/dist/Models/AnalyticsModels/NetworkFlow.js.map +1 -1
  202. package/build/dist/Models/AnalyticsModels/SloHistory.js +218 -0
  203. package/build/dist/Models/AnalyticsModels/SloHistory.js.map +1 -0
  204. package/build/dist/Models/DatabaseModels/Index.js +20 -0
  205. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  206. package/build/dist/Models/DatabaseModels/NetworkDevice.js +458 -6
  207. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  208. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +0 -6
  209. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  210. package/build/dist/Models/DatabaseModels/NetworkEndpoint.js +779 -0
  211. package/build/dist/Models/DatabaseModels/NetworkEndpoint.js.map +1 -0
  212. package/build/dist/Models/DatabaseModels/NetworkSite.js +1180 -0
  213. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -0
  214. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +534 -0
  215. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -0
  216. package/build/dist/Models/DatabaseModels/NetworkSiteLink.js +629 -0
  217. package/build/dist/Models/DatabaseModels/NetworkSiteLink.js.map +1 -0
  218. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +538 -0
  219. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -0
  220. package/build/dist/Models/DatabaseModels/NetworkSiteType.js +522 -0
  221. package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -0
  222. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +1134 -0
  223. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -0
  224. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +769 -0
  225. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -0
  226. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +460 -0
  227. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -0
  228. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +459 -0
  229. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -0
  230. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js +130 -0
  231. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js.map +1 -0
  232. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js +31 -0
  233. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js.map +1 -0
  234. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js +36 -0
  235. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js.map +1 -0
  236. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js +49 -0
  237. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js.map +1 -0
  238. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js +140 -0
  239. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js.map +1 -0
  240. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785066759532-MigrationName.js +21 -0
  241. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785066759532-MigrationName.js.map +1 -0
  242. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
  243. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  244. package/build/dist/Server/Services/AnalyticsDatabaseService.js +23 -6
  245. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  246. package/build/dist/Server/Services/Index.js +24 -0
  247. package/build/dist/Server/Services/Index.js.map +1 -1
  248. package/build/dist/Server/Services/KubernetesCostAllocationService.js +12 -0
  249. package/build/dist/Server/Services/KubernetesCostAllocationService.js.map +1 -0
  250. package/build/dist/Server/Services/MetricService.js +21 -3
  251. package/build/dist/Server/Services/MetricService.js.map +1 -1
  252. package/build/dist/Server/Services/MonitorService.js +19 -0
  253. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  254. package/build/dist/Server/Services/NetworkDeviceService.js +351 -1
  255. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  256. package/build/dist/Server/Services/NetworkEndpointService.js +319 -0
  257. package/build/dist/Server/Services/NetworkEndpointService.js.map +1 -0
  258. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +90 -0
  259. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -0
  260. package/build/dist/Server/Services/NetworkSiteLinkService.js +9 -0
  261. package/build/dist/Server/Services/NetworkSiteLinkService.js.map +1 -0
  262. package/build/dist/Server/Services/NetworkSiteService.js +1038 -0
  263. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -0
  264. package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js +9 -0
  265. package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js.map +1 -0
  266. package/build/dist/Server/Services/NetworkSiteTypeService.js +9 -0
  267. package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -0
  268. package/build/dist/Server/Services/ProjectService.js +98 -2
  269. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  270. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +358 -0
  271. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -0
  272. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +9 -0
  273. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -0
  274. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +9 -0
  275. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -0
  276. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +588 -0
  277. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -0
  278. package/build/dist/Server/Services/SloHistoryService.js +77 -0
  279. package/build/dist/Server/Services/SloHistoryService.js.map +1 -0
  280. package/build/dist/Server/Services/UserNotificationSettingService.js +20 -0
  281. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  282. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +9 -0
  283. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
  284. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +15 -0
  285. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  286. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +31 -0
  287. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  288. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +76 -48
  289. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  290. package/build/dist/Server/Utils/Memory.js +9 -1
  291. package/build/dist/Server/Utils/Memory.js.map +1 -1
  292. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +132 -10
  293. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  294. package/build/dist/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
  295. package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js +77 -0
  296. package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js.map +1 -0
  297. package/build/dist/Server/Utils/Monitor/MonitorResource.js +21 -41
  298. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  299. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +152 -40
  300. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  301. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +262 -0
  302. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -0
  303. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +201 -0
  304. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -0
  305. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +152 -120
  306. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  307. package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js +44 -0
  308. package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js.map +1 -0
  309. package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js +10 -10
  310. package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js.map +1 -1
  311. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +5 -0
  312. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
  313. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +10 -0
  314. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
  315. package/build/dist/Types/BaseDatabase/EqualTo.js +9 -1
  316. package/build/dist/Types/BaseDatabase/EqualTo.js.map +1 -1
  317. package/build/dist/Types/BaseDatabase/EqualToOrNull.js +9 -1
  318. package/build/dist/Types/BaseDatabase/EqualToOrNull.js.map +1 -1
  319. package/build/dist/Types/BaseDatabase/NotEqual.js +9 -1
  320. package/build/dist/Types/BaseDatabase/NotEqual.js.map +1 -1
  321. package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
  322. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  323. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
  324. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  325. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js +23 -0
  326. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js.map +1 -0
  327. package/build/dist/Types/Dashboard/DashboardTemplates.js +205 -0
  328. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  329. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  330. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  331. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js +21 -0
  332. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -0
  333. package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
  334. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  335. package/build/dist/Types/Monitor/MonitorStep.js +5 -5
  336. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  337. package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js +8 -0
  338. package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js.map +1 -1
  339. package/build/dist/Types/Monitor/MonitorType.js +15 -5
  340. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  341. package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js +2 -0
  342. package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js.map +1 -0
  343. package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js +2 -0
  344. package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js.map +1 -0
  345. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +9 -3
  346. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
  347. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js +217 -3
  348. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js.map +1 -1
  349. package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js +21 -0
  350. package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js.map +1 -0
  351. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
  352. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  353. package/build/dist/Types/Permission.js +409 -0
  354. package/build/dist/Types/Permission.js.map +1 -1
  355. package/build/dist/Types/ServiceLevelObjective/SliType.js +7 -0
  356. package/build/dist/Types/ServiceLevelObjective/SliType.js.map +1 -0
  357. package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js +7 -0
  358. package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js.map +1 -0
  359. package/build/dist/Types/ServiceLevelObjective/SloStatus.js +10 -0
  360. package/build/dist/Types/ServiceLevelObjective/SloStatus.js.map +1 -0
  361. package/build/dist/Types/ServiceLevelObjective/SloWindowType.js +7 -0
  362. package/build/dist/Types/ServiceLevelObjective/SloWindowType.js.map +1 -0
  363. package/build/dist/Types/Telemetry/ServiceType.js +1 -0
  364. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  365. package/build/dist/UI/Components/Filters/EntityFilter.js +15 -0
  366. package/build/dist/UI/Components/Filters/EntityFilter.js.map +1 -1
  367. package/build/dist/UI/Components/Filters/FilterViewer.js +19 -4
  368. package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
  369. package/build/dist/UI/Components/List/List.js +1 -1
  370. package/build/dist/UI/Components/List/List.js.map +1 -1
  371. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +235 -89
  372. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  373. package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js +96 -0
  374. package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js.map +1 -0
  375. package/build/dist/UI/Components/Navbar/NavBar.js +14 -2
  376. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  377. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +3 -2
  378. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  379. package/build/dist/UI/Utils/Navigation.js +9 -0
  380. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  381. package/build/dist/UI/Utils/TableFilterUrlState.js +159 -15
  382. package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
  383. package/build/dist/UI/Utils/TableViewUrlState.js +103 -0
  384. package/build/dist/UI/Utils/TableViewUrlState.js.map +1 -0
  385. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +93 -0
  386. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -0
  387. package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
  388. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  389. package/build/dist/Utils/IpCanonicalUtil.js +110 -0
  390. package/build/dist/Utils/IpCanonicalUtil.js.map +1 -0
  391. package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js +311 -0
  392. package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js.map +1 -0
  393. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +98 -5
  394. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  395. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +222 -0
  396. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -0
  397. package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js +89 -0
  398. package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js.map +1 -0
  399. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +60 -0
  400. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -0
  401. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +76 -0
  402. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -0
  403. package/build/dist/Utils/Slo/SloBurnRateRuleState.js +35 -0
  404. package/build/dist/Utils/Slo/SloBurnRateRuleState.js.map +1 -0
  405. package/build/dist/Utils/Slo/SloDuration.js +87 -0
  406. package/build/dist/Utils/Slo/SloDuration.js.map +1 -0
  407. package/build/dist/Utils/Slo/SloEvaluation.js +21 -0
  408. package/build/dist/Utils/Slo/SloEvaluation.js.map +1 -0
  409. package/build/dist/Utils/Slo/SloHealth.js +179 -0
  410. package/build/dist/Utils/Slo/SloHealth.js.map +1 -0
  411. package/build/dist/Utils/Slo/SloStatusColor.js +18 -0
  412. package/build/dist/Utils/Slo/SloStatusColor.js.map +1 -0
  413. package/build/dist/Utils/Slo/SloUtil.js +393 -0
  414. package/build/dist/Utils/Slo/SloUtil.js.map +1 -0
  415. package/build/dist/Utils/Slo/SloWidgetFormat.js +174 -0
  416. package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -0
  417. package/package.json +2 -2
  418. package/Types/Dashboard/DashboardComponents/Index.ts +0 -7
  419. package/build/dist/Types/Dashboard/DashboardComponents/Index.js +0 -8
  420. package/build/dist/Types/Dashboard/DashboardComponents/Index.js.map +0 -1
@@ -7,6 +7,7 @@ import NetworkTopology, {
7
7
  } from "../../Types/Monitor/SnmpMonitor/NetworkTopology";
8
8
  import LldpNeighbor from "../../Types/Monitor/SnmpMonitor/LldpNeighbor";
9
9
  import CdpNeighbor from "../../Types/Monitor/SnmpMonitor/CdpNeighbor";
10
+ import { normalizeMac } from "./EndpointAttachmentUtil";
10
11
 
11
12
  export interface TopologyDeviceInput {
12
13
  id: string;
@@ -39,6 +40,36 @@ export interface TopologyInterfaceInput {
39
40
  errorsPerSecond?: number | undefined;
40
41
  }
41
42
 
43
+ /*
44
+ * One discovered endpoint row (NetworkEndpoint), reduced to what rendering
45
+ * needs. Endpoints attach to their switch via an "fdb" edge; rows without a
46
+ * resolvable attachment are dropped (and counted) rather than floated.
47
+ */
48
+ export interface TopologyEndpointInput {
49
+ id: string;
50
+ macAddress: string;
51
+ ipAddress?: string | undefined;
52
+ vendor?: string | undefined;
53
+ classification?: string | undefined;
54
+ vlanId?: number | undefined;
55
+ attachedNetworkDeviceId?: string | undefined;
56
+ attachedInterfaceIndex?: number | undefined;
57
+ attachedPortName?: string | undefined;
58
+ lastSeenAt?: Date | undefined;
59
+ }
60
+
61
+ /*
62
+ * buildTopology's result: the wire-format NetworkTopology plus endpoint
63
+ * bookkeeping. The extra fields are optional on the wire type, so older
64
+ * readers are unaffected.
65
+ */
66
+ export interface TopologyBuildResult extends NetworkTopology {
67
+ // Endpoints skipped because they had no attachment in the graph.
68
+ droppedEndpointCount?: number | undefined;
69
+ // True when more attachable endpoints existed than the render cap allows.
70
+ endpointsTruncated?: boolean | undefined;
71
+ }
72
+
42
73
  /*
43
74
  * A neighbor claim from either discovery protocol, normalized so LLDP and
44
75
  * CDP entries flow through the same match/dedupe/enrich pipeline.
@@ -56,6 +87,9 @@ interface NeighborClaim {
56
87
  // A device not seen within this window is treated as not currently up.
57
88
  const FRESH_WINDOW_MS: number = 15 * 60 * 1000;
58
89
 
90
+ // Endpoint nodes rendered per graph; the slice is deterministic (by MAC).
91
+ const ENDPOINT_RENDER_CAP: number = 2000;
92
+
59
93
  export default class NetworkTopologyUtil {
60
94
  /*
61
95
  * Builds the topology graph from every device in a project. Nodes are the
@@ -66,13 +100,17 @@ export default class NetworkTopologyUtil {
66
100
  * both protocols, appears once with the union of what each report knew
67
101
  * (ports, protocols, per-end interface state). When `interfaces` rows are
68
102
  * provided, each edge end whose interface is identifiable carries its
69
- * operational state (up/down, utilization, rates).
103
+ * operational state (up/down, utilization, rates). When `endpoints` rows
104
+ * are provided, each one that attaches to a device in the graph becomes an
105
+ * "endpoint" node linked by an "fdb" edge (capped, deterministic by MAC);
106
+ * the rest are dropped and counted in droppedEndpointCount.
70
107
  */
71
108
  public static buildTopology(
72
109
  devices: Array<TopologyDeviceInput>,
73
110
  now: Date,
74
111
  interfaces: Array<TopologyInterfaceInput> = [],
75
- ): NetworkTopology {
112
+ endpoints: Array<TopologyEndpointInput> = [],
113
+ ): TopologyBuildResult {
76
114
  const nodes: Array<NetworkTopologyNode> = [];
77
115
 
78
116
  // Index managed devices by the identifiers neighbor entries reference.
@@ -106,6 +144,7 @@ export default class NetworkTopologyUtil {
106
144
  id: device.id,
107
145
  name: device.name,
108
146
  isManaged: true,
147
+ kind: "device",
109
148
  status: NetworkTopologyUtil.deviceStatus(device, now),
110
149
  interfacesUp: device.interfacesUp,
111
150
  interfacesDown: device.interfacesDown,
@@ -145,6 +184,7 @@ export default class NetworkTopologyUtil {
145
184
  id: toNodeId,
146
185
  name: claim.displayName || "Unknown device",
147
186
  isManaged: false,
187
+ kind: "unmanaged",
148
188
  status: "unknown",
149
189
  deviceModel: claim.remotePlatform,
150
190
  };
@@ -262,7 +302,111 @@ export default class NetworkTopologyUtil {
262
302
  }
263
303
  }
264
304
 
265
- return { nodes, edges: Array.from(edgeByKey.values()) };
305
+ const edges: Array<NetworkTopologyEdge> = Array.from(edgeByKey.values());
306
+
307
+ // --- Endpoint nodes + fdb edges ---
308
+
309
+ const deviceNodeIds: Set<string> = new Set(
310
+ devices.map((device: TopologyDeviceInput) => {
311
+ return device.id;
312
+ }),
313
+ );
314
+
315
+ /*
316
+ * Deterministic render order: by normalized MAC, then id, so the capped
317
+ * slice is stable across rebuilds regardless of query order.
318
+ */
319
+ const sortedEndpoints: Array<TopologyEndpointInput> = [...endpoints].sort(
320
+ (a: TopologyEndpointInput, b: TopologyEndpointInput) => {
321
+ const aMac: string = normalizeMac(a.macAddress) || a.macAddress;
322
+ const bMac: string = normalizeMac(b.macAddress) || b.macAddress;
323
+ if (aMac !== bMac) {
324
+ return aMac < bMac ? -1 : 1;
325
+ }
326
+ return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
327
+ },
328
+ );
329
+
330
+ let droppedEndpointCount: number = 0;
331
+ let renderedEndpointCount: number = 0;
332
+ let endpointsTruncated: boolean = false;
333
+
334
+ for (const endpoint of sortedEndpoints) {
335
+ if (
336
+ !endpoint.attachedNetworkDeviceId ||
337
+ !deviceNodeIds.has(endpoint.attachedNetworkDeviceId)
338
+ ) {
339
+ // No attachment in this graph — nothing to hang the node off.
340
+ droppedEndpointCount++;
341
+ continue;
342
+ }
343
+
344
+ if (renderedEndpointCount >= ENDPOINT_RENDER_CAP) {
345
+ endpointsTruncated = true;
346
+ continue;
347
+ }
348
+ renderedEndpointCount++;
349
+
350
+ const nodeId: string = `endpoint:${endpoint.id}`;
351
+ nodes.push({
352
+ id: nodeId,
353
+ name:
354
+ endpoint.classification ||
355
+ endpoint.vendor ||
356
+ endpoint.ipAddress ||
357
+ endpoint.macAddress,
358
+ isManaged: false,
359
+ kind: "endpoint",
360
+ status: NetworkTopologyUtil.statusFromLastSeen(
361
+ endpoint.lastSeenAt,
362
+ now,
363
+ ),
364
+ vendor: endpoint.vendor,
365
+ macAddress: endpoint.macAddress,
366
+ ipAddress: endpoint.ipAddress,
367
+ classification: endpoint.classification,
368
+ vlanId: endpoint.vlanId,
369
+ });
370
+
371
+ // Port label + interface state on the switch end, when identifiable.
372
+ let switchInterface: TopologyInterfaceInput | undefined = undefined;
373
+ if (endpoint.attachedInterfaceIndex !== undefined) {
374
+ switchInterface = interfaceByDeviceAndIndex.get(
375
+ `${endpoint.attachedNetworkDeviceId}::${endpoint.attachedInterfaceIndex}`,
376
+ );
377
+ }
378
+ let fromPort: string | undefined =
379
+ endpoint.attachedPortName || switchInterface?.name;
380
+ if (!fromPort && endpoint.attachedInterfaceIndex !== undefined) {
381
+ fromPort = `if${endpoint.attachedInterfaceIndex}`;
382
+ }
383
+
384
+ edges.push({
385
+ fromNodeId: endpoint.attachedNetworkDeviceId,
386
+ toNodeId: nodeId,
387
+ fromPort: fromPort,
388
+ protocols: ["fdb"],
389
+ fromInterface: switchInterface
390
+ ? {
391
+ interfaceIndex: switchInterface.interfaceIndex,
392
+ interfaceName: switchInterface.name,
393
+ isOperationallyUp: switchInterface.isOperationallyUp,
394
+ isAdministrativelyUp: switchInterface.isAdministrativelyUp,
395
+ utilizationPercent: switchInterface.utilizationPercent,
396
+ inRateMbps: switchInterface.inRateMbps,
397
+ outRateMbps: switchInterface.outRateMbps,
398
+ errorsPerSecond: switchInterface.errorsPerSecond,
399
+ }
400
+ : undefined,
401
+ });
402
+ }
403
+
404
+ return {
405
+ nodes,
406
+ edges,
407
+ droppedEndpointCount,
408
+ endpointsTruncated,
409
+ };
266
410
  }
267
411
 
268
412
  /*
@@ -359,10 +503,18 @@ export default class NetworkTopologyUtil {
359
503
  device: TopologyDeviceInput,
360
504
  now: Date,
361
505
  ): NetworkTopologyNodeStatus {
362
- if (!device.lastSeenAt) {
506
+ return NetworkTopologyUtil.statusFromLastSeen(device.lastSeenAt, now);
507
+ }
508
+
509
+ // The shared freshness rule: seen within the window = up, stale = down.
510
+ private static statusFromLastSeen(
511
+ lastSeenAt: Date | undefined,
512
+ now: Date,
513
+ ): NetworkTopologyNodeStatus {
514
+ if (!lastSeenAt) {
363
515
  return "unknown";
364
516
  }
365
- const ageMs: number = now.getTime() - new Date(device.lastSeenAt).getTime();
517
+ const ageMs: number = now.getTime() - new Date(lastSeenAt).getTime();
366
518
  if (ageMs > FRESH_WINDOW_MS) {
367
519
  return "down";
368
520
  }
@@ -0,0 +1,296 @@
1
+ /*
2
+ * Matching helpers for NetworkSite auto-assignment rules: IPv4 CIDR
3
+ * containment, case-insensitive '*' wildcard hostname patterns, and the
4
+ * highest-priority-wins rule picker. Pure and dependency-free so the rule
5
+ * engine's decisions are unit-testable.
6
+ */
7
+
8
+ // The shape NetworkSiteAssignmentRule rows are matched with.
9
+ export interface AssignmentRuleCandidate {
10
+ subnetCidr?: string | null | undefined;
11
+ hostnamePattern?: string | null | undefined;
12
+ priority?: number | null | undefined;
13
+ createdAt?: Date | null | undefined;
14
+ }
15
+
16
+ // The device attributes a rule is evaluated against.
17
+ export interface RuleMatchTarget {
18
+ ip?: string | null | undefined;
19
+ hostname?: string | null | undefined;
20
+ sysName?: string | null | undefined;
21
+ }
22
+
23
+ export class CidrMatchUtil {
24
+ /*
25
+ * Longest hostname pattern we will evaluate. The column itself is
26
+ * ShortText (100), and a DNS name tops out at 253 characters, so anything
27
+ * longer is either a mistake or an attempt to make matching expensive.
28
+ */
29
+ public static readonly MAX_HOSTNAME_PATTERN_LENGTH: number = 253;
30
+
31
+ /*
32
+ * Hoisted out of the call sites so the literals are not the object of a
33
+ * member expression, which `wrap-regex` and Prettier cannot agree on.
34
+ */
35
+ private static readonly PREFIX_LENGTH_PATTERN: RegExp = /^\d{1,2}$/;
36
+
37
+ private static readonly OCTET_PATTERN: RegExp = /^\d{1,3}$/;
38
+
39
+ /*
40
+ * True when the IPv4 address `ip` falls inside `cidr` ('10.0.0.0/8').
41
+ * Prefixes /0 through /32 are supported; a bare address is treated as /32.
42
+ * Any invalid input returns false instead of throwing.
43
+ */
44
+ public static ipInCidr(ip: string, cidr: string): boolean {
45
+ const ipValue: number | null = CidrMatchUtil.parseIpv4(ip);
46
+ if (ipValue === null) {
47
+ return false;
48
+ }
49
+
50
+ if (typeof cidr !== "string" || cidr.trim().length === 0) {
51
+ return false;
52
+ }
53
+
54
+ const parts: Array<string> = cidr.trim().split("/");
55
+ if (parts.length > 2) {
56
+ return false;
57
+ }
58
+
59
+ const baseValue: number | null = CidrMatchUtil.parseIpv4(parts[0] || "");
60
+ if (baseValue === null) {
61
+ return false;
62
+ }
63
+
64
+ let prefixLength: number = 32;
65
+ if (parts.length === 2) {
66
+ const prefixText: string = parts[1] || "";
67
+ if (!CidrMatchUtil.PREFIX_LENGTH_PATTERN.test(prefixText)) {
68
+ return false;
69
+ }
70
+ prefixLength = parseInt(prefixText, 10);
71
+ if (prefixLength < 0 || prefixLength > 32) {
72
+ return false;
73
+ }
74
+ }
75
+
76
+ /*
77
+ * JS bitwise ops are 32-bit signed; >>> 0 keeps the mask and the masked
78
+ * addresses unsigned. A shift by 32 is a no-op in JS, so /0 is special
79
+ * cased to the all-zero mask (matches everything).
80
+ */
81
+ const mask: number =
82
+ prefixLength === 0 ? 0 : (0xffffffff << (32 - prefixLength)) >>> 0;
83
+
84
+ return (ipValue & mask) >>> 0 === (baseValue & mask) >>> 0;
85
+ }
86
+
87
+ // True when `cidr` is a well-formed IPv4 CIDR (or bare address == /32).
88
+ public static isValidCidr(cidr: string): boolean {
89
+ if (typeof cidr !== "string" || cidr.trim().length === 0) {
90
+ return false;
91
+ }
92
+ const parts: Array<string> = cidr.trim().split("/");
93
+ if (parts.length > 2) {
94
+ return false;
95
+ }
96
+ if (CidrMatchUtil.parseIpv4(parts[0] || "") === null) {
97
+ return false;
98
+ }
99
+ if (parts.length === 2) {
100
+ const prefixText: string = parts[1] || "";
101
+ if (!CidrMatchUtil.PREFIX_LENGTH_PATTERN.test(prefixText)) {
102
+ return false;
103
+ }
104
+ const prefixLength: number = parseInt(prefixText, 10);
105
+ if (prefixLength < 0 || prefixLength > 32) {
106
+ return false;
107
+ }
108
+ }
109
+ return true;
110
+ }
111
+
112
+ /*
113
+ * Case-insensitive wildcard match where '*' matches any run of characters
114
+ * (including none) and every other character is literal. The pattern must
115
+ * cover the whole hostname. Non-string or missing inputs never match, and
116
+ * so does an over-long pattern.
117
+ *
118
+ * Deliberately NOT a regex: compiling a user-authored pattern into
119
+ * /^.*a.*a.*a...$/ makes the backtracking engine explore an exponential
120
+ * number of split points on a long homogeneous input, which blocks the
121
+ * event loop for minutes. This matcher is O(hostname x pattern) worst case
122
+ * with no recursion, so a hostile rule cannot hang the process.
123
+ */
124
+ public static hostnameMatchesWildcard(
125
+ hostname: string,
126
+ pattern: string,
127
+ ): boolean {
128
+ if (typeof hostname !== "string" || typeof pattern !== "string") {
129
+ return false;
130
+ }
131
+
132
+ const text: string = hostname.trim().toLowerCase();
133
+ const glob: string = pattern.trim().toLowerCase();
134
+
135
+ if (glob.length > CidrMatchUtil.MAX_HOSTNAME_PATTERN_LENGTH) {
136
+ return false;
137
+ }
138
+
139
+ /*
140
+ * Greedy two-pointer glob match. On a mismatch we rewind only to the
141
+ * most recent '*' and advance the character it consumed by one, so each
142
+ * character of the hostname is revisited at most once per '*'.
143
+ */
144
+ let textIndex: number = 0;
145
+ let globIndex: number = 0;
146
+ let lastStarIndex: number = -1;
147
+ let textIndexAtLastStar: number = 0;
148
+
149
+ while (textIndex < text.length) {
150
+ if (globIndex < glob.length && glob[globIndex] === "*") {
151
+ lastStarIndex = globIndex;
152
+ textIndexAtLastStar = textIndex;
153
+ globIndex++;
154
+ } else if (
155
+ globIndex < glob.length &&
156
+ glob[globIndex] === text[textIndex]
157
+ ) {
158
+ globIndex++;
159
+ textIndex++;
160
+ } else if (lastStarIndex !== -1) {
161
+ globIndex = lastStarIndex + 1;
162
+ textIndexAtLastStar++;
163
+ textIndex = textIndexAtLastStar;
164
+ } else {
165
+ return false;
166
+ }
167
+ }
168
+
169
+ // Any trailing '*' in the pattern can still match the empty remainder.
170
+ while (globIndex < glob.length && glob[globIndex] === "*") {
171
+ globIndex++;
172
+ }
173
+
174
+ return globIndex === glob.length;
175
+ }
176
+
177
+ /*
178
+ * True when the rule's populated criteria all match the target. A CIDR
179
+ * criterion matches the target's ip; a hostname pattern matches either the
180
+ * hostname or the SNMP sysName. A rule with no criteria never matches.
181
+ */
182
+ public static ruleMatches(
183
+ rule: AssignmentRuleCandidate,
184
+ target: RuleMatchTarget,
185
+ ): boolean {
186
+ const hasCidr: boolean = Boolean(
187
+ rule.subnetCidr && rule.subnetCidr.trim().length > 0,
188
+ );
189
+ const hasPattern: boolean = Boolean(
190
+ rule.hostnamePattern && rule.hostnamePattern.trim().length > 0,
191
+ );
192
+
193
+ if (!hasCidr && !hasPattern) {
194
+ return false;
195
+ }
196
+
197
+ if (hasCidr) {
198
+ if (!target.ip || !CidrMatchUtil.ipInCidr(target.ip, rule.subnetCidr!)) {
199
+ return false;
200
+ }
201
+ }
202
+
203
+ if (hasPattern) {
204
+ const matchesHostname: boolean = Boolean(
205
+ target.hostname &&
206
+ CidrMatchUtil.hostnameMatchesWildcard(
207
+ target.hostname,
208
+ rule.hostnamePattern!,
209
+ ),
210
+ );
211
+ const matchesSysName: boolean = Boolean(
212
+ target.sysName &&
213
+ CidrMatchUtil.hostnameMatchesWildcard(
214
+ target.sysName,
215
+ rule.hostnamePattern!,
216
+ ),
217
+ );
218
+ if (!matchesHostname && !matchesSysName) {
219
+ return false;
220
+ }
221
+ }
222
+
223
+ return true;
224
+ }
225
+
226
+ /*
227
+ * Picks the winning rule for a target: among matching rules the highest
228
+ * priority number wins; ties go to the earlier createdAt when both rows
229
+ * carry one, otherwise the earlier rule in the input order (stable).
230
+ * Returns null when nothing matches.
231
+ */
232
+ public static pickRule<T extends AssignmentRuleCandidate>(
233
+ rules: Array<T>,
234
+ target: RuleMatchTarget,
235
+ ): T | null {
236
+ let best: T | null = null;
237
+
238
+ for (const rule of rules) {
239
+ if (!CidrMatchUtil.ruleMatches(rule, target)) {
240
+ continue;
241
+ }
242
+
243
+ if (!best) {
244
+ best = rule;
245
+ continue;
246
+ }
247
+
248
+ const bestPriority: number = best.priority || 0;
249
+ const rulePriority: number = rule.priority || 0;
250
+
251
+ if (rulePriority > bestPriority) {
252
+ best = rule;
253
+ continue;
254
+ }
255
+
256
+ if (
257
+ rulePriority === bestPriority &&
258
+ rule.createdAt &&
259
+ best.createdAt &&
260
+ rule.createdAt.getTime() < best.createdAt.getTime()
261
+ ) {
262
+ best = rule;
263
+ }
264
+ }
265
+
266
+ return best;
267
+ }
268
+
269
+ // '10.0.0.1' -> unsigned 32-bit value; anything malformed -> null.
270
+ private static parseIpv4(ip: string): number | null {
271
+ if (typeof ip !== "string") {
272
+ return null;
273
+ }
274
+
275
+ const octets: Array<string> = ip.trim().split(".");
276
+ if (octets.length !== 4) {
277
+ return null;
278
+ }
279
+
280
+ let value: number = 0;
281
+ for (const octetText of octets) {
282
+ if (!CidrMatchUtil.OCTET_PATTERN.test(octetText)) {
283
+ return null;
284
+ }
285
+ const octet: number = parseInt(octetText, 10);
286
+ if (octet > 255) {
287
+ return null;
288
+ }
289
+ value = (value * 256 + octet) >>> 0;
290
+ }
291
+
292
+ return value;
293
+ }
294
+ }
295
+
296
+ export default CidrMatchUtil;
@@ -0,0 +1,115 @@
1
+ /*
2
+ * Materialized-path helpers for the NetworkSite hierarchy.
3
+ *
4
+ * A site's path is the slash-separated list of its ancestor IDs ending with
5
+ * its own ID, in '/rootId/childId/.../ownId/' form. Root sites have the path
6
+ * '/ownId/'. All helpers are pure string operations so the tree math is
7
+ * unit-testable without a database.
8
+ */
9
+ export class MaterializedPathUtil {
10
+ /*
11
+ * Builds the path for a site given its parent's path (null/undefined/empty
12
+ * for root sites). Tolerates a parent path missing its leading or trailing
13
+ * slash so a hand-edited row cannot poison every child path built from it.
14
+ */
15
+ public static buildPath(
16
+ parentPath: string | null | undefined,
17
+ siteId: string,
18
+ ): string {
19
+ const normalizedParent: string = MaterializedPathUtil.normalizePath(
20
+ parentPath || "",
21
+ );
22
+ return `${normalizedParent || "/"}${siteId}/`;
23
+ }
24
+
25
+ // '/a/b/' -> ['a', 'b']; invalid/empty input -> [].
26
+ public static segmentsOf(path: string | null | undefined): Array<string> {
27
+ if (!path || typeof path !== "string") {
28
+ return [];
29
+ }
30
+ return path.split("/").filter((segment: string) => {
31
+ return segment.length > 0;
32
+ });
33
+ }
34
+
35
+ /*
36
+ * Number of ancestors above the site this path belongs to: '/a/' -> 0,
37
+ * '/a/b/' -> 1. Empty/invalid paths report 0.
38
+ */
39
+ public static depthOf(path: string | null | undefined): number {
40
+ const segments: Array<string> = MaterializedPathUtil.segmentsOf(path);
41
+ return segments.length > 0 ? segments.length - 1 : 0;
42
+ }
43
+
44
+ /*
45
+ * True when `path` belongs to a strict descendant of the site that owns
46
+ * `ancestorPath` (a site is not its own descendant).
47
+ */
48
+ public static isDescendant(
49
+ path: string | null | undefined,
50
+ ancestorPath: string | null | undefined,
51
+ ): boolean {
52
+ if (!path || !ancestorPath) {
53
+ return false;
54
+ }
55
+ const normalizedPath: string = MaterializedPathUtil.normalizePath(path);
56
+ const normalizedAncestor: string =
57
+ MaterializedPathUtil.normalizePath(ancestorPath);
58
+ return (
59
+ normalizedPath.startsWith(normalizedAncestor) &&
60
+ normalizedPath !== normalizedAncestor
61
+ );
62
+ }
63
+
64
+ /*
65
+ * True when making the site with `siteId` a child of the site whose path is
66
+ * `newParentPath` would create a cycle - i.e. the proposed parent is the
67
+ * site itself or one of its descendants (its own ID appears anywhere in the
68
+ * parent's path). A null/empty parent path (becoming a root) can never
69
+ * create a cycle.
70
+ */
71
+ public static wouldCreateCycle(
72
+ siteId: string,
73
+ newParentPath: string | null | undefined,
74
+ ): boolean {
75
+ if (!siteId || !newParentPath) {
76
+ return false;
77
+ }
78
+ const segments: Array<string> =
79
+ MaterializedPathUtil.segmentsOf(newParentPath);
80
+ return segments.includes(siteId);
81
+ }
82
+
83
+ /*
84
+ * Rewrites subtree paths for a move: every affected path that starts with
85
+ * `oldParentPath` gets that prefix replaced with `newParentPath`. Paths
86
+ * outside the moved subtree are returned unchanged, in input order.
87
+ */
88
+ public static rebasePaths(
89
+ oldParentPath: string,
90
+ newParentPath: string,
91
+ affectedPaths: Array<string>,
92
+ ): Array<string> {
93
+ const oldPrefix: string = MaterializedPathUtil.normalizePath(oldParentPath);
94
+ const newPrefix: string = MaterializedPathUtil.normalizePath(newParentPath);
95
+
96
+ return affectedPaths.map((path: string) => {
97
+ const normalized: string = MaterializedPathUtil.normalizePath(path);
98
+ if (!oldPrefix || !normalized.startsWith(oldPrefix)) {
99
+ return path;
100
+ }
101
+ return `${newPrefix}${normalized.slice(oldPrefix.length)}`;
102
+ });
103
+ }
104
+
105
+ // Ensures '/a/b/' form: leading + trailing slash, no empty segments.
106
+ private static normalizePath(path: string): string {
107
+ const segments: Array<string> = MaterializedPathUtil.segmentsOf(path);
108
+ if (segments.length === 0) {
109
+ return "";
110
+ }
111
+ return `/${segments.join("/")}/`;
112
+ }
113
+ }
114
+
115
+ export default MaterializedPathUtil;