@oneuptime/common 11.6.0 → 11.6.2

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 (427) hide show
  1. package/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.ts +41 -24
  2. package/Models/AnalyticsModels/Index.ts +4 -0
  3. package/Models/AnalyticsModels/KubernetesCostAllocation.ts +842 -0
  4. package/Models/AnalyticsModels/MetricBaselineHourly.ts +2 -0
  5. package/Models/AnalyticsModels/MetricItemAggMV1m.ts +5 -2
  6. package/Models/AnalyticsModels/MetricItemAggMV1mByContainer.ts +5 -2
  7. package/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.ts +5 -2
  8. package/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +5 -2
  9. package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +5 -2
  10. package/Models/AnalyticsModels/NetworkFlow.ts +54 -0
  11. package/Models/AnalyticsModels/SloHistory.ts +240 -0
  12. package/Models/DatabaseModels/Index.ts +20 -0
  13. package/Models/DatabaseModels/NetworkDevice.ts +453 -6
  14. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +7 -6
  15. package/Models/DatabaseModels/NetworkEndpoint.ts +753 -0
  16. package/Models/DatabaseModels/NetworkSite.ts +1155 -0
  17. package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +517 -0
  18. package/Models/DatabaseModels/NetworkSiteLink.ts +611 -0
  19. package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +520 -0
  20. package/Models/DatabaseModels/NetworkSiteType.ts +499 -0
  21. package/Models/DatabaseModels/ServiceLevelObjective.ts +1106 -0
  22. package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +762 -0
  23. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +444 -0
  24. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +443 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.ts +359 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.ts +48 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.ts +65 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.ts +88 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.ts +391 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  31. package/Server/Services/AnalyticsDatabaseService.ts +38 -10
  32. package/Server/Services/Index.ts +24 -0
  33. package/Server/Services/KubernetesCostAllocationService.ts +14 -0
  34. package/Server/Services/MetricService.ts +21 -2
  35. package/Server/Services/MonitorService.ts +22 -0
  36. package/Server/Services/NetworkDeviceService.ts +438 -2
  37. package/Server/Services/NetworkEndpointService.ts +414 -0
  38. package/Server/Services/NetworkSiteAssignmentRuleService.ts +98 -0
  39. package/Server/Services/NetworkSiteLinkService.ts +10 -0
  40. package/Server/Services/NetworkSiteService.ts +1254 -0
  41. package/Server/Services/NetworkSiteStatusTimelineService.ts +10 -0
  42. package/Server/Services/NetworkSiteTypeService.ts +10 -0
  43. package/Server/Services/ProjectService.ts +122 -2
  44. package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +457 -0
  45. package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +10 -0
  46. package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +10 -0
  47. package/Server/Services/ServiceLevelObjectiveService.ts +677 -0
  48. package/Server/Services/SloHistoryService.ts +101 -0
  49. package/Server/Services/UserNotificationSettingService.ts +37 -0
  50. package/Server/Types/AnalyticsDatabase/AggregateBy.ts +9 -0
  51. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +15 -0
  52. package/Server/Utils/AnalyticsDatabase/Statement.ts +39 -3
  53. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +128 -52
  54. package/Server/Utils/Memory.ts +9 -1
  55. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +190 -12
  56. package/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
  57. package/Server/Utils/Monitor/DnsResolutionCache.ts +129 -0
  58. package/Server/Utils/Monitor/MonitorResource.ts +4 -30
  59. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +214 -39
  60. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +343 -0
  61. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +251 -0
  62. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +176 -142
  63. package/Server/Utils/Monitor/OuiLookupUtil.ts +49 -0
  64. package/Server/Utils/Monitor/SnmpInterfaceRateUtil.ts +17 -13
  65. package/Server/Utils/WhatsAppTemplateUtil.ts +7 -3
  66. package/Tests/Models/AnalyticsModels/AnalyticsBaseModel.test.ts +122 -0
  67. package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +135 -0
  68. package/Tests/Models/NetworkSiteHierarchy.test.ts +134 -0
  69. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +239 -0
  70. package/Tests/Server/Services/KubernetesCostAllocationAggregate.test.ts +338 -0
  71. package/Tests/Server/Services/MetricServiceAggregate.test.ts +142 -0
  72. package/Tests/Server/Services/NetworkDeviceSiteAssignment.test.ts +484 -0
  73. package/Tests/Server/Services/NetworkEndpointServiceUpsert.test.ts +686 -0
  74. package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +185 -0
  75. package/Tests/Server/Services/NetworkSiteService.test.ts +1354 -0
  76. package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +1313 -0
  77. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +1988 -0
  78. package/Tests/Server/Utils/AnalyticsDatabase/ClusterAwareSchema.test.ts +164 -3
  79. package/Tests/Server/Utils/AnalyticsDatabase/Statement.test.ts +22 -0
  80. package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +503 -0
  81. package/Tests/Server/Utils/Encryption.test.ts +70 -0
  82. package/Tests/Server/Utils/FileAttachmentMarkdownUtil.test.ts +225 -0
  83. package/Tests/Server/Utils/JsonWebToken.test.ts +175 -0
  84. package/Tests/Server/Utils/LocalFile.test.ts +258 -0
  85. package/Tests/Server/Utils/Memory.test.ts +213 -0
  86. package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +30 -0
  87. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +385 -0
  88. package/Tests/Server/Utils/Monitor/DnsResolutionCache.test.ts +194 -0
  89. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +155 -0
  90. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +600 -0
  91. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +151 -124
  92. package/Tests/Server/Utils/Monitor/SnmpInterfaceRateUtil.test.ts +496 -0
  93. package/Tests/Server/Utils/MonitorCriteriaDataExtractor.test.ts +175 -0
  94. package/Tests/Server/Utils/MonitorCriteriaMessageFormatter.test.ts +282 -0
  95. package/Tests/Server/Utils/OuiLookupUtil.test.ts +59 -0
  96. package/Tests/Server/Utils/SeriesResourceLabels.test.ts +117 -0
  97. package/Tests/Server/Utils/StackTraceParser.test.ts +370 -0
  98. package/Tests/Server/Utils/Stream.test.ts +87 -0
  99. package/Tests/Server/Utils/ValidateGlobalProviderProjectTeams.test.ts +221 -0
  100. package/Tests/Server/Utils/WhatsAppTemplateUtil.test.ts +199 -0
  101. package/Tests/Types/Database/CompareOperatorWireSerialization.test.ts +33 -0
  102. package/Tests/Types/Email.test.ts +198 -0
  103. package/Tests/Types/HashCode.test.ts +41 -0
  104. package/Tests/Types/Kubernetes/KubernetesObjectParser.test.ts +177 -0
  105. package/Tests/Types/Log/LogQueryParser.test.ts +186 -0
  106. package/Tests/Types/Log/LogQueryToFilter.test.ts +111 -0
  107. package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +141 -1
  108. package/Tests/Types/Monitor/MonitorType.test.ts +59 -1
  109. package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +97 -0
  110. package/Tests/Types/Monitor/SnmpEndpointDiscovery.test.ts +151 -0
  111. package/Tests/Types/Monitor/SnmpVendorTemplate.test.ts +110 -6
  112. package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +129 -0
  113. package/Tests/Types/SerializableObjectDictionary.test.ts +166 -0
  114. package/Tests/Types/Time/RangeStartAndEndDateTime.test.ts +98 -0
  115. package/Tests/Types/WebsiteRequest.test.ts +230 -0
  116. package/Tests/UI/Components/EntityFilterRoundTrip.test.tsx +103 -0
  117. package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +612 -0
  118. package/Tests/UI/Components/ModelTable/FilterDataToQuery.test.ts +275 -0
  119. package/Tests/UI/Utils/LogExport.test.ts +159 -0
  120. package/Tests/UI/Utils/Navigation.test.ts +183 -0
  121. package/Tests/UI/Utils/TableFilterUrlState.test.ts +539 -0
  122. package/Tests/UI/Utils/TableViewUrlState.test.ts +272 -0
  123. package/Tests/Utils/Base64.test.ts +51 -0
  124. package/Tests/Utils/Boolean.test.ts +76 -0
  125. package/Tests/Utils/Crypto.test.ts +48 -0
  126. package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +259 -0
  127. package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +162 -0
  128. package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +197 -0
  129. package/Tests/Utils/Enum.test.ts +54 -0
  130. package/Tests/Utils/IpCanonicalUtil.test.ts +85 -0
  131. package/Tests/Utils/Metrics/MetricSeriesFingerprint.test.ts +160 -0
  132. package/Tests/Utils/Monitor/EndpointAttachmentUtil.test.ts +836 -0
  133. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +218 -0
  134. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +447 -0
  135. package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +440 -0
  136. package/Tests/Utils/NetworkSite/MaterializedPathUtil.test.ts +205 -0
  137. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +221 -0
  138. package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +283 -0
  139. package/Tests/Utils/ObjectUtil.test.ts +30 -0
  140. package/Tests/Utils/Slo/SloStatusColor.test.ts +89 -0
  141. package/Tests/Utils/Slo/SloUtil.test.ts +1980 -0
  142. package/Tests/Utils/Slo/SloWidgetFormat.test.ts +605 -0
  143. package/Tests/Utils/TechStack.test.ts +50 -0
  144. package/Tests/Utils/Traces/CriticalPath.test.ts +178 -0
  145. package/Tests/Utils/ValueFormatter.test.ts +305 -0
  146. package/Types/AnalyticsDatabase/AnalyticsTableName.ts +10 -0
  147. package/Types/AnalyticsDatabase/TableColumn.ts +23 -0
  148. package/Types/BaseDatabase/EqualTo.ts +9 -1
  149. package/Types/BaseDatabase/EqualToOrNull.ts +9 -1
  150. package/Types/BaseDatabase/NotEqual.ts +9 -1
  151. package/Types/Dashboard/DashboardComponentType.ts +1 -0
  152. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
  153. package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +42 -0
  154. package/Types/Dashboard/DashboardTemplates.ts +214 -0
  155. package/Types/Email/EmailTemplateType.ts +2 -0
  156. package/Types/Kubernetes/KubernetesCostIngest.ts +79 -0
  157. package/Types/Monitor/CriteriaFilter.ts +9 -0
  158. package/Types/Monitor/MonitorStep.ts +5 -8
  159. package/Types/Monitor/MonitorStepNetworkDeviceMonitor.ts +27 -5
  160. package/Types/Monitor/MonitorType.ts +15 -5
  161. package/Types/Monitor/SnmpMonitor/ArpEntry.ts +14 -0
  162. package/Types/Monitor/SnmpMonitor/FdbEntry.ts +18 -0
  163. package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +10 -3
  164. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +31 -5
  165. package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +12 -0
  166. package/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.ts +231 -3
  167. package/Types/NetworkSite/DefaultNetworkSiteType.ts +20 -0
  168. package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
  169. package/Types/Permission.ts +449 -0
  170. package/Types/ServiceLevelObjective/SliType.ts +6 -0
  171. package/Types/ServiceLevelObjective/SloMultiMonitorMode.ts +6 -0
  172. package/Types/ServiceLevelObjective/SloStatus.ts +9 -0
  173. package/Types/ServiceLevelObjective/SloWindowType.ts +6 -0
  174. package/Types/Telemetry/ServiceType.ts +1 -0
  175. package/UI/Components/Filters/EntityFilter.tsx +16 -0
  176. package/UI/Components/Filters/FilterViewer.tsx +22 -5
  177. package/UI/Components/List/List.tsx +8 -0
  178. package/UI/Components/ModelTable/BaseModelTable.tsx +309 -106
  179. package/UI/Components/ModelTable/FilterDataToQuery.ts +172 -0
  180. package/UI/Components/Navbar/NavBar.tsx +16 -2
  181. package/UI/Components/Navbar/NavBarMenuModal.tsx +3 -3
  182. package/UI/Utils/Navigation.ts +10 -0
  183. package/UI/Utils/TableFilterUrlState.ts +204 -17
  184. package/UI/Utils/TableViewUrlState.ts +165 -0
  185. package/Utils/Dashboard/Components/DashboardSloComponent.ts +114 -0
  186. package/Utils/Dashboard/Components/Index.ts +7 -0
  187. package/Utils/IpCanonicalUtil.ts +134 -0
  188. package/Utils/Monitor/EndpointAttachmentUtil.ts +508 -0
  189. package/Utils/Monitor/NetworkTopologyUtil.ts +157 -5
  190. package/Utils/NetworkSite/CidrMatchUtil.ts +296 -0
  191. package/Utils/NetworkSite/MaterializedPathUtil.ts +115 -0
  192. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +97 -0
  193. package/Utils/NetworkSite/SiteUptimeUtil.ts +111 -0
  194. package/Utils/Slo/SloStatusColor.ts +54 -0
  195. package/Utils/Slo/SloUtil.ts +637 -0
  196. package/Utils/Slo/SloWidgetFormat.ts +383 -0
  197. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js +25 -20
  198. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js.map +1 -1
  199. package/build/dist/Models/AnalyticsModels/Index.js +4 -0
  200. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  201. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +713 -0
  202. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -0
  203. package/build/dist/Models/AnalyticsModels/MetricBaselineHourly.js +2 -0
  204. package/build/dist/Models/AnalyticsModels/MetricBaselineHourly.js.map +1 -1
  205. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1m.js +5 -2
  206. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1m.js.map +1 -1
  207. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js +5 -2
  208. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js.map +1 -1
  209. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.js +5 -2
  210. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.js.map +1 -1
  211. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +5 -2
  212. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js.map +1 -1
  213. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +5 -2
  214. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js.map +1 -1
  215. package/build/dist/Models/AnalyticsModels/NetworkFlow.js +44 -0
  216. package/build/dist/Models/AnalyticsModels/NetworkFlow.js.map +1 -1
  217. package/build/dist/Models/AnalyticsModels/SloHistory.js +215 -0
  218. package/build/dist/Models/AnalyticsModels/SloHistory.js.map +1 -0
  219. package/build/dist/Models/DatabaseModels/Index.js +20 -0
  220. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  221. package/build/dist/Models/DatabaseModels/NetworkDevice.js +458 -6
  222. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  223. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +0 -6
  224. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  225. package/build/dist/Models/DatabaseModels/NetworkEndpoint.js +779 -0
  226. package/build/dist/Models/DatabaseModels/NetworkEndpoint.js.map +1 -0
  227. package/build/dist/Models/DatabaseModels/NetworkSite.js +1180 -0
  228. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -0
  229. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +534 -0
  230. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -0
  231. package/build/dist/Models/DatabaseModels/NetworkSiteLink.js +629 -0
  232. package/build/dist/Models/DatabaseModels/NetworkSiteLink.js.map +1 -0
  233. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +538 -0
  234. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -0
  235. package/build/dist/Models/DatabaseModels/NetworkSiteType.js +522 -0
  236. package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -0
  237. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +1124 -0
  238. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -0
  239. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +769 -0
  240. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -0
  241. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +460 -0
  242. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -0
  243. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +459 -0
  244. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -0
  245. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js +130 -0
  246. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js.map +1 -0
  247. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js +31 -0
  248. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js.map +1 -0
  249. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js +36 -0
  250. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js.map +1 -0
  251. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js +49 -0
  252. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js.map +1 -0
  253. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js +140 -0
  254. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js.map +1 -0
  255. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  256. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  257. package/build/dist/Server/Services/AnalyticsDatabaseService.js +32 -7
  258. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  259. package/build/dist/Server/Services/Index.js +24 -0
  260. package/build/dist/Server/Services/Index.js.map +1 -1
  261. package/build/dist/Server/Services/KubernetesCostAllocationService.js +12 -0
  262. package/build/dist/Server/Services/KubernetesCostAllocationService.js.map +1 -0
  263. package/build/dist/Server/Services/MetricService.js +21 -3
  264. package/build/dist/Server/Services/MetricService.js.map +1 -1
  265. package/build/dist/Server/Services/MonitorService.js +19 -0
  266. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  267. package/build/dist/Server/Services/NetworkDeviceService.js +351 -1
  268. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  269. package/build/dist/Server/Services/NetworkEndpointService.js +319 -0
  270. package/build/dist/Server/Services/NetworkEndpointService.js.map +1 -0
  271. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +90 -0
  272. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -0
  273. package/build/dist/Server/Services/NetworkSiteLinkService.js +9 -0
  274. package/build/dist/Server/Services/NetworkSiteLinkService.js.map +1 -0
  275. package/build/dist/Server/Services/NetworkSiteService.js +1038 -0
  276. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -0
  277. package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js +9 -0
  278. package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js.map +1 -0
  279. package/build/dist/Server/Services/NetworkSiteTypeService.js +9 -0
  280. package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -0
  281. package/build/dist/Server/Services/ProjectService.js +98 -2
  282. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  283. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +358 -0
  284. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -0
  285. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +9 -0
  286. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -0
  287. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +9 -0
  288. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -0
  289. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +582 -0
  290. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -0
  291. package/build/dist/Server/Services/SloHistoryService.js +77 -0
  292. package/build/dist/Server/Services/SloHistoryService.js.map +1 -0
  293. package/build/dist/Server/Services/UserNotificationSettingService.js +20 -0
  294. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  295. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +9 -0
  296. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
  297. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +15 -0
  298. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  299. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +31 -0
  300. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  301. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +105 -52
  302. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  303. package/build/dist/Server/Utils/Memory.js +9 -1
  304. package/build/dist/Server/Utils/Memory.js.map +1 -1
  305. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +132 -10
  306. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  307. package/build/dist/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
  308. package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js +77 -0
  309. package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js.map +1 -0
  310. package/build/dist/Server/Utils/Monitor/MonitorResource.js +21 -41
  311. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  312. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +152 -40
  313. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  314. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +262 -0
  315. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -0
  316. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +201 -0
  317. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -0
  318. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +152 -120
  319. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  320. package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js +44 -0
  321. package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js.map +1 -0
  322. package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js +10 -10
  323. package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js.map +1 -1
  324. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +5 -0
  325. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
  326. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +10 -0
  327. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
  328. package/build/dist/Types/AnalyticsDatabase/TableColumn.js +7 -0
  329. package/build/dist/Types/AnalyticsDatabase/TableColumn.js.map +1 -1
  330. package/build/dist/Types/BaseDatabase/EqualTo.js +9 -1
  331. package/build/dist/Types/BaseDatabase/EqualTo.js.map +1 -1
  332. package/build/dist/Types/BaseDatabase/EqualToOrNull.js +9 -1
  333. package/build/dist/Types/BaseDatabase/EqualToOrNull.js.map +1 -1
  334. package/build/dist/Types/BaseDatabase/NotEqual.js +9 -1
  335. package/build/dist/Types/BaseDatabase/NotEqual.js.map +1 -1
  336. package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
  337. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  338. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
  339. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  340. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js +23 -0
  341. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js.map +1 -0
  342. package/build/dist/Types/Dashboard/DashboardTemplates.js +205 -0
  343. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  344. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  345. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  346. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js +21 -0
  347. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -0
  348. package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
  349. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  350. package/build/dist/Types/Monitor/MonitorStep.js +5 -5
  351. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  352. package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js +8 -0
  353. package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js.map +1 -1
  354. package/build/dist/Types/Monitor/MonitorType.js +15 -5
  355. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  356. package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js +2 -0
  357. package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js.map +1 -0
  358. package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js +2 -0
  359. package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js.map +1 -0
  360. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +9 -3
  361. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
  362. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js +217 -3
  363. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js.map +1 -1
  364. package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js +21 -0
  365. package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js.map +1 -0
  366. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
  367. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  368. package/build/dist/Types/Permission.js +409 -0
  369. package/build/dist/Types/Permission.js.map +1 -1
  370. package/build/dist/Types/ServiceLevelObjective/SliType.js +7 -0
  371. package/build/dist/Types/ServiceLevelObjective/SliType.js.map +1 -0
  372. package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js +7 -0
  373. package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js.map +1 -0
  374. package/build/dist/Types/ServiceLevelObjective/SloStatus.js +10 -0
  375. package/build/dist/Types/ServiceLevelObjective/SloStatus.js.map +1 -0
  376. package/build/dist/Types/ServiceLevelObjective/SloWindowType.js +7 -0
  377. package/build/dist/Types/ServiceLevelObjective/SloWindowType.js.map +1 -0
  378. package/build/dist/Types/Telemetry/ServiceType.js +1 -0
  379. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  380. package/build/dist/UI/Components/Filters/EntityFilter.js +15 -0
  381. package/build/dist/UI/Components/Filters/EntityFilter.js.map +1 -1
  382. package/build/dist/UI/Components/Filters/FilterViewer.js +19 -4
  383. package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
  384. package/build/dist/UI/Components/List/List.js +1 -1
  385. package/build/dist/UI/Components/List/List.js.map +1 -1
  386. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +235 -89
  387. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  388. package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js +96 -0
  389. package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js.map +1 -0
  390. package/build/dist/UI/Components/Navbar/NavBar.js +14 -2
  391. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  392. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +3 -2
  393. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  394. package/build/dist/UI/Utils/Navigation.js +9 -0
  395. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  396. package/build/dist/UI/Utils/TableFilterUrlState.js +159 -15
  397. package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
  398. package/build/dist/UI/Utils/TableViewUrlState.js +103 -0
  399. package/build/dist/UI/Utils/TableViewUrlState.js.map +1 -0
  400. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +93 -0
  401. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -0
  402. package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
  403. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  404. package/build/dist/Utils/IpCanonicalUtil.js +110 -0
  405. package/build/dist/Utils/IpCanonicalUtil.js.map +1 -0
  406. package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js +311 -0
  407. package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js.map +1 -0
  408. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +98 -5
  409. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  410. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +222 -0
  411. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -0
  412. package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js +89 -0
  413. package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js.map +1 -0
  414. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +60 -0
  415. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -0
  416. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +76 -0
  417. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -0
  418. package/build/dist/Utils/Slo/SloStatusColor.js +18 -0
  419. package/build/dist/Utils/Slo/SloStatusColor.js.map +1 -0
  420. package/build/dist/Utils/Slo/SloUtil.js +393 -0
  421. package/build/dist/Utils/Slo/SloUtil.js.map +1 -0
  422. package/build/dist/Utils/Slo/SloWidgetFormat.js +174 -0
  423. package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -0
  424. package/package.json +2 -2
  425. package/Types/Dashboard/DashboardComponents/Index.ts +0 -7
  426. package/build/dist/Types/Dashboard/DashboardComponents/Index.js +0 -8
  427. package/build/dist/Types/Dashboard/DashboardComponents/Index.js.map +0 -1
