@oneuptime/common 12.0.24 → 12.0.26

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 (870) hide show
  1. package/Models/AnalyticsModels/Index.ts +2 -0
  2. package/Models/AnalyticsModels/Span.ts +101 -0
  3. package/Models/AnalyticsModels/ThreatIntelIndicator.ts +413 -0
  4. package/Models/DatabaseModels/AlertSeverity.ts +4 -1
  5. package/Models/DatabaseModels/CephClusterFeed.ts +625 -0
  6. package/Models/DatabaseModels/CloudResourceFeed.ts +625 -0
  7. package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +13 -0
  8. package/Models/DatabaseModels/DetectionRule.ts +9 -3
  9. package/Models/DatabaseModels/DockerHostFeed.ts +625 -0
  10. package/Models/DatabaseModels/DockerSwarmClusterFeed.ts +628 -0
  11. package/Models/DatabaseModels/GoogleSecOpsConnection.ts +9 -3
  12. package/Models/DatabaseModels/HostFeed.ts +625 -0
  13. package/Models/DatabaseModels/IncidentSeverity.ts +4 -1
  14. package/Models/DatabaseModels/Index.ts +22 -0
  15. package/Models/DatabaseModels/KubernetesClusterFeed.ts +628 -0
  16. package/Models/DatabaseModels/Monitor.ts +87 -0
  17. package/Models/DatabaseModels/NetworkDevice.ts +96 -5
  18. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +92 -6
  19. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +301 -31
  20. package/Models/DatabaseModels/NetworkSite.ts +120 -0
  21. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +1 -0
  22. package/Models/DatabaseModels/PodmanHostFeed.ts +625 -0
  23. package/Models/DatabaseModels/ProxmoxClusterFeed.ts +626 -0
  24. package/Models/DatabaseModels/ScheduledMaintenance.ts +67 -0
  25. package/Models/DatabaseModels/ServiceFeed.ts +625 -0
  26. package/Models/DatabaseModels/TelemetrySourceMap.ts +474 -0
  27. package/Models/DatabaseModels/ThreatIntelFeed.ts +758 -0
  28. package/Models/DatabaseModels/UserOnCallLog.ts +1 -0
  29. package/Models/DatabaseModels/UserTotpAuth.ts +1 -0
  30. package/Models/DatabaseModels/UserWebAuthn.ts +1 -0
  31. package/Server/API/AlertAPI.ts +23 -1
  32. package/Server/API/BaseAPI.ts +14 -27
  33. package/Server/API/IncidentAPI.ts +41 -1
  34. package/Server/API/IncidentEpisodeAPI.ts +23 -1
  35. package/Server/API/MicrosoftTeamsAPI.ts +31 -2
  36. package/Server/API/ScheduledMaintenanceAPI.ts +23 -1
  37. package/Server/API/SlackAPI.ts +48 -2
  38. package/Server/API/TelemetryAPI.ts +167 -42
  39. package/Server/API/UserOnCallLogTimelineAPI.ts +75 -61
  40. package/Server/API/UserTotpAuthAPI.ts +67 -1
  41. package/Server/API/UserWebAuthnAPI.ts +44 -1
  42. package/Server/Infrastructure/Postgres/SchemaMigrations/1787923136162-MigrationName.ts +57 -0
  43. package/Server/Infrastructure/Postgres/SchemaMigrations/1789600000000-AddAutoProvisionedNetworkDeviceMonitors.ts +49 -0
  44. package/Server/Infrastructure/Postgres/SchemaMigrations/1789700000000-AddNetworkScaleIndexes.ts +129 -0
  45. package/Server/Infrastructure/Postgres/SchemaMigrations/1789800000000-WidenSecurityEventLastErrorColumns.ts +54 -0
  46. package/Server/Infrastructure/Postgres/SchemaMigrations/1789900000000-AddNetworkSiteRollupPolicyAndMaintenance.ts +64 -0
  47. package/Server/Infrastructure/Postgres/SchemaMigrations/1790000000000-AddTelemetrySourceMap.ts +64 -0
  48. package/Server/Infrastructure/Postgres/SchemaMigrations/1790000000001-AddSnmpConfigsToNetworkDeviceDiscoveryScan.ts +72 -0
  49. package/Server/Infrastructure/Postgres/SchemaMigrations/1790003445000-AddSnmpEnabledToNetworkDeviceDiscoveryScan.ts +31 -0
  50. package/Server/Infrastructure/Postgres/SchemaMigrations/1790100000000-AddResourceActivityFeeds.ts +489 -0
  51. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +18 -0
  52. package/Server/Middleware/IdentityRateLimit.ts +53 -3
  53. package/Server/Middleware/SlackAuthorization.ts +96 -18
  54. package/Server/Services/AIService.ts +181 -41
  55. package/Server/Services/CephClusterFeedService.ts +99 -0
  56. package/Server/Services/CephClusterLabelRuleEngineService.ts +29 -0
  57. package/Server/Services/CephClusterOwnerRuleEngineService.ts +23 -0
  58. package/Server/Services/CephClusterOwnerTeamService.ts +129 -0
  59. package/Server/Services/CephClusterOwnerUserService.ts +123 -0
  60. package/Server/Services/CephClusterService.ts +223 -2
  61. package/Server/Services/CloudResourceFeedService.ts +99 -0
  62. package/Server/Services/CloudResourceLabelRuleEngineService.ts +30 -0
  63. package/Server/Services/CloudResourceOwnerRuleEngineService.ts +33 -0
  64. package/Server/Services/CloudResourceOwnerTeamService.ts +129 -0
  65. package/Server/Services/CloudResourceOwnerUserService.ts +123 -0
  66. package/Server/Services/CloudResourceService.ts +227 -2
  67. package/Server/Services/DatabaseService.ts +265 -0
  68. package/Server/Services/DockerHostFeedService.ts +99 -0
  69. package/Server/Services/DockerHostLabelRuleEngineService.ts +29 -0
  70. package/Server/Services/DockerHostOwnerRuleEngineService.ts +23 -0
  71. package/Server/Services/DockerHostOwnerTeamService.ts +129 -0
  72. package/Server/Services/DockerHostOwnerUserService.ts +123 -0
  73. package/Server/Services/DockerHostService.ts +227 -2
  74. package/Server/Services/DockerSwarmClusterFeedService.ts +102 -0
  75. package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +30 -0
  76. package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +24 -0
  77. package/Server/Services/DockerSwarmClusterOwnerTeamService.ts +133 -0
  78. package/Server/Services/DockerSwarmClusterOwnerUserService.ts +127 -0
  79. package/Server/Services/DockerSwarmClusterService.ts +229 -2
  80. package/Server/Services/EnterpriseLicenseService.ts +15 -7
  81. package/Server/Services/ExceptionAggregationService.ts +12 -2
  82. package/Server/Services/HostFeedService.ts +99 -0
  83. package/Server/Services/HostLabelRuleEngineService.ts +29 -0
  84. package/Server/Services/HostOwnerRuleEngineService.ts +23 -0
  85. package/Server/Services/HostOwnerTeamService.ts +129 -0
  86. package/Server/Services/HostOwnerUserService.ts +123 -0
  87. package/Server/Services/HostService.ts +215 -2
  88. package/Server/Services/IncidentService.ts +11 -0
  89. package/Server/Services/Index.ts +24 -0
  90. package/Server/Services/KubernetesClusterFeedService.ts +99 -0
  91. package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +30 -0
  92. package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +24 -0
  93. package/Server/Services/KubernetesClusterOwnerTeamService.ts +133 -0
  94. package/Server/Services/KubernetesClusterOwnerUserService.ts +127 -0
  95. package/Server/Services/KubernetesClusterService.ts +231 -2
  96. package/Server/Services/LogAggregationService.ts +23 -280
  97. package/Server/Services/MetricAggregationService.ts +98 -1
  98. package/Server/Services/MonitorService.ts +177 -13
  99. package/Server/Services/MonitorTemplateService.ts +111 -0
  100. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +777 -86
  101. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +199 -16
  102. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +1055 -14
  103. package/Server/Services/NetworkDeviceService.ts +750 -4
  104. package/Server/Services/NetworkInterfaceService.ts +415 -0
  105. package/Server/Services/NetworkSiteService.ts +485 -52
  106. package/Server/Services/PodmanHostFeedService.ts +99 -0
  107. package/Server/Services/PodmanHostLabelRuleEngineService.ts +29 -0
  108. package/Server/Services/PodmanHostOwnerRuleEngineService.ts +23 -0
  109. package/Server/Services/PodmanHostOwnerTeamService.ts +129 -0
  110. package/Server/Services/PodmanHostOwnerUserService.ts +123 -0
  111. package/Server/Services/PodmanHostService.ts +227 -2
  112. package/Server/Services/ProjectService.ts +16 -10
  113. package/Server/Services/ProxmoxClusterFeedService.ts +99 -0
  114. package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +30 -0
  115. package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +24 -0
  116. package/Server/Services/ProxmoxClusterOwnerTeamService.ts +131 -0
  117. package/Server/Services/ProxmoxClusterOwnerUserService.ts +124 -0
  118. package/Server/Services/ProxmoxClusterService.ts +225 -2
  119. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +61 -0
  120. package/Server/Services/ServiceFeedService.ts +99 -0
  121. package/Server/Services/ServiceLabelRuleEngineService.ts +29 -0
  122. package/Server/Services/ServiceOwnerRuleEngineService.ts +26 -0
  123. package/Server/Services/ServiceOwnerTeamService.ts +129 -0
  124. package/Server/Services/ServiceOwnerUserService.ts +123 -0
  125. package/Server/Services/ServiceService.ts +227 -3
  126. package/Server/Services/StatusPageSubscriberService.ts +7 -0
  127. package/Server/Services/TelemetryAttributeService.ts +13 -3
  128. package/Server/Services/TelemetrySourceMapService.ts +307 -0
  129. package/Server/Services/ThreatIntelFeedService.ts +222 -0
  130. package/Server/Services/ThreatIntelIndicatorService.ts +428 -0
  131. package/Server/Services/TraceAggregationService.ts +101 -11
  132. package/Server/Services/UserService.ts +13 -6
  133. package/Server/Services/UserTwoFactorBackupCodeService.ts +127 -0
  134. package/Server/Services/UserWebhookService.ts +11 -2
  135. package/Server/Static/Brand/README.md +38 -0
  136. package/Server/Static/Brand/favicons/apple-touch-icon.png +0 -0
  137. package/Server/Static/Brand/favicons/favicon-16x16.png +0 -0
  138. package/Server/Static/Brand/favicons/favicon-32x32.png +0 -0
  139. package/Server/Static/Brand/favicons/favicon.ico +0 -0
  140. package/Server/Static/Brand/favicons/safari-pinned-tab.svg +31 -0
  141. package/Server/Static/Brand/hou-wb.svg +1 -0
  142. package/Server/Static/Brand/oneuptime-logo.svg +1 -0
  143. package/Server/Static/Brand/ou-wb.svg +1 -0
  144. package/Server/Static/Vendor/README.md +4 -0
  145. package/Server/Types/AnalyticsDatabase/ModelPermission.ts +13 -3
  146. package/Server/Types/Database/AggregateBy.ts +83 -0
  147. package/Server/Types/Database/AggregateResultUtil.ts +126 -0
  148. package/Server/Types/Database/JSONColumnQuery.ts +18 -0
  149. package/Server/Types/Database/QueryHelper.ts +40 -0
  150. package/Server/Types/Database/QueryUtil.ts +26 -0
  151. package/Server/Types/Workflow/Components/API/Utils.ts +10 -1
  152. package/Server/Types/Workflow/Components/JavaScript.ts +8 -0
  153. package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +9 -0
  154. package/Server/Utils/AI/SRE/InvestigationGrader.ts +18 -0
  155. package/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.ts +422 -0
  156. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +176 -0
  157. package/Server/Utils/DataSource/HttpFetch.ts +18 -0
  158. package/Server/Utils/Database/RelationIdUtil.ts +42 -0
  159. package/Server/Utils/Marketing/MarketingEventUtil.ts +38 -9
  160. package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +34 -3
  161. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +9 -1
  162. package/Server/Utils/Monitor/Criteria/SyntheticMonitor.ts +28 -10
  163. package/Server/Utils/Monitor/MonitorAlert.ts +541 -332
  164. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +330 -64
  165. package/Server/Utils/Monitor/MonitorIncident.ts +640 -434
  166. package/Server/Utils/Monitor/MonitorResource.ts +226 -49
  167. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +46 -3
  168. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +23 -102
  169. package/Server/Utils/Monitor/PerEntityCriteriaFanOut.ts +329 -0
  170. package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +427 -0
  171. package/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.ts +310 -0
  172. package/Server/Utils/OnCallNotificationContext.ts +686 -0
  173. package/Server/Utils/PrivateNetworkWebhookConfig.ts +549 -0
  174. package/Server/Utils/ResourceFeed/ResourceFeedUtil.ts +139 -0
  175. package/Server/Utils/Response.ts +11 -1
  176. package/Server/Utils/SSRFProtection.ts +230 -60
  177. package/Server/Utils/SecurityEvent/ConnectorErrorMessage.ts +106 -0
  178. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +84 -284
  179. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +47 -20
  180. package/Server/Utils/SecurityEvent/SecurityEventAlerting.ts +318 -0
  181. package/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.ts +199 -0
  182. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.ts +252 -0
  183. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +739 -0
  184. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.ts +533 -0
  185. package/Server/Utils/StartServer.ts +83 -56
  186. package/Server/Utils/StatusPageSubscriberWebhook.ts +3 -0
  187. package/Server/Utils/Telemetry/LlmMetricSpend.ts +56 -5
  188. package/Server/Utils/Telemetry/LlmSpan.ts +46 -0
  189. package/Server/Utils/Telemetry/SourceMapResolver.ts +480 -0
  190. package/Server/Utils/TwoFactorBackupCodeNotification.ts +106 -0
  191. package/Server/Utils/VM/VMAPI.ts +3 -0
  192. package/Server/Utils/VM/VMRunner.ts +27 -1
  193. package/Server/Utils/VendorAssets.ts +42 -0
  194. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +136 -6
  195. package/Server/Utils/Workspace/Slack/Actions/Auth.ts +0 -12
  196. package/Server/Views/AcknowledgeUserOnCallNotification.ejs +11 -9
  197. package/Server/Views/Partials/Head.ejs +9 -9
  198. package/Server/Views/Partials/OnCallNotificationDetails.ejs +48 -0
  199. package/Server/Views/ViewMessage.ejs +11 -9
  200. package/Tests/App/Accounts/LoginTwoFactorRecovery.test.tsx +972 -0
  201. package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +401 -0
  202. package/Tests/App/Dashboard/DiscoveryScanEditForm.test.tsx +707 -0
  203. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +1908 -18
  204. package/Tests/App/Dashboard/LlmCallsTableIdentity.test.tsx +322 -0
  205. package/Tests/App/Dashboard/LlmOverview.test.tsx +335 -0
  206. package/Tests/App/Dashboard/LlmSpanDisplay.test.ts +391 -0
  207. package/Tests/App/Dashboard/LlmUsageBreakdown.test.tsx +1007 -0
  208. package/Tests/App/Dashboard/ResourceFeed.test.tsx +230 -0
  209. package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +216 -0
  210. package/Tests/App/Dashboard/TopologyAddToMonitoring.test.tsx +192 -0
  211. package/Tests/App/Dashboard/WorkspaceNotificationRuleConditions.test.tsx +439 -0
  212. package/Tests/Models/DatabaseModels/DateColumnDeserialization.test.ts +182 -0
  213. package/Tests/Models/DatabaseModels/RelationColumnModelTypeCoverage.test.ts +82 -0
  214. package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +398 -0
  215. package/Tests/Models/DiscoveryScanNameColumn.test.ts +151 -16
  216. package/Tests/Models/DiscoveryScanSnmpEnabledColumn.test.ts +593 -0
  217. package/Tests/Models/NetworkDeviceCreateContract.test.ts +102 -0
  218. package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +607 -0
  219. package/Tests/Server/API/AIGenerationRequestBudget.test.ts +355 -0
  220. package/Tests/Server/API/AIKillSwitchBackstop.test.ts +602 -0
  221. package/Tests/Server/API/BaseAPI.test.ts +41 -0
  222. package/Tests/Server/API/BaseAPIUpdateDateColumns.test.ts +154 -0
  223. package/Tests/Server/API/BaseAPIUpdatePayloadValidation.test.ts +9 -16
  224. package/Tests/Server/API/MicrosoftTeamsBotTestEndpoint.test.ts +335 -0
  225. package/Tests/Server/API/UserOnCallLogTimelineAcknowledgePage.test.ts +611 -0
  226. package/Tests/Server/API/UserTotpAuthAPI.test.ts +498 -4
  227. package/Tests/Server/API/UserWebAuthnBackupCodeMinting.test.ts +682 -0
  228. package/Tests/Server/Infrastructure/ExampleDockerfiles.test.ts +595 -0
  229. package/Tests/Server/Middleware/SlackAuthorization.test.ts +262 -5
  230. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +9 -0
  231. package/Tests/Server/Services/AIServiceProjectAccess.test.ts +6 -0
  232. package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +18 -0
  233. package/Tests/Server/Services/DatabaseServiceAggregateBy.test.ts +590 -0
  234. package/Tests/Server/Services/DatabaseServiceUpdateWriteRouting.test.ts +12 -0
  235. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +162 -26
  236. package/Tests/Server/Services/EnterpriseLicenseServiceCreate.test.ts +292 -0
  237. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +119 -12
  238. package/Tests/Server/Services/LogAggregationAttributeOperators.test.ts +109 -0
  239. package/Tests/Server/Services/MetricAggregationAttributeOperators.test.ts +170 -0
  240. package/Tests/Server/Services/MonitorTemplateServiceNetworkDeviceSync.test.ts +383 -0
  241. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +997 -3
  242. package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +830 -0
  243. package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +528 -0
  244. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +3141 -1
  245. package/Tests/Server/Services/NetworkDeviceRegisteredHostnames.test.ts +1023 -0
  246. package/Tests/Server/Services/NetworkDeviceSiteAssignmentRuleSkip.test.ts +728 -0
  247. package/Tests/Server/Services/NetworkInterfaceServiceUpsert.test.ts +795 -0
  248. package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +903 -0
  249. package/Tests/Server/Services/NetworkSiteService.test.ts +165 -24
  250. package/Tests/Server/Services/ProjectServiceChangePlan.test.ts +5 -3
  251. package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +5 -2
  252. package/Tests/Server/Services/ResourceCreationFeedWrites.test.ts +304 -0
  253. package/Tests/Server/Services/ResourceFeedServices.test.ts +269 -0
  254. package/Tests/Server/Services/ResourceOwnerFeedWrites.test.ts +245 -0
  255. package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +792 -0
  256. package/Tests/Server/Services/TelemetrySourceMapService.test.ts +483 -0
  257. package/Tests/Server/Services/ThreatIntelFeedService.test.ts +351 -0
  258. package/Tests/Server/Services/ThreatIntelIndicatorService.test.ts +366 -0
  259. package/Tests/Server/Services/TraceAggregationAttributeOperators.test.ts +507 -0
  260. package/Tests/Server/Services/UserTwoFactorBackupCodeGenerateIfNone.test.ts +705 -0
  261. package/Tests/Server/Services/WorkspaceNotificationRuleOnCallDutyPolicy.test.ts +306 -0
  262. package/Tests/Server/Types/Database/AggregateResultUtil.test.ts +386 -0
  263. package/Tests/Server/Types/Database/Permissions/SelectRejectionMessageContract.test.ts +424 -0
  264. package/Tests/Server/Types/Database/QueryHelperWildcard.test.ts +142 -0
  265. package/Tests/Server/Types/Workflow/Components/ApiComponentPrivateNetwork.test.ts +163 -0
  266. package/Tests/Server/Types/Workflow/Components/JavaScriptPrivateNetwork.test.ts +124 -0
  267. package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +5 -0
  268. package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +39 -1
  269. package/Tests/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.test.ts +338 -0
  270. package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWildcard.test.ts +383 -0
  271. package/Tests/Server/Utils/Marketing/EmittedMarketingEvent.ts +23 -0
  272. package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +51 -0
  273. package/Tests/Server/Utils/Monitor/Criteria/SyntheticMonitorCriteria.test.ts +259 -0
  274. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPerSeriesFanout.test.ts +557 -0
  275. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +12 -2
  276. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkLogWritePath.test.ts +404 -0
  277. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +8 -2
  278. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +125 -98
  279. package/Tests/Server/Utils/Monitor/PerEntityCriteriaFanOut.test.ts +444 -0
  280. package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1112 -0
  281. package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +717 -0
  282. package/Tests/Server/Utils/NetworkDevice/RulePatternValidator.test.ts +78 -0
  283. package/Tests/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.test.ts +363 -0
  284. package/Tests/Server/Utils/OfflineAssetHygiene.test.ts +35 -0
  285. package/Tests/Server/Utils/OnCallNotificationContext.test.ts +908 -0
  286. package/Tests/Server/Utils/PrivateNetworkWebhookConfig.test.ts +423 -0
  287. package/Tests/Server/Utils/ResourceFeed/ResourceFeedUtil.test.ts +191 -0
  288. package/Tests/Server/Utils/SSRFProtectionPrivateNetwork.test.ts +597 -0
  289. package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +819 -0
  290. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +381 -0
  291. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +417 -0
  292. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +819 -0
  293. package/Tests/Server/Utils/SecurityEvent/SecurityEventAlerting.test.ts +246 -0
  294. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.test.ts +282 -0
  295. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.test.ts +312 -0
  296. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.test.ts +854 -0
  297. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.test.ts +437 -0
  298. package/Tests/Server/Utils/StartServerErrorStatus.test.ts +225 -0
  299. package/Tests/Server/Utils/StatusPage/MonitorRulePatternValidator.test.ts +62 -0
  300. package/Tests/Server/Utils/StatusPageSubscriberWebhookPrivateNetwork.test.ts +119 -0
  301. package/Tests/Server/Utils/Telemetry/LlmCostBudgetEvaluator.test.ts +37 -18
  302. package/Tests/Server/Utils/Telemetry/LlmMetricSpend.test.ts +143 -2
  303. package/Tests/Server/Utils/Telemetry/LlmSpan.test.ts +804 -0
  304. package/Tests/Server/Utils/Telemetry/SourceMapResolver.test.ts +542 -0
  305. package/Tests/Server/Utils/TwoFactorBackupCodeNotification.test.ts +272 -0
  306. package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +111 -0
  307. package/Tests/Server/Utils/VendorAssets.test.ts +117 -0
  308. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +101 -4
  309. package/Tests/Server/Utils/Workspace/MicrosoftTeamsInstallStateDiagnostics.test.ts +922 -0
  310. package/Tests/Server/Utils/Workspace/MicrosoftTeamsRosterDiagnosticMessages.test.ts +642 -0
  311. package/Tests/Server/Views/OnCallAcknowledgePage.test.ts +430 -0
  312. package/Tests/Types/API/URLQueryString.test.ts +472 -0
  313. package/Tests/Types/BaseDatabase/Wildcard.test.ts +163 -0
  314. package/Tests/Types/BaseDatabase/WildcardPattern.test.ts +149 -0
  315. package/Tests/Types/Database/DateColumnValue.test.ts +265 -0
  316. package/Tests/Types/DateToIsoStringOrNull.test.ts +67 -0
  317. package/Tests/Types/Log/LogQueryToFilter.test.ts +218 -43
  318. package/Tests/Types/Monitor/KubernetesTemplateGroupByKeys.test.ts +225 -0
  319. package/Tests/Types/Monitor/TemplateGroupByKeys.test.ts +296 -0
  320. package/Tests/Types/NetworkAutomation/RuleRunResult.test.ts +102 -0
  321. package/Tests/Types/NetworkAutomation/RuleRunResultDescribe.test.ts +145 -0
  322. package/Tests/Types/NetworkSite/SiteHealthRollupPolicy.test.ts +58 -0
  323. package/Tests/Types/SerializableObjectDictionaryImportCycle.test.ts +15 -0
  324. package/Tests/Types/Telemetry/LlmMetricConventions.test.ts +391 -0
  325. package/Tests/Types/Telemetry/TelemetrySearchQuery.test.ts +620 -0
  326. package/Tests/Types/WhatsApp/WhatsAppTemplates.test.ts +110 -0
  327. package/Tests/Types/Workspace/NotificationRuleConditionUtil.test.ts +76 -6
  328. package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +16 -4
  329. package/Tests/Types/Workspace/NotificationRules/OnCallDutyPolicyConditions.test.ts +669 -0
  330. package/Tests/UI/Components/DictionaryFilterOperatorWildcard.test.ts +175 -0
  331. package/Tests/UI/Components/IconOpticalSize.test.tsx +377 -0
  332. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardInstallGuidance.test.tsx +332 -0
  333. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsInstallGuidanceContent.test.tsx +643 -0
  334. package/Tests/Utils/Monitor/InterfaceInventoryUtil.test.ts +824 -0
  335. package/Tests/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.test.ts +626 -0
  336. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +718 -0
  337. package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +59 -0
  338. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +287 -2
  339. package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +73 -0
  340. package/Tests/Utils/NetworkDiscovery/PingMonitorBuilder.test.ts +317 -0
  341. package/Tests/Utils/NetworkDiscovery/RescanIntervalUtil.test.ts +262 -0
  342. package/Tests/Utils/NetworkDiscovery/ScanModeUtil.test.ts +474 -0
  343. package/Tests/Utils/NetworkDiscovery/SnmpScanConfigUtil.test.ts +2442 -0
  344. package/Tests/Utils/NetworkSite/SiteMaintenanceUtil.test.ts +188 -0
  345. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +522 -0
  346. package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +694 -0
  347. package/Tests/Utils/SecurityEvent/ThreatIntel/StixPatternParser.test.ts +281 -0
  348. package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +87 -67
  349. package/Tests/Utils/Telemetry/LlmMetricQuery.test.ts +298 -0
  350. package/Types/API/URL.ts +45 -10
  351. package/Types/AnalyticsDatabase/AnalyticsTableName.ts +8 -0
  352. package/Types/BaseDatabase/NotWildcard.ts +86 -0
  353. package/Types/BaseDatabase/Wildcard.ts +89 -0
  354. package/Types/BaseDatabase/WildcardPattern.ts +176 -0
  355. package/Types/Database/DateColumnValue.ts +184 -0
  356. package/Types/Database/TableColumn.ts +40 -5
  357. package/Types/Date.ts +37 -0
  358. package/Types/Email/EmailTemplateType.ts +1 -0
  359. package/Types/JSON.ts +8 -0
  360. package/Types/Log/LogQueryToFilter.ts +167 -129
  361. package/Types/Monitor/DockerAlertTemplates.ts +43 -12
  362. package/Types/Monitor/HostAlertTemplates.ts +31 -3
  363. package/Types/Monitor/KubernetesAlertTemplates.ts +98 -0
  364. package/Types/Monitor/MonitorStep.ts +49 -0
  365. package/Types/Monitor/PodmanAlertTemplates.ts +39 -12
  366. package/Types/Monitor/SnmpMonitor/CdpNeighbor.ts +14 -0
  367. package/Types/Monitor/SnmpMonitor/LldpNeighbor.ts +11 -0
  368. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +11 -4
  369. package/Types/NetworkAutomation/RuleRunResult.ts +191 -2
  370. package/Types/NetworkSite/SiteHealthRollupPolicy.ts +96 -0
  371. package/Types/Permission.ts +411 -0
  372. package/Types/Probe/ProbeApiIngestResponse.ts +42 -0
  373. package/Types/SecurityEvent/ThreatIntelConstants.ts +118 -0
  374. package/Types/SerializableObjectDictionary.ts +8 -0
  375. package/Types/Telemetry/LlmConventions.ts +255 -0
  376. package/Types/Telemetry/LlmMetricConventions.ts +212 -7
  377. package/Types/Telemetry/SourceMap.ts +56 -0
  378. package/Types/Telemetry/TelemetrySearchQuery.ts +949 -0
  379. package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +12 -1
  380. package/UI/Components/Dictionary/DictionaryFilterOperator.ts +83 -0
  381. package/UI/Components/Icon/Icon.tsx +28 -1
  382. package/UI/Components/LogsViewer/components/LogSearchBar.tsx +26 -4
  383. package/UI/Components/LogsViewer/components/LogSearchHelp.tsx +34 -16
  384. package/UI/Components/TelemetryViewer/components/TelemetrySearchBar.tsx +15 -2
  385. package/Utils/Metrics/MetricExplorerUrl.ts +77 -15
  386. package/Utils/Monitor/InterfaceInventoryUtil.ts +251 -0
  387. package/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.ts +333 -0
  388. package/Utils/Monitor/NetworkTopologyUtil.ts +249 -28
  389. package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +14 -6
  390. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +2 -0
  391. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +49 -18
  392. package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +215 -0
  393. package/Utils/NetworkDiscovery/RescanIntervalUtil.ts +148 -0
  394. package/Utils/NetworkDiscovery/ScanModeUtil.ts +105 -0
  395. package/Utils/NetworkDiscovery/SnmpScanConfigUtil.ts +827 -0
  396. package/Utils/NetworkSite/SiteMaintenanceUtil.ts +110 -0
  397. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +350 -19
  398. package/Utils/NetworkSite/SiteUptimeUtil.ts +422 -21
  399. package/Utils/SecurityEvent/ThreatIntel/StixPatternParser.ts +383 -0
  400. package/Utils/Telemetry/CrossSignalScope.ts +37 -39
  401. package/Utils/Telemetry/LlmMetricQuery.ts +83 -0
  402. package/build/dist/Models/AnalyticsModels/Index.js +2 -0
  403. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  404. package/build/dist/Models/AnalyticsModels/Span.js +89 -0
  405. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  406. package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js +325 -0
  407. package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js.map +1 -0
  408. package/build/dist/Models/DatabaseModels/AlertSeverity.js +4 -1
  409. package/build/dist/Models/DatabaseModels/AlertSeverity.js.map +1 -1
  410. package/build/dist/Models/DatabaseModels/CephClusterFeed.js +648 -0
  411. package/build/dist/Models/DatabaseModels/CephClusterFeed.js.map +1 -0
  412. package/build/dist/Models/DatabaseModels/CloudResourceFeed.js +648 -0
  413. package/build/dist/Models/DatabaseModels/CloudResourceFeed.js.map +1 -0
  414. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +11 -0
  415. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
  416. package/build/dist/Models/DatabaseModels/DetectionRule.js +9 -3
  417. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  418. package/build/dist/Models/DatabaseModels/DockerHostFeed.js +648 -0
  419. package/build/dist/Models/DatabaseModels/DockerHostFeed.js.map +1 -0
  420. package/build/dist/Models/DatabaseModels/DockerSwarmClusterFeed.js +648 -0
  421. package/build/dist/Models/DatabaseModels/DockerSwarmClusterFeed.js.map +1 -0
  422. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +9 -3
  423. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +1 -1
  424. package/build/dist/Models/DatabaseModels/HostFeed.js +648 -0
  425. package/build/dist/Models/DatabaseModels/HostFeed.js.map +1 -0
  426. package/build/dist/Models/DatabaseModels/IncidentSeverity.js +4 -1
  427. package/build/dist/Models/DatabaseModels/IncidentSeverity.js.map +1 -1
  428. package/build/dist/Models/DatabaseModels/Index.js +22 -0
  429. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  430. package/build/dist/Models/DatabaseModels/KubernetesClusterFeed.js +648 -0
  431. package/build/dist/Models/DatabaseModels/KubernetesClusterFeed.js.map +1 -0
  432. package/build/dist/Models/DatabaseModels/Monitor.js +81 -0
  433. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  434. package/build/dist/Models/DatabaseModels/NetworkDevice.js +103 -7
  435. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  436. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +91 -6
  437. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
  438. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +276 -31
  439. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  440. package/build/dist/Models/DatabaseModels/NetworkSite.js +124 -1
  441. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
  442. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +1 -0
  443. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
  444. package/build/dist/Models/DatabaseModels/PodmanHostFeed.js +648 -0
  445. package/build/dist/Models/DatabaseModels/PodmanHostFeed.js.map +1 -0
  446. package/build/dist/Models/DatabaseModels/ProxmoxClusterFeed.js +648 -0
  447. package/build/dist/Models/DatabaseModels/ProxmoxClusterFeed.js.map +1 -0
  448. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +66 -0
  449. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  450. package/build/dist/Models/DatabaseModels/ServiceFeed.js +648 -0
  451. package/build/dist/Models/DatabaseModels/ServiceFeed.js.map +1 -0
  452. package/build/dist/Models/DatabaseModels/TelemetrySourceMap.js +496 -0
  453. package/build/dist/Models/DatabaseModels/TelemetrySourceMap.js.map +1 -0
  454. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +800 -0
  455. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js.map +1 -0
  456. package/build/dist/Models/DatabaseModels/UserOnCallLog.js +1 -0
  457. package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
  458. package/build/dist/Models/DatabaseModels/UserTotpAuth.js +1 -0
  459. package/build/dist/Models/DatabaseModels/UserTotpAuth.js.map +1 -1
  460. package/build/dist/Models/DatabaseModels/UserWebAuthn.js +1 -0
  461. package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -1
  462. package/build/dist/Server/API/AlertAPI.js +18 -1
  463. package/build/dist/Server/API/AlertAPI.js.map +1 -1
  464. package/build/dist/Server/API/BaseAPI.js +11 -20
  465. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  466. package/build/dist/Server/API/IncidentAPI.js +35 -1
  467. package/build/dist/Server/API/IncidentAPI.js.map +1 -1
  468. package/build/dist/Server/API/IncidentEpisodeAPI.js +18 -1
  469. package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
  470. package/build/dist/Server/API/MicrosoftTeamsAPI.js +30 -2
  471. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  472. package/build/dist/Server/API/ScheduledMaintenanceAPI.js +18 -1
  473. package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
  474. package/build/dist/Server/API/SlackAPI.js +45 -2
  475. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  476. package/build/dist/Server/API/TelemetryAPI.js +100 -35
  477. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  478. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +64 -59
  479. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
  480. package/build/dist/Server/API/UserTotpAuthAPI.js +65 -1
  481. package/build/dist/Server/API/UserTotpAuthAPI.js.map +1 -1
  482. package/build/dist/Server/API/UserWebAuthnAPI.js +42 -1
  483. package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
  484. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787923136162-MigrationName.js +26 -0
  485. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787923136162-MigrationName.js.map +1 -0
  486. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789600000000-AddAutoProvisionedNetworkDeviceMonitors.js +22 -0
  487. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789600000000-AddAutoProvisionedNetworkDeviceMonitors.js.map +1 -0
  488. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789700000000-AddNetworkScaleIndexes.js +88 -0
  489. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789700000000-AddNetworkScaleIndexes.js.map +1 -0
  490. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789800000000-WidenSecurityEventLastErrorColumns.js +39 -0
  491. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789800000000-WidenSecurityEventLastErrorColumns.js.map +1 -0
  492. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789900000000-AddNetworkSiteRollupPolicyAndMaintenance.js +34 -0
  493. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789900000000-AddNetworkSiteRollupPolicyAndMaintenance.js.map +1 -0
  494. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000000-AddTelemetrySourceMap.js +32 -0
  495. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000000-AddTelemetrySourceMap.js.map +1 -0
  496. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000001-AddSnmpConfigsToNetworkDeviceDiscoveryScan.js +61 -0
  497. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000001-AddSnmpConfigsToNetworkDeviceDiscoveryScan.js.map +1 -0
  498. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790003445000-AddSnmpEnabledToNetworkDeviceDiscoveryScan.js +23 -0
  499. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790003445000-AddSnmpEnabledToNetworkDeviceDiscoveryScan.js.map +1 -0
  500. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790100000000-AddResourceActivityFeeds.js +179 -0
  501. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790100000000-AddResourceActivityFeeds.js.map +1 -0
  502. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +18 -0
  503. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  504. package/build/dist/Server/Middleware/IdentityRateLimit.js +40 -3
  505. package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
  506. package/build/dist/Server/Middleware/SlackAuthorization.js +58 -7
  507. package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
  508. package/build/dist/Server/Services/AIService.js +177 -30
  509. package/build/dist/Server/Services/AIService.js.map +1 -1
  510. package/build/dist/Server/Services/CephClusterFeedService.js +89 -0
  511. package/build/dist/Server/Services/CephClusterFeedService.js.map +1 -0
  512. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +27 -3
  513. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
  514. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +21 -0
  515. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
  516. package/build/dist/Server/Services/CephClusterOwnerTeamService.js +120 -0
  517. package/build/dist/Server/Services/CephClusterOwnerTeamService.js.map +1 -1
  518. package/build/dist/Server/Services/CephClusterOwnerUserService.js +113 -0
  519. package/build/dist/Server/Services/CephClusterOwnerUserService.js.map +1 -1
  520. package/build/dist/Server/Services/CephClusterService.js +175 -1
  521. package/build/dist/Server/Services/CephClusterService.js.map +1 -1
  522. package/build/dist/Server/Services/CloudResourceFeedService.js +89 -0
  523. package/build/dist/Server/Services/CloudResourceFeedService.js.map +1 -0
  524. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +27 -3
  525. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
  526. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +28 -3
  527. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
  528. package/build/dist/Server/Services/CloudResourceOwnerTeamService.js +120 -0
  529. package/build/dist/Server/Services/CloudResourceOwnerTeamService.js.map +1 -1
  530. package/build/dist/Server/Services/CloudResourceOwnerUserService.js +113 -0
  531. package/build/dist/Server/Services/CloudResourceOwnerUserService.js.map +1 -1
  532. package/build/dist/Server/Services/CloudResourceService.js +177 -1
  533. package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
  534. package/build/dist/Server/Services/DatabaseService.js +201 -0
  535. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  536. package/build/dist/Server/Services/DockerHostFeedService.js +89 -0
  537. package/build/dist/Server/Services/DockerHostFeedService.js.map +1 -0
  538. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +27 -3
  539. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
  540. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +21 -0
  541. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
  542. package/build/dist/Server/Services/DockerHostOwnerTeamService.js +120 -0
  543. package/build/dist/Server/Services/DockerHostOwnerTeamService.js.map +1 -1
  544. package/build/dist/Server/Services/DockerHostOwnerUserService.js +113 -0
  545. package/build/dist/Server/Services/DockerHostOwnerUserService.js.map +1 -1
  546. package/build/dist/Server/Services/DockerHostService.js +177 -1
  547. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  548. package/build/dist/Server/Services/DockerSwarmClusterFeedService.js +90 -0
  549. package/build/dist/Server/Services/DockerSwarmClusterFeedService.js.map +1 -0
  550. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +27 -3
  551. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
  552. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +21 -0
  553. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
  554. package/build/dist/Server/Services/DockerSwarmClusterOwnerTeamService.js +120 -0
  555. package/build/dist/Server/Services/DockerSwarmClusterOwnerTeamService.js.map +1 -1
  556. package/build/dist/Server/Services/DockerSwarmClusterOwnerUserService.js +113 -0
  557. package/build/dist/Server/Services/DockerSwarmClusterOwnerUserService.js.map +1 -1
  558. package/build/dist/Server/Services/DockerSwarmClusterService.js +175 -1
  559. package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
  560. package/build/dist/Server/Services/EnterpriseLicenseService.js +40 -30
  561. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  562. package/build/dist/Server/Services/ExceptionAggregationService.js +8 -2
  563. package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
  564. package/build/dist/Server/Services/HostFeedService.js +89 -0
  565. package/build/dist/Server/Services/HostFeedService.js.map +1 -0
  566. package/build/dist/Server/Services/HostLabelRuleEngineService.js +27 -3
  567. package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
  568. package/build/dist/Server/Services/HostOwnerRuleEngineService.js +21 -0
  569. package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
  570. package/build/dist/Server/Services/HostOwnerTeamService.js +120 -0
  571. package/build/dist/Server/Services/HostOwnerTeamService.js.map +1 -1
  572. package/build/dist/Server/Services/HostOwnerUserService.js +113 -0
  573. package/build/dist/Server/Services/HostOwnerUserService.js.map +1 -1
  574. package/build/dist/Server/Services/HostService.js +175 -1
  575. package/build/dist/Server/Services/HostService.js.map +1 -1
  576. package/build/dist/Server/Services/IncidentService.js +10 -0
  577. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  578. package/build/dist/Server/Services/Index.js +24 -0
  579. package/build/dist/Server/Services/Index.js.map +1 -1
  580. package/build/dist/Server/Services/KubernetesClusterFeedService.js +89 -0
  581. package/build/dist/Server/Services/KubernetesClusterFeedService.js.map +1 -0
  582. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +27 -3
  583. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
  584. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +21 -0
  585. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
  586. package/build/dist/Server/Services/KubernetesClusterOwnerTeamService.js +120 -0
  587. package/build/dist/Server/Services/KubernetesClusterOwnerTeamService.js.map +1 -1
  588. package/build/dist/Server/Services/KubernetesClusterOwnerUserService.js +113 -0
  589. package/build/dist/Server/Services/KubernetesClusterOwnerUserService.js.map +1 -1
  590. package/build/dist/Server/Services/KubernetesClusterService.js +177 -1
  591. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  592. package/build/dist/Server/Services/LogAggregationService.js +19 -196
  593. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  594. package/build/dist/Server/Services/MetricAggregationService.js +59 -0
  595. package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
  596. package/build/dist/Server/Services/MonitorService.js +115 -13
  597. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  598. package/build/dist/Server/Services/MonitorTemplateService.js +86 -0
  599. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  600. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +561 -67
  601. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  602. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +130 -16
  603. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
  604. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +850 -8
  605. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  606. package/build/dist/Server/Services/NetworkDeviceService.js +594 -5
  607. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  608. package/build/dist/Server/Services/NetworkInterfaceService.js +306 -0
  609. package/build/dist/Server/Services/NetworkInterfaceService.js.map +1 -1
  610. package/build/dist/Server/Services/NetworkSiteService.js +408 -47
  611. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  612. package/build/dist/Server/Services/PodmanHostFeedService.js +89 -0
  613. package/build/dist/Server/Services/PodmanHostFeedService.js.map +1 -0
  614. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +27 -3
  615. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
  616. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +21 -0
  617. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
  618. package/build/dist/Server/Services/PodmanHostOwnerTeamService.js +120 -0
  619. package/build/dist/Server/Services/PodmanHostOwnerTeamService.js.map +1 -1
  620. package/build/dist/Server/Services/PodmanHostOwnerUserService.js +113 -0
  621. package/build/dist/Server/Services/PodmanHostOwnerUserService.js.map +1 -1
  622. package/build/dist/Server/Services/PodmanHostService.js +177 -1
  623. package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
  624. package/build/dist/Server/Services/ProjectService.js +40 -30
  625. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  626. package/build/dist/Server/Services/ProxmoxClusterFeedService.js +89 -0
  627. package/build/dist/Server/Services/ProxmoxClusterFeedService.js.map +1 -0
  628. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +27 -3
  629. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
  630. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +21 -0
  631. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
  632. package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js +120 -0
  633. package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js.map +1 -1
  634. package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js +113 -0
  635. package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js.map +1 -1
  636. package/build/dist/Server/Services/ProxmoxClusterService.js +175 -1
  637. package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
  638. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +56 -0
  639. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  640. package/build/dist/Server/Services/ServiceFeedService.js +89 -0
  641. package/build/dist/Server/Services/ServiceFeedService.js.map +1 -0
  642. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +27 -3
  643. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
  644. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +24 -0
  645. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
  646. package/build/dist/Server/Services/ServiceOwnerTeamService.js +120 -0
  647. package/build/dist/Server/Services/ServiceOwnerTeamService.js.map +1 -1
  648. package/build/dist/Server/Services/ServiceOwnerUserService.js +113 -0
  649. package/build/dist/Server/Services/ServiceOwnerUserService.js.map +1 -1
  650. package/build/dist/Server/Services/ServiceService.js +173 -2
  651. package/build/dist/Server/Services/ServiceService.js.map +1 -1
  652. package/build/dist/Server/Services/StatusPageSubscriberService.js +7 -0
  653. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  654. package/build/dist/Server/Services/TelemetryAttributeService.js +9 -3
  655. package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
  656. package/build/dist/Server/Services/TelemetrySourceMapService.js +265 -0
  657. package/build/dist/Server/Services/TelemetrySourceMapService.js.map +1 -0
  658. package/build/dist/Server/Services/ThreatIntelFeedService.js +157 -0
  659. package/build/dist/Server/Services/ThreatIntelFeedService.js.map +1 -0
  660. package/build/dist/Server/Services/ThreatIntelIndicatorService.js +276 -0
  661. package/build/dist/Server/Services/ThreatIntelIndicatorService.js.map +1 -0
  662. package/build/dist/Server/Services/TraceAggregationService.js +62 -6
  663. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  664. package/build/dist/Server/Services/UserService.js +22 -13
  665. package/build/dist/Server/Services/UserService.js.map +1 -1
  666. package/build/dist/Server/Services/UserTwoFactorBackupCodeService.js +120 -0
  667. package/build/dist/Server/Services/UserTwoFactorBackupCodeService.js.map +1 -1
  668. package/build/dist/Server/Services/UserWebhookService.js +11 -2
  669. package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
  670. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +12 -1
  671. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
  672. package/build/dist/Server/Types/Database/AggregateBy.js +2 -0
  673. package/build/dist/Server/Types/Database/AggregateBy.js.map +1 -0
  674. package/build/dist/Server/Types/Database/AggregateResultUtil.js +90 -0
  675. package/build/dist/Server/Types/Database/AggregateResultUtil.js.map +1 -0
  676. package/build/dist/Server/Types/Database/JSONColumnQuery.js +14 -0
  677. package/build/dist/Server/Types/Database/JSONColumnQuery.js.map +1 -1
  678. package/build/dist/Server/Types/Database/QueryHelper.js +42 -0
  679. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  680. package/build/dist/Server/Types/Database/QueryUtil.js +18 -0
  681. package/build/dist/Server/Types/Database/QueryUtil.js.map +1 -1
  682. package/build/dist/Server/Types/Workflow/Components/API/Utils.js +10 -1
  683. package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
  684. package/build/dist/Server/Types/Workflow/Components/JavaScript.js +8 -0
  685. package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
  686. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +8 -0
  687. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -1
  688. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +15 -0
  689. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -1
  690. package/build/dist/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.js +266 -0
  691. package/build/dist/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.js.map +1 -0
  692. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +134 -0
  693. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  694. package/build/dist/Server/Utils/DataSource/HttpFetch.js +8 -0
  695. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
  696. package/build/dist/Server/Utils/Database/RelationIdUtil.js +31 -0
  697. package/build/dist/Server/Utils/Database/RelationIdUtil.js.map +1 -1
  698. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +26 -8
  699. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
  700. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +42 -17
  701. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
  702. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +9 -1
  703. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  704. package/build/dist/Server/Utils/Monitor/Criteria/SyntheticMonitor.js +15 -2
  705. package/build/dist/Server/Utils/Monitor/Criteria/SyntheticMonitor.js.map +1 -1
  706. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +386 -271
  707. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  708. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +278 -64
  709. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  710. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +469 -350
  711. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  712. package/build/dist/Server/Utils/Monitor/MonitorResource.js +183 -44
  713. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  714. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +46 -3
  715. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
  716. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +18 -91
  717. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  718. package/build/dist/Server/Utils/Monitor/PerEntityCriteriaFanOut.js +194 -0
  719. package/build/dist/Server/Utils/Monitor/PerEntityCriteriaFanOut.js.map +1 -0
  720. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +332 -0
  721. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -0
  722. package/build/dist/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.js +279 -0
  723. package/build/dist/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.js.map +1 -0
  724. package/build/dist/Server/Utils/OnCallNotificationContext.js +415 -0
  725. package/build/dist/Server/Utils/OnCallNotificationContext.js.map +1 -0
  726. package/build/dist/Server/Utils/PrivateNetworkWebhookConfig.js +424 -0
  727. package/build/dist/Server/Utils/PrivateNetworkWebhookConfig.js.map +1 -0
  728. package/build/dist/Server/Utils/ResourceFeed/ResourceFeedUtil.js +108 -0
  729. package/build/dist/Server/Utils/ResourceFeed/ResourceFeedUtil.js.map +1 -0
  730. package/build/dist/Server/Utils/Response.js +12 -1
  731. package/build/dist/Server/Utils/Response.js.map +1 -1
  732. package/build/dist/Server/Utils/SSRFProtection.js +160 -58
  733. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  734. package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js +89 -0
  735. package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js.map +1 -0
  736. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +75 -234
  737. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  738. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +41 -16
  739. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
  740. package/build/dist/Server/Utils/SecurityEvent/SecurityEventAlerting.js +217 -0
  741. package/build/dist/Server/Utils/SecurityEvent/SecurityEventAlerting.js.map +1 -0
  742. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.js +103 -0
  743. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.js.map +1 -0
  744. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.js +168 -0
  745. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.js.map +1 -0
  746. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +527 -0
  747. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js.map +1 -0
  748. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js +376 -0
  749. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js.map +1 -0
  750. package/build/dist/Server/Utils/StartServer.js +70 -44
  751. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  752. package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js +3 -0
  753. package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js.map +1 -1
  754. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js +52 -3
  755. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js.map +1 -1
  756. package/build/dist/Server/Utils/Telemetry/LlmSpan.js +24 -1
  757. package/build/dist/Server/Utils/Telemetry/LlmSpan.js.map +1 -1
  758. package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js +327 -0
  759. package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js.map +1 -0
  760. package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js +84 -0
  761. package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js.map +1 -0
  762. package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
  763. package/build/dist/Server/Utils/VM/VMRunner.js +10 -1
  764. package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
  765. package/build/dist/Server/Utils/VendorAssets.js +29 -0
  766. package/build/dist/Server/Utils/VendorAssets.js.map +1 -1
  767. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +121 -6
  768. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  769. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js +0 -10
  770. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js.map +1 -1
  771. package/build/dist/Types/API/URL.js +40 -10
  772. package/build/dist/Types/API/URL.js.map +1 -1
  773. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +8 -0
  774. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
  775. package/build/dist/Types/BaseDatabase/NotWildcard.js +72 -0
  776. package/build/dist/Types/BaseDatabase/NotWildcard.js.map +1 -0
  777. package/build/dist/Types/BaseDatabase/Wildcard.js +75 -0
  778. package/build/dist/Types/BaseDatabase/Wildcard.js.map +1 -0
  779. package/build/dist/Types/BaseDatabase/WildcardPattern.js +137 -0
  780. package/build/dist/Types/BaseDatabase/WildcardPattern.js.map +1 -0
  781. package/build/dist/Types/Database/DateColumnValue.js +125 -0
  782. package/build/dist/Types/Database/DateColumnValue.js.map +1 -0
  783. package/build/dist/Types/Database/TableColumn.js +18 -2
  784. package/build/dist/Types/Database/TableColumn.js.map +1 -1
  785. package/build/dist/Types/Date.js +31 -0
  786. package/build/dist/Types/Date.js.map +1 -1
  787. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  788. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  789. package/build/dist/Types/JSON.js +2 -0
  790. package/build/dist/Types/JSON.js.map +1 -1
  791. package/build/dist/Types/Log/LogQueryToFilter.js +111 -108
  792. package/build/dist/Types/Log/LogQueryToFilter.js.map +1 -1
  793. package/build/dist/Types/Monitor/DockerAlertTemplates.js +40 -16
  794. package/build/dist/Types/Monitor/DockerAlertTemplates.js.map +1 -1
  795. package/build/dist/Types/Monitor/HostAlertTemplates.js +29 -7
  796. package/build/dist/Types/Monitor/HostAlertTemplates.js.map +1 -1
  797. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +98 -4
  798. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
  799. package/build/dist/Types/Monitor/MonitorStep.js +40 -0
  800. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  801. package/build/dist/Types/Monitor/PodmanAlertTemplates.js +36 -16
  802. package/build/dist/Types/Monitor/PodmanAlertTemplates.js.map +1 -1
  803. package/build/dist/Types/NetworkAutomation/RuleRunResult.js +90 -0
  804. package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -1
  805. package/build/dist/Types/NetworkSite/SiteHealthRollupPolicy.js +84 -0
  806. package/build/dist/Types/NetworkSite/SiteHealthRollupPolicy.js.map +1 -0
  807. package/build/dist/Types/Permission.js +354 -0
  808. package/build/dist/Types/Permission.js.map +1 -1
  809. package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js +100 -0
  810. package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js.map +1 -0
  811. package/build/dist/Types/SerializableObjectDictionary.js +8 -0
  812. package/build/dist/Types/SerializableObjectDictionary.js.map +1 -1
  813. package/build/dist/Types/Telemetry/LlmConventions.js +236 -0
  814. package/build/dist/Types/Telemetry/LlmConventions.js.map +1 -1
  815. package/build/dist/Types/Telemetry/LlmMetricConventions.js +197 -5
  816. package/build/dist/Types/Telemetry/LlmMetricConventions.js.map +1 -1
  817. package/build/dist/Types/Telemetry/SourceMap.js +9 -0
  818. package/build/dist/Types/Telemetry/SourceMap.js.map +1 -0
  819. package/build/dist/Types/Telemetry/TelemetrySearchQuery.js +661 -0
  820. package/build/dist/Types/Telemetry/TelemetrySearchQuery.js.map +1 -0
  821. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +12 -1
  822. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -1
  823. package/build/dist/UI/Components/Dictionary/DictionaryFilterOperator.js +67 -0
  824. package/build/dist/UI/Components/Dictionary/DictionaryFilterOperator.js.map +1 -1
  825. package/build/dist/UI/Components/Icon/Icon.js +28 -1
  826. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  827. package/build/dist/UI/Components/LogsViewer/components/LogSearchBar.js +25 -4
  828. package/build/dist/UI/Components/LogsViewer/components/LogSearchBar.js.map +1 -1
  829. package/build/dist/UI/Components/LogsViewer/components/LogSearchHelp.js +36 -16
  830. package/build/dist/UI/Components/LogsViewer/components/LogSearchHelp.js.map +1 -1
  831. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js +14 -2
  832. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js.map +1 -1
  833. package/build/dist/Utils/Metrics/MetricExplorerUrl.js +54 -9
  834. package/build/dist/Utils/Metrics/MetricExplorerUrl.js.map +1 -1
  835. package/build/dist/Utils/Monitor/InterfaceInventoryUtil.js +128 -0
  836. package/build/dist/Utils/Monitor/InterfaceInventoryUtil.js.map +1 -0
  837. package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js +190 -0
  838. package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js.map +1 -0
  839. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +206 -28
  840. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  841. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +14 -7
  842. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
  843. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
  844. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +34 -18
  845. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
  846. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +163 -0
  847. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -0
  848. package/build/dist/Utils/NetworkDiscovery/RescanIntervalUtil.js +99 -0
  849. package/build/dist/Utils/NetworkDiscovery/RescanIntervalUtil.js.map +1 -0
  850. package/build/dist/Utils/NetworkDiscovery/ScanModeUtil.js +85 -0
  851. package/build/dist/Utils/NetworkDiscovery/ScanModeUtil.js.map +1 -0
  852. package/build/dist/Utils/NetworkDiscovery/SnmpScanConfigUtil.js +560 -0
  853. package/build/dist/Utils/NetworkDiscovery/SnmpScanConfigUtil.js.map +1 -0
  854. package/build/dist/Utils/NetworkSite/SiteMaintenanceUtil.js +56 -0
  855. package/build/dist/Utils/NetworkSite/SiteMaintenanceUtil.js.map +1 -0
  856. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +185 -10
  857. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
  858. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +248 -21
  859. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -1
  860. package/build/dist/Utils/SecurityEvent/ThreatIntel/StixPatternParser.js +255 -0
  861. package/build/dist/Utils/SecurityEvent/ThreatIntel/StixPatternParser.js.map +1 -0
  862. package/build/dist/Utils/Telemetry/CrossSignalScope.js +27 -30
  863. package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
  864. package/build/dist/Utils/Telemetry/LlmMetricQuery.js +57 -1
  865. package/build/dist/Utils/Telemetry/LlmMetricQuery.js.map +1 -1
  866. package/package.json +2 -1
  867. package/Tests/Types/Log/LogQueryParser.test.ts +0 -186
  868. package/Types/Log/LogQueryParser.ts +0 -252
  869. package/build/dist/Types/Log/LogQueryParser.js +0 -200
  870. package/build/dist/Types/Log/LogQueryParser.js.map +0 -1
