@oneuptime/common 12.0.25 → 12.0.27

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 (856) hide show
  1. package/Models/AnalyticsModels/Index.ts +2 -0
  2. package/Models/AnalyticsModels/ThreatIntelIndicator.ts +413 -0
  3. package/Models/DatabaseModels/AlertSeverity.ts +4 -1
  4. package/Models/DatabaseModels/CephClusterFeed.ts +625 -0
  5. package/Models/DatabaseModels/CloudResourceFeed.ts +625 -0
  6. package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +13 -0
  7. package/Models/DatabaseModels/DetectionRule.ts +9 -3
  8. package/Models/DatabaseModels/DockerHostFeed.ts +625 -0
  9. package/Models/DatabaseModels/DockerSwarmClusterFeed.ts +628 -0
  10. package/Models/DatabaseModels/GoogleSecOpsConnection.ts +9 -3
  11. package/Models/DatabaseModels/HostFeed.ts +625 -0
  12. package/Models/DatabaseModels/IncidentSeverity.ts +4 -1
  13. package/Models/DatabaseModels/Index.ts +22 -0
  14. package/Models/DatabaseModels/KubernetesClusterFeed.ts +628 -0
  15. package/Models/DatabaseModels/Monitor.ts +87 -0
  16. package/Models/DatabaseModels/NetworkDevice.ts +96 -5
  17. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +92 -6
  18. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +301 -31
  19. package/Models/DatabaseModels/NetworkSite.ts +120 -0
  20. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +1 -0
  21. package/Models/DatabaseModels/PodmanHostFeed.ts +625 -0
  22. package/Models/DatabaseModels/ProxmoxClusterFeed.ts +626 -0
  23. package/Models/DatabaseModels/ScheduledMaintenance.ts +67 -0
  24. package/Models/DatabaseModels/ServiceFeed.ts +625 -0
  25. package/Models/DatabaseModels/TelemetrySourceMap.ts +474 -0
  26. package/Models/DatabaseModels/ThreatIntelFeed.ts +758 -0
  27. package/Models/DatabaseModels/UserOnCallLog.ts +1 -0
  28. package/Models/DatabaseModels/UserTotpAuth.ts +1 -0
  29. package/Models/DatabaseModels/UserWebAuthn.ts +1 -0
  30. package/Server/API/AlertAPI.ts +23 -1
  31. package/Server/API/BaseAPI.ts +14 -3
  32. package/Server/API/IncidentAPI.ts +41 -1
  33. package/Server/API/IncidentEpisodeAPI.ts +23 -1
  34. package/Server/API/MicrosoftTeamsAPI.ts +31 -2
  35. package/Server/API/ScheduledMaintenanceAPI.ts +23 -1
  36. package/Server/API/SlackAPI.ts +48 -0
  37. package/Server/API/TelemetryAPI.ts +167 -42
  38. package/Server/API/UserOnCallLogTimelineAPI.ts +75 -61
  39. package/Server/API/UserTotpAuthAPI.ts +67 -1
  40. package/Server/API/UserWebAuthnAPI.ts +44 -1
  41. package/Server/Infrastructure/Postgres/SchemaMigrations/1787923136162-MigrationName.ts +57 -0
  42. package/Server/Infrastructure/Postgres/SchemaMigrations/1789600000000-AddAutoProvisionedNetworkDeviceMonitors.ts +49 -0
  43. package/Server/Infrastructure/Postgres/SchemaMigrations/1789700000000-AddNetworkScaleIndexes.ts +129 -0
  44. package/Server/Infrastructure/Postgres/SchemaMigrations/1789800000000-WidenSecurityEventLastErrorColumns.ts +54 -0
  45. package/Server/Infrastructure/Postgres/SchemaMigrations/1789900000000-AddNetworkSiteRollupPolicyAndMaintenance.ts +64 -0
  46. package/Server/Infrastructure/Postgres/SchemaMigrations/1790000000000-AddTelemetrySourceMap.ts +64 -0
  47. package/Server/Infrastructure/Postgres/SchemaMigrations/1790000000001-AddSnmpConfigsToNetworkDeviceDiscoveryScan.ts +72 -0
  48. package/Server/Infrastructure/Postgres/SchemaMigrations/1790003445000-AddSnmpEnabledToNetworkDeviceDiscoveryScan.ts +31 -0
  49. package/Server/Infrastructure/Postgres/SchemaMigrations/1790100000000-AddResourceActivityFeeds.ts +489 -0
  50. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +18 -0
  51. package/Server/Middleware/IdentityRateLimit.ts +53 -3
  52. package/Server/Services/AIService.ts +181 -41
  53. package/Server/Services/CephClusterFeedService.ts +99 -0
  54. package/Server/Services/CephClusterLabelRuleEngineService.ts +29 -0
  55. package/Server/Services/CephClusterOwnerRuleEngineService.ts +23 -0
  56. package/Server/Services/CephClusterOwnerTeamService.ts +129 -0
  57. package/Server/Services/CephClusterOwnerUserService.ts +123 -0
  58. package/Server/Services/CephClusterService.ts +223 -2
  59. package/Server/Services/CloudResourceFeedService.ts +99 -0
  60. package/Server/Services/CloudResourceLabelRuleEngineService.ts +30 -0
  61. package/Server/Services/CloudResourceOwnerRuleEngineService.ts +33 -0
  62. package/Server/Services/CloudResourceOwnerTeamService.ts +129 -0
  63. package/Server/Services/CloudResourceOwnerUserService.ts +123 -0
  64. package/Server/Services/CloudResourceService.ts +227 -2
  65. package/Server/Services/DatabaseService.ts +265 -0
  66. package/Server/Services/DockerHostFeedService.ts +99 -0
  67. package/Server/Services/DockerHostLabelRuleEngineService.ts +29 -0
  68. package/Server/Services/DockerHostOwnerRuleEngineService.ts +23 -0
  69. package/Server/Services/DockerHostOwnerTeamService.ts +129 -0
  70. package/Server/Services/DockerHostOwnerUserService.ts +123 -0
  71. package/Server/Services/DockerHostService.ts +227 -2
  72. package/Server/Services/DockerSwarmClusterFeedService.ts +102 -0
  73. package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +30 -0
  74. package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +24 -0
  75. package/Server/Services/DockerSwarmClusterOwnerTeamService.ts +133 -0
  76. package/Server/Services/DockerSwarmClusterOwnerUserService.ts +127 -0
  77. package/Server/Services/DockerSwarmClusterService.ts +229 -2
  78. package/Server/Services/EnterpriseLicenseService.ts +15 -7
  79. package/Server/Services/ExceptionAggregationService.ts +12 -2
  80. package/Server/Services/HostFeedService.ts +99 -0
  81. package/Server/Services/HostLabelRuleEngineService.ts +29 -0
  82. package/Server/Services/HostOwnerRuleEngineService.ts +23 -0
  83. package/Server/Services/HostOwnerTeamService.ts +129 -0
  84. package/Server/Services/HostOwnerUserService.ts +123 -0
  85. package/Server/Services/HostService.ts +215 -2
  86. package/Server/Services/IncidentService.ts +11 -0
  87. package/Server/Services/Index.ts +24 -0
  88. package/Server/Services/KubernetesClusterFeedService.ts +99 -0
  89. package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +30 -0
  90. package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +24 -0
  91. package/Server/Services/KubernetesClusterOwnerTeamService.ts +133 -0
  92. package/Server/Services/KubernetesClusterOwnerUserService.ts +127 -0
  93. package/Server/Services/KubernetesClusterService.ts +231 -2
  94. package/Server/Services/LogAggregationService.ts +23 -280
  95. package/Server/Services/MetricAggregationService.ts +98 -1
  96. package/Server/Services/MonitorService.ts +177 -13
  97. package/Server/Services/MonitorTemplateService.ts +111 -0
  98. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +777 -86
  99. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +199 -16
  100. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +1055 -14
  101. package/Server/Services/NetworkDeviceService.ts +750 -4
  102. package/Server/Services/NetworkInterfaceService.ts +415 -0
  103. package/Server/Services/NetworkSiteService.ts +485 -52
  104. package/Server/Services/PodmanHostFeedService.ts +99 -0
  105. package/Server/Services/PodmanHostLabelRuleEngineService.ts +29 -0
  106. package/Server/Services/PodmanHostOwnerRuleEngineService.ts +23 -0
  107. package/Server/Services/PodmanHostOwnerTeamService.ts +129 -0
  108. package/Server/Services/PodmanHostOwnerUserService.ts +123 -0
  109. package/Server/Services/PodmanHostService.ts +227 -2
  110. package/Server/Services/ProjectService.ts +16 -10
  111. package/Server/Services/ProxmoxClusterFeedService.ts +99 -0
  112. package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +30 -0
  113. package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +24 -0
  114. package/Server/Services/ProxmoxClusterOwnerTeamService.ts +131 -0
  115. package/Server/Services/ProxmoxClusterOwnerUserService.ts +124 -0
  116. package/Server/Services/ProxmoxClusterService.ts +225 -2
  117. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +61 -0
  118. package/Server/Services/ServiceFeedService.ts +99 -0
  119. package/Server/Services/ServiceLabelRuleEngineService.ts +29 -0
  120. package/Server/Services/ServiceOwnerRuleEngineService.ts +26 -0
  121. package/Server/Services/ServiceOwnerTeamService.ts +129 -0
  122. package/Server/Services/ServiceOwnerUserService.ts +123 -0
  123. package/Server/Services/ServiceService.ts +227 -3
  124. package/Server/Services/StatusPageSubscriberService.ts +7 -0
  125. package/Server/Services/TelemetryAttributeService.ts +13 -3
  126. package/Server/Services/TelemetrySourceMapService.ts +307 -0
  127. package/Server/Services/ThreatIntelFeedService.ts +222 -0
  128. package/Server/Services/ThreatIntelIndicatorService.ts +428 -0
  129. package/Server/Services/TraceAggregationService.ts +101 -11
  130. package/Server/Services/UserService.ts +13 -6
  131. package/Server/Services/UserTwoFactorBackupCodeService.ts +127 -0
  132. package/Server/Services/UserWebhookService.ts +11 -2
  133. package/Server/Static/Brand/README.md +38 -0
  134. package/Server/Static/Brand/favicons/apple-touch-icon.png +0 -0
  135. package/Server/Static/Brand/favicons/favicon-16x16.png +0 -0
  136. package/Server/Static/Brand/favicons/favicon-32x32.png +0 -0
  137. package/Server/Static/Brand/favicons/favicon.ico +0 -0
  138. package/Server/Static/Brand/favicons/safari-pinned-tab.svg +31 -0
  139. package/Server/Static/Brand/hou-wb.svg +1 -0
  140. package/Server/Static/Brand/oneuptime-logo.svg +1 -0
  141. package/Server/Static/Brand/ou-wb.svg +1 -0
  142. package/Server/Static/Vendor/README.md +4 -0
  143. package/Server/Types/AnalyticsDatabase/ModelPermission.ts +13 -3
  144. package/Server/Types/Database/AggregateBy.ts +83 -0
  145. package/Server/Types/Database/AggregateResultUtil.ts +126 -0
  146. package/Server/Types/Database/JSONColumnQuery.ts +18 -0
  147. package/Server/Types/Database/QueryHelper.ts +40 -0
  148. package/Server/Types/Database/QueryUtil.ts +26 -0
  149. package/Server/Types/Workflow/Components/API/Utils.ts +10 -1
  150. package/Server/Types/Workflow/Components/JavaScript.ts +8 -0
  151. package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +9 -0
  152. package/Server/Utils/AI/SRE/InvestigationGrader.ts +18 -0
  153. package/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.ts +422 -0
  154. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +176 -0
  155. package/Server/Utils/DataSource/HttpFetch.ts +18 -0
  156. package/Server/Utils/Database/RelationIdUtil.ts +42 -0
  157. package/Server/Utils/Marketing/MarketingEventUtil.ts +38 -9
  158. package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +34 -3
  159. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +9 -1
  160. package/Server/Utils/Monitor/Criteria/SyntheticMonitor.ts +28 -10
  161. package/Server/Utils/Monitor/MonitorAlert.ts +541 -332
  162. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +330 -64
  163. package/Server/Utils/Monitor/MonitorIncident.ts +640 -434
  164. package/Server/Utils/Monitor/MonitorResource.ts +226 -49
  165. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +46 -3
  166. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +23 -102
  167. package/Server/Utils/Monitor/PerEntityCriteriaFanOut.ts +329 -0
  168. package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +427 -0
  169. package/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.ts +310 -0
  170. package/Server/Utils/OnCallNotificationContext.ts +686 -0
  171. package/Server/Utils/PrivateNetworkWebhookConfig.ts +549 -0
  172. package/Server/Utils/ResourceFeed/ResourceFeedUtil.ts +139 -0
  173. package/Server/Utils/Response.ts +11 -1
  174. package/Server/Utils/SSRFProtection.ts +230 -60
  175. package/Server/Utils/SecurityEvent/ConnectorErrorMessage.ts +106 -0
  176. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +84 -284
  177. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +47 -20
  178. package/Server/Utils/SecurityEvent/SecurityEventAlerting.ts +318 -0
  179. package/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.ts +199 -0
  180. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.ts +252 -0
  181. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +739 -0
  182. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.ts +533 -0
  183. package/Server/Utils/StartServer.ts +83 -56
  184. package/Server/Utils/StatusPageSubscriberWebhook.ts +3 -0
  185. package/Server/Utils/Telemetry/SourceMapResolver.ts +480 -0
  186. package/Server/Utils/TwoFactorBackupCodeNotification.ts +106 -0
  187. package/Server/Utils/VM/VMAPI.ts +3 -0
  188. package/Server/Utils/VM/VMRunner.ts +27 -1
  189. package/Server/Utils/VendorAssets.ts +42 -0
  190. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +136 -6
  191. package/Server/Views/AcknowledgeUserOnCallNotification.ejs +11 -9
  192. package/Server/Views/Partials/Head.ejs +9 -9
  193. package/Server/Views/Partials/OnCallNotificationDetails.ejs +48 -0
  194. package/Server/Views/ViewMessage.ejs +11 -9
  195. package/Tests/App/Accounts/LoginTwoFactorRecovery.test.tsx +972 -0
  196. package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +401 -0
  197. package/Tests/App/Dashboard/DiscoveryScanEditForm.test.tsx +707 -0
  198. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +1908 -18
  199. package/Tests/App/Dashboard/ResourceFeed.test.tsx +230 -0
  200. package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +216 -0
  201. package/Tests/App/Dashboard/TopologyAddToMonitoring.test.tsx +192 -0
  202. package/Tests/App/Dashboard/WorkspaceNotificationRuleConditions.test.tsx +439 -0
  203. package/Tests/Models/DatabaseModels/DateColumnDeserialization.test.ts +182 -0
  204. package/Tests/Models/DatabaseModels/RelationColumnModelTypeCoverage.test.ts +82 -0
  205. package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +398 -0
  206. package/Tests/Models/DiscoveryScanNameColumn.test.ts +151 -16
  207. package/Tests/Models/DiscoveryScanSnmpEnabledColumn.test.ts +593 -0
  208. package/Tests/Models/NetworkDeviceCreateContract.test.ts +102 -0
  209. package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +607 -0
  210. package/Tests/Server/API/AIGenerationRequestBudget.test.ts +355 -0
  211. package/Tests/Server/API/AIKillSwitchBackstop.test.ts +602 -0
  212. package/Tests/Server/API/BaseAPIUpdateDateColumns.test.ts +154 -0
  213. package/Tests/Server/API/MicrosoftTeamsBotTestEndpoint.test.ts +335 -0
  214. package/Tests/Server/API/UserOnCallLogTimelineAcknowledgePage.test.ts +611 -0
  215. package/Tests/Server/API/UserTotpAuthAPI.test.ts +498 -4
  216. package/Tests/Server/API/UserWebAuthnBackupCodeMinting.test.ts +682 -0
  217. package/Tests/Server/Infrastructure/ExampleDockerfiles.test.ts +595 -0
  218. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +9 -0
  219. package/Tests/Server/Services/AIServiceProjectAccess.test.ts +6 -0
  220. package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +18 -0
  221. package/Tests/Server/Services/DatabaseServiceAggregateBy.test.ts +590 -0
  222. package/Tests/Server/Services/DatabaseServiceUpdateWriteRouting.test.ts +12 -0
  223. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +162 -26
  224. package/Tests/Server/Services/EnterpriseLicenseServiceCreate.test.ts +292 -0
  225. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +119 -12
  226. package/Tests/Server/Services/LogAggregationAttributeOperators.test.ts +109 -0
  227. package/Tests/Server/Services/MetricAggregationAttributeOperators.test.ts +170 -0
  228. package/Tests/Server/Services/MonitorTemplateServiceNetworkDeviceSync.test.ts +383 -0
  229. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +997 -3
  230. package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +830 -0
  231. package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +528 -0
  232. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +3141 -1
  233. package/Tests/Server/Services/NetworkDeviceRegisteredHostnames.test.ts +1023 -0
  234. package/Tests/Server/Services/NetworkDeviceSiteAssignmentRuleSkip.test.ts +728 -0
  235. package/Tests/Server/Services/NetworkInterfaceServiceUpsert.test.ts +795 -0
  236. package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +903 -0
  237. package/Tests/Server/Services/NetworkSiteService.test.ts +165 -24
  238. package/Tests/Server/Services/ProjectServiceChangePlan.test.ts +5 -3
  239. package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +5 -2
  240. package/Tests/Server/Services/ResourceCreationFeedWrites.test.ts +304 -0
  241. package/Tests/Server/Services/ResourceFeedServices.test.ts +269 -0
  242. package/Tests/Server/Services/ResourceOwnerFeedWrites.test.ts +245 -0
  243. package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +792 -0
  244. package/Tests/Server/Services/TelemetrySourceMapService.test.ts +483 -0
  245. package/Tests/Server/Services/ThreatIntelFeedService.test.ts +351 -0
  246. package/Tests/Server/Services/ThreatIntelIndicatorService.test.ts +366 -0
  247. package/Tests/Server/Services/TraceAggregationAttributeOperators.test.ts +507 -0
  248. package/Tests/Server/Services/UserTwoFactorBackupCodeGenerateIfNone.test.ts +705 -0
  249. package/Tests/Server/Services/WorkspaceNotificationRuleOnCallDutyPolicy.test.ts +306 -0
  250. package/Tests/Server/Types/Database/AggregateResultUtil.test.ts +386 -0
  251. package/Tests/Server/Types/Database/Permissions/SelectRejectionMessageContract.test.ts +424 -0
  252. package/Tests/Server/Types/Database/QueryHelperWildcard.test.ts +142 -0
  253. package/Tests/Server/Types/Workflow/Components/ApiComponentPrivateNetwork.test.ts +163 -0
  254. package/Tests/Server/Types/Workflow/Components/JavaScriptPrivateNetwork.test.ts +124 -0
  255. package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +5 -0
  256. package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +39 -1
  257. package/Tests/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.test.ts +338 -0
  258. package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWildcard.test.ts +383 -0
  259. package/Tests/Server/Utils/Marketing/EmittedMarketingEvent.ts +23 -0
  260. package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +51 -0
  261. package/Tests/Server/Utils/Monitor/Criteria/SyntheticMonitorCriteria.test.ts +259 -0
  262. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPerSeriesFanout.test.ts +557 -0
  263. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +12 -2
  264. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkLogWritePath.test.ts +404 -0
  265. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +8 -2
  266. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +125 -98
  267. package/Tests/Server/Utils/Monitor/PerEntityCriteriaFanOut.test.ts +444 -0
  268. package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1112 -0
  269. package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +717 -0
  270. package/Tests/Server/Utils/NetworkDevice/RulePatternValidator.test.ts +78 -0
  271. package/Tests/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.test.ts +363 -0
  272. package/Tests/Server/Utils/OfflineAssetHygiene.test.ts +35 -0
  273. package/Tests/Server/Utils/OnCallNotificationContext.test.ts +908 -0
  274. package/Tests/Server/Utils/PrivateNetworkWebhookConfig.test.ts +423 -0
  275. package/Tests/Server/Utils/ResourceFeed/ResourceFeedUtil.test.ts +191 -0
  276. package/Tests/Server/Utils/SSRFProtectionPrivateNetwork.test.ts +597 -0
  277. package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +819 -0
  278. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +381 -0
  279. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +417 -0
  280. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +819 -0
  281. package/Tests/Server/Utils/SecurityEvent/SecurityEventAlerting.test.ts +246 -0
  282. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.test.ts +282 -0
  283. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.test.ts +312 -0
  284. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.test.ts +854 -0
  285. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.test.ts +437 -0
  286. package/Tests/Server/Utils/StartServerErrorStatus.test.ts +225 -0
  287. package/Tests/Server/Utils/StatusPage/MonitorRulePatternValidator.test.ts +62 -0
  288. package/Tests/Server/Utils/StatusPageSubscriberWebhookPrivateNetwork.test.ts +119 -0
  289. package/Tests/Server/Utils/Telemetry/SourceMapResolver.test.ts +542 -0
  290. package/Tests/Server/Utils/TwoFactorBackupCodeNotification.test.ts +272 -0
  291. package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +111 -0
  292. package/Tests/Server/Utils/VendorAssets.test.ts +117 -0
  293. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +101 -4
  294. package/Tests/Server/Utils/Workspace/MicrosoftTeamsInstallStateDiagnostics.test.ts +922 -0
  295. package/Tests/Server/Utils/Workspace/MicrosoftTeamsRosterDiagnosticMessages.test.ts +642 -0
  296. package/Tests/Server/Views/OnCallAcknowledgePage.test.ts +430 -0
  297. package/Tests/Types/API/HostnameAuthorityParsing.test.ts +1 -0
  298. package/Tests/Types/API/URLMailtoQueryString.test.ts +439 -0
  299. package/Tests/Types/API/URLQueryString.test.ts +481 -0
  300. package/Tests/Types/API/URLRouteQuerySeparation.test.ts +491 -0
  301. package/Tests/Types/BaseDatabase/Wildcard.test.ts +163 -0
  302. package/Tests/Types/BaseDatabase/WildcardPattern.test.ts +149 -0
  303. package/Tests/Types/Database/DateColumnValue.test.ts +265 -0
  304. package/Tests/Types/DateToIsoStringOrNull.test.ts +67 -0
  305. package/Tests/Types/Log/LogQueryToFilter.test.ts +218 -43
  306. package/Tests/Types/Monitor/KubernetesTemplateGroupByKeys.test.ts +225 -0
  307. package/Tests/Types/Monitor/TemplateGroupByKeys.test.ts +296 -0
  308. package/Tests/Types/NetworkAutomation/RuleRunResult.test.ts +102 -0
  309. package/Tests/Types/NetworkAutomation/RuleRunResultDescribe.test.ts +145 -0
  310. package/Tests/Types/NetworkSite/SiteHealthRollupPolicy.test.ts +58 -0
  311. package/Tests/Types/SerializableObjectDictionaryImportCycle.test.ts +15 -0
  312. package/Tests/Types/Telemetry/TelemetrySearchQuery.test.ts +620 -0
  313. package/Tests/Types/WhatsApp/WhatsAppTemplates.test.ts +110 -0
  314. package/Tests/Types/Workspace/NotificationRuleConditionUtil.test.ts +76 -6
  315. package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +16 -4
  316. package/Tests/Types/Workspace/NotificationRules/OnCallDutyPolicyConditions.test.ts +669 -0
  317. package/Tests/UI/Components/DictionaryFilterOperatorWildcard.test.ts +175 -0
  318. package/Tests/UI/Components/IconOpticalSize.test.tsx +377 -0
  319. package/Tests/UI/Components/LogsHistogramDragTooltip.test.tsx +393 -0
  320. package/Tests/UI/Components/LogsViewerHistogramZoom.test.tsx +248 -0
  321. package/Tests/UI/Components/TelemetryHistogramDragTooltip.test.tsx +205 -0
  322. package/Tests/UI/Components/UseHistogramZoom.test.tsx +262 -0
  323. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardInstallGuidance.test.tsx +332 -0
  324. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsInstallGuidanceContent.test.tsx +643 -0
  325. package/Tests/Utils/Monitor/InterfaceInventoryUtil.test.ts +824 -0
  326. package/Tests/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.test.ts +626 -0
  327. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +718 -0
  328. package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +59 -0
  329. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +287 -2
  330. package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +73 -0
  331. package/Tests/Utils/NetworkDiscovery/PingMonitorBuilder.test.ts +317 -0
  332. package/Tests/Utils/NetworkDiscovery/RescanIntervalUtil.test.ts +262 -0
  333. package/Tests/Utils/NetworkDiscovery/ScanModeUtil.test.ts +474 -0
  334. package/Tests/Utils/NetworkDiscovery/SnmpScanConfigUtil.test.ts +2442 -0
  335. package/Tests/Utils/NetworkSite/SiteMaintenanceUtil.test.ts +188 -0
  336. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +522 -0
  337. package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +694 -0
  338. package/Tests/Utils/SecurityEvent/ThreatIntel/StixPatternParser.test.ts +281 -0
  339. package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +87 -67
  340. package/Types/API/URL.ts +100 -28
  341. package/Types/AnalyticsDatabase/AnalyticsTableName.ts +8 -0
  342. package/Types/BaseDatabase/NotWildcard.ts +86 -0
  343. package/Types/BaseDatabase/Wildcard.ts +89 -0
  344. package/Types/BaseDatabase/WildcardPattern.ts +176 -0
  345. package/Types/Database/DateColumnValue.ts +184 -0
  346. package/Types/Database/TableColumn.ts +40 -5
  347. package/Types/Date.ts +37 -0
  348. package/Types/Email/EmailTemplateType.ts +1 -0
  349. package/Types/JSON.ts +8 -0
  350. package/Types/Log/LogQueryToFilter.ts +167 -129
  351. package/Types/Monitor/DockerAlertTemplates.ts +43 -12
  352. package/Types/Monitor/HostAlertTemplates.ts +31 -3
  353. package/Types/Monitor/KubernetesAlertTemplates.ts +98 -0
  354. package/Types/Monitor/MonitorStep.ts +49 -0
  355. package/Types/Monitor/PodmanAlertTemplates.ts +39 -12
  356. package/Types/Monitor/SnmpMonitor/CdpNeighbor.ts +14 -0
  357. package/Types/Monitor/SnmpMonitor/LldpNeighbor.ts +11 -0
  358. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +11 -4
  359. package/Types/NetworkAutomation/RuleRunResult.ts +191 -2
  360. package/Types/NetworkSite/SiteHealthRollupPolicy.ts +96 -0
  361. package/Types/Permission.ts +411 -0
  362. package/Types/Probe/ProbeApiIngestResponse.ts +42 -0
  363. package/Types/SecurityEvent/ThreatIntelConstants.ts +118 -0
  364. package/Types/SerializableObjectDictionary.ts +8 -0
  365. package/Types/Telemetry/SourceMap.ts +56 -0
  366. package/Types/Telemetry/TelemetrySearchQuery.ts +949 -0
  367. package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +12 -1
  368. package/UI/Components/Charts/Utils/useHistogramZoom.ts +101 -0
  369. package/UI/Components/Dictionary/DictionaryFilterOperator.ts +83 -0
  370. package/UI/Components/Icon/Icon.tsx +28 -1
  371. package/UI/Components/LogsViewer/LogsViewer.tsx +19 -3
  372. package/UI/Components/LogsViewer/components/LogSearchBar.tsx +26 -4
  373. package/UI/Components/LogsViewer/components/LogSearchHelp.tsx +34 -16
  374. package/UI/Components/LogsViewer/components/LogsHistogram.tsx +52 -1
  375. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +18 -2
  376. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +52 -1
  377. package/UI/Components/TelemetryViewer/components/TelemetrySearchBar.tsx +15 -2
  378. package/Utils/Metrics/MetricExplorerUrl.ts +77 -15
  379. package/Utils/Monitor/InterfaceInventoryUtil.ts +251 -0
  380. package/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.ts +333 -0
  381. package/Utils/Monitor/NetworkTopologyUtil.ts +249 -28
  382. package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +14 -6
  383. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +2 -0
  384. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +49 -18
  385. package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +215 -0
  386. package/Utils/NetworkDiscovery/RescanIntervalUtil.ts +148 -0
  387. package/Utils/NetworkDiscovery/ScanModeUtil.ts +105 -0
  388. package/Utils/NetworkDiscovery/SnmpScanConfigUtil.ts +827 -0
  389. package/Utils/NetworkSite/SiteMaintenanceUtil.ts +110 -0
  390. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +350 -19
  391. package/Utils/NetworkSite/SiteUptimeUtil.ts +422 -21
  392. package/Utils/SecurityEvent/ThreatIntel/StixPatternParser.ts +383 -0
  393. package/Utils/Telemetry/CrossSignalScope.ts +37 -39
  394. package/build/dist/Models/AnalyticsModels/Index.js +2 -0
  395. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  396. package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js +325 -0
  397. package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js.map +1 -0
  398. package/build/dist/Models/DatabaseModels/AlertSeverity.js +4 -1
  399. package/build/dist/Models/DatabaseModels/AlertSeverity.js.map +1 -1
  400. package/build/dist/Models/DatabaseModels/CephClusterFeed.js +648 -0
  401. package/build/dist/Models/DatabaseModels/CephClusterFeed.js.map +1 -0
  402. package/build/dist/Models/DatabaseModels/CloudResourceFeed.js +648 -0
  403. package/build/dist/Models/DatabaseModels/CloudResourceFeed.js.map +1 -0
  404. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +11 -0
  405. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
  406. package/build/dist/Models/DatabaseModels/DetectionRule.js +9 -3
  407. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  408. package/build/dist/Models/DatabaseModels/DockerHostFeed.js +648 -0
  409. package/build/dist/Models/DatabaseModels/DockerHostFeed.js.map +1 -0
  410. package/build/dist/Models/DatabaseModels/DockerSwarmClusterFeed.js +648 -0
  411. package/build/dist/Models/DatabaseModels/DockerSwarmClusterFeed.js.map +1 -0
  412. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +9 -3
  413. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +1 -1
  414. package/build/dist/Models/DatabaseModels/HostFeed.js +648 -0
  415. package/build/dist/Models/DatabaseModels/HostFeed.js.map +1 -0
  416. package/build/dist/Models/DatabaseModels/IncidentSeverity.js +4 -1
  417. package/build/dist/Models/DatabaseModels/IncidentSeverity.js.map +1 -1
  418. package/build/dist/Models/DatabaseModels/Index.js +22 -0
  419. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  420. package/build/dist/Models/DatabaseModels/KubernetesClusterFeed.js +648 -0
  421. package/build/dist/Models/DatabaseModels/KubernetesClusterFeed.js.map +1 -0
  422. package/build/dist/Models/DatabaseModels/Monitor.js +81 -0
  423. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  424. package/build/dist/Models/DatabaseModels/NetworkDevice.js +103 -7
  425. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  426. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +91 -6
  427. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
  428. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +276 -31
  429. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  430. package/build/dist/Models/DatabaseModels/NetworkSite.js +124 -1
  431. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
  432. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +1 -0
  433. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
  434. package/build/dist/Models/DatabaseModels/PodmanHostFeed.js +648 -0
  435. package/build/dist/Models/DatabaseModels/PodmanHostFeed.js.map +1 -0
  436. package/build/dist/Models/DatabaseModels/ProxmoxClusterFeed.js +648 -0
  437. package/build/dist/Models/DatabaseModels/ProxmoxClusterFeed.js.map +1 -0
  438. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +66 -0
  439. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  440. package/build/dist/Models/DatabaseModels/ServiceFeed.js +648 -0
  441. package/build/dist/Models/DatabaseModels/ServiceFeed.js.map +1 -0
  442. package/build/dist/Models/DatabaseModels/TelemetrySourceMap.js +496 -0
  443. package/build/dist/Models/DatabaseModels/TelemetrySourceMap.js.map +1 -0
  444. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +800 -0
  445. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js.map +1 -0
  446. package/build/dist/Models/DatabaseModels/UserOnCallLog.js +1 -0
  447. package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
  448. package/build/dist/Models/DatabaseModels/UserTotpAuth.js +1 -0
  449. package/build/dist/Models/DatabaseModels/UserTotpAuth.js.map +1 -1
  450. package/build/dist/Models/DatabaseModels/UserWebAuthn.js +1 -0
  451. package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -1
  452. package/build/dist/Server/API/AlertAPI.js +18 -1
  453. package/build/dist/Server/API/AlertAPI.js.map +1 -1
  454. package/build/dist/Server/API/BaseAPI.js +8 -1
  455. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  456. package/build/dist/Server/API/IncidentAPI.js +35 -1
  457. package/build/dist/Server/API/IncidentAPI.js.map +1 -1
  458. package/build/dist/Server/API/IncidentEpisodeAPI.js +18 -1
  459. package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
  460. package/build/dist/Server/API/MicrosoftTeamsAPI.js +30 -2
  461. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  462. package/build/dist/Server/API/ScheduledMaintenanceAPI.js +18 -1
  463. package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
  464. package/build/dist/Server/API/SlackAPI.js +45 -0
  465. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  466. package/build/dist/Server/API/TelemetryAPI.js +100 -35
  467. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  468. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +64 -59
  469. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
  470. package/build/dist/Server/API/UserTotpAuthAPI.js +65 -1
  471. package/build/dist/Server/API/UserTotpAuthAPI.js.map +1 -1
  472. package/build/dist/Server/API/UserWebAuthnAPI.js +42 -1
  473. package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
  474. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787923136162-MigrationName.js +26 -0
  475. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787923136162-MigrationName.js.map +1 -0
  476. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789600000000-AddAutoProvisionedNetworkDeviceMonitors.js +22 -0
  477. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789600000000-AddAutoProvisionedNetworkDeviceMonitors.js.map +1 -0
  478. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789700000000-AddNetworkScaleIndexes.js +88 -0
  479. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789700000000-AddNetworkScaleIndexes.js.map +1 -0
  480. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789800000000-WidenSecurityEventLastErrorColumns.js +39 -0
  481. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789800000000-WidenSecurityEventLastErrorColumns.js.map +1 -0
  482. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789900000000-AddNetworkSiteRollupPolicyAndMaintenance.js +34 -0
  483. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789900000000-AddNetworkSiteRollupPolicyAndMaintenance.js.map +1 -0
  484. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000000-AddTelemetrySourceMap.js +32 -0
  485. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000000-AddTelemetrySourceMap.js.map +1 -0
  486. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000001-AddSnmpConfigsToNetworkDeviceDiscoveryScan.js +61 -0
  487. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790000000001-AddSnmpConfigsToNetworkDeviceDiscoveryScan.js.map +1 -0
  488. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790003445000-AddSnmpEnabledToNetworkDeviceDiscoveryScan.js +23 -0
  489. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790003445000-AddSnmpEnabledToNetworkDeviceDiscoveryScan.js.map +1 -0
  490. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790100000000-AddResourceActivityFeeds.js +179 -0
  491. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790100000000-AddResourceActivityFeeds.js.map +1 -0
  492. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +18 -0
  493. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  494. package/build/dist/Server/Middleware/IdentityRateLimit.js +40 -3
  495. package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
  496. package/build/dist/Server/Services/AIService.js +177 -30
  497. package/build/dist/Server/Services/AIService.js.map +1 -1
  498. package/build/dist/Server/Services/CephClusterFeedService.js +89 -0
  499. package/build/dist/Server/Services/CephClusterFeedService.js.map +1 -0
  500. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +27 -3
  501. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
  502. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +21 -0
  503. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
  504. package/build/dist/Server/Services/CephClusterOwnerTeamService.js +120 -0
  505. package/build/dist/Server/Services/CephClusterOwnerTeamService.js.map +1 -1
  506. package/build/dist/Server/Services/CephClusterOwnerUserService.js +113 -0
  507. package/build/dist/Server/Services/CephClusterOwnerUserService.js.map +1 -1
  508. package/build/dist/Server/Services/CephClusterService.js +175 -1
  509. package/build/dist/Server/Services/CephClusterService.js.map +1 -1
  510. package/build/dist/Server/Services/CloudResourceFeedService.js +89 -0
  511. package/build/dist/Server/Services/CloudResourceFeedService.js.map +1 -0
  512. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +27 -3
  513. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
  514. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +28 -3
  515. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
  516. package/build/dist/Server/Services/CloudResourceOwnerTeamService.js +120 -0
  517. package/build/dist/Server/Services/CloudResourceOwnerTeamService.js.map +1 -1
  518. package/build/dist/Server/Services/CloudResourceOwnerUserService.js +113 -0
  519. package/build/dist/Server/Services/CloudResourceOwnerUserService.js.map +1 -1
  520. package/build/dist/Server/Services/CloudResourceService.js +177 -1
  521. package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
  522. package/build/dist/Server/Services/DatabaseService.js +201 -0
  523. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  524. package/build/dist/Server/Services/DockerHostFeedService.js +89 -0
  525. package/build/dist/Server/Services/DockerHostFeedService.js.map +1 -0
  526. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +27 -3
  527. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
  528. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +21 -0
  529. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
  530. package/build/dist/Server/Services/DockerHostOwnerTeamService.js +120 -0
  531. package/build/dist/Server/Services/DockerHostOwnerTeamService.js.map +1 -1
  532. package/build/dist/Server/Services/DockerHostOwnerUserService.js +113 -0
  533. package/build/dist/Server/Services/DockerHostOwnerUserService.js.map +1 -1
  534. package/build/dist/Server/Services/DockerHostService.js +177 -1
  535. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  536. package/build/dist/Server/Services/DockerSwarmClusterFeedService.js +90 -0
  537. package/build/dist/Server/Services/DockerSwarmClusterFeedService.js.map +1 -0
  538. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +27 -3
  539. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
  540. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +21 -0
  541. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
  542. package/build/dist/Server/Services/DockerSwarmClusterOwnerTeamService.js +120 -0
  543. package/build/dist/Server/Services/DockerSwarmClusterOwnerTeamService.js.map +1 -1
  544. package/build/dist/Server/Services/DockerSwarmClusterOwnerUserService.js +113 -0
  545. package/build/dist/Server/Services/DockerSwarmClusterOwnerUserService.js.map +1 -1
  546. package/build/dist/Server/Services/DockerSwarmClusterService.js +175 -1
  547. package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
  548. package/build/dist/Server/Services/EnterpriseLicenseService.js +40 -30
  549. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  550. package/build/dist/Server/Services/ExceptionAggregationService.js +8 -2
  551. package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
  552. package/build/dist/Server/Services/HostFeedService.js +89 -0
  553. package/build/dist/Server/Services/HostFeedService.js.map +1 -0
  554. package/build/dist/Server/Services/HostLabelRuleEngineService.js +27 -3
  555. package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
  556. package/build/dist/Server/Services/HostOwnerRuleEngineService.js +21 -0
  557. package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
  558. package/build/dist/Server/Services/HostOwnerTeamService.js +120 -0
  559. package/build/dist/Server/Services/HostOwnerTeamService.js.map +1 -1
  560. package/build/dist/Server/Services/HostOwnerUserService.js +113 -0
  561. package/build/dist/Server/Services/HostOwnerUserService.js.map +1 -1
  562. package/build/dist/Server/Services/HostService.js +175 -1
  563. package/build/dist/Server/Services/HostService.js.map +1 -1
  564. package/build/dist/Server/Services/IncidentService.js +10 -0
  565. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  566. package/build/dist/Server/Services/Index.js +24 -0
  567. package/build/dist/Server/Services/Index.js.map +1 -1
  568. package/build/dist/Server/Services/KubernetesClusterFeedService.js +89 -0
  569. package/build/dist/Server/Services/KubernetesClusterFeedService.js.map +1 -0
  570. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +27 -3
  571. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
  572. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +21 -0
  573. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
  574. package/build/dist/Server/Services/KubernetesClusterOwnerTeamService.js +120 -0
  575. package/build/dist/Server/Services/KubernetesClusterOwnerTeamService.js.map +1 -1
  576. package/build/dist/Server/Services/KubernetesClusterOwnerUserService.js +113 -0
  577. package/build/dist/Server/Services/KubernetesClusterOwnerUserService.js.map +1 -1
  578. package/build/dist/Server/Services/KubernetesClusterService.js +177 -1
  579. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  580. package/build/dist/Server/Services/LogAggregationService.js +19 -196
  581. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  582. package/build/dist/Server/Services/MetricAggregationService.js +59 -0
  583. package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
  584. package/build/dist/Server/Services/MonitorService.js +115 -13
  585. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  586. package/build/dist/Server/Services/MonitorTemplateService.js +86 -0
  587. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  588. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +561 -67
  589. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  590. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +130 -16
  591. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
  592. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +850 -8
  593. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  594. package/build/dist/Server/Services/NetworkDeviceService.js +594 -5
  595. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  596. package/build/dist/Server/Services/NetworkInterfaceService.js +306 -0
  597. package/build/dist/Server/Services/NetworkInterfaceService.js.map +1 -1
  598. package/build/dist/Server/Services/NetworkSiteService.js +408 -47
  599. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  600. package/build/dist/Server/Services/PodmanHostFeedService.js +89 -0
  601. package/build/dist/Server/Services/PodmanHostFeedService.js.map +1 -0
  602. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +27 -3
  603. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
  604. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +21 -0
  605. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
  606. package/build/dist/Server/Services/PodmanHostOwnerTeamService.js +120 -0
  607. package/build/dist/Server/Services/PodmanHostOwnerTeamService.js.map +1 -1
  608. package/build/dist/Server/Services/PodmanHostOwnerUserService.js +113 -0
  609. package/build/dist/Server/Services/PodmanHostOwnerUserService.js.map +1 -1
  610. package/build/dist/Server/Services/PodmanHostService.js +177 -1
  611. package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
  612. package/build/dist/Server/Services/ProjectService.js +40 -30
  613. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  614. package/build/dist/Server/Services/ProxmoxClusterFeedService.js +89 -0
  615. package/build/dist/Server/Services/ProxmoxClusterFeedService.js.map +1 -0
  616. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +27 -3
  617. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
  618. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +21 -0
  619. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
  620. package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js +120 -0
  621. package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js.map +1 -1
  622. package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js +113 -0
  623. package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js.map +1 -1
  624. package/build/dist/Server/Services/ProxmoxClusterService.js +175 -1
  625. package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
  626. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +56 -0
  627. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  628. package/build/dist/Server/Services/ServiceFeedService.js +89 -0
  629. package/build/dist/Server/Services/ServiceFeedService.js.map +1 -0
  630. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +27 -3
  631. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
  632. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +24 -0
  633. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
  634. package/build/dist/Server/Services/ServiceOwnerTeamService.js +120 -0
  635. package/build/dist/Server/Services/ServiceOwnerTeamService.js.map +1 -1
  636. package/build/dist/Server/Services/ServiceOwnerUserService.js +113 -0
  637. package/build/dist/Server/Services/ServiceOwnerUserService.js.map +1 -1
  638. package/build/dist/Server/Services/ServiceService.js +173 -2
  639. package/build/dist/Server/Services/ServiceService.js.map +1 -1
  640. package/build/dist/Server/Services/StatusPageSubscriberService.js +7 -0
  641. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  642. package/build/dist/Server/Services/TelemetryAttributeService.js +9 -3
  643. package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
  644. package/build/dist/Server/Services/TelemetrySourceMapService.js +265 -0
  645. package/build/dist/Server/Services/TelemetrySourceMapService.js.map +1 -0
  646. package/build/dist/Server/Services/ThreatIntelFeedService.js +157 -0
  647. package/build/dist/Server/Services/ThreatIntelFeedService.js.map +1 -0
  648. package/build/dist/Server/Services/ThreatIntelIndicatorService.js +276 -0
  649. package/build/dist/Server/Services/ThreatIntelIndicatorService.js.map +1 -0
  650. package/build/dist/Server/Services/TraceAggregationService.js +62 -6
  651. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  652. package/build/dist/Server/Services/UserService.js +22 -13
  653. package/build/dist/Server/Services/UserService.js.map +1 -1
  654. package/build/dist/Server/Services/UserTwoFactorBackupCodeService.js +120 -0
  655. package/build/dist/Server/Services/UserTwoFactorBackupCodeService.js.map +1 -1
  656. package/build/dist/Server/Services/UserWebhookService.js +11 -2
  657. package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
  658. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +12 -1
  659. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
  660. package/build/dist/Server/Types/Database/AggregateBy.js +2 -0
  661. package/build/dist/Server/Types/Database/AggregateBy.js.map +1 -0
  662. package/build/dist/Server/Types/Database/AggregateResultUtil.js +90 -0
  663. package/build/dist/Server/Types/Database/AggregateResultUtil.js.map +1 -0
  664. package/build/dist/Server/Types/Database/JSONColumnQuery.js +14 -0
  665. package/build/dist/Server/Types/Database/JSONColumnQuery.js.map +1 -1
  666. package/build/dist/Server/Types/Database/QueryHelper.js +42 -0
  667. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  668. package/build/dist/Server/Types/Database/QueryUtil.js +18 -0
  669. package/build/dist/Server/Types/Database/QueryUtil.js.map +1 -1
  670. package/build/dist/Server/Types/Workflow/Components/API/Utils.js +10 -1
  671. package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
  672. package/build/dist/Server/Types/Workflow/Components/JavaScript.js +8 -0
  673. package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
  674. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +8 -0
  675. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -1
  676. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +15 -0
  677. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -1
  678. package/build/dist/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.js +266 -0
  679. package/build/dist/Server/Utils/AnalyticsDatabase/AttributeFilterStatement.js.map +1 -0
  680. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +134 -0
  681. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  682. package/build/dist/Server/Utils/DataSource/HttpFetch.js +8 -0
  683. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
  684. package/build/dist/Server/Utils/Database/RelationIdUtil.js +31 -0
  685. package/build/dist/Server/Utils/Database/RelationIdUtil.js.map +1 -1
  686. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +26 -8
  687. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
  688. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +42 -17
  689. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
  690. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +9 -1
  691. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  692. package/build/dist/Server/Utils/Monitor/Criteria/SyntheticMonitor.js +15 -2
  693. package/build/dist/Server/Utils/Monitor/Criteria/SyntheticMonitor.js.map +1 -1
  694. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +386 -271
  695. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  696. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +278 -64
  697. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  698. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +469 -350
  699. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  700. package/build/dist/Server/Utils/Monitor/MonitorResource.js +183 -44
  701. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  702. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +46 -3
  703. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
  704. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +18 -91
  705. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  706. package/build/dist/Server/Utils/Monitor/PerEntityCriteriaFanOut.js +194 -0
  707. package/build/dist/Server/Utils/Monitor/PerEntityCriteriaFanOut.js.map +1 -0
  708. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +332 -0
  709. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -0
  710. package/build/dist/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.js +279 -0
  711. package/build/dist/Server/Utils/NetworkSite/NetworkSiteMaintenanceSuppression.js.map +1 -0
  712. package/build/dist/Server/Utils/OnCallNotificationContext.js +415 -0
  713. package/build/dist/Server/Utils/OnCallNotificationContext.js.map +1 -0
  714. package/build/dist/Server/Utils/PrivateNetworkWebhookConfig.js +424 -0
  715. package/build/dist/Server/Utils/PrivateNetworkWebhookConfig.js.map +1 -0
  716. package/build/dist/Server/Utils/ResourceFeed/ResourceFeedUtil.js +108 -0
  717. package/build/dist/Server/Utils/ResourceFeed/ResourceFeedUtil.js.map +1 -0
  718. package/build/dist/Server/Utils/Response.js +12 -1
  719. package/build/dist/Server/Utils/Response.js.map +1 -1
  720. package/build/dist/Server/Utils/SSRFProtection.js +160 -58
  721. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  722. package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js +89 -0
  723. package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js.map +1 -0
  724. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +75 -234
  725. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  726. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +41 -16
  727. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
  728. package/build/dist/Server/Utils/SecurityEvent/SecurityEventAlerting.js +217 -0
  729. package/build/dist/Server/Utils/SecurityEvent/SecurityEventAlerting.js.map +1 -0
  730. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.js +103 -0
  731. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClient.js.map +1 -0
  732. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.js +168 -0
  733. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelEnricher.js.map +1 -0
  734. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +527 -0
  735. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js.map +1 -0
  736. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js +376 -0
  737. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js.map +1 -0
  738. package/build/dist/Server/Utils/StartServer.js +70 -44
  739. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  740. package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js +3 -0
  741. package/build/dist/Server/Utils/StatusPageSubscriberWebhook.js.map +1 -1
  742. package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js +327 -0
  743. package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js.map +1 -0
  744. package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js +84 -0
  745. package/build/dist/Server/Utils/TwoFactorBackupCodeNotification.js.map +1 -0
  746. package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
  747. package/build/dist/Server/Utils/VM/VMRunner.js +10 -1
  748. package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
  749. package/build/dist/Server/Utils/VendorAssets.js +29 -0
  750. package/build/dist/Server/Utils/VendorAssets.js.map +1 -1
  751. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +121 -6
  752. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  753. package/build/dist/Types/API/URL.js +88 -27
  754. package/build/dist/Types/API/URL.js.map +1 -1
  755. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +8 -0
  756. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
  757. package/build/dist/Types/BaseDatabase/NotWildcard.js +72 -0
  758. package/build/dist/Types/BaseDatabase/NotWildcard.js.map +1 -0
  759. package/build/dist/Types/BaseDatabase/Wildcard.js +75 -0
  760. package/build/dist/Types/BaseDatabase/Wildcard.js.map +1 -0
  761. package/build/dist/Types/BaseDatabase/WildcardPattern.js +137 -0
  762. package/build/dist/Types/BaseDatabase/WildcardPattern.js.map +1 -0
  763. package/build/dist/Types/Database/DateColumnValue.js +125 -0
  764. package/build/dist/Types/Database/DateColumnValue.js.map +1 -0
  765. package/build/dist/Types/Database/TableColumn.js +18 -2
  766. package/build/dist/Types/Database/TableColumn.js.map +1 -1
  767. package/build/dist/Types/Date.js +31 -0
  768. package/build/dist/Types/Date.js.map +1 -1
  769. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  770. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  771. package/build/dist/Types/JSON.js +2 -0
  772. package/build/dist/Types/JSON.js.map +1 -1
  773. package/build/dist/Types/Log/LogQueryToFilter.js +111 -108
  774. package/build/dist/Types/Log/LogQueryToFilter.js.map +1 -1
  775. package/build/dist/Types/Monitor/DockerAlertTemplates.js +40 -16
  776. package/build/dist/Types/Monitor/DockerAlertTemplates.js.map +1 -1
  777. package/build/dist/Types/Monitor/HostAlertTemplates.js +29 -7
  778. package/build/dist/Types/Monitor/HostAlertTemplates.js.map +1 -1
  779. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +98 -4
  780. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
  781. package/build/dist/Types/Monitor/MonitorStep.js +40 -0
  782. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  783. package/build/dist/Types/Monitor/PodmanAlertTemplates.js +36 -16
  784. package/build/dist/Types/Monitor/PodmanAlertTemplates.js.map +1 -1
  785. package/build/dist/Types/NetworkAutomation/RuleRunResult.js +90 -0
  786. package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -1
  787. package/build/dist/Types/NetworkSite/SiteHealthRollupPolicy.js +84 -0
  788. package/build/dist/Types/NetworkSite/SiteHealthRollupPolicy.js.map +1 -0
  789. package/build/dist/Types/Permission.js +354 -0
  790. package/build/dist/Types/Permission.js.map +1 -1
  791. package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js +100 -0
  792. package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js.map +1 -0
  793. package/build/dist/Types/SerializableObjectDictionary.js +8 -0
  794. package/build/dist/Types/SerializableObjectDictionary.js.map +1 -1
  795. package/build/dist/Types/Telemetry/SourceMap.js +9 -0
  796. package/build/dist/Types/Telemetry/SourceMap.js.map +1 -0
  797. package/build/dist/Types/Telemetry/TelemetrySearchQuery.js +661 -0
  798. package/build/dist/Types/Telemetry/TelemetrySearchQuery.js.map +1 -0
  799. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +12 -1
  800. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -1
  801. package/build/dist/UI/Components/Charts/Utils/useHistogramZoom.js +47 -0
  802. package/build/dist/UI/Components/Charts/Utils/useHistogramZoom.js.map +1 -0
  803. package/build/dist/UI/Components/Dictionary/DictionaryFilterOperator.js +67 -0
  804. package/build/dist/UI/Components/Dictionary/DictionaryFilterOperator.js.map +1 -1
  805. package/build/dist/UI/Components/Icon/Icon.js +28 -1
  806. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  807. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +15 -3
  808. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  809. package/build/dist/UI/Components/LogsViewer/components/LogSearchBar.js +25 -4
  810. package/build/dist/UI/Components/LogsViewer/components/LogSearchBar.js.map +1 -1
  811. package/build/dist/UI/Components/LogsViewer/components/LogSearchHelp.js +36 -16
  812. package/build/dist/UI/Components/LogsViewer/components/LogSearchHelp.js.map +1 -1
  813. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +33 -5
  814. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
  815. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +14 -2
  816. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  817. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +33 -5
  818. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  819. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js +14 -2
  820. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js.map +1 -1
  821. package/build/dist/Utils/Metrics/MetricExplorerUrl.js +54 -9
  822. package/build/dist/Utils/Metrics/MetricExplorerUrl.js.map +1 -1
  823. package/build/dist/Utils/Monitor/InterfaceInventoryUtil.js +128 -0
  824. package/build/dist/Utils/Monitor/InterfaceInventoryUtil.js.map +1 -0
  825. package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js +190 -0
  826. package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js.map +1 -0
  827. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +206 -28
  828. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  829. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +14 -7
  830. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
  831. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
  832. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +34 -18
  833. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
  834. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +163 -0
  835. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -0
  836. package/build/dist/Utils/NetworkDiscovery/RescanIntervalUtil.js +99 -0
  837. package/build/dist/Utils/NetworkDiscovery/RescanIntervalUtil.js.map +1 -0
  838. package/build/dist/Utils/NetworkDiscovery/ScanModeUtil.js +85 -0
  839. package/build/dist/Utils/NetworkDiscovery/ScanModeUtil.js.map +1 -0
  840. package/build/dist/Utils/NetworkDiscovery/SnmpScanConfigUtil.js +560 -0
  841. package/build/dist/Utils/NetworkDiscovery/SnmpScanConfigUtil.js.map +1 -0
  842. package/build/dist/Utils/NetworkSite/SiteMaintenanceUtil.js +56 -0
  843. package/build/dist/Utils/NetworkSite/SiteMaintenanceUtil.js.map +1 -0
  844. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +185 -10
  845. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
  846. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +248 -21
  847. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -1
  848. package/build/dist/Utils/SecurityEvent/ThreatIntel/StixPatternParser.js +255 -0
  849. package/build/dist/Utils/SecurityEvent/ThreatIntel/StixPatternParser.js.map +1 -0
  850. package/build/dist/Utils/Telemetry/CrossSignalScope.js +27 -30
  851. package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
  852. package/package.json +2 -1
  853. package/Tests/Types/Log/LogQueryParser.test.ts +0 -186
  854. package/Types/Log/LogQueryParser.ts +0 -252
  855. package/build/dist/Types/Log/LogQueryParser.js +0 -200
  856. package/build/dist/Types/Log/LogQueryParser.js.map +0 -1