@@ -0,0 +1,414 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/NetworkEndpoint";
3
+ import ColumnLength from "../../Types/Database/ColumnLength";
4
+ import LIMIT_MAX from "../../Types/Database/LimitMax";
5
+ import ObjectID from "../../Types/ObjectID";
6
+ import EndpointAttachmentUtil, {
7
+ EndpointAttachment,
8
+ EndpointIncomingObservation,
9
+ EndpointIpBinding,
10
+ EndpointUpsertContext,
11
+ EndpointUpsertDecision,
12
+ } from "../../Utils/Monitor/EndpointAttachmentUtil";
13
+ import OuiLookupUtil from "../Utils/Monitor/OuiLookupUtil";
14
+ import QueryHelper from "../Types/Database/QueryHelper";
15
+ import logger from "../Utils/Logger";
16
+
17
+ /*
18
+ * Rows written per statement. Endpoint rows are narrow (12 params each),
19
+ * so 500 keeps a chunk well under Postgres' parameter ceiling while
20
+ * turning a 4096-MAC switch into 9 round trips instead of 4096.
21
+ */
22
+ const UPSERT_BATCH_SIZE: number = 500;
23
+
24
+ /*
25
+ * Hard ceiling on how many MACs one device walk may write. This is the
26
+ * findBy limit too — reading more than we can look up would silently
27
+ * treat known endpoints as new. A switch under a MAC-flood attack (or a
28
+ * misconfigured trunk dumping a whole campus into one FDB) is capped
29
+ * here and logged rather than allowed to monopolise the ingest thread.
30
+ */
31
+ const MAX_ENDPOINTS_PER_WALK: number = LIMIT_MAX;
32
+
33
+ /*
34
+ * Column order used by the INSERT in upsertDiscoveredEndpoints. Keep
35
+ * this and the generated parameter tuples in perfect sync.
36
+ */
37
+ const INSERT_COLUMNS: Array<string> = [
38
+ "projectId",
39
+ "macAddress",
40
+ "ipAddress",
41
+ "vendor",
42
+ "attachedNetworkDeviceId",
43
+ "attachedInterfaceIndex",
44
+ "attachedPortName",
45
+ "vlanId",
46
+ "siteId",
47
+ "firstSeenAt",
48
+ "lastSeenAt",
49
+ "version",
50
+ ];
51
+
52
+ /*
53
+ * ShortText columns are 100 chars. Truncating BEFORE the decision is
54
+ * made (rather than at write time) matters twice over: one over-long
55
+ * value can never fail the whole chunk it rides in, and the
56
+ * unchanged-since-last-poll comparison compares what we would store
57
+ * against what is stored, not against the untruncated observation.
58
+ */
59
+ function truncateShortText(value: string | undefined): string | undefined {
60
+ if (!value) {
61
+ return undefined;
62
+ }
63
+ return value.length > ColumnLength.ShortText
64
+ ? value.substring(0, ColumnLength.ShortText)
65
+ : value;
66
+ }
67
+
68
+ export class Service extends DatabaseService<Model> {
69
+ public constructor() {
70
+ super(Model);
71
+ }
72
+
73
+ /*
74
+ * Applies one device walk's endpoint observations to the per-project
75
+ * endpoint inventory. Precedence between switch-FDB attachments and
76
+ * router-ARP sightings lives in EndpointAttachmentUtil.decideUpsert (pure,
77
+ * exhaustively tested); this method only batches the reads and applies
78
+ * the decisions:
79
+ *
80
+ * - one findBy for every observed MAC, then ONE INSERT per 500 new
81
+ * MACs and ONE UPDATE per 500 changed MACs — this runs inline on
82
+ * the probe-ingest request path, so per-MAC round trips are not an
83
+ * option at restaurant-chain scale (thousands of sites x thousands
84
+ * of L2 endpoints),
85
+ * - endpoints that have not moved since the last poll produce no
86
+ * write at all (see ENDPOINT_LAST_SEEN_REFRESH_MS), so a stable
87
+ * switch costs one SELECT and nothing else,
88
+ * - vendor is stamped from the MAC OUI on create only (user-correctable),
89
+ * - siteId follows the attaching device's site whenever an attachment is
90
+ * (re)written and the caller knows the site,
91
+ * - firstSeenAt is set on create, lastSeenAt on every touch that writes.
92
+ */
93
+ public async upsertDiscoveredEndpoints(data: {
94
+ projectId: ObjectID;
95
+ deviceId: ObjectID;
96
+ deviceSiteId?: ObjectID | undefined;
97
+ attachments: Array<EndpointAttachment>;
98
+ ipBindings: Array<EndpointIpBinding>;
99
+ now: Date;
100
+ }): Promise<void> {
101
+ // Merge both observation kinds per MAC — an L3 switch yields both.
102
+ const incomingByMac: Map<string, EndpointIncomingObservation> = new Map();
103
+
104
+ for (const attachment of data.attachments) {
105
+ incomingByMac.set(attachment.macAddress, {
106
+ macAddress: attachment.macAddress,
107
+ deviceId: data.deviceId.toString(),
108
+ attachment: {
109
+ interfaceIndex: attachment.attachedInterfaceIndex,
110
+ portName: truncateShortText(attachment.attachedPortName),
111
+ vlanId: attachment.vlanId,
112
+ },
113
+ });
114
+ }
115
+
116
+ for (const binding of data.ipBindings) {
117
+ const existing: EndpointIncomingObservation | undefined =
118
+ incomingByMac.get(binding.macAddress);
119
+ const ipAddress: string | undefined = truncateShortText(
120
+ binding.ipAddress,
121
+ );
122
+ if (!ipAddress) {
123
+ continue;
124
+ }
125
+ if (existing) {
126
+ existing.ipBinding = {
127
+ ipAddress: ipAddress,
128
+ routerInterfaceIndex: binding.routerInterfaceIndex,
129
+ };
130
+ } else {
131
+ incomingByMac.set(binding.macAddress, {
132
+ macAddress: binding.macAddress,
133
+ deviceId: data.deviceId.toString(),
134
+ ipBinding: {
135
+ ipAddress: ipAddress,
136
+ routerInterfaceIndex: binding.routerInterfaceIndex,
137
+ },
138
+ });
139
+ }
140
+ }
141
+
142
+ /*
143
+ * Deterministic order, capped so a pathological FDB dump (or a MAC
144
+ * flood attack on a customer switch) cannot write unbounded rows or
145
+ * exceed the findBy limit.
146
+ */
147
+ const allMacs: Array<string> = Array.from(incomingByMac.keys()).sort();
148
+ const macs: Array<string> = allMacs.slice(0, MAX_ENDPOINTS_PER_WALK);
149
+
150
+ if (macs.length === 0) {
151
+ return;
152
+ }
153
+
154
+ if (allMacs.length > macs.length) {
155
+ logger.warn(
156
+ `NetworkEndpointService: device ${data.deviceId.toString()} reported ${allMacs.length} endpoint MACs; capping this walk at ${MAX_ENDPOINTS_PER_WALK}.`,
157
+ );
158
+ }
159
+
160
+ const existingRows: Array<Model> = await this.findBy({
161
+ query: {
162
+ projectId: data.projectId,
163
+ macAddress: QueryHelper.any(macs),
164
+ },
165
+ select: {
166
+ _id: true,
167
+ macAddress: true,
168
+ attachedNetworkDeviceId: true,
169
+ attachedInterfaceIndex: true,
170
+ attachedPortName: true,
171
+ vlanId: true,
172
+ ipAddress: true,
173
+ siteId: true,
174
+ firstSeenAt: true,
175
+ lastSeenAt: true,
176
+ },
177
+ limit: LIMIT_MAX,
178
+ skip: 0,
179
+ props: {
180
+ isRoot: true,
181
+ },
182
+ });
183
+
184
+ const existingByMac: Map<string, Model> = new Map();
185
+ for (const row of existingRows) {
186
+ if (row.macAddress) {
187
+ existingByMac.set(row.macAddress, row);
188
+ }
189
+ }
190
+
191
+ const context: EndpointUpsertContext = {
192
+ now: data.now,
193
+ siteId: data.deviceSiteId?.toString(),
194
+ };
195
+
196
+ const creates: Array<{ mac: string; decision: EndpointUpsertDecision }> =
197
+ [];
198
+ const updates: Array<{ mac: string; decision: EndpointUpsertDecision }> =
199
+ [];
200
+
201
+ for (const mac of macs) {
202
+ const incoming: EndpointIncomingObservation = incomingByMac.get(mac)!;
203
+ const existing: Model | undefined = existingByMac.get(mac);
204
+
205
+ const decision: EndpointUpsertDecision =
206
+ EndpointAttachmentUtil.decideUpsert(
207
+ existing
208
+ ? {
209
+ attachedNetworkDeviceId:
210
+ existing.attachedNetworkDeviceId?.toString(),
211
+ attachedInterfaceIndex: existing.attachedInterfaceIndex,
212
+ attachedPortName: existing.attachedPortName,
213
+ vlanId: existing.vlanId,
214
+ ipAddress: existing.ipAddress,
215
+ siteId: existing.siteId?.toString(),
216
+ firstSeenAt: existing.firstSeenAt,
217
+ lastSeenAt: existing.lastSeenAt,
218
+ }
219
+ : null,
220
+ incoming,
221
+ context,
222
+ );
223
+
224
+ if (decision.action === "create") {
225
+ creates.push({ mac, decision });
226
+ } else if (decision.action === "update") {
227
+ updates.push({ mac, decision });
228
+ }
229
+ }
230
+
231
+ await this.bulkInsertEndpoints({
232
+ projectId: data.projectId,
233
+ deviceId: data.deviceId,
234
+ deviceSiteId: data.deviceSiteId,
235
+ now: data.now,
236
+ rows: creates,
237
+ });
238
+
239
+ await this.bulkUpdateEndpoints({
240
+ projectId: data.projectId,
241
+ deviceId: data.deviceId,
242
+ deviceSiteId: data.deviceSiteId,
243
+ now: data.now,
244
+ rows: updates,
245
+ });
246
+ }
247
+
248
+ /*
249
+ * New MACs. Every create-path decision has setAttachment === true (a
250
+ * row with no stored attachment can never be "attached elsewhere"), so
251
+ * the conflict branch can write the attachment unconditionally.
252
+ *
253
+ * ON CONFLICT names the partial unique index on
254
+ * (projectId, macAddress) WHERE "deletedAt" IS NULL — the predicate is
255
+ * required for index inference, and it is what keeps a soft-deleted
256
+ * row from colliding with a rediscovered MAC. The DO UPDATE branch
257
+ * only fires when a concurrent walk created the row between our findBy
258
+ * and this INSERT; it then applies the same semantics the UPDATE path
259
+ * would have, so the observation is never silently dropped.
260
+ *
261
+ * `vendor` is deliberately absent from DO UPDATE SET: it is stamped
262
+ * from the OUI on create and is user-correctable thereafter.
263
+ */
264
+ private async bulkInsertEndpoints(data: {
265
+ projectId: ObjectID;
266
+ deviceId: ObjectID;
267
+ deviceSiteId?: ObjectID | undefined;
268
+ now: Date;
269
+ rows: Array<{ mac: string; decision: EndpointUpsertDecision }>;
270
+ }): Promise<void> {
271
+ if (data.rows.length === 0) {
272
+ return;
273
+ }
274
+
275
+ for (let i: number = 0; i < data.rows.length; i += UPSERT_BATCH_SIZE) {
276
+ const chunk: Array<{ mac: string; decision: EndpointUpsertDecision }> =
277
+ data.rows.slice(i, i + UPSERT_BATCH_SIZE);
278
+
279
+ const valueFragments: Array<string> = [];
280
+ const params: Array<unknown> = [];
281
+ let paramIndex: number = 1;
282
+
283
+ for (const row of chunk) {
284
+ const placeholders: Array<string> = [];
285
+ for (let c: number = 0; c < INSERT_COLUMNS.length; c++) {
286
+ placeholders.push(`$${paramIndex++}`);
287
+ }
288
+ valueFragments.push(`(${placeholders.join(", ")})`);
289
+
290
+ params.push(
291
+ data.projectId.toString(),
292
+ row.mac,
293
+ row.decision.setIpAddress && row.decision.ipAddress
294
+ ? row.decision.ipAddress
295
+ : null,
296
+ truncateShortText(OuiLookupUtil.lookupVendor(row.mac)) ?? null,
297
+ data.deviceId.toString(),
298
+ row.decision.attachedInterfaceIndex ?? null,
299
+ row.decision.attachedPortName ?? null,
300
+ row.decision.vlanId ?? null,
301
+ data.deviceSiteId?.toString() ?? null,
302
+ data.now,
303
+ data.now,
304
+ 0, // version (BaseModel @VersionColumn)
305
+ );
306
+ }
307
+
308
+ const sql: string = `
309
+ INSERT INTO "NetworkEndpoint" (
310
+ "projectId", "macAddress", "ipAddress", "vendor",
311
+ "attachedNetworkDeviceId", "attachedInterfaceIndex",
312
+ "attachedPortName", "vlanId", "siteId",
313
+ "firstSeenAt", "lastSeenAt", "version"
314
+ )
315
+ VALUES ${valueFragments.join(", ")}
316
+ ON CONFLICT ("projectId", "macAddress") WHERE "deletedAt" IS NULL
317
+ DO UPDATE SET
318
+ "attachedNetworkDeviceId" = EXCLUDED."attachedNetworkDeviceId",
319
+ "attachedInterfaceIndex" = COALESCE(EXCLUDED."attachedInterfaceIndex", "NetworkEndpoint"."attachedInterfaceIndex"),
320
+ "attachedPortName" = COALESCE(EXCLUDED."attachedPortName", "NetworkEndpoint"."attachedPortName"),
321
+ "vlanId" = COALESCE(EXCLUDED."vlanId", "NetworkEndpoint"."vlanId"),
322
+ "siteId" = COALESCE(EXCLUDED."siteId", "NetworkEndpoint"."siteId"),
323
+ "ipAddress" = COALESCE(EXCLUDED."ipAddress", "NetworkEndpoint"."ipAddress"),
324
+ "firstSeenAt" = COALESCE("NetworkEndpoint"."firstSeenAt", EXCLUDED."firstSeenAt"),
325
+ "lastSeenAt" = EXCLUDED."lastSeenAt",
326
+ "updatedAt" = now()
327
+ `;
328
+
329
+ await this.getRepository().manager.query(sql, params);
330
+ }
331
+ }
332
+
333
+ /*
334
+ * Known MACs whose observation actually changed something. One
335
+ * UPDATE ... FROM (VALUES ...) per chunk, joined on the same
336
+ * (projectId, macAddress) key the unique index covers, with
337
+ * "deletedAt" IS NULL so a soft-deleted row is never resurrected.
338
+ *
339
+ * Per-row conditionality rides in the VALUES tuple: `setAttachment`
340
+ * gates the whole attachment group, and NULL means "the walk did not
341
+ * report one" — COALESCE keeps whatever is stored, which is the
342
+ * "undefined never clears a stored value" rule from decideUpsert.
343
+ */
344
+ private async bulkUpdateEndpoints(data: {
345
+ projectId: ObjectID;
346
+ deviceId: ObjectID;
347
+ deviceSiteId?: ObjectID | undefined;
348
+ now: Date;
349
+ rows: Array<{ mac: string; decision: EndpointUpsertDecision }>;
350
+ }): Promise<void> {
351
+ if (data.rows.length === 0) {
352
+ return;
353
+ }
354
+
355
+ for (let i: number = 0; i < data.rows.length; i += UPSERT_BATCH_SIZE) {
356
+ const chunk: Array<{ mac: string; decision: EndpointUpsertDecision }> =
357
+ data.rows.slice(i, i + UPSERT_BATCH_SIZE);
358
+
359
+ const valueFragments: Array<string> = [];
360
+ const params: Array<unknown> = [data.projectId.toString()];
361
+ let paramIndex: number = 2;
362
+
363
+ for (const row of chunk) {
364
+ valueFragments.push(
365
+ `($${paramIndex++}::character varying, $${paramIndex++}::boolean, $${paramIndex++}::uuid, $${paramIndex++}::integer, $${paramIndex++}::character varying, $${paramIndex++}::integer, $${paramIndex++}::uuid, $${paramIndex++}::character varying, $${paramIndex++}::timestamptz)`,
366
+ );
367
+
368
+ params.push(
369
+ row.mac,
370
+ row.decision.setAttachment,
371
+ row.decision.setAttachment ? data.deviceId.toString() : null,
372
+ row.decision.setAttachment
373
+ ? row.decision.attachedInterfaceIndex ?? null
374
+ : null,
375
+ row.decision.setAttachment
376
+ ? row.decision.attachedPortName ?? null
377
+ : null,
378
+ row.decision.setAttachment ? row.decision.vlanId ?? null : null,
379
+ row.decision.setAttachment
380
+ ? data.deviceSiteId?.toString() ?? null
381
+ : null,
382
+ row.decision.setIpAddress && row.decision.ipAddress
383
+ ? row.decision.ipAddress
384
+ : null,
385
+ data.now,
386
+ );
387
+ }
388
+
389
+ const sql: string = `
390
+ UPDATE "NetworkEndpoint" AS e
391
+ SET
392
+ "attachedNetworkDeviceId" = CASE WHEN v."setAttachment" THEN v."deviceId" ELSE e."attachedNetworkDeviceId" END,
393
+ "attachedInterfaceIndex" = CASE WHEN v."setAttachment" THEN COALESCE(v."attachedInterfaceIndex", e."attachedInterfaceIndex") ELSE e."attachedInterfaceIndex" END,
394
+ "attachedPortName" = CASE WHEN v."setAttachment" THEN COALESCE(v."attachedPortName", e."attachedPortName") ELSE e."attachedPortName" END,
395
+ "vlanId" = CASE WHEN v."setAttachment" THEN COALESCE(v."vlanId", e."vlanId") ELSE e."vlanId" END,
396
+ "siteId" = CASE WHEN v."setAttachment" THEN COALESCE(v."siteId", e."siteId") ELSE e."siteId" END,
397
+ "ipAddress" = COALESCE(v."ipAddress", e."ipAddress"),
398
+ "firstSeenAt" = COALESCE(e."firstSeenAt", v."lastSeenAt"),
399
+ "lastSeenAt" = v."lastSeenAt",
400
+ "updatedAt" = now()
401
+ FROM (VALUES ${valueFragments.join(", ")})
402
+ AS v("macAddress", "setAttachment", "deviceId", "attachedInterfaceIndex", "attachedPortName", "vlanId", "siteId", "ipAddress", "lastSeenAt")
403
+ WHERE
404
+ e."projectId" = $1
405
+ AND e."macAddress" = v."macAddress"
406
+ AND e."deletedAt" IS NULL
407
+ `;
408
+
409
+ await this.getRepository().manager.query(sql, params);
410
+ }
411
+ }
412
+ }
413
+
414
+ export default new Service();
@@ -0,0 +1,98 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/NetworkSiteAssignmentRule";
3
+ import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
4
+ import CreateBy from "../Types/Database/CreateBy";
5
+ import UpdateBy from "../Types/Database/UpdateBy";
6
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
7
+ import LIMIT_MAX from "../../Types/Database/LimitMax";
8
+ import BadDataException from "../../Types/Exception/BadDataException";
9
+ import CidrMatchUtil from "../../Utils/NetworkSite/CidrMatchUtil";
10
+
11
+ export class Service extends DatabaseService<Model> {
12
+ public constructor() {
13
+ super(Model);
14
+ }
15
+
16
+ /*
17
+ * A rule with neither criterion would match nothing (or, worse, read as
18
+ * "match everything" to a future maintainer) - reject it at write time.
19
+ */
20
+ @CaptureSpan()
21
+ protected override async onBeforeCreate(
22
+ createBy: CreateBy<Model>,
23
+ ): Promise<OnCreate<Model>> {
24
+ this.validateCriteria({
25
+ subnetCidr: createBy.data.subnetCidr,
26
+ hostnamePattern: createBy.data.hostnamePattern,
27
+ });
28
+
29
+ return { createBy, carryForward: null };
30
+ }
31
+
32
+ @CaptureSpan()
33
+ protected override async onBeforeUpdate(
34
+ updateBy: UpdateBy<Model>,
35
+ ): Promise<OnUpdate<Model>> {
36
+ const dataKeys: Array<string> = Object.keys(updateBy.data || {});
37
+
38
+ if (
39
+ !dataKeys.includes("subnetCidr") &&
40
+ !dataKeys.includes("hostnamePattern")
41
+ ) {
42
+ return { updateBy, carryForward: null };
43
+ }
44
+
45
+ /*
46
+ * The update may clear one criterion while the other only exists on the
47
+ * stored row, so validate the RESULTING state of every matched row.
48
+ */
49
+ const existingRules: Array<Model> = await this.findBy({
50
+ query: updateBy.query,
51
+ select: {
52
+ _id: true,
53
+ subnetCidr: true,
54
+ hostnamePattern: true,
55
+ },
56
+ limit: LIMIT_MAX,
57
+ skip: 0,
58
+ props: {
59
+ isRoot: true,
60
+ },
61
+ });
62
+
63
+ for (const existingRule of existingRules) {
64
+ this.validateCriteria({
65
+ subnetCidr: dataKeys.includes("subnetCidr")
66
+ ? ((updateBy.data as any)["subnetCidr"] as string | null)
67
+ : existingRule.subnetCidr,
68
+ hostnamePattern: dataKeys.includes("hostnamePattern")
69
+ ? ((updateBy.data as any)["hostnamePattern"] as string | null)
70
+ : existingRule.hostnamePattern,
71
+ });
72
+ }
73
+
74
+ return { updateBy, carryForward: null };
75
+ }
76
+
77
+ private validateCriteria(data: {
78
+ subnetCidr?: string | null | undefined;
79
+ hostnamePattern?: string | null | undefined;
80
+ }): void {
81
+ const subnetCidr: string = (data.subnetCidr || "").trim();
82
+ const hostnamePattern: string = (data.hostnamePattern || "").trim();
83
+
84
+ if (!subnetCidr && !hostnamePattern) {
85
+ throw new BadDataException(
86
+ "At least one of Subnet CIDR or Hostname Pattern is required.",
87
+ );
88
+ }
89
+
90
+ if (subnetCidr && !CidrMatchUtil.isValidCidr(subnetCidr)) {
91
+ throw new BadDataException(
92
+ `${subnetCidr} is not a valid IPv4 CIDR (expected e.g. 10.0.0.0/24).`,
93
+ );
94
+ }
95
+ }
96
+ }
97
+
98
+ export default new Service();
@@ -0,0 +1,10 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/NetworkSiteLink";
3
+
4
+ export class Service extends DatabaseService<Model> {
5
+ public constructor() {
6
+ super(Model);
7
+ }
8
+ }
9
+
10
+ export default new Service();