@@ -42,6 +42,7 @@ jest.mock("../../../Server/Services/NetworkDeviceService", () => {
42
42
  create: jest.fn(),
43
43
  findBy: jest.fn(),
44
44
  findOneBy: jest.fn(),
45
+ getDevicesByHostnames: jest.fn(),
45
46
  },
46
47
  };
47
48
  });
@@ -67,6 +68,26 @@ jest.mock("../../../Server/Services/NetworkDeviceAutoImportRuleService", () => {
67
68
  };
68
69
  });
69
70
 
71
+ jest.mock("../../../Server/Services/MonitorService", () => {
72
+ return {
73
+ __esModule: true,
74
+ default: {
75
+ create: jest.fn(),
76
+ findBy: jest.fn(),
77
+ findOneBy: jest.fn(),
78
+ },
79
+ };
80
+ });
81
+
82
+ jest.mock("../../../Server/Services/MonitorTemplateService", () => {
83
+ return {
84
+ __esModule: true,
85
+ default: {
86
+ findBy: jest.fn(),
87
+ },
88
+ };
89
+ });
90
+
70
91
  jest.mock("../../../Server/Infrastructure/Semaphore", () => {
71
92
  return {
72
93
  __esModule: true,
@@ -95,23 +116,33 @@ import NetworkDeviceAutoImportRuleEngineService, {
95
116
  AUTO_IMPORT_SWEEP_LOCK_NAMESPACE,
96
117
  AUTO_IMPORT_SWEEP_LOCK_TIMEOUT_MS,
97
118
  ExistingHostnamesByProjectId,
119
+ ImportAttemptBudgetsByProjectId,
98
120
  MAX_DEVICES_PER_AUTO_IMPORT_RUN,
121
+ MAX_MONITORS_PER_AUTO_IMPORT_RUN,
99
122
  MAX_RESULT_AGE_IN_HOURS,
100
123
  MAX_SCANS_PER_AUTO_IMPORT_RULE_RUN,
101
124
  } from "../../../Server/Services/NetworkDeviceAutoImportRuleEngineService";
102
125
  import NetworkDeviceAutoImportRuleService from "../../../Server/Services/NetworkDeviceAutoImportRuleService";
103
126
  import NetworkDeviceDiscoveryScanService from "../../../Server/Services/NetworkDeviceDiscoveryScanService";
104
127
  import NetworkDeviceService from "../../../Server/Services/NetworkDeviceService";
128
+ import MonitorService from "../../../Server/Services/MonitorService";
129
+ import MonitorTemplateService from "../../../Server/Services/MonitorTemplateService";
105
130
  import Semaphore from "../../../Server/Infrastructure/Semaphore";
106
131
  import logger from "../../../Server/Utils/Logger";
107
132
  import NetworkDevice from "../../../Models/DatabaseModels/NetworkDevice";
133
+ import Monitor from "../../../Models/DatabaseModels/Monitor";
134
+ import MonitorTemplate from "../../../Models/DatabaseModels/MonitorTemplate";
108
135
  import NetworkDeviceAutoImportRule from "../../../Models/DatabaseModels/NetworkDeviceAutoImportRule";
109
136
  import NetworkDeviceDiscoveryScan, {
110
137
  DiscoveredNetworkDevice,
111
138
  } from "../../../Models/DatabaseModels/NetworkDeviceDiscoveryScan";
139
+ import { DiscoveryScanSnmpConfig } from "../../../Utils/NetworkDiscovery/SnmpScanConfigUtil";
112
140
  import BadDataException from "../../../Types/Exception/BadDataException";
113
141
  import ObjectID from "../../../Types/ObjectID";
114
142
  import OneUptimeDate from "../../../Types/Date";
143
+ import MonitorSteps from "../../../Types/Monitor/MonitorSteps";
144
+ import MonitorStep from "../../../Types/Monitor/MonitorStep";
145
+ import MonitorType from "../../../Types/Monitor/MonitorType";
115
146
  import {
116
147
  AutoImportRuleRunResult,
117
148
  MAX_MATCHED_IP_SAMPLE,
@@ -138,6 +169,10 @@ const PROJECT_ID: ObjectID = new ObjectID(
138
169
  const PROBE_ID: ObjectID = new ObjectID("11111111-1111-4111-8111-111111111111");
139
170
  const SCAN_ID: ObjectID = new ObjectID("33333333-3333-4333-8333-333333333333");
140
171
  const RULE_ID: ObjectID = new ObjectID("77777777-7777-4777-8777-777777777777");
172
+ const TEMPLATE_ID: ObjectID = new ObjectID(
173
+ "88888888-8888-4888-8888-888888888888",
174
+ );
175
+ const TEMPLATE_DEVICE_ID: string = "99999999-9999-4999-8999-999999999999";
141
176
 
142
177
  // What the mocked Semaphore.lock hands back and release must get back.
143
178
  const FAKE_MUTEX: { id: string } = { id: "fake-sweep-mutex" };
@@ -148,6 +183,27 @@ const deviceFindByMock: jest.Mock =
148
183
  NetworkDeviceService.findBy as unknown as jest.Mock;
149
184
  const deviceFindOneByMock: jest.Mock =
150
185
  NetworkDeviceService.findOneBy as unknown as jest.Mock;
186
+ /*
187
+ * "Which of THESE addresses already have a device", asked of the database per
188
+ * scan. It replaced a paged walk of every device in the project — which sorted
189
+ * by `createdAt`, a value a bulk import stamps identically on every row it
190
+ * creates, so its pages overlapped and skipped and a missed hostname created a
191
+ * DUPLICATE device.
192
+ *
193
+ * Backed by the same `deviceFindByMock` fixtures every case already sets up, so
194
+ * a test still says "the inventory contains these devices" and this narrows
195
+ * them the way the real query does.
196
+ */
197
+ const devicesByHostnamesMock: jest.Mock =
198
+ NetworkDeviceService.getDevicesByHostnames as unknown as jest.Mock;
199
+ const monitorCreateMock: jest.Mock =
200
+ MonitorService.create as unknown as jest.Mock;
201
+ const monitorFindByMock: jest.Mock =
202
+ MonitorService.findBy as unknown as jest.Mock;
203
+ const monitorFindOneByMock: jest.Mock =
204
+ MonitorService.findOneBy as unknown as jest.Mock;
205
+ const monitorTemplateFindByMock: jest.Mock =
206
+ MonitorTemplateService.findBy as unknown as jest.Mock;
151
207
  const scanFindOneByMock: jest.Mock =
152
208
  NetworkDeviceDiscoveryScanService.findOneBy as unknown as jest.Mock;
153
209
  const scanFindByMock: jest.Mock =
@@ -165,9 +221,51 @@ const loggerErrorMock: jest.Mock = logger.error as unknown as jest.Mock;
165
221
 
166
222
  const RECENT_COMPLETED_AT: Date = OneUptimeDate.getCurrentDate();
167
223
 
224
+ /*
225
+ * The scan's credential sets (issue #3458), and the ids the probe stamps onto
226
+ * a discovered host to record which one answered it. Opaque literals, because
227
+ * that is how they are really used — written into the scan's jsonb by the
228
+ * form, copied onto a host by the probe, and looked up again here, in another
229
+ * process, out of a list the operator may have reordered since. Nothing may
230
+ * treat them as positions.
231
+ *
232
+ * The two sets share no credential value, so a device built with the wrong one
233
+ * shows up as a wrong value rather than as a coincidence that still passes.
234
+ */
235
+ const ACCESS_SNMP_CONFIG_ID: string = "access-switches-v2c";
236
+ const CORE_SNMP_CONFIG_ID: string = "core-routers-v3";
237
+
238
+ const ACCESS_SNMP_CONFIG: DiscoveryScanSnmpConfig = {
239
+ id: ACCESS_SNMP_CONFIG_ID,
240
+ name: "Access switches",
241
+ snmpVersion: "V2c",
242
+ snmpCommunityString: "public",
243
+ snmpPort: 161,
244
+ };
245
+
246
+ const CORE_SNMP_CONFIG: DiscoveryScanSnmpConfig = {
247
+ id: CORE_SNMP_CONFIG_ID,
248
+ name: "Core routers",
249
+ snmpVersion: "V3",
250
+ snmpPort: 1161,
251
+ snmpV3SecurityLevel: "authPriv",
252
+ snmpV3Username: "core-observer",
253
+ snmpV3AuthProtocol: "SHA",
254
+ snmpV3AuthKey: "core-auth-key",
255
+ snmpV3PrivProtocol: "AES",
256
+ snmpV3PrivKey: "core-priv-key",
257
+ };
258
+
168
259
  /*
169
260
  * The scan as the engine selects it: identity, results, and the credential
170
261
  * columns the builder copies onto every SNMP device it creates.
262
+ *
263
+ * It carries BOTH halves of the credential story, exactly as a saved scan
264
+ * does: the ordered `snmpConfigs` list, and the flattened mirror of its FIRST
265
+ * entry. The service writes that mirror on every save so a probe deployed a
266
+ * version behind still has something to sweep with — which also means a
267
+ * fixture with only the flattened half could not tell an engine that resolves
268
+ * each host's own credentials from one that just copies the scan row.
171
269
  */
172
270
  function makeScan(
173
271
  overrides: Record<string, unknown> = {},
@@ -181,6 +279,7 @@ function makeScan(
181
279
  autoImportProcessedAt: undefined,
182
280
  discoveredDevices: [],
183
281
  probeId: PROBE_ID,
282
+ snmpConfigs: [ACCESS_SNMP_CONFIG],
184
283
  snmpVersion: "V2c",
185
284
  snmpCommunityString: "public",
186
285
  snmpPort: 161,
@@ -214,6 +313,67 @@ function makeHost(
214
313
  };
215
314
  }
216
315
 
316
+ function makeMonitorSteps(
317
+ networkDeviceId: string = TEMPLATE_DEVICE_ID,
318
+ ): MonitorSteps {
319
+ const step: MonitorStep = new MonitorStep();
320
+ step.data!.networkDeviceMonitor = {
321
+ networkDeviceId: networkDeviceId,
322
+ monitorInterfaces: true,
323
+ collectEndpoints: true,
324
+ oids: [
325
+ {
326
+ oid: "1.3.6.1.2.1.1.3.0",
327
+ name: "sysUpTime",
328
+ description: "System uptime",
329
+ },
330
+ ],
331
+ };
332
+
333
+ const monitorSteps: MonitorSteps = new MonitorSteps();
334
+ monitorSteps.data = {
335
+ monitorStepsInstanceArray: [step],
336
+ defaultMonitorStatusId: new ObjectID(
337
+ "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
338
+ ),
339
+ };
340
+ return monitorSteps;
341
+ }
342
+
343
+ function makeTemplate(
344
+ overrides: Record<string, unknown> = {},
345
+ ): MonitorTemplate {
346
+ const template: MonitorTemplate = new MonitorTemplate();
347
+ template.id = TEMPLATE_ID;
348
+ template.projectId = PROJECT_ID;
349
+ template.templateName = "Core switch health";
350
+ template.monitorName = "SNMP health";
351
+ template.monitorDescription = "Provisioned from discovery";
352
+ template.monitorType = MonitorType.NetworkDevice;
353
+ template.monitorSteps = makeMonitorSteps();
354
+ template.monitoringInterval = "*/5 * * * *";
355
+ template.minimumProbeAgreement = 2;
356
+ template.customFields = { source: "auto-import" };
357
+ Object.assign(template, overrides);
358
+ return template;
359
+ }
360
+
361
+ function makeExistingDevice(
362
+ overrides: Record<string, unknown> = {},
363
+ ): NetworkDevice {
364
+ const device: NetworkDevice = new NetworkDevice();
365
+ device.id = new ObjectID("44444444-4444-4444-8444-444444444444");
366
+ device.projectId = PROJECT_ID;
367
+ device.name = "core-switch-01";
368
+ device.hostname = "10.0.0.5";
369
+ Object.assign(device, overrides);
370
+ return device;
371
+ }
372
+
373
+ function provisionedMonitor(callIndex: number): Monitor {
374
+ return monitorCreateMock.mock.calls[callIndex]![0].data as Monitor;
375
+ }
376
+
217
377
  // Enough unique in-target addresses to overrun the attempt budget.
218
378
  function makeHostsBeyondTheCap(): Array<DiscoveredNetworkDevice> {
219
379
  const hosts: Array<DiscoveredNetworkDevice> = [];
@@ -284,8 +444,43 @@ beforeEach(() => {
284
444
  * lock — the happy defaults each test narrows as needed.
285
445
  */
286
446
  deviceFindByMock.mockResolvedValue([]);
447
+ devicesByHostnamesMock.mockImplementation(
448
+ async (data: {
449
+ hostnames: Array<string>;
450
+ }): Promise<Map<string, NetworkDevice>> => {
451
+ const wanted: Set<string> = new Set<string>(data.hostnames);
452
+ const inventory: Array<NetworkDevice> =
453
+ (await deviceFindByMock.mock.results[
454
+ deviceFindByMock.mock.results.length - 1
455
+ ]?.value) || (await deviceFindByMock());
456
+ const found: Map<string, NetworkDevice> = new Map<
457
+ string,
458
+ NetworkDevice
459
+ >();
460
+ for (const device of inventory) {
461
+ if (device.hostname && wanted.has(device.hostname)) {
462
+ found.set(device.hostname, device);
463
+ }
464
+ }
465
+ return found;
466
+ },
467
+ );
287
468
  deviceFindOneByMock.mockResolvedValue(null);
288
- createMock.mockResolvedValue({});
469
+ createMock.mockImplementation(
470
+ ({ data }: { data: NetworkDevice }): Promise<NetworkDevice> => {
471
+ data.id = data.id || ObjectID.generate();
472
+ return Promise.resolve(data);
473
+ },
474
+ );
475
+ monitorFindByMock.mockResolvedValue([]);
476
+ monitorFindOneByMock.mockResolvedValue(null);
477
+ monitorTemplateFindByMock.mockResolvedValue([]);
478
+ monitorCreateMock.mockImplementation(
479
+ ({ data }: { data: Monitor }): Promise<Monitor> => {
480
+ data.id = data.id || ObjectID.generate();
481
+ return Promise.resolve(data);
482
+ },
483
+ );
289
484
  scanUpdateMock.mockResolvedValue(undefined);
290
485
  ruleFindByMock.mockResolvedValue([makeRule()]);
291
486
  semaphoreLockMock.mockResolvedValue(FAKE_MUTEX);
@@ -386,6 +581,8 @@ describe("NetworkDeviceAutoImportRuleEngineService.processCompletedScan", () =>
386
581
  });
387
582
 
388
583
  expect(createMock).toHaveBeenCalledTimes(1);
584
+ expect(monitorFindByMock).not.toHaveBeenCalled();
585
+ expect(monitorTemplateFindByMock).not.toHaveBeenCalled();
389
586
  const device: NetworkDevice = createdDevice(0);
390
587
  // The address is the hostname AND the dedup key downstream.
391
588
  expect(device.hostname).toBe("10.0.0.5");
@@ -397,8 +594,13 @@ describe("NetworkDeviceAutoImportRuleEngineService.processCompletedScan", () =>
397
594
  * device into the poll-time auto-apply instead.
398
595
  */
399
596
  expect(device.autoApplyVendorHealthTemplate).toBe(true);
400
- // Built from THIS scan: the scan's credentials rode along.
597
+ /*
598
+ * Built from THIS scan: the scan's credentials rode along. The host is
599
+ * unstamped, so the credentials are the scan's FIRST config — see the
600
+ * per-host case below for the stamped ones.
601
+ */
401
602
  expect(device.snmpVersion).toBe("V2c");
603
+ expect(device.snmpCommunityString).toBe("public");
402
604
  expect(createMock.mock.calls[0]![0].props).toEqual({ isRoot: true });
403
605
 
404
606
  expect(scanUpdateMock).toHaveBeenCalledTimes(1);
@@ -417,6 +619,94 @@ describe("NetworkDeviceAutoImportRuleEngineService.processCompletedScan", () =>
417
619
  expect(restamped[2]).toBe(unmatchedRow);
418
620
  });
419
621
 
622
+ /*
623
+ * The multi-credential guarantee (issue #3458) on the AUTOMATIC path, which
624
+ * is where it matters most.
625
+ *
626
+ * A scan now tries several credential sets per host and the probe records
627
+ * which one answered. An import that copied the scan's first set regardless
628
+ * would create every host found by any other set with credentials its agent
629
+ * rejects — and on this path nobody is looking: there is no Review dialog, no
630
+ * human reading the list, and no error at create time. The devices simply
631
+ * appear, poll red, and report "SNMP timeout", with nothing on them to say
632
+ * the right community string is sitting one entry further down the scan's own
633
+ * list.
634
+ *
635
+ * The engine has no credential logic of its own — it hands the scan and the
636
+ * host to DiscoveredDeviceBuilder — so what this pins is that it hands over
637
+ * the WHOLE scan (list included, not just the flattened columns its select
638
+ * used to carry) and the host row with its stamp intact.
639
+ */
640
+ it("imports each matched host with the credential set that actually answered it", async () => {
641
+ const accessSwitch: DiscoveredNetworkDevice = makeHost({
642
+ ipAddress: "10.0.0.5",
643
+ sysName: "access-switch-01",
644
+ snmpConfigId: ACCESS_SNMP_CONFIG_ID,
645
+ });
646
+ const coreRouter: DiscoveredNetworkDevice = makeHost({
647
+ ipAddress: "10.0.0.6",
648
+ sysName: "core-router-01",
649
+ snmpConfigId: CORE_SNMP_CONFIG_ID,
650
+ });
651
+ /*
652
+ * No stamp: a result from a probe that predates the field, or one stored
653
+ * before it existed. Neither is an error, and both have to import as
654
+ * something that can poll — so they take the first config, which is
655
+ * exactly the credential set such a probe was handed through the mirror.
656
+ */
657
+ const unstampedHost: DiscoveredNetworkDevice = makeHost({
658
+ ipAddress: "10.0.0.7",
659
+ sysName: "unstamped-host-01",
660
+ });
661
+
662
+ scanFindOneByMock.mockResolvedValue(
663
+ makeScan({
664
+ discoveredDevices: [accessSwitch, coreRouter, unstampedHost],
665
+ snmpConfigs: [ACCESS_SNMP_CONFIG, CORE_SNMP_CONFIG],
666
+ }),
667
+ );
668
+
669
+ const result: AutoImportRuleRunResult | null = await processScan();
670
+
671
+ expect(result).toMatchObject({
672
+ hostsEvaluated: 3,
673
+ hostsMatched: 3,
674
+ devicesCreated: 3,
675
+ devicesFailed: 0,
676
+ });
677
+ expect(createMock).toHaveBeenCalledTimes(3);
678
+
679
+ // Hosts are imported in the order the scan reported them.
680
+ const accessDevice: NetworkDevice = createdDevice(0);
681
+ expect(accessDevice.hostname).toBe("10.0.0.5");
682
+ expect(accessDevice.snmpVersion).toBe("V2c");
683
+ expect(accessDevice.snmpCommunityString).toBe("public");
684
+ expect(accessDevice.snmpPort).toBe(161);
685
+
686
+ const coreDevice: NetworkDevice = createdDevice(1);
687
+ expect(coreDevice.hostname).toBe("10.0.0.6");
688
+ expect(coreDevice.snmpVersion).toBe("V3");
689
+ expect(coreDevice.snmpPort).toBe(1161);
690
+ expect(coreDevice.snmpV3SecurityLevel).toBe("authPriv");
691
+ expect(coreDevice.snmpV3Username).toBe("core-observer");
692
+ expect(coreDevice.snmpV3AuthProtocol).toBe("SHA");
693
+ expect(coreDevice.snmpV3AuthKey).toBe("core-auth-key");
694
+ expect(coreDevice.snmpV3PrivProtocol).toBe("AES");
695
+ expect(coreDevice.snmpV3PrivKey).toBe("core-priv-key");
696
+ /*
697
+ * The v3 config has no community string, so neither may the device — this
698
+ * is the assertion that catches the first config leaking in through the
699
+ * flattened columns the scan row still mirrors it onto.
700
+ */
701
+ expect(coreDevice.snmpCommunityString).toBeUndefined();
702
+
703
+ const fallbackDevice: NetworkDevice = createdDevice(2);
704
+ expect(fallbackDevice.hostname).toBe("10.0.0.7");
705
+ expect(fallbackDevice.snmpVersion).toBe("V2c");
706
+ expect(fallbackDevice.snmpCommunityString).toBe("public");
707
+ expect(fallbackDevice.snmpV3Username).toBeUndefined();
708
+ });
709
+
420
710
  /*
421
711
  * Recurring scans re-report the same hosts every interval; seeing the
422
712
  * same results twice must create nothing twice.
@@ -444,6 +734,502 @@ describe("NetworkDeviceAutoImportRuleEngineService.processCompletedScan", () =>
444
734
  expect(Object.keys(updateCall.data)).toEqual(["autoImportProcessedAt"]);
445
735
  });
446
736
 
737
+ describe("monitor-template provisioning", () => {
738
+ it("creates an active monitor from the selected template and rebinds it to the new device", async () => {
739
+ const template: MonitorTemplate = makeTemplate();
740
+ scanFindOneByMock.mockResolvedValue(
741
+ makeScan({ discoveredDevices: [makeHost()] }),
742
+ );
743
+ ruleFindByMock.mockResolvedValue([
744
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
745
+ ]);
746
+ monitorTemplateFindByMock.mockResolvedValue([template]);
747
+
748
+ const result: AutoImportRuleRunResult | null = await processScan();
749
+
750
+ expect(result).toMatchObject({
751
+ devicesCreated: 1,
752
+ monitorsCreated: 1,
753
+ monitorsWouldCreate: 0,
754
+ monitorsFailed: 0,
755
+ });
756
+ expect(monitorCreateMock).toHaveBeenCalledTimes(1);
757
+
758
+ const device: NetworkDevice = createdDevice(0);
759
+ const monitor: Monitor = provisionedMonitor(0);
760
+ expect(monitor.name).toBe("core-switch-01 - SNMP health");
761
+ expect(monitor.description).toBe("Provisioned from discovery");
762
+ expect(monitor.monitorType).toBe(MonitorType.NetworkDevice);
763
+ expect(monitor.monitorTemplateId?.toString()).toBe(
764
+ TEMPLATE_ID.toString(),
765
+ );
766
+ expect(monitor.autoProvisionedNetworkDeviceId?.toString()).toBe(
767
+ device.id?.toString(),
768
+ );
769
+ expect(
770
+ monitor.monitorSteps?.data?.monitorStepsInstanceArray[0]?.data
771
+ ?.networkDeviceMonitor?.networkDeviceId,
772
+ ).toBe(device.id?.toString());
773
+ expect(monitor.monitoringInterval).toBe("*/5 * * * *");
774
+ expect(monitor.minimumProbeAgreement).toBe(2);
775
+ expect(monitor.customFields).toEqual({ source: "auto-import" });
776
+ expect(monitorCreateMock.mock.calls[0]![0].props).toEqual({
777
+ isRoot: true,
778
+ tenantId: PROJECT_ID,
779
+ });
780
+
781
+ // A cached template is reused across an estate and must never mutate.
782
+ expect(
783
+ template.monitorSteps?.data?.monitorStepsInstanceArray[0]?.data
784
+ ?.networkDeviceMonitor?.networkDeviceId,
785
+ ).toBe(TEMPLATE_DEVICE_ID);
786
+ });
787
+
788
+ it("backfills a selected template monitor for an already-registered matching device", async () => {
789
+ const existingDevice: NetworkDevice = makeExistingDevice();
790
+ scanFindOneByMock.mockResolvedValue(
791
+ makeScan({
792
+ discoveredDevices: [makeHost({ isAlreadyRegistered: true })],
793
+ }),
794
+ );
795
+ deviceFindByMock.mockResolvedValue([existingDevice]);
796
+ ruleFindByMock.mockResolvedValue([
797
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
798
+ ]);
799
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
800
+
801
+ const result: AutoImportRuleRunResult | null = await processScan();
802
+
803
+ expect(result).toMatchObject({
804
+ hostsSkippedAlreadyRegistered: 1,
805
+ devicesCreated: 0,
806
+ monitorsCreated: 1,
807
+ });
808
+ expect(createMock).not.toHaveBeenCalled();
809
+ expect(devicesByHostnamesMock.mock.calls[0]![0].select.projectId).toBe(
810
+ true,
811
+ );
812
+ expect(
813
+ provisionedMonitor(0).autoProvisionedNetworkDeviceId?.toString(),
814
+ ).toBe(existingDevice.id?.toString());
815
+ });
816
+
817
+ it("does not duplicate a manually configured monitor already watching the device", async () => {
818
+ const existingDevice: NetworkDevice = makeExistingDevice();
819
+ const manualMonitor: Monitor = new Monitor();
820
+ manualMonitor.id = ObjectID.generate();
821
+ manualMonitor.monitorType = MonitorType.NetworkDevice;
822
+ manualMonitor.monitorSteps = makeMonitorSteps(
823
+ existingDevice.id!.toString(),
824
+ );
825
+
826
+ scanFindOneByMock.mockResolvedValue(
827
+ makeScan({ discoveredDevices: [makeHost()] }),
828
+ );
829
+ deviceFindByMock.mockResolvedValue([existingDevice]);
830
+ monitorFindByMock.mockResolvedValue([manualMonitor]);
831
+ ruleFindByMock.mockResolvedValue([
832
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
833
+ ]);
834
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
835
+
836
+ const result: AutoImportRuleRunResult | null = await processScan();
837
+
838
+ expect(result).toMatchObject({
839
+ monitorsCreated: 0,
840
+ monitorsSkippedAlreadyExisting: 1,
841
+ });
842
+ expect(monitorCreateMock).not.toHaveBeenCalled();
843
+ expect(monitorFindByMock).toHaveBeenCalledTimes(1);
844
+ });
845
+
846
+ it("uses provenance to skip an automatic monitor that already exists", async () => {
847
+ const existingDevice: NetworkDevice = makeExistingDevice();
848
+ const existingMonitor: Monitor = new Monitor();
849
+ existingMonitor.id = ObjectID.generate();
850
+ existingMonitor.monitorType = MonitorType.NetworkDevice;
851
+ existingMonitor.monitorTemplateId = TEMPLATE_ID;
852
+ existingMonitor.autoProvisionedNetworkDeviceId = existingDevice.id!;
853
+ existingMonitor.monitorSteps = makeMonitorSteps(
854
+ existingDevice.id!.toString(),
855
+ );
856
+
857
+ scanFindOneByMock.mockResolvedValue(
858
+ makeScan({ discoveredDevices: [makeHost()] }),
859
+ );
860
+ deviceFindByMock.mockResolvedValue([existingDevice]);
861
+ monitorFindByMock.mockResolvedValue([existingMonitor]);
862
+ ruleFindByMock.mockResolvedValue([
863
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
864
+ ]);
865
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
866
+
867
+ const result: AutoImportRuleRunResult | null = await processScan();
868
+
869
+ expect(result).toMatchObject({
870
+ monitorsCreated: 0,
871
+ monitorsSkippedAlreadyExisting: 1,
872
+ });
873
+ expect(monitorCreateMock).not.toHaveBeenCalled();
874
+ expect(monitorFindByMock).toHaveBeenCalledTimes(1);
875
+ });
876
+
877
+ it("deduplicates two matching rules that select the same template", async () => {
878
+ scanFindOneByMock.mockResolvedValue(
879
+ makeScan({ discoveredDevices: [makeHost()] }),
880
+ );
881
+ ruleFindByMock.mockResolvedValue([
882
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
883
+ makeRule({
884
+ id: ObjectID.generate(),
885
+ ipMatchTarget: undefined,
886
+ sysNamePattern: "core-switch",
887
+ monitorTemplateId: TEMPLATE_ID,
888
+ }),
889
+ ]);
890
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
891
+
892
+ const result: AutoImportRuleRunResult | null = await processScan();
893
+
894
+ expect(result?.monitorsCreated).toBe(1);
895
+ expect(monitorCreateMock).toHaveBeenCalledTimes(1);
896
+ expect(monitorTemplateFindByMock).toHaveBeenCalledTimes(1);
897
+ });
898
+
899
+ it("creates one monitor per distinct template selected by matching rules", async () => {
900
+ const secondTemplateId: ObjectID = new ObjectID(
901
+ "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
902
+ );
903
+ scanFindOneByMock.mockResolvedValue(
904
+ makeScan({ discoveredDevices: [makeHost()] }),
905
+ );
906
+ ruleFindByMock.mockResolvedValue([
907
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
908
+ makeRule({
909
+ id: ObjectID.generate(),
910
+ ipMatchTarget: undefined,
911
+ sysNamePattern: "core-switch",
912
+ monitorTemplateId: secondTemplateId,
913
+ }),
914
+ ]);
915
+ monitorTemplateFindByMock.mockResolvedValue([
916
+ makeTemplate(),
917
+ makeTemplate({
918
+ id: secondTemplateId,
919
+ monitorName: "Interface health",
920
+ }),
921
+ ]);
922
+
923
+ const result: AutoImportRuleRunResult | null = await processScan();
924
+
925
+ expect(result?.monitorsCreated).toBe(2);
926
+ expect(monitorCreateMock).toHaveBeenCalledTimes(2);
927
+ expect(
928
+ monitorCreateMock.mock.calls.map((call: Array<any>): string => {
929
+ return call[0].data.monitorTemplateId.toString();
930
+ }),
931
+ ).toEqual([TEMPLATE_ID.toString(), secondTemplateId.toString()]);
932
+ });
933
+
934
+ it("reports monitor failures separately and leaves them retryable", async () => {
935
+ scanFindOneByMock.mockResolvedValue(
936
+ makeScan({ discoveredDevices: [makeHost()] }),
937
+ );
938
+ ruleFindByMock.mockResolvedValue([
939
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
940
+ ]);
941
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
942
+ monitorCreateMock.mockRejectedValueOnce(new Error("plan limit reached"));
943
+
944
+ const firstResult: AutoImportRuleRunResult | null = await processScan();
945
+
946
+ expect(firstResult).toMatchObject({
947
+ devicesCreated: 1,
948
+ monitorsCreated: 0,
949
+ monitorsFailed: 1,
950
+ });
951
+
952
+ const created: NetworkDevice = createdDevice(0);
953
+ jest.clearAllMocks();
954
+ deviceFindByMock.mockResolvedValue([created]);
955
+ monitorFindByMock.mockResolvedValue([]);
956
+ monitorFindOneByMock.mockResolvedValue(null);
957
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
958
+ ruleFindByMock.mockResolvedValue([
959
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
960
+ ]);
961
+ scanFindOneByMock.mockResolvedValue(
962
+ makeScan({ discoveredDevices: [makeHost()] }),
963
+ );
964
+ scanUpdateMock.mockResolvedValue(undefined);
965
+ monitorCreateMock.mockImplementation(
966
+ ({ data }: { data: Monitor }): Promise<Monitor> => {
967
+ return Promise.resolve(data);
968
+ },
969
+ );
970
+
971
+ const retryResult: AutoImportRuleRunResult | null = await processScan();
972
+
973
+ expect(retryResult).toMatchObject({
974
+ devicesCreated: 0,
975
+ monitorsCreated: 1,
976
+ monitorsFailed: 0,
977
+ });
978
+ });
979
+
980
+ it("defensively skips inert Network Device monitors for ping-only hosts", async () => {
981
+ scanFindOneByMock.mockResolvedValue(
982
+ makeScan({
983
+ discoveredDevices: [makeHost({ snmpReachable: false })],
984
+ }),
985
+ );
986
+ ruleFindByMock.mockResolvedValue([
987
+ makeRule({
988
+ includePingOnlyHosts: true,
989
+ monitorTemplateId: TEMPLATE_ID,
990
+ }),
991
+ ]);
992
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
993
+
994
+ const result: AutoImportRuleRunResult | null = await processScan();
995
+
996
+ expect(result).toMatchObject({
997
+ devicesCreated: 1,
998
+ monitorsCreated: 0,
999
+ monitorsSkippedUnsupportedHost: 1,
1000
+ });
1001
+ expect(monitorCreateMock).not.toHaveBeenCalled();
1002
+ });
1003
+
1004
+ it("does not backfill an SNMP monitor onto an existing monitor-backed device", async () => {
1005
+ const existingDevice: NetworkDevice = makeExistingDevice({
1006
+ monitoringMethod: "Monitor",
1007
+ });
1008
+ scanFindOneByMock.mockResolvedValue(
1009
+ makeScan({ discoveredDevices: [makeHost({ snmpReachable: true })] }),
1010
+ );
1011
+ deviceFindByMock.mockResolvedValue([existingDevice]);
1012
+ ruleFindByMock.mockResolvedValue([
1013
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
1014
+ ]);
1015
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
1016
+
1017
+ const result: AutoImportRuleRunResult | null = await processScan();
1018
+
1019
+ expect(result).toMatchObject({
1020
+ monitorsCreated: 0,
1021
+ monitorsSkippedUnsupportedHost: 1,
1022
+ });
1023
+ expect(monitorCreateMock).not.toHaveBeenCalled();
1024
+ });
1025
+
1026
+ it("sees a manual monitor created after the initial project snapshot", async () => {
1027
+ const existingDevice: NetworkDevice = makeExistingDevice();
1028
+ const manualMonitor: Monitor = new Monitor();
1029
+ manualMonitor.monitorType = MonitorType.NetworkDevice;
1030
+ manualMonitor.monitorSteps = makeMonitorSteps(
1031
+ existingDevice.id!.toString(),
1032
+ );
1033
+
1034
+ scanFindOneByMock.mockResolvedValue(
1035
+ makeScan({ discoveredDevices: [makeHost()] }),
1036
+ );
1037
+ deviceFindByMock.mockResolvedValue([existingDevice]);
1038
+ monitorFindByMock
1039
+ .mockResolvedValueOnce([])
1040
+ .mockResolvedValueOnce([manualMonitor]);
1041
+ ruleFindByMock.mockResolvedValue([
1042
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
1043
+ ]);
1044
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
1045
+
1046
+ const result: AutoImportRuleRunResult | null = await processScan();
1047
+
1048
+ expect(result).toMatchObject({
1049
+ monitorsCreated: 0,
1050
+ monitorsSkippedAlreadyExisting: 1,
1051
+ });
1052
+ expect(monitorCreateMock).not.toHaveBeenCalled();
1053
+ expect(monitorFindByMock).toHaveBeenCalledTimes(2);
1054
+ expect(monitorFindByMock.mock.calls[1]![0].select.monitorType).toBe(true);
1055
+ });
1056
+
1057
+ it("reports a conflicting drifted provenance row instead of treating it as a successful race winner", async () => {
1058
+ const existingDevice: NetworkDevice = makeExistingDevice();
1059
+ const otherDeviceId: ObjectID = new ObjectID(
1060
+ "cccccccc-cccc-4ccc-8ccc-cccccccccccc",
1061
+ );
1062
+ const driftedMonitor: Monitor = new Monitor();
1063
+ driftedMonitor.monitorType = MonitorType.NetworkDevice;
1064
+ driftedMonitor.monitorTemplateId = TEMPLATE_ID;
1065
+ driftedMonitor.autoProvisionedNetworkDeviceId = existingDevice.id!;
1066
+ driftedMonitor.monitorSteps = makeMonitorSteps(otherDeviceId.toString());
1067
+
1068
+ scanFindOneByMock.mockResolvedValue(
1069
+ makeScan({ discoveredDevices: [makeHost()] }),
1070
+ );
1071
+ deviceFindByMock.mockResolvedValue([existingDevice]);
1072
+ monitorFindByMock.mockResolvedValue([driftedMonitor]);
1073
+ monitorCreateMock.mockRejectedValue(new Error("duplicate key"));
1074
+ monitorFindOneByMock.mockResolvedValue(driftedMonitor);
1075
+ ruleFindByMock.mockResolvedValue([
1076
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
1077
+ ]);
1078
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
1079
+
1080
+ const result: AutoImportRuleRunResult | null = await processScan();
1081
+
1082
+ expect(result).toMatchObject({
1083
+ monitorsCreated: 0,
1084
+ monitorsSkippedAlreadyExisting: 0,
1085
+ monitorsFailed: 1,
1086
+ });
1087
+ expect(monitorCreateMock).toHaveBeenCalledTimes(1);
1088
+ expect(monitorFindOneByMock.mock.calls[0]![0].select).toMatchObject({
1089
+ monitorType: true,
1090
+ monitorSteps: true,
1091
+ monitorTemplateId: true,
1092
+ autoProvisionedNetworkDeviceId: true,
1093
+ });
1094
+ });
1095
+
1096
+ it("classifies a valid concurrent automatic create as an idempotent skip", async () => {
1097
+ const existingDevice: NetworkDevice = makeExistingDevice();
1098
+ const concurrentMonitor: Monitor = new Monitor();
1099
+ concurrentMonitor.monitorType = MonitorType.NetworkDevice;
1100
+ concurrentMonitor.monitorTemplateId = TEMPLATE_ID;
1101
+ concurrentMonitor.autoProvisionedNetworkDeviceId = existingDevice.id!;
1102
+ concurrentMonitor.monitorSteps = makeMonitorSteps(
1103
+ existingDevice.id!.toString(),
1104
+ );
1105
+
1106
+ scanFindOneByMock.mockResolvedValue(
1107
+ makeScan({ discoveredDevices: [makeHost()] }),
1108
+ );
1109
+ deviceFindByMock.mockResolvedValue([existingDevice]);
1110
+ monitorFindByMock.mockResolvedValue([]);
1111
+ monitorCreateMock.mockRejectedValue(new Error("duplicate key"));
1112
+ monitorFindOneByMock.mockResolvedValue(concurrentMonitor);
1113
+ ruleFindByMock.mockResolvedValue([
1114
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
1115
+ ]);
1116
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
1117
+
1118
+ const result: AutoImportRuleRunResult | null = await processScan();
1119
+
1120
+ expect(result).toMatchObject({
1121
+ monitorsCreated: 0,
1122
+ monitorsSkippedAlreadyExisting: 1,
1123
+ monitorsFailed: 0,
1124
+ });
1125
+ });
1126
+
1127
+ it("treats an automatic monitor orphaned from its template as an existing operator-managed monitor", async () => {
1128
+ const existingDevice: NetworkDevice = makeExistingDevice();
1129
+ const orphanedMonitor: Monitor = new Monitor();
1130
+ orphanedMonitor.monitorType = MonitorType.NetworkDevice;
1131
+ orphanedMonitor.autoProvisionedNetworkDeviceId = existingDevice.id!;
1132
+ orphanedMonitor.monitorSteps = makeMonitorSteps(
1133
+ existingDevice.id!.toString(),
1134
+ );
1135
+
1136
+ scanFindOneByMock.mockResolvedValue(
1137
+ makeScan({ discoveredDevices: [makeHost()] }),
1138
+ );
1139
+ deviceFindByMock.mockResolvedValue([existingDevice]);
1140
+ monitorFindByMock.mockResolvedValue([orphanedMonitor]);
1141
+ ruleFindByMock.mockResolvedValue([
1142
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
1143
+ ]);
1144
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
1145
+
1146
+ const result: AutoImportRuleRunResult | null = await processScan();
1147
+
1148
+ expect(result).toMatchObject({
1149
+ monitorsCreated: 0,
1150
+ monitorsSkippedAlreadyExisting: 1,
1151
+ });
1152
+ });
1153
+
1154
+ it("attempts one failed device-template key only once per run even when the host is duplicated", async () => {
1155
+ scanFindOneByMock.mockResolvedValue(
1156
+ makeScan({ discoveredDevices: [makeHost(), makeHost()] }),
1157
+ );
1158
+ ruleFindByMock.mockResolvedValue([
1159
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
1160
+ ]);
1161
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
1162
+ monitorCreateMock.mockRejectedValue(new Error("plan limit reached"));
1163
+
1164
+ const result: AutoImportRuleRunResult | null = await processScan();
1165
+
1166
+ expect(result).toMatchObject({
1167
+ monitorsCreated: 0,
1168
+ monitorsFailed: 1,
1169
+ });
1170
+ expect(monitorCreateMock).toHaveBeenCalledTimes(1);
1171
+ });
1172
+
1173
+ it("reports a missing template consistently instead of promising it in a dry run", async () => {
1174
+ ruleFindOneByMock.mockResolvedValue(
1175
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
1176
+ );
1177
+ ruleFindByMock.mockResolvedValue([]);
1178
+ monitorTemplateFindByMock.mockResolvedValue([]);
1179
+ mockRunNowScans([makeScan({ discoveredDevices: [makeHost()] })]);
1180
+
1181
+ const result: AutoImportRuleRunResult = await runRule(true);
1182
+
1183
+ expect(result).toMatchObject({
1184
+ monitorsWouldCreate: 0,
1185
+ monitorsFailed: 1,
1186
+ });
1187
+ expect(monitorCreateMock).not.toHaveBeenCalled();
1188
+ });
1189
+
1190
+ it("caps missing-template failures across a large existing estate", async () => {
1191
+ const hosts: Array<DiscoveredNetworkDevice> = Array.from(
1192
+ { length: MAX_MONITORS_PER_AUTO_IMPORT_RUN + 1 },
1193
+ (_value: unknown, index: number): DiscoveredNetworkDevice => {
1194
+ return makeHost({
1195
+ ipAddress: `10.2.${Math.floor(index / 256)}.${index % 256}`,
1196
+ sysName: `missing-template-switch-${index}`,
1197
+ });
1198
+ },
1199
+ );
1200
+ const devices: Array<NetworkDevice> = hosts.map(
1201
+ (host: DiscoveredNetworkDevice): NetworkDevice => {
1202
+ return makeExistingDevice({
1203
+ id: ObjectID.generate(),
1204
+ hostname: host.ipAddress,
1205
+ name: host.sysName,
1206
+ });
1207
+ },
1208
+ );
1209
+
1210
+ ruleFindOneByMock.mockResolvedValue(
1211
+ makeRule({
1212
+ ipMatchTarget: "10.0.0.0/8",
1213
+ monitorTemplateId: TEMPLATE_ID,
1214
+ }),
1215
+ );
1216
+ ruleFindByMock.mockResolvedValue([]);
1217
+ deviceFindByMock.mockResolvedValue(devices);
1218
+ monitorTemplateFindByMock.mockResolvedValue([]);
1219
+ mockRunNowScans([makeScan({ discoveredDevices: hosts })]);
1220
+
1221
+ const result: AutoImportRuleRunResult = await runRule(true);
1222
+
1223
+ expect(result).toMatchObject({
1224
+ monitorsWouldCreate: 0,
1225
+ monitorsFailed: MAX_MONITORS_PER_AUTO_IMPORT_RUN,
1226
+ isTruncated: true,
1227
+ isDryRun: true,
1228
+ });
1229
+ expect(monitorCreateMock).not.toHaveBeenCalled();
1230
+ });
1231
+ });
1232
+
447
1233
  /*
448
1234
  * An over-long "address" is junk that would fail the varchar(100)
449
1235
  * hostname on every pass, identically, forever — so it is refused before
@@ -527,6 +1313,7 @@ describe("NetworkDeviceAutoImportRuleEngineService.processCompletedScan", () =>
527
1313
  const result: AutoImportRuleRunResult | null = await processScan();
528
1314
 
529
1315
  expect(createMock).toHaveBeenCalledTimes(1);
1316
+ expect(deviceFindOneByMock.mock.calls[0]![0].select.projectId).toBe(true);
530
1317
  expect(result).toMatchObject({
531
1318
  hostsMatched: 1,
532
1319
  hostsSkippedAlreadyRegistered: 1,
@@ -566,6 +1353,126 @@ describe("NetworkDeviceAutoImportRuleEngineService.processCompletedScan", () =>
566
1353
  expect(Object.keys(updateCall.data)).not.toContain("autoImportProcessedAt");
567
1354
  });
568
1355
 
1356
+ it("does not stamp a later scan when an earlier scan exactly exhausted the shared project budget", async () => {
1357
+ scanFindOneByMock.mockResolvedValue(
1358
+ makeScan({ discoveredDevices: [makeHost()] }),
1359
+ );
1360
+ ruleFindByMock.mockResolvedValue([
1361
+ makeRule({ ipMatchTarget: "10.0.0.0/8" }),
1362
+ ]);
1363
+ const attemptBudgets: ImportAttemptBudgetsByProjectId = new Map([
1364
+ [
1365
+ PROJECT_ID.toString(),
1366
+ {
1367
+ deviceCount: MAX_DEVICES_PER_AUTO_IMPORT_RUN,
1368
+ monitorCount: 0,
1369
+ },
1370
+ ],
1371
+ ]);
1372
+
1373
+ const result: AutoImportRuleRunResult | null =
1374
+ await NetworkDeviceAutoImportRuleEngineService.processCompletedScan({
1375
+ scanId: SCAN_ID,
1376
+ existingHostnamesByProjectId: new Map(),
1377
+ attemptBudgetsByProjectId: attemptBudgets,
1378
+ });
1379
+
1380
+ expect(result).toMatchObject({
1381
+ devicesCreated: 0,
1382
+ devicesFailed: 0,
1383
+ isTruncated: true,
1384
+ });
1385
+ expect(createMock).not.toHaveBeenCalled();
1386
+ // This scan contains unattempted work. The next sweep must see it again.
1387
+ expect(scanUpdateMock).not.toHaveBeenCalled();
1388
+ expect(
1389
+ loggerErrorMock.mock.calls.some((call: Array<unknown>) => {
1390
+ return String(call[0]).includes("without making progress");
1391
+ }),
1392
+ ).toBe(false);
1393
+ });
1394
+
1395
+ it("does not run a per-device monitor JSON search after the inherited monitor budget is exhausted", async () => {
1396
+ const existingDevice: NetworkDevice = makeExistingDevice();
1397
+ scanFindOneByMock.mockResolvedValue(
1398
+ makeScan({ discoveredDevices: [makeHost()] }),
1399
+ );
1400
+ deviceFindByMock.mockResolvedValue([existingDevice]);
1401
+ ruleFindByMock.mockResolvedValue([
1402
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
1403
+ ]);
1404
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
1405
+ const attemptBudgets: ImportAttemptBudgetsByProjectId = new Map([
1406
+ [
1407
+ PROJECT_ID.toString(),
1408
+ {
1409
+ deviceCount: 0,
1410
+ monitorCount: MAX_MONITORS_PER_AUTO_IMPORT_RUN,
1411
+ },
1412
+ ],
1413
+ ]);
1414
+
1415
+ const result: AutoImportRuleRunResult | null =
1416
+ await NetworkDeviceAutoImportRuleEngineService.processCompletedScan({
1417
+ scanId: SCAN_ID,
1418
+ existingHostnamesByProjectId: new Map(),
1419
+ existingMonitorsByProjectId: new Map(),
1420
+ attemptBudgetsByProjectId: attemptBudgets,
1421
+ });
1422
+
1423
+ expect(result).toMatchObject({
1424
+ monitorsCreated: 0,
1425
+ monitorsFailed: 0,
1426
+ isTruncated: true,
1427
+ });
1428
+ // One project snapshot only; no second JSON-search refresh for the host.
1429
+ expect(monitorFindByMock).toHaveBeenCalledTimes(1);
1430
+ expect(monitorCreateMock).not.toHaveBeenCalled();
1431
+ expect(scanUpdateMock).not.toHaveBeenCalled();
1432
+ });
1433
+
1434
+ it("does not retire unattempted hosts when a partial inherited budget is exhausted by failures", async () => {
1435
+ scanFindOneByMock.mockResolvedValue(
1436
+ makeScan({
1437
+ discoveredDevices: [
1438
+ makeHost(),
1439
+ makeHost({ ipAddress: "10.0.0.6", sysName: "core-switch-02" }),
1440
+ ],
1441
+ }),
1442
+ );
1443
+ ruleFindByMock.mockResolvedValue([
1444
+ makeRule({ ipMatchTarget: "10.0.0.0/8" }),
1445
+ ]);
1446
+ createMock.mockRejectedValue(new BadDataException("create is broken"));
1447
+ deviceFindOneByMock.mockResolvedValue(null);
1448
+ const attemptBudgets: ImportAttemptBudgetsByProjectId = new Map([
1449
+ [
1450
+ PROJECT_ID.toString(),
1451
+ {
1452
+ deviceCount: MAX_DEVICES_PER_AUTO_IMPORT_RUN - 1,
1453
+ monitorCount: 0,
1454
+ },
1455
+ ],
1456
+ ]);
1457
+
1458
+ const result: AutoImportRuleRunResult | null =
1459
+ await NetworkDeviceAutoImportRuleEngineService.processCompletedScan({
1460
+ scanId: SCAN_ID,
1461
+ existingHostnamesByProjectId: new Map(),
1462
+ attemptBudgetsByProjectId: attemptBudgets,
1463
+ });
1464
+
1465
+ expect(result).toMatchObject({
1466
+ hostsEvaluated: 2,
1467
+ hostsMatched: 2,
1468
+ devicesCreated: 0,
1469
+ devicesFailed: 1,
1470
+ isTruncated: true,
1471
+ });
1472
+ expect(createMock).toHaveBeenCalledTimes(2); // primary + fallback name
1473
+ expect(scanUpdateMock).not.toHaveBeenCalled();
1474
+ });
1475
+
569
1476
  /*
570
1477
  * The resume protocol's other half: a truncated pass that created NOTHING
571
1478
  * — every attempt failed — is stamped anyway. Leaving the marker NULL
@@ -600,7 +1507,7 @@ describe("NetworkDeviceAutoImportRuleEngineService.processCompletedScan", () =>
600
1507
  // And the operator is told, loudly, why nothing imported.
601
1508
  expect(
602
1509
  loggerErrorMock.mock.calls.some((call: Array<unknown>) => {
603
- return String(call[0]).includes("every create failing");
1510
+ return String(call[0]).includes("without making progress");
604
1511
  }),
605
1512
  ).toBe(true);
606
1513
  });
@@ -682,6 +1589,75 @@ describe("NetworkDeviceAutoImportRuleEngineService.applyRuleToCompletedScans", (
682
1589
  expect(semaphoreLockMock).not.toHaveBeenCalled();
683
1590
  });
684
1591
 
1592
+ it("dry-runs monitor reconciliation without creating a device or monitor", async () => {
1593
+ ruleFindOneByMock.mockResolvedValue(
1594
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
1595
+ );
1596
+ ruleFindByMock.mockResolvedValue([]);
1597
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
1598
+ mockRunNowScans([
1599
+ makeScan({ discoveredDevices: [makeHost(), makeHost()] }),
1600
+ ]);
1601
+
1602
+ const result: AutoImportRuleRunResult = await runRule(true);
1603
+
1604
+ expect(result).toMatchObject({
1605
+ hostsMatched: 2,
1606
+ hostsSkippedAlreadyRegistered: 1,
1607
+ devicesCreated: 0,
1608
+ monitorsWouldCreate: 1,
1609
+ monitorsCreated: 0,
1610
+ monitorsSkippedAlreadyExisting: 1,
1611
+ monitorsFailed: 0,
1612
+ isDryRun: true,
1613
+ });
1614
+ expect(createMock).not.toHaveBeenCalled();
1615
+ expect(monitorCreateMock).not.toHaveBeenCalled();
1616
+ expect(scanUpdateMock).not.toHaveBeenCalled();
1617
+ });
1618
+
1619
+ it("caps monitor backfill work even when every matching device already exists", async () => {
1620
+ const hosts: Array<DiscoveredNetworkDevice> = Array.from(
1621
+ { length: MAX_MONITORS_PER_AUTO_IMPORT_RUN + 1 },
1622
+ (_value: unknown, index: number): DiscoveredNetworkDevice => {
1623
+ return makeHost({
1624
+ ipAddress: `10.1.${Math.floor(index / 256)}.${index % 256}`,
1625
+ sysName: `existing-switch-${index}`,
1626
+ });
1627
+ },
1628
+ );
1629
+ const devices: Array<NetworkDevice> = hosts.map(
1630
+ (host: DiscoveredNetworkDevice): NetworkDevice => {
1631
+ return makeExistingDevice({
1632
+ id: ObjectID.generate(),
1633
+ hostname: host.ipAddress,
1634
+ name: host.sysName,
1635
+ });
1636
+ },
1637
+ );
1638
+
1639
+ ruleFindOneByMock.mockResolvedValue(
1640
+ makeRule({
1641
+ ipMatchTarget: "10.0.0.0/8",
1642
+ monitorTemplateId: TEMPLATE_ID,
1643
+ }),
1644
+ );
1645
+ ruleFindByMock.mockResolvedValue([]);
1646
+ deviceFindByMock.mockResolvedValue(devices);
1647
+ monitorTemplateFindByMock.mockResolvedValue([makeTemplate()]);
1648
+ mockRunNowScans([makeScan({ discoveredDevices: hosts })]);
1649
+
1650
+ const result: AutoImportRuleRunResult = await runRule(true);
1651
+
1652
+ expect(result).toMatchObject({
1653
+ devicesCreated: 0,
1654
+ monitorsWouldCreate: MAX_MONITORS_PER_AUTO_IMPORT_RUN,
1655
+ isTruncated: true,
1656
+ isDryRun: true,
1657
+ });
1658
+ expect(monitorCreateMock).not.toHaveBeenCalled();
1659
+ });
1660
+
685
1661
  /*
686
1662
  * The two-phase scan read: the listing is {_id} stubs only, and each scan
687
1663
  * is re-read individually with its status re-checked — so one manual run
@@ -929,5 +1905,23 @@ describe("NetworkDeviceAutoImportRuleEngineService.applyRuleToCompletedScans", (
929
1905
  "Auto-import rule not found.",
930
1906
  );
931
1907
  });
1908
+
1909
+ it("rejects a rule whose template changed after the caller authorized it", async () => {
1910
+ ruleFindOneByMock.mockResolvedValue(
1911
+ makeRule({ monitorTemplateId: TEMPLATE_ID }),
1912
+ );
1913
+
1914
+ await expect(
1915
+ NetworkDeviceAutoImportRuleEngineService.applyRuleToCompletedScans({
1916
+ ruleId: RULE_ID,
1917
+ projectId: PROJECT_ID,
1918
+ isDryRun: true,
1919
+ expectedMonitorTemplateId: null,
1920
+ }),
1921
+ ).rejects.toThrow("changed while the run was being authorized");
1922
+
1923
+ expect(scanFindByMock).not.toHaveBeenCalled();
1924
+ expect(monitorCreateMock).not.toHaveBeenCalled();
1925
+ });
932
1926
  });
933
1927
  });