@@ -5,8 +5,170 @@ import CreateBy from "../Types/Database/CreateBy";
5
5
  import UpdateBy from "../Types/Database/UpdateBy";
6
6
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
7
7
  import BadDataException from "../../Types/Exception/BadDataException";
8
+ import ObjectID from "../../Types/ObjectID";
9
+ import OneUptimeDate from "../../Types/Date";
10
+ import LIMIT_MAX from "../../Types/Database/LimitMax";
11
+ import QueryDeepPartialEntity from "../../Types/Database/PartialEntity";
12
+ import ProbeService from "./ProbeService";
13
+ import Probe from "../../Models/DatabaseModels/Probe";
14
+ import RelationIdUtil from "../Utils/Database/RelationIdUtil";
8
15
  import ScanTargetUtil from "../../Utils/NetworkDiscovery/ScanTargetUtil";
9
16
  import ScanNameUtil from "../../Utils/NetworkDiscovery/ScanNameUtil";
17
+ import SnmpScanConfigUtil, {
18
+ DiscoveryScanSnmpConfig,
19
+ SnmpScanConfigSource,
20
+ } from "../../Utils/NetworkDiscovery/SnmpScanConfigUtil";
21
+ import { getNextScanAt } from "../../Utils/NetworkDiscovery/RescanIntervalUtil";
22
+ import ScanModeUtil from "../../Utils/NetworkDiscovery/ScanModeUtil";
23
+
24
+ /*
25
+ * The two spellings a many-to-one reference reaches a hook under: the
26
+ * dashboard posts the relation object, server callers write the FK column.
27
+ * See RelationIdUtil.
28
+ */
29
+ const PROBE_RELATION_KEYS: Array<string> = ["probeId", "probe"];
30
+
31
+ /*
32
+ * The columns that decide what the probe sweeps, and what it sweeps with.
33
+ * Changing any of them means the results already on the row describe a sweep
34
+ * that no longer exists — which is what onUpdateSuccess below acts on.
35
+ *
36
+ * `probe` is folded into `probeId` by RelationIdUtil rather than listed here,
37
+ * because the same reference arrives under either name.
38
+ */
39
+ const SWEEP_COLUMNS: Array<string> = [
40
+ "cidr",
41
+ "probeId",
42
+ /*
43
+ * The method as well as the credentials: turning SNMP off (or back on)
44
+ * changes what the sweep asks of every address, so the hosts already on the
45
+ * row answered a different question (issue #3445).
46
+ */
47
+ "isSnmpEnabled",
48
+ /*
49
+ * The ordered credential list. Listed FIRST among the credential columns
50
+ * because it is the one the form actually posts now; the flattened columns
51
+ * below it are mirrored from its first entry (see applySnmpConfigs) and
52
+ * remain here so a scan edited through the API with only those fields still
53
+ * retires its run (issue #3458).
54
+ */
55
+ "snmpConfigs",
56
+ "snmpVersion",
57
+ "snmpCommunityString",
58
+ "snmpPort",
59
+ "snmpV3SecurityLevel",
60
+ "snmpV3Username",
61
+ "snmpV3AuthProtocol",
62
+ "snmpV3AuthKey",
63
+ "snmpV3PrivProtocol",
64
+ "snmpV3PrivKey",
65
+ ];
66
+
67
+ /*
68
+ * The numeric columns a form can hand back as an empty string.
69
+ *
70
+ * A Number field posts its value as text (Common/UI/Components/Forms/Fields/
71
+ * FormField.tsx sets it straight from the input), so an operator who clears
72
+ * the box sends "" — and "" into an integer column is a Postgres error, i.e. a
73
+ * 500 where the operator simply meant "leave this unset". Clearing a box was
74
+ * hard to do before these fields were editable, because a create form starts
75
+ * them empty; an edit form starts them filled.
76
+ */
77
+ const NULLABLE_NUMBER_COLUMNS: Array<string> = [
78
+ "snmpPort",
79
+ "rescanIntervalInMinutes",
80
+ ];
81
+
82
+ /*
83
+ * The columns that decide WHEN the scan runs again, and nothing else. They
84
+ * never retire a result — they only re-derive nextScanAt.
85
+ */
86
+ /*
87
+ * The single credential set a scan carried before `snmpConfigs` existed. Still
88
+ * written — mirrored from the list's first entry — so a probe that predates
89
+ * the list keeps sweeping with real credentials; see applySnmpConfigs.
90
+ */
91
+ const LEGACY_SNMP_COLUMNS: Array<string> = [
92
+ "snmpVersion",
93
+ "snmpCommunityString",
94
+ "snmpPort",
95
+ "snmpV3SecurityLevel",
96
+ "snmpV3Username",
97
+ "snmpV3AuthProtocol",
98
+ "snmpV3AuthKey",
99
+ "snmpV3PrivProtocol",
100
+ "snmpV3PrivKey",
101
+ ];
102
+
103
+ const SCHEDULE_COLUMNS: Array<string> = [
104
+ "isRecurring",
105
+ "rescanIntervalInMinutes",
106
+ ];
107
+
108
+ /*
109
+ * Everything a finished run left on the row. Written together, as one
110
+ * statement, to put the scan back in the state a brand-new one is created in:
111
+ * queued, with nothing to show yet.
112
+ *
113
+ * This is the same reset the requeue worker performs on a recurring scan that
114
+ * is due (Workers/Jobs/NetworkDeviceDiscovery/RequeueRecurringScans.ts) with
115
+ * one deliberate difference: the results ARE cleared here. The worker keeps
116
+ * them because a recurring scan re-runs the SAME sweep, so last run's
117
+ * inventory is still the best answer available until the next one lands. A
118
+ * scan whose target or credentials just changed has no such excuse — its
119
+ * hosts came from somewhere the scan no longer points at.
120
+ */
121
+ const RETIRE_RUN_PAYLOAD: Record<string, unknown> = {
122
+ status: "Pending",
123
+ /*
124
+ * Not cleared but replaced, because the row has some explaining to do: the
125
+ * operator saved a settings change and the scan's results vanished. The
126
+ * scans list renders this sentence in the results cell of a scan that has
127
+ * not reported (Dashboard Components/NetworkDevice/DiscoveryScanOutcome),
128
+ * which is exactly where the missing results used to be. The claim endpoint
129
+ * clears it the moment a probe picks the scan up.
130
+ */
131
+ statusMessage:
132
+ "Settings changed, so this scan is queued to run again. The hosts the previous run found have been cleared - they described settings this scan no longer has.",
133
+ startedAt: null,
134
+ completedAt: null,
135
+ nextScanAt: null,
136
+ discoveredDevices: null,
137
+ scannedHostCount: null,
138
+ respondedHostCount: null,
139
+ autoImportProcessedAt: null,
140
+ };
141
+
142
+ /*
143
+ * The one thing onUpdateSuccess cannot work out for itself, because answering
144
+ * it needs the values the update has already overwritten: did this save
145
+ * actually change what the probe sweeps?
146
+ *
147
+ * Everything else it needs — the schedule, the run state — it re-reads from
148
+ * the row afterwards rather than predicting from the payload. Predicting would
149
+ * mean trusting the request's types (a number field posted as "60", a toggle
150
+ * posted as "false"), and a schedule mis-read as "no cadence" silently
151
+ * unschedules a recurring scan.
152
+ */
153
+ interface ScanUpdatePlan {
154
+ isSweepChanged: boolean;
155
+ /*
156
+ * Whether this row's credential LIST has to be rebuilt from its flattened
157
+ * columns once the update has landed — the answer to a save written through
158
+ * the old single-credential API (see reconcileLegacySnmpUpdate).
159
+ *
160
+ * Deferred to onUpdateSuccess rather than done in the payload because the
161
+ * rebuilt list is a function of the ROW, and one update payload is shared by
162
+ * every row the query matches. onUpdateSuccess already writes per row, by id.
163
+ */
164
+ isLegacySnmpWritten: boolean;
165
+ /*
166
+ * Whether the save asked about the schedule at all. Only a save that did
167
+ * gets its next run re-derived — so an edit that leaves the recurrence boxes
168
+ * alone cannot move a scan the stale-scan reaper had made due immediately.
169
+ */
170
+ isScheduleWritten: boolean;
171
+ }
10
172
 
11
173
  export class Service extends DatabaseService<Model> {
12
174
  public constructor() {
@@ -53,25 +215,128 @@ export class Service extends DatabaseService<Model> {
53
215
  (createBy.data as unknown as Record<string, unknown>)["name"] =
54
216
  ScanNameUtil.normalize(createBy.data.name) ?? undefined;
55
217
 
218
+ this.nullEmptyNumbers(
219
+ createBy.data as unknown as Record<string, unknown>,
220
+ Object.keys(createBy.data || {}),
221
+ );
222
+
223
+ const createData: Record<string, unknown> =
224
+ createBy.data as unknown as Record<string, unknown>;
225
+
226
+ /*
227
+ * The keys the CLIENT actually supplied, not the keys the object has.
228
+ *
229
+ * `createBy.data` is a model INSTANCE, and every column on it is declared
230
+ * as a class field with `= undefined` — so `Object.keys()` returns all 37
231
+ * column names on a brand-new scan no matter what was posted. Handing that
232
+ * to applySnmpConfigs made its "the payload wins where it speaks for
233
+ * itself" guard fire for all nine flattened columns, every time, and the
234
+ * mirror it protects became a permanent no-op on this path: a scan created
235
+ * through the wizard (which posts `snmpConfigs` and nothing else) stored
236
+ * its credentials in the list while its flattened columns kept the bare
237
+ * Postgres defaults, and every probe a version behind swept it with
238
+ * v2c/"public"/161 and reported the confident zero the mirror exists to
239
+ * prevent.
240
+ *
241
+ * A column the client really did send carries a DEFINED value — including
242
+ * an explicit null, which is a caller clearing it — so testing for
243
+ * definedness is exactly the distinction the guard wanted in the first
244
+ * place. The update path never had this problem: BaseAPI builds a plain
245
+ * partial there, holding only the posted keys.
246
+ */
247
+ const suppliedCreateKeys: Array<string> = Object.keys(
248
+ createData || {},
249
+ ).filter((key: string): boolean => {
250
+ return createData[key] !== undefined;
251
+ });
252
+
253
+ /*
254
+ * Only for a scan that will actually send SNMP. An ICMP-only scan has its
255
+ * whole SNMP set nulled at the end of this hook, so validating a credential
256
+ * list it is about to discard would refuse the create over a value nothing
257
+ * will ever read — and the wizard posts the field whether or not the step
258
+ * was visible.
259
+ */
260
+ const isSnmpEnabledOnCreate: boolean = ScanModeUtil.isSnmpEnabled(
261
+ createBy.data,
262
+ );
263
+
264
+ if (isSnmpEnabledOnCreate) {
265
+ this.applySnmpConfigs(createData, suppliedCreateKeys);
266
+ }
267
+
268
+ /*
269
+ * Every scan leaves this hook WITH a credential list, even one created
270
+ * through the flattened columns alone (an API caller, an integration
271
+ * written before this column existed).
272
+ *
273
+ * The invariant is what the Edit dialog depends on. That form's only SNMP
274
+ * control is the list editor, so it selects `snmpConfigs` and nothing else
275
+ * — a scan whose list were NULL would open with an empty card, and saving
276
+ * it would replace the credentials the operator could not see. The reader
277
+ * (SnmpScanConfigUtil.resolve) still falls back to the flattened columns,
278
+ * because rows written out of band exist; this just means the product
279
+ * never creates one.
280
+ */
281
+ if (
282
+ isSnmpEnabledOnCreate &&
283
+ !SnmpScanConfigUtil.readStoredList(createData["snmpConfigs"])
284
+ ) {
285
+ createData["snmpConfigs"] = SnmpScanConfigUtil.normalizeForStorage(
286
+ SnmpScanConfigUtil.resolve(
287
+ createData as unknown as SnmpScanConfigSource,
288
+ ),
289
+ );
290
+ }
291
+
292
+ await this.validateProbeIsUsable({
293
+ data: createBy.data as unknown as Record<string, unknown>,
294
+ dataKeys: Object.keys(createBy.data || {}),
295
+ projectId: createBy.data.projectId || createBy.props.tenantId,
296
+ });
297
+
298
+ /*
299
+ * A scan that will not send SNMP stores no SNMP settings. Enforced here
300
+ * rather than in the form alone, so it holds for a direct API call too —
301
+ * the same reason the scan target is validated on this hook rather than
302
+ * only in the wizard.
303
+ *
304
+ * Read through ScanModeUtil so an ABSENT flag reads as an SNMP scan, which
305
+ * is what every scan created before this column existed was, and what
306
+ * every API client that has never heard of the column means.
307
+ *
308
+ * LAST, after nullEmptyNumbers: that pass turns an empty snmpPort box into
309
+ * null, and this one nulls the whole SNMP set anyway, so running it after
310
+ * means there is exactly one answer for what an ICMP-only row holds.
311
+ */
312
+ if (ScanModeUtil.isIcmpOnly(createBy.data)) {
313
+ this.clearSnmpConfig(createBy.data);
314
+ }
315
+
56
316
  return { createBy, carryForward: null };
57
317
  }
58
318
 
59
319
  /*
60
- * The target column is not user-updatable (its ColumnAccessControl grants no
61
- * update permission), but root writers the probe-ingest endpoints, workers,
62
- * migrations bypass that. Validating any update that carries the column
63
- * keeps the invariant true for every writer instead of just the form.
320
+ * Everything that has to be true of an update before it is allowed to land,
321
+ * plus the reading of the row that onUpdateSuccess needs and can no longer
322
+ * take once the write has happened.
323
+ *
324
+ * Two classes of writer arrive here. The form, editing a scan's settings —
325
+ * which is what this hook mostly exists for now (OneUptime issue #3444) —
326
+ * and the server's own root writers: the probe-ingest endpoints, the
327
+ * recurring-scan worker, migrations. The root writers carry only run-state
328
+ * columns and take the cheap exit below without paying for a read.
64
329
  */
65
330
  @CaptureSpan()
66
331
  protected override async onBeforeUpdate(
67
332
  updateBy: UpdateBy<Model>,
68
333
  ): Promise<OnUpdate<Model>> {
69
- const dataKeys: Array<string> = Object.keys(updateBy.data || {});
334
+ const data: Record<string, unknown> = (updateBy.data ||
335
+ {}) as unknown as Record<string, unknown>;
336
+ const dataKeys: Array<string> = Object.keys(data);
70
337
 
71
338
  if (dataKeys.includes("cidr")) {
72
- this.validateScanTarget(
73
- (updateBy.data as Record<string, unknown>)["cidr"],
74
- );
339
+ this.validateScanTarget(data["cidr"]);
75
340
  }
76
341
 
77
342
  /*
@@ -86,16 +351,792 @@ export class Service extends DatabaseService<Model> {
86
351
  * would try to write.
87
352
  */
88
353
  if (dataKeys.includes("name")) {
89
- const data: Record<string, unknown> = updateBy.data as Record<
90
- string,
91
- unknown
92
- >;
93
-
94
354
  this.validateScanName(data["name"]);
95
355
  data["name"] = ScanNameUtil.normalize(data["name"]);
96
356
  }
97
357
 
98
- return { updateBy, carryForward: null };
358
+ this.nullEmptyNumbers(data, dataKeys);
359
+
360
+ /*
361
+ * Turning the method off clears the credentials in the same statement, so
362
+ * the row can never say "sends no SNMP" while carrying a community string
363
+ * or a v3 passphrase (issue #3445). The edit form posts every declared
364
+ * field regardless of visibility, so the SNMP boxes the operator just hid
365
+ * are still in this payload.
366
+ *
367
+ * Gated on the key being WRITTEN, not merely on the stored value being
368
+ * false: a rename, or the probe-ingest endpoints writing run state, must
369
+ * not reach in and null a column they never mentioned. `data` is mutated
370
+ * in place because onUpdateSuccess is handed back the same updateBy object.
371
+ */
372
+ const isTurningSnmpOff: boolean =
373
+ dataKeys.includes("isSnmpEnabled") && ScanModeUtil.isIcmpOnly(data);
374
+
375
+ if (isTurningSnmpOff) {
376
+ this.clearSnmpConfig(data);
377
+ } else {
378
+ /*
379
+ * Runs BEFORE isSweepWritten is computed, because it can ADD the
380
+ * flattened SNMP columns to the payload — and those are sweep columns. A
381
+ * mirror written after that flag was read would be invisible to the
382
+ * reconciliation and could hand the probe one credential while the row
383
+ * advertised another.
384
+ *
385
+ * Skipped entirely when the save is turning SNMP OFF, and that is not
386
+ * merely an optimisation: this pass VALIDATES the credential list, and
387
+ * the form posts every declared field whether or not it was visible. An
388
+ * operator who unticked Check SNMP would otherwise be refused their save
389
+ * over a half-finished credential set they had just told the product to
390
+ * stop using. clearSnmpConfig nulls the list along with the flattened
391
+ * columns, so there is nothing left to validate.
392
+ */
393
+ this.applySnmpConfigs(data, dataKeys);
394
+ }
395
+
396
+ const dataKeysAfterMirror: Array<string> = Object.keys(data);
397
+
398
+ const isSweepWritten: boolean =
399
+ RelationIdUtil.isWritten(dataKeysAfterMirror, PROBE_RELATION_KEYS) ||
400
+ SWEEP_COLUMNS.some((column: string) => {
401
+ return dataKeysAfterMirror.includes(column);
402
+ });
403
+
404
+ const isScheduleWritten: boolean = SCHEDULE_COLUMNS.some(
405
+ (column: string) => {
406
+ return dataKeysAfterMirror.includes(column);
407
+ },
408
+ );
409
+
410
+ /*
411
+ * THE CHEAP EXIT, and it is load-bearing rather than an optimisation.
412
+ *
413
+ * Every server-side writer of this model touches run state only — the
414
+ * claim writes status/startedAt/statusMessage, the result ingest writes
415
+ * the results, the requeue worker and the stale-scan reaper write status
416
+ * and timestamps, the unclaimed-diagnosis pass writes statusMessage. None
417
+ * of them carries a sweep or schedule column, so none of them reads a row
418
+ * here, and none can trip the reconciliation below into retiring the very
419
+ * result it is in the middle of storing.
420
+ *
421
+ * `updateBy` is also handed back as the SAME object, which is what
422
+ * Common/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts
423
+ * pins: the claim's hook-free write is only safe while this hook is a
424
+ * pass-through for the claim's payload.
425
+ */
426
+ if (!isSweepWritten && !isScheduleWritten) {
427
+ return { updateBy, carryForward: null };
428
+ }
429
+
430
+ /*
431
+ * Scoped by hand, because this hook runs BEFORE
432
+ * ModelPermission.checkUpdateQueryPermissions and BaseAPI hands the
433
+ * service a bare `{_id}` query — so reading with the caller's own query as
434
+ * root, unscoped, would answer "does this id exist, and what are its
435
+ * credentials" for every project on the instance. Same shape as
436
+ * MonitorService.onBeforeUpdate.
437
+ */
438
+ const scans: Array<Model> = await this.findBy({
439
+ query:
440
+ !updateBy.props.isRoot && updateBy.props.tenantId
441
+ ? { ...updateBy.query, projectId: updateBy.props.tenantId }
442
+ : updateBy.query,
443
+ select: {
444
+ _id: true,
445
+ projectId: true,
446
+ cidr: true,
447
+ probeId: true,
448
+ snmpConfigs: true,
449
+ snmpVersion: true,
450
+ snmpCommunityString: true,
451
+ snmpPort: true,
452
+ snmpV3SecurityLevel: true,
453
+ snmpV3Username: true,
454
+ snmpV3AuthProtocol: true,
455
+ snmpV3AuthKey: true,
456
+ snmpV3PrivProtocol: true,
457
+ snmpV3PrivKey: true,
458
+ },
459
+ limit: LIMIT_MAX,
460
+ skip: 0,
461
+ props: {
462
+ isRoot: true,
463
+ ignoreHooks: true,
464
+ },
465
+ });
466
+
467
+ const plans: Record<string, ScanUpdatePlan> = {};
468
+
469
+ for (const scan of scans) {
470
+ const scanId: string | undefined = scan._id?.toString();
471
+
472
+ if (!scanId) {
473
+ continue;
474
+ }
475
+
476
+ /*
477
+ * Checked per matched scan, because the answer depends on which project
478
+ * the scan belongs to — and read from the row rather than from the
479
+ * caller's tenant, so a root writer is held to the same rule.
480
+ */
481
+ await this.validateProbeIsUsable({
482
+ data: data,
483
+ dataKeys: dataKeysAfterMirror,
484
+ projectId: scan.projectId,
485
+ });
486
+
487
+ const isLegacySnmpWritten: boolean = this.reconcileLegacySnmpUpdate({
488
+ data: data,
489
+ dataKeys: dataKeysAfterMirror,
490
+ scan: scan,
491
+ });
492
+
493
+ plans[scanId] = {
494
+ isSweepChanged: isSweepWritten
495
+ ? this.hasSweepChanged(scan, data, dataKeysAfterMirror)
496
+ : false,
497
+ isScheduleWritten: isScheduleWritten,
498
+ isLegacySnmpWritten: isLegacySnmpWritten,
499
+ };
500
+ }
501
+
502
+ return { updateBy, carryForward: plans };
503
+ }
504
+
505
+ /*
506
+ * Put the row back into a state that describes itself honestly.
507
+ *
508
+ * Two things can be wrong the moment a settings edit lands, and neither can
509
+ * be fixed in the update itself: the columns that would fix them
510
+ * (status, nextScanAt, the result columns) grant no update permission to
511
+ * anybody, and ModelPermission checks the payload AFTER onBeforeUpdate has
512
+ * run — so a payload carrying them would be refused for the very user doing
513
+ * the editing. They are written here instead, as root, through the same
514
+ * hook-free single-statement path the probe's claim uses.
515
+ *
516
+ * 1. A changed target, probe or credential leaves the row advertising
517
+ * hosts from a sweep that is no longer the sweep this scan describes:
518
+ * "12 of 254 hosts" beside a range it never visited, a Review Results
519
+ * dialog offering them for import under the new credentials, and an
520
+ * auto-import worker willing to create devices from them. The run is
521
+ * retired and the scan re-queued, so the probe simply sweeps again.
522
+ *
523
+ * 2. nextScanAt is derived state that only the result-ingest endpoint used
524
+ * to write. Turning recurrence ON for a scan that had already finished
525
+ * therefore scheduled nothing at all — the column stayed NULL, and the
526
+ * requeue worker's `nextScanAt <= now` is never true of NULL — so the
527
+ * list said "Every 60 min" over a scan that would never run again.
528
+ * Shortening the interval had the same shape of bug: the new cadence
529
+ * only took effect one full old cadence later.
530
+ *
531
+ * A known and deliberate gap: this is a second statement, so between the two
532
+ * writes the row briefly holds the new settings with the old run state. Two
533
+ * things can go wrong inside that window, both of them one database round
534
+ * trip wide. A probe result landing there is stamped onto the new settings;
535
+ * closing that needs the probe to echo a run identity back, which is a probe
536
+ * protocol change. And if this write itself fails while the settings write
537
+ * succeeded, the row keeps the new settings with the old results until the
538
+ * next edit that actually changes something — the operator sees the error,
539
+ * but re-saving the same values will not repair it, because by then nothing
540
+ * has changed.
541
+ *
542
+ * Doing it FIRST instead, in onBeforeUpdate, would be worse rather than
543
+ * better: that hook runs before the row-level gate as well, so a caller
544
+ * whose update is about to be refused would have retired the scan on the way
545
+ * through.
546
+ */
547
+ @CaptureSpan()
548
+ protected override async onUpdateSuccess(
549
+ onUpdate: OnUpdate<Model>,
550
+ updatedItemIds: Array<ObjectID>,
551
+ ): Promise<OnUpdate<Model>> {
552
+ const plans: Record<string, ScanUpdatePlan> | null =
553
+ (onUpdate.carryForward as Record<string, ScanUpdatePlan> | null) || null;
554
+
555
+ if (!plans) {
556
+ return onUpdate;
557
+ }
558
+
559
+ const now: Date = OneUptimeDate.getCurrentDate();
560
+
561
+ for (const itemId of updatedItemIds) {
562
+ const plan: ScanUpdatePlan | undefined = plans[itemId.toString()];
563
+
564
+ if (!plan) {
565
+ continue;
566
+ }
567
+
568
+ /*
569
+ * Nothing to do at all: the save named a setting but changed none of
570
+ * them, and never mentioned the schedule.
571
+ */
572
+ if (
573
+ !plan.isSweepChanged &&
574
+ !plan.isScheduleWritten &&
575
+ !plan.isLegacySnmpWritten
576
+ ) {
577
+ continue;
578
+ }
579
+
580
+ /*
581
+ * The row as it stands now that the update has landed. Read rather than
582
+ * predicted from the payload: the schedule columns are what the next run
583
+ * is derived from, and reading them back means the derivation sees the
584
+ * values the DATABASE holds — properly typed — instead of whatever
585
+ * shape the request happened to send them in.
586
+ */
587
+ const scan: Model | null = await this.findOneById({
588
+ id: itemId,
589
+ select: {
590
+ status: true,
591
+ isRecurring: true,
592
+ rescanIntervalInMinutes: true,
593
+ completedAt: true,
594
+ nextScanAt: true,
595
+ /*
596
+ * For the legacy-write rebuild below. Read back rather than taken
597
+ * from the payload, so the list is built from the values the
598
+ * database actually holds — the payload may have named only some of
599
+ * them, and the rest are whatever the row already had.
600
+ */
601
+ isSnmpEnabled: true,
602
+ snmpVersion: true,
603
+ snmpCommunityString: true,
604
+ snmpPort: true,
605
+ snmpV3SecurityLevel: true,
606
+ snmpV3Username: true,
607
+ snmpV3AuthProtocol: true,
608
+ snmpV3AuthKey: true,
609
+ snmpV3PrivProtocol: true,
610
+ snmpV3PrivKey: true,
611
+ },
612
+ props: {
613
+ isRoot: true,
614
+ ignoreHooks: true,
615
+ },
616
+ });
617
+
618
+ // Hard-deleted between the write and this read. Nothing to reconcile.
619
+ if (!scan) {
620
+ continue;
621
+ }
622
+
623
+ const reconcile: Record<string, unknown> = plan.isSweepChanged
624
+ ? { ...RETIRE_RUN_PAYLOAD }
625
+ : {};
626
+
627
+ /*
628
+ * The save came through the old single-credential API, so put the list
629
+ * back in step with the flattened columns it just wrote.
630
+ *
631
+ * Rebuilt from the ROW, which is why it happens here: one update payload
632
+ * is shared by every row the query matched, and the values to rebuild
633
+ * from are per row. resolve() over a row with no list synthesizes exactly
634
+ * one config from those columns, which is the whole of a
635
+ * single-credential scan — reconcileLegacySnmpUpdate has already refused
636
+ * the case where the row has more.
637
+ *
638
+ * An ICMP-only scan is skipped: it stores no SNMP settings at all, and
639
+ * materializing a list of the nulls it holds would be a credential set
640
+ * that says nothing, on a scan that sends nothing.
641
+ */
642
+ if (plan.isLegacySnmpWritten && ScanModeUtil.isSnmpEnabled(scan)) {
643
+ reconcile["snmpConfigs"] = SnmpScanConfigUtil.normalizeForStorage(
644
+ SnmpScanConfigUtil.resolve(scan as unknown as SnmpScanConfigSource),
645
+ );
646
+ }
647
+
648
+ /*
649
+ * Only a save that changed the sweep or asked about the schedule gets
650
+ * its next run re-derived — and the gate has to be stated here rather
651
+ * than left to the early `continue` above.
652
+ *
653
+ * It used to be left to it: that exit returned unless the sweep had
654
+ * changed or the schedule was written, so nothing else could reach this.
655
+ * Adding the credential-list rebuild to that condition opened a third
656
+ * way in, and a save through the flattened columns alone — which asks
657
+ * about neither — began re-deriving the column. On a recurring scan the
658
+ * stale-scan reaper had made due immediately (nextScanAt pulled back to
659
+ * completedAt so the requeue worker picks it up now), that pushed the
660
+ * recovery a full cadence into the future for a save that changed
661
+ * nothing about when the scan should run.
662
+ *
663
+ * For a retired run the state to derive from is the queued one written
664
+ * just above, not the finished one the row still shows.
665
+ */
666
+ if (plan.isSweepChanged || plan.isScheduleWritten) {
667
+ const nextScanAt: Date | null = getNextScanAt(
668
+ {
669
+ isRecurring: scan.isRecurring,
670
+ rescanIntervalInMinutes: scan.rescanIntervalInMinutes,
671
+ status: plan.isSweepChanged ? "Pending" : scan.status,
672
+ completedAt: plan.isSweepChanged ? null : scan.completedAt,
673
+ },
674
+ now,
675
+ );
676
+
677
+ if (!this.isSameMoment(nextScanAt, scan.nextScanAt)) {
678
+ reconcile["nextScanAt"] = nextScanAt;
679
+ }
680
+ }
681
+
682
+ if (Object.keys(reconcile).length === 0) {
683
+ continue;
684
+ }
685
+
686
+ await this.updateColumnsByIdWithoutHooks({
687
+ id: itemId,
688
+ // Cast: the model's JSON column makes DeepPartial recursion blow up.
689
+ data: reconcile as unknown as QueryDeepPartialEntity<Model>,
690
+ });
691
+ }
692
+
693
+ return onUpdate;
694
+ }
695
+
696
+ /*
697
+ * Whether this update actually changes what the probe would sweep.
698
+ *
699
+ * VALUE comparison, never key presence: ModelForm posts every field it
700
+ * declares on every save, dirty or not, so an operator who opened Edit and
701
+ * pressed Save without typing sends the whole sweep back verbatim. Keyed on
702
+ * presence, that would retire a good result set on every no-op save.
703
+ */
704
+ private hasSweepChanged(
705
+ scan: Model,
706
+ data: Record<string, unknown>,
707
+ dataKeys: Array<string>,
708
+ ): boolean {
709
+ if (RelationIdUtil.isWritten(dataKeys, PROBE_RELATION_KEYS)) {
710
+ const probeId: ObjectID | null = RelationIdUtil.read(
711
+ data,
712
+ PROBE_RELATION_KEYS,
713
+ );
714
+
715
+ if (probeId?.toString() !== scan.probeId?.toString()) {
716
+ return true;
717
+ }
718
+ }
719
+
720
+ for (const column of SWEEP_COLUMNS) {
721
+ if (column === "probeId" || !dataKeys.includes(column)) {
722
+ continue;
723
+ }
724
+
725
+ if (
726
+ this.normalizeSweepValue(data[column]) !==
727
+ this.normalizeSweepValue(
728
+ (scan as unknown as Record<string, unknown>)[column],
729
+ )
730
+ ) {
731
+ return true;
732
+ }
733
+ }
734
+
735
+ return false;
736
+ }
737
+
738
+ /*
739
+ * The probe a scan is pointed at has to be one this project may actually use
740
+ * — its own, or a global one.
741
+ *
742
+ * The scan is dispatched by probe id alone: the claim endpoint hands a
743
+ * Pending scan to whichever probe authenticates as that id, with no project
744
+ * check of its own, and the results are written back onto this row. So a
745
+ * scan pointing at ANOTHER project's probe is a scan that makes that
746
+ * project's probe sweep its own network and report the hosts it finds into
747
+ * this one. The ids are not guessable and the probe list is tenant-scoped,
748
+ * so this is a lock rather than a repair — but it is the lock that has to
749
+ * exist now that the column can be re-pointed after creation, and it is
750
+ * applied on create for the same reason.
751
+ *
752
+ * A probe with no project is a global probe and is available to everyone.
753
+ */
754
+ private async validateProbeIsUsable(input: {
755
+ data: Record<string, unknown>;
756
+ dataKeys: Array<string>;
757
+ projectId: ObjectID | undefined;
758
+ }): Promise<void> {
759
+ if (!RelationIdUtil.isWritten(input.dataKeys, PROBE_RELATION_KEYS)) {
760
+ return;
761
+ }
762
+
763
+ /*
764
+ * readConsistent, not read: a payload that points the FK column and the
765
+ * relation object at two different probes must be refused rather than
766
+ * validated against whichever one TypeORM happens to persist.
767
+ */
768
+ const probeId: ObjectID | null = RelationIdUtil.readConsistent(
769
+ input.data,
770
+ PROBE_RELATION_KEYS,
771
+ "Probe",
772
+ );
773
+
774
+ /*
775
+ * probeId is NOT NULL, so a payload that names the probe and resolves to
776
+ * nothing is an operator clearing the box. Without this it reaches
777
+ * Postgres as a constraint violation — a 500 where the truthful answer is
778
+ * a 400 with a sentence in it.
779
+ */
780
+ if (!probeId) {
781
+ throw new BadDataException(
782
+ "A discovery scan needs a probe to run it. Pick the probe that can reach this address range.",
783
+ );
784
+ }
785
+
786
+ // Nothing to compare against; the write itself is still tenant-checked.
787
+ if (!input.projectId) {
788
+ return;
789
+ }
790
+
791
+ const probe: Probe | null = await ProbeService.findOneById({
792
+ id: probeId,
793
+ select: {
794
+ _id: true,
795
+ projectId: true,
796
+ },
797
+ props: {
798
+ isRoot: true,
799
+ },
800
+ });
801
+
802
+ if (!probe) {
803
+ throw new BadDataException(
804
+ "That probe could not be found. Pick a probe that can reach this address range.",
805
+ );
806
+ }
807
+
808
+ if (
809
+ probe.projectId &&
810
+ probe.projectId.toString() !== input.projectId.toString()
811
+ ) {
812
+ throw new BadDataException(
813
+ "That probe belongs to another project. Pick one of this project's probes, or a global probe.",
814
+ );
815
+ }
816
+ }
817
+
818
+ /*
819
+ * An emptied number box means "unset", not "the empty string".
820
+ *
821
+ * Written in place, like the name normalization above, so the value the rest
822
+ * of the pipeline sees is the value that will be stored.
823
+ */
824
+ private nullEmptyNumbers(
825
+ data: Record<string, unknown>,
826
+ dataKeys: Array<string>,
827
+ ): void {
828
+ for (const column of NULLABLE_NUMBER_COLUMNS) {
829
+ if (!dataKeys.includes(column)) {
830
+ continue;
831
+ }
832
+
833
+ const value: unknown = data[column];
834
+
835
+ if (typeof value === "string" && value.trim() === "") {
836
+ data[column] = null;
837
+ }
838
+ }
839
+ }
840
+
841
+ /*
842
+ * A sweep column's value as a comparable string.
843
+ *
844
+ * An empty box and an unset column are the SAME setting and must compare
845
+ * equal, or a V3 scan — whose community string is NULL in the database and
846
+ * "" in the form — would read as changed on the first save and retire its
847
+ * own results. Numbers are compared as numbers so the port arriving as the
848
+ * string "161" from a form field does not read as a change either.
849
+ */
850
+ private normalizeSweepValue(value: unknown): string {
851
+ if (value === undefined || value === null || value === "") {
852
+ return "";
853
+ }
854
+
855
+ if (typeof value === "number") {
856
+ return String(value);
857
+ }
858
+
859
+ if (typeof value === "string") {
860
+ return value.trim();
861
+ }
862
+
863
+ /*
864
+ * The credential LIST, and the reason the fall-through below cannot be
865
+ * left to speak for it: `String([{ ... }])` is "[object Object]" for every
866
+ * possible list, so two completely different sets of credentials would
867
+ * compare equal and a save that swapped them would leave the row
868
+ * advertising hosts found with the old ones.
869
+ *
870
+ * Compared through the same normalizer the probe and the importer read the
871
+ * column with, so the comparison is of the credentials that will actually
872
+ * be USED — an empty box against an unset field, "161" against 161, "V3"
873
+ * against "3" — rather than of the shape the form happened to post. That
874
+ * is what stops a no-op Save (ModelForm posts every field, dirty or not)
875
+ * from retiring a good result set on every visit to the Edit dialog.
876
+ *
877
+ * An empty array normalizes to "" — the same answer as an unset column —
878
+ * because both mean "this scan has no list of its own". A list is refused
879
+ * as empty at validation time anyway; this only decides whether the two
880
+ * shapes read as a CHANGE.
881
+ */
882
+ if (Array.isArray(value)) {
883
+ /*
884
+ * Compared on what the PROBE would do differently, which is neither the
885
+ * whole stored object nor a naive stringify of it. Two fields are
886
+ * deliberately excluded, and each one caused a real bug:
887
+ *
888
+ * - `name` is the operator's label. It reaches a log line and the
889
+ * scan's status message and nothing else — never the wire. Including
890
+ * it meant renaming a credential card retired the run and deleted
891
+ * every host the scan had found, for a change that alters nothing
892
+ * about the sweep.
893
+ * - `id` is server-minted bookkeeping. applySnmpConfigs runs BEFORE
894
+ * this comparison and mints a fresh ObjectID for any entry that
895
+ * arrived without one, so a client that does not echo ids back — an
896
+ * API caller, a reconciler re-applying the same desired state — sent
897
+ * a byte-identical body twice and had the second read as a credential
898
+ * change. A scan under such a reconciler could never hold a result
899
+ * set at all.
900
+ *
901
+ * What survives is exactly the session parameters: version, community,
902
+ * port and the v3 block, in the operator's order. A REORDER still reads
903
+ * as a change, because order decides which credential each host is tried
904
+ * with first.
905
+ *
906
+ * Through resolve(), NOT normalizeForStorage(): the latter mints ids, and
907
+ * a comparison has to be a pure function of its input.
908
+ */
909
+ const configs: Array<DiscoveryScanSnmpConfig> =
910
+ SnmpScanConfigUtil.resolve({
911
+ snmpConfigs: value as Array<DiscoveryScanSnmpConfig>,
912
+ });
913
+
914
+ const sweepShape: Array<Record<string, unknown>> = configs.map(
915
+ (config: DiscoveryScanSnmpConfig): Record<string, unknown> => {
916
+ const sweepFields: Record<string, unknown> = {
917
+ ...config,
918
+ } as unknown as Record<string, unknown>;
919
+
920
+ delete sweepFields["id"];
921
+ delete sweepFields["name"];
922
+
923
+ return sweepFields;
924
+ },
925
+ );
926
+
927
+ return value.length === 0 ? "" : JSON.stringify(sweepShape);
928
+ }
929
+
930
+ return String(value);
931
+ }
932
+
933
+ /*
934
+ * An update written through the FLATTENED columns alone, on a scan that has
935
+ * a credential list.
936
+ *
937
+ * The list shadows those columns — SnmpScanConfigUtil.resolve reads it and
938
+ * ignores them — so such a write would land in the database and change
939
+ * nothing about the sweep, which is the worst of both outcomes: the caller
940
+ * is told it succeeded and the scan keeps the credentials it had.
941
+ *
942
+ * There are exactly two honest answers, and which one applies depends only
943
+ * on how many configs the row holds:
944
+ *
945
+ * - ONE (or none): the scan is single-credential, so the flattened columns
946
+ * can describe it completely. This returns true and onUpdateSuccess
947
+ * REBUILDS the list from the row's own flattened columns once the write
948
+ * has landed — the behaviour this API had before the list existed, with
949
+ * the list kept in step rather than discarded.
950
+ * - MORE THAN ONE: there is no flattened column set that could express the
951
+ * scan, and picking one config to overwrite would silently discard the
952
+ * others. Refused, naming the field to use instead.
953
+ *
954
+ * It does NOT null the column, which is what it used to do. A NULL list is
955
+ * readable — SnmpScanConfigUtil.resolve falls back to the flattened columns
956
+ * — but it is not EDITABLE: the Edit dialog's only SNMP control is the list
957
+ * editor, so it selects `snmpConfigs` alone, and a NULL there opened a blank
958
+ * card over a scan that had real credentials. Saving that card then mirrored
959
+ * its emptiness back over all nine columns and wiped them. The invariant
960
+ * "every scan the product has touched has a list" is what makes that
961
+ * unreachable, and this is the third place that maintains it, after the
962
+ * backfill migration and onBeforeCreate.
963
+ */
964
+ private reconcileLegacySnmpUpdate(input: {
965
+ data: Record<string, unknown>;
966
+ dataKeys: Array<string>;
967
+ scan: Model;
968
+ }): boolean {
969
+ if (input.dataKeys.includes("snmpConfigs")) {
970
+ return false;
971
+ }
972
+
973
+ const isLegacyColumnWritten: boolean = LEGACY_SNMP_COLUMNS.some(
974
+ (column: string) => {
975
+ return input.dataKeys.includes(column);
976
+ },
977
+ );
978
+
979
+ if (!isLegacyColumnWritten) {
980
+ return false;
981
+ }
982
+
983
+ const stored: Array<DiscoveryScanSnmpConfig> | null =
984
+ SnmpScanConfigUtil.readStoredList(input.scan.snmpConfigs);
985
+
986
+ if (stored && stored.length > 1) {
987
+ throw new BadDataException(
988
+ `This scan tries ${stored.length} SNMP configs, which the single snmp* fields cannot describe. ` +
989
+ `Send the whole "snmpConfigs" list instead.`,
990
+ );
991
+ }
992
+
993
+ return true;
994
+ }
995
+
996
+ /*
997
+ * The scan's ordered SNMP credential list: validated, normalized, and
998
+ * mirrored into the flattened columns.
999
+ *
1000
+ * Called from BOTH write hooks, and a no-op for a payload that does not
1001
+ * mention `snmpConfigs` — which is every server-side writer of this model
1002
+ * (the probe claim, the result ingest, the requeue worker) and every API
1003
+ * caller still using the flattened columns alone.
1004
+ *
1005
+ * THE MIRROR IS THE POINT. A probe is deployed separately from the server
1006
+ * and is routinely a version behind, and a probe that has never heard of
1007
+ * `snmpConfigs` reads the flattened columns and nothing else. Without this,
1008
+ * saving a multi-config scan would leave those columns holding whatever the
1009
+ * scan was created with — or, for a scan created after this feature, the
1010
+ * bare column defaults — and every older probe in the fleet would sweep with
1011
+ * "public"/v2c and report a confident zero. Mirroring the FIRST config keeps
1012
+ * such a probe doing exactly what it would have done under the old
1013
+ * single-config UI.
1014
+ */
1015
+ private applySnmpConfigs(
1016
+ data: Record<string, unknown>,
1017
+ dataKeys: Array<string>,
1018
+ ): void {
1019
+ if (!dataKeys.includes("snmpConfigs")) {
1020
+ return;
1021
+ }
1022
+
1023
+ const raw: unknown = data["snmpConfigs"];
1024
+
1025
+ /*
1026
+ * An absent list is not the same as a bad one. The edit form always posts
1027
+ * the key, so a null/empty value here is an API caller clearing the column
1028
+ * — which puts the scan back on its flattened columns, exactly where a
1029
+ * scan created before this feature already is. Nothing is mirrored in that
1030
+ * case: there is no first config to mirror from, and overwriting the
1031
+ * flattened columns with defaults would erase the credentials that clearing
1032
+ * the list just fell back to.
1033
+ */
1034
+ if (raw === undefined || raw === null || raw === "") {
1035
+ data["snmpConfigs"] = null;
1036
+ return;
1037
+ }
1038
+
1039
+ const validationError: string | null =
1040
+ SnmpScanConfigUtil.getValidationError(raw);
1041
+
1042
+ if (validationError) {
1043
+ throw new BadDataException(validationError);
1044
+ }
1045
+
1046
+ const configs: Array<DiscoveryScanSnmpConfig> | null =
1047
+ SnmpScanConfigUtil.normalizeForStorage(raw);
1048
+
1049
+ data["snmpConfigs"] = configs;
1050
+
1051
+ if (!configs || configs.length === 0) {
1052
+ return;
1053
+ }
1054
+
1055
+ const mirrored: Record<string, string | number | null> =
1056
+ SnmpScanConfigUtil.getMirroredLegacyColumns(configs);
1057
+
1058
+ for (const column of Object.keys(mirrored)) {
1059
+ /*
1060
+ * The payload wins where it speaks for itself. An API caller that sends
1061
+ * BOTH the list and a flattened column meant the flattened one, and
1062
+ * silently overwriting it would make the two disagree in a way only the
1063
+ * database could reveal.
1064
+ */
1065
+ if (dataKeys.includes(column)) {
1066
+ continue;
1067
+ }
1068
+
1069
+ data[column] = mirrored[column] ?? null;
1070
+ }
1071
+ }
1072
+
1073
+ /*
1074
+ * Two nullable timestamps, compared by the instant they name. The stored
1075
+ * value comes back from Postgres and the derived one is built here, so a
1076
+ * strict equality between the two objects is never true even when the moment
1077
+ * is identical, and every no-op save would write the column again.
1078
+ */
1079
+ private isSameMoment(
1080
+ left: Date | null | undefined,
1081
+ right: Date | null | undefined,
1082
+ ): boolean {
1083
+ if (!left || !right) {
1084
+ return !left && !right;
1085
+ }
1086
+
1087
+ return (
1088
+ OneUptimeDate.fromString(left).getTime() ===
1089
+ OneUptimeDate.fromString(right).getTime()
1090
+ );
1091
+ }
1092
+
1093
+ /*
1094
+ * The columns an ICMP-only scan must not carry (OneUptime issue #3445).
1095
+ *
1096
+ * Hiding the fields in the form is not enough on its own, for two separate
1097
+ * reasons. ModelForm builds the request body out of every DECLARED field
1098
+ * without checking whether it was visible, so a v3 passphrase typed before
1099
+ * the operator changed their mind is still posted — and TypeORM OMITS an
1100
+ * undefined property from the INSERT, at which point Postgres fills in the
1101
+ * column defaults, which for this table are 'V2c' and 161. Either way the
1102
+ * stored row claims to be an SNMP v2c scan on port 161 while its own method
1103
+ * column says it sends no SNMP at all.
1104
+ *
1105
+ * An explicit null is the only value that beats a column default, which is
1106
+ * why these are nulled rather than deleted.
1107
+ */
1108
+ private static readonly SNMP_CONFIG_COLUMNS: Array<string> = [
1109
+ /*
1110
+ * The credential LIST belongs here as much as the flattened columns do,
1111
+ * and more urgently: it is where the community strings and v3 passphrases
1112
+ * of a multi-credential scan actually live (issue #3458). Clearing the
1113
+ * nine below while leaving this behind would store an ICMP-only scan whose
1114
+ * own method column says it sends no SNMP, carrying every credential the
1115
+ * operator had typed.
1116
+ */
1117
+ "snmpConfigs",
1118
+ "snmpVersion",
1119
+ "snmpCommunityString",
1120
+ "snmpPort",
1121
+ "snmpV3SecurityLevel",
1122
+ "snmpV3Username",
1123
+ "snmpV3AuthProtocol",
1124
+ "snmpV3AuthKey",
1125
+ "snmpV3PrivProtocol",
1126
+ "snmpV3PrivKey",
1127
+ ];
1128
+
1129
+ /*
1130
+ * Written through a cast for the same reason the name normalize above is:
1131
+ * the properties are typed `string | number | undefined` and
1132
+ * exactOptionalPropertyTypes forbids assigning null to them directly.
1133
+ */
1134
+ private clearSnmpConfig(data: unknown): void {
1135
+ const record: Record<string, unknown> = data as Record<string, unknown>;
1136
+
1137
+ for (const column of Service.SNMP_CONFIG_COLUMNS) {
1138
+ record[column] = null;
1139
+ }
99
1140
  }
100
1141
 
101
1142
  /*