@oneuptime/common 13.0.6 → 13.0.7

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 (589) hide show
  1. package/Models/DatabaseModels/AIAgentOwnerTeam.ts +6 -0
  2. package/Models/DatabaseModels/AIAgentOwnerUser.ts +6 -0
  3. package/Models/DatabaseModels/Alert.ts +12 -0
  4. package/Models/DatabaseModels/AlertEpisodeOwnerTeam.ts +6 -1
  5. package/Models/DatabaseModels/AlertEpisodeOwnerUser.ts +6 -1
  6. package/Models/DatabaseModels/AlertOwnerTeam.ts +6 -1
  7. package/Models/DatabaseModels/AlertOwnerUser.ts +6 -1
  8. package/Models/DatabaseModels/CephClusterOwnerTeam.ts +6 -0
  9. package/Models/DatabaseModels/CephClusterOwnerUser.ts +6 -0
  10. package/Models/DatabaseModels/CloudResourceOwnerTeam.ts +6 -0
  11. package/Models/DatabaseModels/CloudResourceOwnerUser.ts +6 -0
  12. package/Models/DatabaseModels/DashboardOwnerTeam.ts +6 -1
  13. package/Models/DatabaseModels/DashboardOwnerUser.ts +6 -1
  14. package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +8 -0
  15. package/Models/DatabaseModels/DockerHostOwnerTeam.ts +6 -0
  16. package/Models/DatabaseModels/DockerHostOwnerUser.ts +6 -0
  17. package/Models/DatabaseModels/DockerSwarmClusterOwnerTeam.ts +6 -0
  18. package/Models/DatabaseModels/DockerSwarmClusterOwnerUser.ts +6 -0
  19. package/Models/DatabaseModels/HostOwnerTeam.ts +6 -0
  20. package/Models/DatabaseModels/HostOwnerUser.ts +6 -0
  21. package/Models/DatabaseModels/Incident.ts +12 -0
  22. package/Models/DatabaseModels/IncidentEpisodeOwnerTeam.ts +6 -1
  23. package/Models/DatabaseModels/IncidentEpisodeOwnerUser.ts +6 -1
  24. package/Models/DatabaseModels/IncidentOwnerTeam.ts +6 -1
  25. package/Models/DatabaseModels/IncidentOwnerUser.ts +6 -1
  26. package/Models/DatabaseModels/IncidentTemplateOwnerTeam.ts +6 -0
  27. package/Models/DatabaseModels/IncidentTemplateOwnerUser.ts +6 -0
  28. package/Models/DatabaseModels/IncomingCallPolicyOwnerTeam.ts +6 -1
  29. package/Models/DatabaseModels/IncomingCallPolicyOwnerUser.ts +6 -1
  30. package/Models/DatabaseModels/IoTFleetOwnerTeam.ts +6 -0
  31. package/Models/DatabaseModels/IoTFleetOwnerUser.ts +6 -0
  32. package/Models/DatabaseModels/KubernetesClusterOwnerTeam.ts +6 -0
  33. package/Models/DatabaseModels/KubernetesClusterOwnerUser.ts +6 -0
  34. package/Models/DatabaseModels/Monitor.ts +2 -3
  35. package/Models/DatabaseModels/MonitorGroupOwnerTeam.ts +6 -0
  36. package/Models/DatabaseModels/MonitorGroupOwnerUser.ts +6 -0
  37. package/Models/DatabaseModels/MonitorOwnerTeam.ts +6 -1
  38. package/Models/DatabaseModels/MonitorOwnerUser.ts +6 -1
  39. package/Models/DatabaseModels/MonitorTemplate.ts +2 -3
  40. package/Models/DatabaseModels/NetworkDeviceOwnerTeam.ts +6 -0
  41. package/Models/DatabaseModels/NetworkDeviceOwnerUser.ts +6 -0
  42. package/Models/DatabaseModels/OnCallDutyPolicyOwnerTeam.ts +6 -1
  43. package/Models/DatabaseModels/OnCallDutyPolicyOwnerUser.ts +6 -1
  44. package/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerTeam.ts +6 -1
  45. package/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerUser.ts +6 -1
  46. package/Models/DatabaseModels/PodmanHostOwnerTeam.ts +6 -0
  47. package/Models/DatabaseModels/PodmanHostOwnerUser.ts +6 -0
  48. package/Models/DatabaseModels/ProbeOwnerTeam.ts +6 -0
  49. package/Models/DatabaseModels/ProbeOwnerUser.ts +6 -0
  50. package/Models/DatabaseModels/ProxmoxClusterOwnerTeam.ts +6 -0
  51. package/Models/DatabaseModels/ProxmoxClusterOwnerUser.ts +6 -0
  52. package/Models/DatabaseModels/RumApplicationOwnerTeam.ts +6 -0
  53. package/Models/DatabaseModels/RumApplicationOwnerUser.ts +6 -0
  54. package/Models/DatabaseModels/RunbookOwnerTeam.ts +6 -1
  55. package/Models/DatabaseModels/RunbookOwnerUser.ts +6 -1
  56. package/Models/DatabaseModels/RunnerOwnerTeam.ts +6 -1
  57. package/Models/DatabaseModels/RunnerOwnerUser.ts +6 -1
  58. package/Models/DatabaseModels/ScheduledMaintenanceOwnerTeam.ts +6 -1
  59. package/Models/DatabaseModels/ScheduledMaintenanceOwnerUser.ts +6 -1
  60. package/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerTeam.ts +8 -0
  61. package/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.ts +8 -0
  62. package/Models/DatabaseModels/ServerlessFunctionOwnerTeam.ts +6 -0
  63. package/Models/DatabaseModels/ServerlessFunctionOwnerUser.ts +6 -0
  64. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +6 -1
  65. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +6 -1
  66. package/Models/DatabaseModels/ServiceOwnerTeam.ts +6 -0
  67. package/Models/DatabaseModels/ServiceOwnerUser.ts +6 -0
  68. package/Models/DatabaseModels/StatusPageOwnerTeam.ts +6 -1
  69. package/Models/DatabaseModels/StatusPageOwnerUser.ts +6 -1
  70. package/Models/DatabaseModels/VMwareVCenterOwnerTeam.ts +6 -0
  71. package/Models/DatabaseModels/VMwareVCenterOwnerUser.ts +6 -0
  72. package/Models/DatabaseModels/WorkflowOwnerTeam.ts +6 -1
  73. package/Models/DatabaseModels/WorkflowOwnerUser.ts +6 -1
  74. package/Scripts/benchmark-fanin-capacity.js +2 -2
  75. package/Server/API/AIAgentDataAPI.ts +1 -1
  76. package/Server/API/AIChatAPI.ts +6 -4
  77. package/Server/API/AIInvestigationAPI.ts +7 -0
  78. package/Server/API/StatusPageAPI.ts +13 -0
  79. package/Server/Infrastructure/Postgres/LocalMigrationGenerationDataSource.ts +1 -1
  80. package/Server/Infrastructure/Postgres/SchemaMigrations/1793500000000-MakeOwnerRowsUnique.ts +1057 -0
  81. package/Server/Infrastructure/Postgres/SchemaMigrations/1793700000000-AddAIInvestigationDecision.ts +25 -0
  82. package/Server/Infrastructure/Postgres/SchemaMigrations/1793800000000-RemoveMonitorDescriptionLengthLimit.ts +31 -0
  83. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  84. package/Server/Infrastructure/Postgres/SchemaMigrations/Readme.md +6 -4
  85. package/Server/Middleware/IdentityRateLimit.ts +34 -1
  86. package/Server/Middleware/PublicDashboardRateLimit.ts +169 -39
  87. package/Server/Services/AlertEpisodeService.ts +13 -34
  88. package/Server/Services/AlertGroupingEngineService.ts +7 -4
  89. package/Server/Services/AlertService.ts +13 -32
  90. package/Server/Services/CephClusterOwnerRuleEngineService.ts +18 -10
  91. package/Server/Services/CloudResourceOwnerRuleEngineService.ts +18 -10
  92. package/Server/Services/DashboardOwnerRuleEngineService.ts +18 -10
  93. package/Server/Services/DatabaseService.ts +101 -1
  94. package/Server/Services/DockerHostOwnerRuleEngineService.ts +18 -10
  95. package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +18 -10
  96. package/Server/Services/HostOwnerRuleEngineService.ts +18 -10
  97. package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +6 -4
  98. package/Server/Services/IncidentEpisodeService.ts +15 -75
  99. package/Server/Services/IncidentGroupingEngineService.ts +7 -4
  100. package/Server/Services/IncidentService.ts +13 -32
  101. package/Server/Services/IncidentTemplateService.ts +13 -36
  102. package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +18 -10
  103. package/Server/Services/IoTFleetOwnerRuleEngineService.ts +18 -10
  104. package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +18 -10
  105. package/Server/Services/MonitorService.ts +13 -32
  106. package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +18 -10
  107. package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +18 -10
  108. package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +18 -10
  109. package/Server/Services/PodmanHostOwnerRuleEngineService.ts +18 -10
  110. package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +18 -10
  111. package/Server/Services/RumApplicationOwnerRuleEngineService.ts +18 -10
  112. package/Server/Services/RunbookOwnerRuleEngineService.ts +18 -10
  113. package/Server/Services/ScheduledMaintenanceService.ts +13 -34
  114. package/Server/Services/ScheduledMaintenanceTemplateService.ts +12 -34
  115. package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +18 -10
  116. package/Server/Services/ServiceOwnerRuleEngineService.ts +18 -10
  117. package/Server/Services/StatusPagePrivateUserService.ts +38 -29
  118. package/Server/Services/StatusPagePrivateUserSessionService.ts +49 -1
  119. package/Server/Services/StatusPageService.ts +59 -36
  120. package/Server/Services/UserSessionService.ts +6 -0
  121. package/Server/Services/VMwareVCenterOwnerRuleEngineService.ts +18 -10
  122. package/Server/Services/WorkflowOwnerRuleEngineService.ts +18 -10
  123. package/Server/Static/Brand/README.md +7 -7
  124. package/Server/Static/Vendor/README.md +7 -7
  125. package/Server/Types/Database/Permissions/OwnedScopePermission.ts +18 -9
  126. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +82 -0
  127. package/Server/Utils/AI/Chat/ChatAgentRunner.ts +21 -8
  128. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +41 -4
  129. package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +1 -1
  130. package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +1 -1
  131. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +13 -5
  132. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +53 -13
  133. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +51 -14
  134. package/Server/Utils/AI/SRE/InvestigationEligibility.ts +292 -0
  135. package/Server/Utils/AI/SRE/InvestigationQueue.ts +25 -0
  136. package/Server/Utils/AI/Toolbox/Index.ts +43 -13
  137. package/Server/Utils/AI/Toolbox/ResourceTools.ts +952 -0
  138. package/Server/Utils/AI/Toolbox/RumTools.ts +424 -0
  139. package/Server/Utils/AI/Toolbox/ToolTypes.ts +10 -0
  140. package/Server/Utils/AI/Toolbox/TraceTools.ts +2 -1
  141. package/Server/Utils/Database/PostgresErrorTranslator.ts +14 -0
  142. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +137 -126
  143. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +4 -1
  144. package/Server/Utils/Rules/OwnerRuleAssignment.ts +157 -6
  145. package/Server/Utils/Telemetry/TelemetryEntity.ts +205 -6
  146. package/SslCertificates/GlobalSign.crt +26 -0
  147. package/SslCertificates/Readme.md +3 -0
  148. package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +451 -0
  149. package/Tests/App/Dashboard/AIInsightsChatPanel.test.tsx +881 -0
  150. package/Tests/App/Dashboard/AIInsightsPageContext.test.ts +458 -0
  151. package/Tests/App/Dashboard/AIInsightsResourceCitations.test.ts +124 -0
  152. package/Tests/App/Dashboard/AIInsightsResourcePageContext.test.ts +798 -0
  153. package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +7 -0
  154. package/Tests/App/Dashboard/DashboardChartWidgetZoom.test.tsx +104 -0
  155. package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +156 -64
  156. package/Tests/App/Dashboard/DiscoveryScanStatusMessage.test.tsx +970 -0
  157. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +406 -12
  158. package/Tests/App/Dashboard/EmbeddedMetricEventScope.test.tsx +358 -0
  159. package/Tests/App/Dashboard/ErrorPatternEventScope.test.tsx +148 -0
  160. package/Tests/App/Dashboard/EventOverlayAdditionalResourceScope.test.ts +255 -0
  161. package/Tests/App/Dashboard/EventOverlayScope.test.ts +845 -0
  162. package/Tests/App/Dashboard/EventOverlayScopeHook.test.tsx +903 -0
  163. package/Tests/App/Dashboard/ExternalStatusPageCriteriaFilter.test.ts +3 -3
  164. package/Tests/App/Dashboard/InvestigationDrawer.test.tsx +21 -0
  165. package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +761 -0
  166. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +7 -4
  167. package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +15 -7
  168. package/Tests/App/Dashboard/MetricsViewerEventScopeNavigation.test.tsx +264 -0
  169. package/Tests/App/Dashboard/MonitorSummaryTestMonitorButton.test.tsx +342 -0
  170. package/Tests/App/Dashboard/MonitorTestForm.test.tsx +612 -0
  171. package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +301 -0
  172. package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +74 -2
  173. package/Tests/App/Dashboard/TextClampLayoutHarness.ts +224 -0
  174. package/Tests/Models/InventoryItemNaming.test.ts +54 -0
  175. package/Tests/Server/API/AIChatRouteAuthorization.test.ts +161 -0
  176. package/Tests/Server/API/AIInvestigationAPI.test.ts +14 -0
  177. package/Tests/Server/API/AIInvestigationAvailabilityAuthorization.test.ts +260 -0
  178. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +133 -0
  179. package/Tests/Server/API/StatusPageMasterPasswordRateLimit.test.ts +482 -0
  180. package/Tests/Server/EnvironmentConfigOnCallCalendarFeed.test.ts +1 -1
  181. package/Tests/Server/Infrastructure/ClickhouseKeepAliveOptions.test.ts +1 -1
  182. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +38 -16
  183. package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +106 -31
  184. package/Tests/Server/Infrastructure/ExampleDockerfiles.test.ts +46 -12
  185. package/Tests/Server/Infrastructure/Postgres/MonitorDescriptionMigration.test.ts +422 -0
  186. package/Tests/Server/Infrastructure/TelemetryExporterDeploymentConfig.test.ts +1 -1
  187. package/Tests/Server/Infrastructure/ValkeyDeploymentConfig.test.ts +25 -4
  188. package/Tests/Server/Middleware/IdentityRateLimit.test.ts +72 -0
  189. package/Tests/Server/Middleware/PublicDashboardRateLimit.test.ts +12 -12
  190. package/Tests/Server/Middleware/PublicDashboardRateLimitStatusPage.test.ts +800 -0
  191. package/Tests/Server/Services/AIInvestigationDecisionPostgres.test.ts +346 -0
  192. package/Tests/Server/Services/AddOwnersIdempotency.test.ts +471 -0
  193. package/Tests/Server/Services/DatabaseServiceAutoOwnerOnCreate.test.ts +250 -0
  194. package/Tests/Server/Services/DatabaseServiceUniqueColumnsTogether.test.ts +622 -0
  195. package/Tests/Server/Services/MonitorDescriptionValidation.test.ts +211 -0
  196. package/Tests/Server/Services/MonitorTemplateDescriptionPropagation.test.ts +269 -0
  197. package/Tests/Server/Services/OwnerRowUniqueness.test.ts +504 -0
  198. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupARun.test.ts +43 -0
  199. package/Tests/Server/Services/SessionRetention.test.ts +334 -0
  200. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +172 -0
  201. package/Tests/Server/Services/StatusPagePrivateUserReadAccess.test.ts +178 -0
  202. package/Tests/Server/Services/StatusPagePrivateUserReadAccessPostgres.test.ts +311 -0
  203. package/Tests/Server/Services/StatusPagePrivateUserSessionService.test.ts +216 -1
  204. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +1 -1
  205. package/Tests/Server/Services/UserOnCallLogNoNotificationRules.test.ts +1 -1
  206. package/Tests/Server/Types/Database/EventOverlayScopePostgres.test.ts +626 -0
  207. package/Tests/Server/Types/Database/Permissions/InfrastructureOwnershipScope.test.ts +668 -0
  208. package/Tests/Server/Types/Database/Permissions/SelectRejectionMessageContract.test.ts +1 -0
  209. package/Tests/Server/Types/Database/Permissions/UserNotificationRuleScoping.test.ts +1 -1
  210. package/Tests/Server/Utils/AI/AIIncidentGating.test.ts +16 -9
  211. package/Tests/Server/Utils/AI/ChatAgentRunner.test.ts +137 -1
  212. package/Tests/Server/Utils/AI/InvestigationEligibility.test.ts +697 -0
  213. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +105 -0
  214. package/Tests/Server/Utils/AI/RemediationHandoff.test.ts +16 -5
  215. package/Tests/Server/Utils/AI/ResourceTools.test.ts +1304 -0
  216. package/Tests/Server/Utils/AI/RumTools.test.ts +769 -0
  217. package/Tests/Server/Utils/Database/PostgresErrorTranslator.test.ts +63 -0
  218. package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaEvaluateOverTime.test.ts +11 -9
  219. package/Tests/Server/Utils/Monitor/Criteria/CompareCriteria.test.ts +62 -45
  220. package/Tests/Server/Utils/Monitor/Criteria/CompareCriteriaAggregation.test.ts +25 -24
  221. package/Tests/Server/Utils/Monitor/Criteria/CompareCriteriaHumanMessages.test.ts +513 -0
  222. package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +2 -2
  223. package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +1 -1
  224. package/Tests/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.test.ts +9 -9
  225. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +7 -5
  226. package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +2 -2
  227. package/Tests/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.test.ts +4 -3
  228. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +2 -2
  229. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +3 -2
  230. package/Tests/Server/Utils/Monitor/MonitorCriteriaHumanMessages.test.ts +529 -0
  231. package/Tests/Server/Utils/Rules/OwnerRuleAssignment.test.ts +412 -4
  232. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingClickhouseIntegration.test.ts +1 -1
  233. package/Tests/Server/Utils/TailwindBuildCopy.test.ts +14 -2
  234. package/Tests/Server/Utils/Telemetry/HostAssetAttributesFromOtlp.test.ts +235 -0
  235. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +385 -2
  236. package/Tests/Server/Utils/VendorAssets.test.ts +17 -3
  237. package/Tests/Types/AI/AIChatPageContext.test.ts +0 -0
  238. package/Tests/Types/AI/AIResourceContext.test.ts +312 -0
  239. package/Tests/Types/Database/UniqueColumnsTogether.test.ts +100 -0
  240. package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +4 -4
  241. package/Tests/Types/Monitor/MonitorStepRetryPersistence.test.ts +125 -0
  242. package/Tests/Types/WebsiteRequest.test.ts +44 -0
  243. package/Tests/UI/Components/Forms/MonitorDescriptionForm.test.tsx +410 -0
  244. package/Tests/UI/Components/ModelTable/BaseModelTableReadPermissions.test.tsx +439 -0
  245. package/Tests/UI/Components/NavBarMenuSearch.test.tsx +372 -0
  246. package/Tests/UI/EsbuildConfig.test.ts +1 -1
  247. package/Tests/UI/Monitor/MonitorStepRetrySettings.test.tsx +616 -0
  248. package/Tests/UI/ReactRouterSingletonBuild.test.ts +4 -2
  249. package/Tests/UI/Rum/ReplayEngine.test.ts +179 -0
  250. package/Tests/UI/Rum/ReplayHeader.test.tsx +23 -0
  251. package/Tests/UI/Rum/ReplayScrubber.test.tsx +88 -0
  252. package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +83 -0
  253. package/Tests/UI/Rum/ReplayTabSwitcher.test.tsx +33 -0
  254. package/Tests/Utils/API.test.ts +96 -0
  255. package/Tests/Utils/HTTPResponseBodyReader.test.ts +188 -1
  256. package/Tests/Utils/Metrics/MetricEventScopeUrl.test.ts +101 -0
  257. package/Tests/Utils/Monitor/MonitorTestAvailabilityUtil.test.ts +256 -0
  258. package/Tests/Utils/Telemetry/HostIpAddresses.test.ts +105 -0
  259. package/Types/AI/AIChatPageContext.ts +87 -2
  260. package/Types/AI/AIChatTypes.ts +4 -0
  261. package/Types/AI/AIResourceContext.ts +198 -0
  262. package/Types/AI/InvestigationNotStartedReason.ts +30 -0
  263. package/Types/Database/UniqueColumnsTogether.ts +55 -0
  264. package/Types/Metrics/MetricQueryConfigData.ts +8 -0
  265. package/Types/Rum/WebVitals.ts +71 -0
  266. package/Types/WebsiteRequest.ts +2 -0
  267. package/UI/Components/EditionLabel/EditionLabel.tsx +7 -5
  268. package/UI/Components/KeyboardShortcut/Screenshots/README.md +1 -1
  269. package/UI/Components/ModelTable/BaseModelTable.tsx +8 -0
  270. package/UI/Components/Navbar/NavBar.tsx +2 -0
  271. package/UI/Components/Navbar/NavBarMenuModal.tsx +6 -2
  272. package/UI/esbuild-config.js +4 -4
  273. package/Utils/API.ts +10 -1
  274. package/Utils/Dashboard/HtmlWidgetDocument.ts +1 -1
  275. package/Utils/HTTPResponseBodyReader.ts +64 -8
  276. package/Utils/Metrics/MetricExplorerUrl.ts +19 -0
  277. package/Utils/Monitor/MonitorTestAvailabilityUtil.ts +92 -0
  278. package/Utils/Telemetry/HostIpAddresses.ts +46 -2
  279. package/build/dist/Models/DatabaseModels/AIAgentOwnerTeam.js +4 -1
  280. package/build/dist/Models/DatabaseModels/AIAgentOwnerTeam.js.map +1 -1
  281. package/build/dist/Models/DatabaseModels/AIAgentOwnerUser.js +4 -1
  282. package/build/dist/Models/DatabaseModels/AIAgentOwnerUser.js.map +1 -1
  283. package/build/dist/Models/DatabaseModels/Alert.js +12 -0
  284. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  285. package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerTeam.js +3 -1
  286. package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerTeam.js.map +1 -1
  287. package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerUser.js +3 -1
  288. package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerUser.js.map +1 -1
  289. package/build/dist/Models/DatabaseModels/AlertOwnerTeam.js +3 -1
  290. package/build/dist/Models/DatabaseModels/AlertOwnerTeam.js.map +1 -1
  291. package/build/dist/Models/DatabaseModels/AlertOwnerUser.js +3 -1
  292. package/build/dist/Models/DatabaseModels/AlertOwnerUser.js.map +1 -1
  293. package/build/dist/Models/DatabaseModels/CephClusterOwnerTeam.js +4 -1
  294. package/build/dist/Models/DatabaseModels/CephClusterOwnerTeam.js.map +1 -1
  295. package/build/dist/Models/DatabaseModels/CephClusterOwnerUser.js +4 -1
  296. package/build/dist/Models/DatabaseModels/CephClusterOwnerUser.js.map +1 -1
  297. package/build/dist/Models/DatabaseModels/CloudResourceOwnerTeam.js +4 -1
  298. package/build/dist/Models/DatabaseModels/CloudResourceOwnerTeam.js.map +1 -1
  299. package/build/dist/Models/DatabaseModels/CloudResourceOwnerUser.js +4 -1
  300. package/build/dist/Models/DatabaseModels/CloudResourceOwnerUser.js.map +1 -1
  301. package/build/dist/Models/DatabaseModels/DashboardOwnerTeam.js +3 -1
  302. package/build/dist/Models/DatabaseModels/DashboardOwnerTeam.js.map +1 -1
  303. package/build/dist/Models/DatabaseModels/DashboardOwnerUser.js +3 -1
  304. package/build/dist/Models/DatabaseModels/DashboardOwnerUser.js.map +1 -1
  305. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +3 -0
  306. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
  307. package/build/dist/Models/DatabaseModels/DockerHostOwnerTeam.js +4 -1
  308. package/build/dist/Models/DatabaseModels/DockerHostOwnerTeam.js.map +1 -1
  309. package/build/dist/Models/DatabaseModels/DockerHostOwnerUser.js +4 -1
  310. package/build/dist/Models/DatabaseModels/DockerHostOwnerUser.js.map +1 -1
  311. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerTeam.js +4 -1
  312. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerTeam.js.map +1 -1
  313. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerUser.js +4 -1
  314. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerUser.js.map +1 -1
  315. package/build/dist/Models/DatabaseModels/HostOwnerTeam.js +4 -1
  316. package/build/dist/Models/DatabaseModels/HostOwnerTeam.js.map +1 -1
  317. package/build/dist/Models/DatabaseModels/HostOwnerUser.js +4 -1
  318. package/build/dist/Models/DatabaseModels/HostOwnerUser.js.map +1 -1
  319. package/build/dist/Models/DatabaseModels/Incident.js +12 -0
  320. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  321. package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerTeam.js +3 -1
  322. package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerTeam.js.map +1 -1
  323. package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerUser.js +3 -1
  324. package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerUser.js.map +1 -1
  325. package/build/dist/Models/DatabaseModels/IncidentOwnerTeam.js +3 -1
  326. package/build/dist/Models/DatabaseModels/IncidentOwnerTeam.js.map +1 -1
  327. package/build/dist/Models/DatabaseModels/IncidentOwnerUser.js +3 -1
  328. package/build/dist/Models/DatabaseModels/IncidentOwnerUser.js.map +1 -1
  329. package/build/dist/Models/DatabaseModels/IncidentTemplateOwnerTeam.js +4 -1
  330. package/build/dist/Models/DatabaseModels/IncidentTemplateOwnerTeam.js.map +1 -1
  331. package/build/dist/Models/DatabaseModels/IncidentTemplateOwnerUser.js +4 -1
  332. package/build/dist/Models/DatabaseModels/IncidentTemplateOwnerUser.js.map +1 -1
  333. package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerTeam.js +3 -1
  334. package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerTeam.js.map +1 -1
  335. package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerUser.js +3 -1
  336. package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerUser.js.map +1 -1
  337. package/build/dist/Models/DatabaseModels/IoTFleetOwnerTeam.js +4 -1
  338. package/build/dist/Models/DatabaseModels/IoTFleetOwnerTeam.js.map +1 -1
  339. package/build/dist/Models/DatabaseModels/IoTFleetOwnerUser.js +4 -1
  340. package/build/dist/Models/DatabaseModels/IoTFleetOwnerUser.js.map +1 -1
  341. package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerTeam.js +4 -1
  342. package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerTeam.js.map +1 -1
  343. package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerUser.js +4 -1
  344. package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerUser.js.map +1 -1
  345. package/build/dist/Models/DatabaseModels/Monitor.js +2 -3
  346. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  347. package/build/dist/Models/DatabaseModels/MonitorGroupOwnerTeam.js +4 -1
  348. package/build/dist/Models/DatabaseModels/MonitorGroupOwnerTeam.js.map +1 -1
  349. package/build/dist/Models/DatabaseModels/MonitorGroupOwnerUser.js +4 -1
  350. package/build/dist/Models/DatabaseModels/MonitorGroupOwnerUser.js.map +1 -1
  351. package/build/dist/Models/DatabaseModels/MonitorOwnerTeam.js +3 -1
  352. package/build/dist/Models/DatabaseModels/MonitorOwnerTeam.js.map +1 -1
  353. package/build/dist/Models/DatabaseModels/MonitorOwnerUser.js +3 -1
  354. package/build/dist/Models/DatabaseModels/MonitorOwnerUser.js.map +1 -1
  355. package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -3
  356. package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
  357. package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerTeam.js +4 -1
  358. package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerTeam.js.map +1 -1
  359. package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerUser.js +4 -1
  360. package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerUser.js.map +1 -1
  361. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerTeam.js +3 -1
  362. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerTeam.js.map +1 -1
  363. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerUser.js +3 -1
  364. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerUser.js.map +1 -1
  365. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerTeam.js +3 -1
  366. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerTeam.js.map +1 -1
  367. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerUser.js +3 -1
  368. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerUser.js.map +1 -1
  369. package/build/dist/Models/DatabaseModels/PodmanHostOwnerTeam.js +4 -1
  370. package/build/dist/Models/DatabaseModels/PodmanHostOwnerTeam.js.map +1 -1
  371. package/build/dist/Models/DatabaseModels/PodmanHostOwnerUser.js +4 -1
  372. package/build/dist/Models/DatabaseModels/PodmanHostOwnerUser.js.map +1 -1
  373. package/build/dist/Models/DatabaseModels/ProbeOwnerTeam.js +4 -1
  374. package/build/dist/Models/DatabaseModels/ProbeOwnerTeam.js.map +1 -1
  375. package/build/dist/Models/DatabaseModels/ProbeOwnerUser.js +4 -1
  376. package/build/dist/Models/DatabaseModels/ProbeOwnerUser.js.map +1 -1
  377. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerTeam.js +4 -1
  378. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerTeam.js.map +1 -1
  379. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerUser.js +4 -1
  380. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerUser.js.map +1 -1
  381. package/build/dist/Models/DatabaseModels/RumApplicationOwnerTeam.js +4 -1
  382. package/build/dist/Models/DatabaseModels/RumApplicationOwnerTeam.js.map +1 -1
  383. package/build/dist/Models/DatabaseModels/RumApplicationOwnerUser.js +4 -1
  384. package/build/dist/Models/DatabaseModels/RumApplicationOwnerUser.js.map +1 -1
  385. package/build/dist/Models/DatabaseModels/RunbookOwnerTeam.js +3 -1
  386. package/build/dist/Models/DatabaseModels/RunbookOwnerTeam.js.map +1 -1
  387. package/build/dist/Models/DatabaseModels/RunbookOwnerUser.js +3 -1
  388. package/build/dist/Models/DatabaseModels/RunbookOwnerUser.js.map +1 -1
  389. package/build/dist/Models/DatabaseModels/RunnerOwnerTeam.js +3 -1
  390. package/build/dist/Models/DatabaseModels/RunnerOwnerTeam.js.map +1 -1
  391. package/build/dist/Models/DatabaseModels/RunnerOwnerUser.js +3 -1
  392. package/build/dist/Models/DatabaseModels/RunnerOwnerUser.js.map +1 -1
  393. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerTeam.js +3 -1
  394. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerTeam.js.map +1 -1
  395. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerUser.js +3 -1
  396. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerUser.js.map +1 -1
  397. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerTeam.js +6 -1
  398. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerTeam.js.map +1 -1
  399. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.js +6 -1
  400. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.js.map +1 -1
  401. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerTeam.js +4 -1
  402. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerTeam.js.map +1 -1
  403. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerUser.js +4 -1
  404. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerUser.js.map +1 -1
  405. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +3 -1
  406. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -1
  407. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +3 -1
  408. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -1
  409. package/build/dist/Models/DatabaseModels/ServiceOwnerTeam.js +4 -1
  410. package/build/dist/Models/DatabaseModels/ServiceOwnerTeam.js.map +1 -1
  411. package/build/dist/Models/DatabaseModels/ServiceOwnerUser.js +4 -1
  412. package/build/dist/Models/DatabaseModels/ServiceOwnerUser.js.map +1 -1
  413. package/build/dist/Models/DatabaseModels/StatusPageOwnerTeam.js +3 -1
  414. package/build/dist/Models/DatabaseModels/StatusPageOwnerTeam.js.map +1 -1
  415. package/build/dist/Models/DatabaseModels/StatusPageOwnerUser.js +3 -1
  416. package/build/dist/Models/DatabaseModels/StatusPageOwnerUser.js.map +1 -1
  417. package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerTeam.js +4 -1
  418. package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerTeam.js.map +1 -1
  419. package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerUser.js +4 -1
  420. package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerUser.js.map +1 -1
  421. package/build/dist/Models/DatabaseModels/WorkflowOwnerTeam.js +3 -1
  422. package/build/dist/Models/DatabaseModels/WorkflowOwnerTeam.js.map +1 -1
  423. package/build/dist/Models/DatabaseModels/WorkflowOwnerUser.js +3 -1
  424. package/build/dist/Models/DatabaseModels/WorkflowOwnerUser.js.map +1 -1
  425. package/build/dist/Server/API/AIAgentDataAPI.js +1 -1
  426. package/build/dist/Server/API/AIChatAPI.js +3 -1
  427. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  428. package/build/dist/Server/API/AIInvestigationAPI.js +3 -0
  429. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  430. package/build/dist/Server/API/StatusPageAPI.js +9 -1
  431. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  432. package/build/dist/Server/Infrastructure/Postgres/LocalMigrationGenerationDataSource.js +1 -1
  433. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793500000000-MakeOwnerRowsUnique.js +602 -0
  434. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793500000000-MakeOwnerRowsUnique.js.map +1 -0
  435. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793700000000-AddAIInvestigationDecision.js +14 -0
  436. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793700000000-AddAIInvestigationDecision.js.map +1 -0
  437. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793800000000-RemoveMonitorDescriptionLengthLimit.js +20 -0
  438. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793800000000-RemoveMonitorDescriptionLengthLimit.js.map +1 -0
  439. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  440. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  441. package/build/dist/Server/Middleware/IdentityRateLimit.js +22 -1
  442. package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
  443. package/build/dist/Server/Middleware/PublicDashboardRateLimit.js +117 -36
  444. package/build/dist/Server/Middleware/PublicDashboardRateLimit.js.map +1 -1
  445. package/build/dist/Server/Services/AlertEpisodeService.js +13 -31
  446. package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
  447. package/build/dist/Server/Services/AlertGroupingEngineService.js +7 -4
  448. package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
  449. package/build/dist/Server/Services/AlertService.js +13 -31
  450. package/build/dist/Server/Services/AlertService.js.map +1 -1
  451. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +12 -8
  452. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
  453. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +12 -8
  454. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
  455. package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +12 -8
  456. package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
  457. package/build/dist/Server/Services/DatabaseService.js +71 -1
  458. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  459. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +12 -8
  460. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
  461. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +12 -8
  462. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
  463. package/build/dist/Server/Services/HostOwnerRuleEngineService.js +12 -8
  464. package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
  465. package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +6 -4
  466. package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
  467. package/build/dist/Server/Services/IncidentEpisodeService.js +15 -68
  468. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  469. package/build/dist/Server/Services/IncidentGroupingEngineService.js +7 -4
  470. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  471. package/build/dist/Server/Services/IncidentService.js +13 -31
  472. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  473. package/build/dist/Server/Services/IncidentTemplateService.js +13 -31
  474. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  475. package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +12 -8
  476. package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
  477. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +12 -8
  478. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
  479. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +12 -8
  480. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
  481. package/build/dist/Server/Services/MonitorService.js +13 -31
  482. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  483. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +12 -8
  484. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
  485. package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +12 -8
  486. package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
  487. package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +12 -8
  488. package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
  489. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +12 -8
  490. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
  491. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +12 -8
  492. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
  493. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +12 -8
  494. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
  495. package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +12 -8
  496. package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
  497. package/build/dist/Server/Services/ScheduledMaintenanceService.js +13 -31
  498. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  499. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js +12 -29
  500. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js.map +1 -1
  501. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +12 -8
  502. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
  503. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +12 -8
  504. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
  505. package/build/dist/Server/Services/StatusPagePrivateUserService.js +33 -25
  506. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  507. package/build/dist/Server/Services/StatusPagePrivateUserSessionService.js +36 -1
  508. package/build/dist/Server/Services/StatusPagePrivateUserSessionService.js.map +1 -1
  509. package/build/dist/Server/Services/StatusPageService.js +50 -35
  510. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  511. package/build/dist/Server/Services/UserSessionService.js +5 -0
  512. package/build/dist/Server/Services/UserSessionService.js.map +1 -1
  513. package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js +12 -8
  514. package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js.map +1 -1
  515. package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +12 -8
  516. package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
  517. package/build/dist/Server/Types/Database/Permissions/OwnedScopePermission.js +15 -10
  518. package/build/dist/Server/Types/Database/Permissions/OwnedScopePermission.js.map +1 -1
  519. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +82 -0
  520. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  521. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +12 -3
  522. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
  523. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +32 -4
  524. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
  525. package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +1 -1
  526. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +1 -1
  527. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +8 -5
  528. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  529. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +33 -13
  530. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  531. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +31 -10
  532. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  533. package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js +205 -0
  534. package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js.map +1 -0
  535. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +13 -0
  536. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
  537. package/build/dist/Server/Utils/AI/Toolbox/Index.js +30 -6
  538. package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
  539. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js +721 -0
  540. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js.map +1 -0
  541. package/build/dist/Server/Utils/AI/Toolbox/RumTools.js +330 -0
  542. package/build/dist/Server/Utils/AI/Toolbox/RumTools.js.map +1 -0
  543. package/build/dist/Server/Utils/AI/Toolbox/ToolTypes.js.map +1 -1
  544. package/build/dist/Server/Utils/AI/Toolbox/TraceTools.js +1 -1
  545. package/build/dist/Server/Utils/AI/Toolbox/TraceTools.js.map +1 -1
  546. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js +11 -0
  547. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js.map +1 -1
  548. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +106 -101
  549. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
  550. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +4 -2
  551. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
  552. package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js +94 -0
  553. package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js.map +1 -1
  554. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +171 -6
  555. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  556. package/build/dist/Types/AI/AIChatPageContext.js +68 -2
  557. package/build/dist/Types/AI/AIChatPageContext.js.map +1 -1
  558. package/build/dist/Types/AI/AIChatTypes.js +4 -0
  559. package/build/dist/Types/AI/AIChatTypes.js.map +1 -1
  560. package/build/dist/Types/AI/AIResourceContext.js +162 -0
  561. package/build/dist/Types/AI/AIResourceContext.js.map +1 -0
  562. package/build/dist/Types/AI/InvestigationNotStartedReason.js +2 -0
  563. package/build/dist/Types/AI/InvestigationNotStartedReason.js.map +1 -0
  564. package/build/dist/Types/Database/UniqueColumnsTogether.js +19 -0
  565. package/build/dist/Types/Database/UniqueColumnsTogether.js.map +1 -0
  566. package/build/dist/Types/Metrics/MetricQueryConfigData.js.map +1 -1
  567. package/build/dist/Types/Rum/WebVitals.js +64 -0
  568. package/build/dist/Types/Rum/WebVitals.js.map +1 -0
  569. package/build/dist/Types/WebsiteRequest.js +2 -0
  570. package/build/dist/Types/WebsiteRequest.js.map +1 -1
  571. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +7 -5
  572. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  573. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +7 -0
  574. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  575. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  576. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +4 -2
  577. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  578. package/build/dist/Utils/API.js +8 -4
  579. package/build/dist/Utils/API.js.map +1 -1
  580. package/build/dist/Utils/HTTPResponseBodyReader.js +50 -6
  581. package/build/dist/Utils/HTTPResponseBodyReader.js.map +1 -1
  582. package/build/dist/Utils/Metrics/MetricExplorerUrl.js +14 -3
  583. package/build/dist/Utils/Metrics/MetricExplorerUrl.js.map +1 -1
  584. package/build/dist/Utils/Monitor/MonitorTestAvailabilityUtil.js +68 -0
  585. package/build/dist/Utils/Monitor/MonitorTestAvailabilityUtil.js.map +1 -0
  586. package/build/dist/Utils/Telemetry/HostIpAddresses.js +42 -3
  587. package/build/dist/Utils/Telemetry/HostIpAddresses.js.map +1 -1
  588. package/package.json +5 -5
  589. package/test-setup.sh +2 -2
@@ -0,0 +1,903 @@
1
+ import "@testing-library/jest-dom";
2
+ import {
3
+ afterEach,
4
+ beforeEach,
5
+ describe,
6
+ expect,
7
+ jest,
8
+ test,
9
+ } from "@jest/globals";
10
+ import { act, cleanup, render, screen, waitFor } from "@testing-library/react";
11
+ import * as React from "react";
12
+ import getJestMockFunction, { MockFunction } from "../../MockType";
13
+ import InBetween from "../../../Types/BaseDatabase/InBetween";
14
+ import Includes from "../../../Types/BaseDatabase/Includes";
15
+ import SortOrder from "../../../Types/BaseDatabase/SortOrder";
16
+ import MetricQueryConfigData from "../../../Types/Metrics/MetricQueryConfigData";
17
+ import ObjectID from "../../../Types/ObjectID";
18
+ import ChartTimeReferenceLineProps from "../../../UI/Components/Charts/Types/TimeReferenceLineProps";
19
+ import ProjectUtil from "../../../UI/Utils/Project";
20
+ import useEventTimeReferenceLines, {
21
+ EVENT_OVERLAY_FETCH_LIMIT,
22
+ EventTimeReferenceLines,
23
+ } from "../../../../App/FeatureSet/Dashboard/src/Components/Metrics/Utils/UseEventTimeReferenceLines";
24
+
25
+ const getListMock: MockFunction = getJestMockFunction();
26
+ const analyticsGetListMock: MockFunction = getJestMockFunction();
27
+ const isPublicDashboardMock: MockFunction = getJestMockFunction();
28
+
29
+ jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
30
+ return {
31
+ __esModule: true,
32
+ default: {
33
+ getList: (...args: Array<any>) => {
34
+ return getListMock(...args);
35
+ },
36
+ },
37
+ };
38
+ });
39
+
40
+ jest.mock("../../../UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI", () => {
41
+ return {
42
+ __esModule: true,
43
+ default: {
44
+ getList: (...args: Array<any>) => {
45
+ return analyticsGetListMock(...args);
46
+ },
47
+ },
48
+ };
49
+ });
50
+
51
+ jest.mock(
52
+ "../../../../App/FeatureSet/Dashboard/src/Components/Dashboard/Utils/PublicDashboardContext",
53
+ () => {
54
+ return {
55
+ __esModule: true,
56
+ isPublicDashboard: (...args: Array<any>) => {
57
+ return isPublicDashboardMock(...args);
58
+ },
59
+ };
60
+ },
61
+ );
62
+
63
+ const PROJECT_ID: ObjectID = new ObjectID(
64
+ "9e1b6b0e-0000-4000-8000-000000000011",
65
+ );
66
+ const OTHER_PROJECT_ID: ObjectID = new ObjectID(
67
+ "9e1b6b0e-0000-4000-8000-000000000012",
68
+ );
69
+ const MONITOR_A: string = "aaaaaaaa-0000-4000-8000-000000000001";
70
+ const MONITOR_B: string = "bbbbbbbb-0000-4000-8000-000000000002";
71
+ const WINDOW: InBetween<Date> = new InBetween<Date>(
72
+ new Date("2026-08-20T10:00:00.000Z"),
73
+ new Date("2026-08-20T11:00:00.000Z"),
74
+ );
75
+
76
+ interface ProbeProps {
77
+ queryConfigs?: Array<MetricQueryConfigData> | undefined;
78
+ enabled?: boolean | undefined;
79
+ window?: InBetween<Date> | null | undefined;
80
+ refreshTick?: number | undefined;
81
+ }
82
+
83
+ interface EventRequest {
84
+ modelType: { name: string };
85
+ query: Record<string, unknown>;
86
+ limit: number;
87
+ skip: number;
88
+ sort: Record<string, SortOrder>;
89
+ }
90
+
91
+ interface TestEvent {
92
+ id: ObjectID;
93
+ createdAt: string;
94
+ time: string;
95
+ title: string;
96
+ eventType: string;
97
+ monitorId?: string | undefined;
98
+ monitors?: Array<string> | undefined;
99
+ }
100
+
101
+ interface DeferredEvents {
102
+ promise: Promise<{ data: Array<TestEvent> }>;
103
+ resolve: (data: Array<TestEvent>) => void;
104
+ }
105
+
106
+ function Probe(props: ProbeProps): React.ReactElement {
107
+ const { lines, markerCount }: EventTimeReferenceLines =
108
+ useEventTimeReferenceLines({
109
+ enabled: props.enabled ?? true,
110
+ window: props.window === undefined ? WINDOW : props.window,
111
+ queryConfigs: props.queryConfigs,
112
+ refreshTick: props.refreshTick,
113
+ });
114
+
115
+ return (
116
+ <div>
117
+ <span data-testid="marker-count">{markerCount}</span>
118
+ {lines.map((line: ChartTimeReferenceLineProps, index: number) => {
119
+ return (
120
+ <div key={index} data-testid="marker" data-kind={line.kind}>
121
+ {line.label}
122
+ </div>
123
+ );
124
+ })}
125
+ </div>
126
+ );
127
+ }
128
+
129
+ function monitorConfig(monitorId: string): MetricQueryConfigData {
130
+ return {
131
+ metricQueryData: {
132
+ filterData: {
133
+ metricName: "oneuptime.monitor.response_time",
134
+ attributes: { monitorId: monitorId },
135
+ },
136
+ },
137
+ };
138
+ }
139
+
140
+ function event(
141
+ title: string,
142
+ number: number = 1,
143
+ monitorId: string = MONITOR_A,
144
+ ): TestEvent {
145
+ return {
146
+ id: new ObjectID(
147
+ `11111111-0000-4000-8000-${number.toString().padStart(12, "0")}`,
148
+ ),
149
+ createdAt: new Date(
150
+ new Date("2026-08-20T10:00:00.000Z").getTime() + number * 1000,
151
+ ).toISOString(),
152
+ time: new Date(
153
+ new Date("2026-08-20T10:00:00.000Z").getTime() + number * 1000,
154
+ ).toISOString(),
155
+ title: title,
156
+ eventType: "deployment",
157
+ monitorId: monitorId,
158
+ monitors: [monitorId],
159
+ };
160
+ }
161
+
162
+ function deferredEvents(): DeferredEvents {
163
+ let resolveEvents: (data: Array<TestEvent>) => void = (): void => {};
164
+ const promise: Promise<{ data: Array<TestEvent> }> = new Promise(
165
+ (resolve: (result: { data: Array<TestEvent> }) => void): void => {
166
+ resolveEvents = (data: Array<TestEvent>): void => {
167
+ resolve({ data: data });
168
+ };
169
+ },
170
+ );
171
+
172
+ return { promise: promise, resolve: resolveEvents };
173
+ }
174
+
175
+ function queryValues(value: unknown): Array<string> {
176
+ if (value instanceof Includes) {
177
+ return value.values.map((item: string | number | ObjectID): string => {
178
+ return item.toString();
179
+ });
180
+ }
181
+ if (value !== null && typeof value === "object" && "_id" in value) {
182
+ return queryValues(value._id);
183
+ }
184
+ return value === undefined ? [] : [String(value)];
185
+ }
186
+
187
+ function requestsFor(modelName: string): Array<EventRequest> {
188
+ return getListMock.mock.calls
189
+ .map((call: Array<unknown>): EventRequest => {
190
+ return call[0] as EventRequest;
191
+ })
192
+ .filter((request: EventRequest): boolean => {
193
+ return request.modelType.name === modelName;
194
+ });
195
+ }
196
+
197
+ async function expectMarkerCount(count: number): Promise<void> {
198
+ await waitFor((): void => {
199
+ expect(screen.getByTestId("marker-count").textContent).toBe(String(count));
200
+ });
201
+ }
202
+
203
+ beforeEach((): void => {
204
+ getListMock.mockReset();
205
+ analyticsGetListMock.mockReset();
206
+ isPublicDashboardMock.mockReset();
207
+ getListMock.mockResolvedValue({ data: [] });
208
+ analyticsGetListMock.mockResolvedValue({ data: [] });
209
+ isPublicDashboardMock.mockReturnValue(false);
210
+ jest.spyOn(ProjectUtil, "getCurrentProjectId").mockReturnValue(PROJECT_ID);
211
+ });
212
+
213
+ afterEach((): void => {
214
+ cleanup();
215
+ jest.restoreAllMocks();
216
+ });
217
+
218
+ describe("resource-scoped event overlay requests", (): void => {
219
+ test("filters every event source by monitor before the newest-50 limit", async (): Promise<void> => {
220
+ const unrelated: Array<TestEvent> = Array.from(
221
+ { length: EVENT_OVERLAY_FETCH_LIMIT + 10 },
222
+ (_value: unknown, index: number): TestEvent => {
223
+ return event(`Unrelated ${index}`, index + 100, MONITOR_B);
224
+ },
225
+ );
226
+ const related: TestEvent = event("Selected monitor is down");
227
+ const unassociated: TestEvent = {
228
+ ...event("Project-wide event", 90),
229
+ monitorId: undefined,
230
+ monitors: [],
231
+ };
232
+ const records: Array<TestEvent> = [
233
+ ...unrelated,
234
+ related,
235
+ unassociated,
236
+ ].sort((first: TestEvent, second: TestEvent): number => {
237
+ return second.createdAt.localeCompare(first.createdAt);
238
+ });
239
+
240
+ /*
241
+ * Behave like the list endpoint: apply the request's filter, then its
242
+ * limit. A project-wide fetch followed by client filtering loses the
243
+ * selected monitor because its record is older than 50 unrelated ones.
244
+ */
245
+ getListMock.mockImplementation((request: EventRequest) => {
246
+ const ids: Array<string> = queryValues(
247
+ request.modelType.name === "Incident"
248
+ ? request.query["monitors"]
249
+ : request.query["monitorId"],
250
+ );
251
+ return Promise.resolve({
252
+ data: records
253
+ .filter((record: TestEvent): boolean => {
254
+ return (
255
+ ids.length === 0 ||
256
+ (request.modelType.name === "Incident"
257
+ ? (record.monitors || []).some((id: string): boolean => {
258
+ return ids.includes(id);
259
+ })
260
+ : ids.includes(record.monitorId || ""))
261
+ );
262
+ })
263
+ .slice(request.skip, request.skip + request.limit),
264
+ });
265
+ });
266
+ analyticsGetListMock.mockImplementation((request: EventRequest) => {
267
+ const attributes: Record<string, unknown> | undefined = request.query[
268
+ "attributes"
269
+ ] as Record<string, unknown> | undefined;
270
+ const ids: Array<string> = queryValues(attributes?.["monitorId"]);
271
+ return Promise.resolve({
272
+ data: records
273
+ .filter((record: TestEvent): boolean => {
274
+ return ids.length === 0 || ids.includes(record.monitorId || "");
275
+ })
276
+ .slice(request.skip, request.skip + request.limit),
277
+ });
278
+ });
279
+
280
+ render(<Probe queryConfigs={[monitorConfig(MONITOR_A)]} />);
281
+
282
+ await expectMarkerCount(3);
283
+ expect(
284
+ screen.getByText("Incident: Selected monitor is down"),
285
+ ).toBeVisible();
286
+ expect(screen.getByText("Alert: Selected monitor is down")).toBeVisible();
287
+ expect(screen.getByText("Deploy: Selected monitor is down")).toBeVisible();
288
+ expect(screen.queryByText(/Unrelated/)).not.toBeInTheDocument();
289
+ expect(screen.queryByText(/Project-wide event/)).not.toBeInTheDocument();
290
+
291
+ for (const modelName of ["Incident", "Alert"]) {
292
+ const request: EventRequest = requestsFor(modelName)[0]!;
293
+ expect(request.query["projectId"]).toEqual(PROJECT_ID);
294
+ expect(request.query["createdAt"]).toEqual(WINDOW);
295
+ expect(request.limit).toBe(EVENT_OVERLAY_FETCH_LIMIT);
296
+ expect(request.skip).toBe(0);
297
+ expect(request.sort).toEqual({ createdAt: SortOrder.Descending });
298
+ expect(
299
+ queryValues(
300
+ request.query[modelName === "Incident" ? "monitors" : "monitorId"],
301
+ ),
302
+ ).toEqual([MONITOR_A]);
303
+ }
304
+ expect(requestsFor("Incident")[0]!.query["monitors"]).toEqual({
305
+ _id: MONITOR_A,
306
+ });
307
+ expect(analyticsGetListMock).toHaveBeenCalledWith(
308
+ expect.objectContaining({
309
+ query: {
310
+ projectId: PROJECT_ID,
311
+ time: WINDOW,
312
+ attributes: { monitorId: MONITOR_A },
313
+ },
314
+ limit: EVENT_OVERLAY_FETCH_LIMIT,
315
+ }),
316
+ );
317
+ });
318
+
319
+ test.each([
320
+ ["serviceLevelObjectiveId", "serviceLevelObjectives"],
321
+ ["hostId", "hosts"],
322
+ ["dockerHostId", "dockerHosts"],
323
+ ["podmanHostId", "podmanHosts"],
324
+ ["kubernetesClusterId", "kubernetesClusters"],
325
+ ["kubernetesResourceId", "kubernetesResources"],
326
+ ["kubernetesContainerId", "kubernetesContainers"],
327
+ ["dockerResourceId", "dockerResources"],
328
+ ["podmanResourceId", "podmanResources"],
329
+ ["proxmoxClusterId", "proxmoxClusters"],
330
+ ["vmwareVCenterId", "vmwareVCenters"],
331
+ ["cephClusterId", "cephClusters"],
332
+ ["dockerSwarmClusterId", "dockerSwarmClusters"],
333
+ ["iotFleetId", "iotFleets"],
334
+ ["serviceId", "services"],
335
+ ])(
336
+ "carries %s into every event source's request",
337
+ async (attribute: string, relation: string): Promise<void> => {
338
+ getListMock.mockResolvedValue({ data: [event("Related resource")] });
339
+ analyticsGetListMock.mockResolvedValue({
340
+ data: [event("Related release")],
341
+ });
342
+
343
+ render(
344
+ <Probe
345
+ queryConfigs={[
346
+ {
347
+ metricQueryData: {
348
+ filterData: {
349
+ metricName: "resource.metric",
350
+ attributes: { [attribute]: MONITOR_A },
351
+ },
352
+ },
353
+ },
354
+ ]}
355
+ />,
356
+ );
357
+
358
+ await expectMarkerCount(3);
359
+ for (const modelName of ["Incident", "Alert"]) {
360
+ expect(requestsFor(modelName)).toHaveLength(1);
361
+ expect(requestsFor(modelName)[0]!.query).toEqual({
362
+ projectId: PROJECT_ID,
363
+ createdAt: WINDOW,
364
+ [relation]: { _id: MONITOR_A },
365
+ });
366
+ }
367
+ expect(analyticsGetListMock).toHaveBeenCalledWith(
368
+ expect.objectContaining({
369
+ query: {
370
+ projectId: PROJECT_ID,
371
+ time: WINDOW,
372
+ ...(attribute === "serviceId"
373
+ ? { primaryEntityId: MONITOR_A }
374
+ : { attributes: { [attribute]: MONITOR_A } }),
375
+ },
376
+ }),
377
+ );
378
+ },
379
+ );
380
+
381
+ test.each(["networkDeviceId", "cloudResourceId", "rumApplicationId"])(
382
+ "does not fetch project-wide incidents or alerts for unlinked %s resources",
383
+ async (attribute: string): Promise<void> => {
384
+ analyticsGetListMock.mockResolvedValue({
385
+ data: [event("Scoped change")],
386
+ });
387
+ render(
388
+ <Probe
389
+ queryConfigs={[
390
+ {
391
+ metricQueryData: {
392
+ filterData: {
393
+ metricName: "resource.metric",
394
+ attributes: { [attribute]: MONITOR_A },
395
+ },
396
+ },
397
+ },
398
+ ]}
399
+ />,
400
+ );
401
+
402
+ await expectMarkerCount(1);
403
+ expect(getListMock).not.toHaveBeenCalled();
404
+ expect(screen.getByText("Deploy: Scoped change")).toBeVisible();
405
+ expect(analyticsGetListMock).toHaveBeenCalledWith(
406
+ expect.objectContaining({
407
+ query: {
408
+ projectId: PROJECT_ID,
409
+ time: WINDOW,
410
+ attributes: { [attribute]: MONITOR_A },
411
+ },
412
+ }),
413
+ );
414
+ },
415
+ );
416
+
417
+ test("retains the project overview when no metric scope is supplied", async (): Promise<void> => {
418
+ getListMock.mockImplementation((request: EventRequest) => {
419
+ return Promise.resolve({ data: [event(request.modelType.name)] });
420
+ });
421
+ analyticsGetListMock.mockResolvedValue({ data: [event("Release")] });
422
+
423
+ render(<Probe />);
424
+
425
+ await expectMarkerCount(3);
426
+ for (const request of [
427
+ ...requestsFor("Incident"),
428
+ ...requestsFor("Alert"),
429
+ ]) {
430
+ expect(request.query).toEqual({
431
+ projectId: PROJECT_ID,
432
+ createdAt: WINDOW,
433
+ });
434
+ }
435
+ expect(analyticsGetListMock).toHaveBeenCalledWith(
436
+ expect.objectContaining({
437
+ query: { projectId: PROJECT_ID, time: WINDOW },
438
+ }),
439
+ );
440
+ });
441
+
442
+ test("fetches duplicate chart scopes only once and ignores presentation changes", async (): Promise<void> => {
443
+ getListMock.mockImplementation((request: EventRequest) => {
444
+ return Promise.resolve({ data: [event(request.modelType.name)] });
445
+ });
446
+ const { rerender } = render(
447
+ <Probe
448
+ queryConfigs={[monitorConfig(MONITOR_A), monitorConfig(MONITOR_A)]}
449
+ />,
450
+ );
451
+ await expectMarkerCount(2);
452
+ expect(requestsFor("Incident")).toHaveLength(1);
453
+ expect(requestsFor("Alert")).toHaveLength(1);
454
+ const analyticsCalls: number = analyticsGetListMock.mock.calls.length;
455
+
456
+ rerender(
457
+ <Probe
458
+ queryConfigs={[
459
+ {
460
+ ...monitorConfig(MONITOR_A),
461
+ id: "new-chart-identity",
462
+ color: "#123456",
463
+ warningThreshold: 100,
464
+ metricAliasData: {
465
+ metricVariable: "a",
466
+ title: "Renamed chart",
467
+ description: "",
468
+ legend: "",
469
+ legendUnit: "",
470
+ },
471
+ },
472
+ ]}
473
+ window={
474
+ new InBetween<Date>(
475
+ new Date(WINDOW.startValue!),
476
+ new Date(WINDOW.endValue!),
477
+ )
478
+ }
479
+ />,
480
+ );
481
+ await act(async (): Promise<void> => {
482
+ await Promise.resolve();
483
+ });
484
+
485
+ expect(requestsFor("Incident")).toHaveLength(1);
486
+ expect(requestsFor("Alert")).toHaveLength(1);
487
+ expect(analyticsGetListMock.mock.calls.length).toBe(analyticsCalls);
488
+ expect(screen.getByTestId("marker-count").textContent).toBe("2");
489
+ });
490
+
491
+ test.each(["Incident", "Alert", "ChangeEvent"])(
492
+ "deduplicates overlapping %s results and keeps the newest 50",
493
+ async (source: string): Promise<void> => {
494
+ const shared: TestEvent = event("Shared event", 1000);
495
+ const fetch: (
496
+ request: EventRequest,
497
+ ) => Promise<{ data: Array<TestEvent> }> = (request: EventRequest) => {
498
+ if (request.modelType.name !== source) {
499
+ return Promise.resolve({ data: [] });
500
+ }
501
+ const monitorQuery: unknown =
502
+ source === "ChangeEvent"
503
+ ? (request.query["attributes"] as Record<string, unknown>)[
504
+ "monitorId"
505
+ ]
506
+ : request.query[source === "Incident" ? "monitors" : "monitorId"];
507
+ const isMonitorA: boolean =
508
+ queryValues(monitorQuery).includes(MONITOR_A);
509
+ return Promise.resolve({
510
+ data: [
511
+ shared,
512
+ ...Array.from(
513
+ { length: EVENT_OVERLAY_FETCH_LIMIT - 1 },
514
+ (_value: unknown, index: number): TestEvent => {
515
+ const number: number = index + (isMonitorA ? 1 : 101);
516
+ return event(`Event ${number}`, number);
517
+ },
518
+ ),
519
+ ],
520
+ });
521
+ };
522
+ getListMock.mockImplementation(fetch);
523
+ analyticsGetListMock.mockImplementation(fetch);
524
+
525
+ render(
526
+ <Probe
527
+ queryConfigs={[monitorConfig(MONITOR_A), monitorConfig(MONITOR_B)]}
528
+ />,
529
+ );
530
+
531
+ await expectMarkerCount(EVENT_OVERLAY_FETCH_LIMIT);
532
+ const label: string = source === "ChangeEvent" ? "Deploy" : source;
533
+ expect(screen.getAllByText(`${label}: Shared event`)).toHaveLength(1);
534
+ expect(screen.getByText(`${label}: Event 149`)).toBeVisible();
535
+ expect(screen.queryByText(`${label}: Event 1`)).not.toBeInTheDocument();
536
+ const requests: Array<EventRequest> =
537
+ source === "ChangeEvent"
538
+ ? analyticsGetListMock.mock.calls.map(
539
+ (call: Array<unknown>): EventRequest => {
540
+ return call[0] as EventRequest;
541
+ },
542
+ )
543
+ : requestsFor(source);
544
+ expect(requests).toHaveLength(2);
545
+ for (const request of requests) {
546
+ expect(request.limit).toBe(EVENT_OVERLAY_FETCH_LIMIT);
547
+ }
548
+ },
549
+ );
550
+
551
+ test("changing the order of chart scopes does not issue new requests", async (): Promise<void> => {
552
+ getListMock.mockImplementation((request: EventRequest) => {
553
+ return Promise.resolve({ data: [event(request.modelType.name)] });
554
+ });
555
+ const { rerender } = render(
556
+ <Probe
557
+ queryConfigs={[monitorConfig(MONITOR_A), monitorConfig(MONITOR_B)]}
558
+ />,
559
+ );
560
+ await expectMarkerCount(2);
561
+ const calls: number = getListMock.mock.calls.length;
562
+ const analyticsCalls: number = analyticsGetListMock.mock.calls.length;
563
+
564
+ rerender(
565
+ <Probe
566
+ queryConfigs={[monitorConfig(MONITOR_B), monitorConfig(MONITOR_A)]}
567
+ />,
568
+ );
569
+ await act(async (): Promise<void> => {
570
+ await Promise.resolve();
571
+ });
572
+
573
+ expect(getListMock.mock.calls.length).toBe(calls);
574
+ expect(analyticsGetListMock.mock.calls.length).toBe(analyticsCalls);
575
+ });
576
+ });
577
+
578
+ describe("resource-scoped event overlay lifecycle", (): void => {
579
+ test("an invalid resource scope clears previous markers and never falls back to the project", async (): Promise<void> => {
580
+ getListMock.mockResolvedValue({ data: [event("Valid monitor")] });
581
+ const { rerender } = render(
582
+ <Probe queryConfigs={[monitorConfig(MONITOR_A)]} />,
583
+ );
584
+ await expectMarkerCount(2);
585
+ const calls: number = getListMock.mock.calls.length;
586
+ const analyticsCalls: number = analyticsGetListMock.mock.calls.length;
587
+
588
+ rerender(<Probe queryConfigs={[monitorConfig("invalid-monitor-id")]} />);
589
+
590
+ expect(screen.getByTestId("marker-count").textContent).toBe("0");
591
+ await act(async (): Promise<void> => {
592
+ await Promise.resolve();
593
+ });
594
+ expect(getListMock.mock.calls.length).toBe(calls);
595
+ expect(analyticsGetListMock.mock.calls.length).toBe(analyticsCalls);
596
+ });
597
+
598
+ test("clears the previous resource while its replacement request is loading", async (): Promise<void> => {
599
+ const next: DeferredEvents = deferredEvents();
600
+ getListMock.mockImplementation((request: EventRequest) => {
601
+ if (request.modelType.name !== "Incident") {
602
+ return Promise.resolve({ data: [] });
603
+ }
604
+ return queryValues(request.query["monitors"]).includes(MONITOR_A)
605
+ ? Promise.resolve({ data: [event("Monitor A")] })
606
+ : next.promise;
607
+ });
608
+ const { rerender } = render(
609
+ <Probe queryConfigs={[monitorConfig(MONITOR_A)]} />,
610
+ );
611
+ await expectMarkerCount(1);
612
+
613
+ rerender(<Probe queryConfigs={[monitorConfig(MONITOR_B)]} />);
614
+
615
+ expect(screen.getByTestId("marker-count").textContent).toBe("0");
616
+ expect(screen.queryByText("Incident: Monitor A")).not.toBeInTheDocument();
617
+ await act(async (): Promise<void> => {
618
+ next.resolve([event("Monitor B", 2, MONITOR_B)]);
619
+ await next.promise;
620
+ });
621
+ await expectMarkerCount(1);
622
+ expect(screen.getByText("Incident: Monitor B")).toBeVisible();
623
+ });
624
+
625
+ test("an older resource response cannot overwrite the current resource", async (): Promise<void> => {
626
+ const first: DeferredEvents = deferredEvents();
627
+ const second: DeferredEvents = deferredEvents();
628
+ getListMock.mockImplementation((request: EventRequest) => {
629
+ if (request.modelType.name !== "Incident") {
630
+ return Promise.resolve({ data: [] });
631
+ }
632
+ return queryValues(request.query["monitors"]).includes(MONITOR_A)
633
+ ? first.promise
634
+ : second.promise;
635
+ });
636
+ const { rerender } = render(
637
+ <Probe queryConfigs={[monitorConfig(MONITOR_A)]} />,
638
+ );
639
+ rerender(<Probe queryConfigs={[monitorConfig(MONITOR_B)]} />);
640
+
641
+ await act(async (): Promise<void> => {
642
+ second.resolve([event("Current monitor", 2, MONITOR_B)]);
643
+ await second.promise;
644
+ });
645
+ await expectMarkerCount(1);
646
+ await act(async (): Promise<void> => {
647
+ first.resolve([event("Stale monitor")]);
648
+ await first.promise;
649
+ });
650
+
651
+ expect(screen.getByText("Incident: Current monitor")).toBeVisible();
652
+ expect(
653
+ screen.queryByText("Incident: Stale monitor"),
654
+ ).not.toBeInTheDocument();
655
+ expect(screen.getByTestId("marker-count").textContent).toBe("1");
656
+ });
657
+
658
+ test("switching project refetches and immediately removes the old project markers", async (): Promise<void> => {
659
+ const nextProject: DeferredEvents = deferredEvents();
660
+ getListMock.mockImplementation((request: EventRequest) => {
661
+ if (request.modelType.name !== "Incident") {
662
+ return Promise.resolve({ data: [] });
663
+ }
664
+ return String(request.query["projectId"]) === PROJECT_ID.toString()
665
+ ? Promise.resolve({ data: [event("Old project")] })
666
+ : nextProject.promise;
667
+ });
668
+ const { rerender } = render(
669
+ <Probe queryConfigs={[monitorConfig(MONITOR_A)]} />,
670
+ );
671
+ await expectMarkerCount(1);
672
+
673
+ jest
674
+ .spyOn(ProjectUtil, "getCurrentProjectId")
675
+ .mockReturnValue(OTHER_PROJECT_ID);
676
+ rerender(<Probe queryConfigs={[monitorConfig(MONITOR_A)]} />);
677
+
678
+ expect(screen.getByTestId("marker-count").textContent).toBe("0");
679
+ expect(requestsFor("Incident")).toHaveLength(2);
680
+ expect(requestsFor("Incident")[1]!.query["projectId"]).toEqual(
681
+ OTHER_PROJECT_ID,
682
+ );
683
+ await act(async (): Promise<void> => {
684
+ nextProject.resolve([event("New project")]);
685
+ await nextProject.promise;
686
+ });
687
+ await expectMarkerCount(1);
688
+ expect(screen.getByText("Incident: New project")).toBeVisible();
689
+ expect(screen.queryByText("Incident: Old project")).not.toBeInTheDocument();
690
+ });
691
+
692
+ test("an equivalent project ID object does not trigger another fetch", async (): Promise<void> => {
693
+ getListMock.mockImplementation((request: EventRequest) => {
694
+ return Promise.resolve({ data: [event(request.modelType.name)] });
695
+ });
696
+ const { rerender } = render(
697
+ <Probe queryConfigs={[monitorConfig(MONITOR_A)]} />,
698
+ );
699
+ await expectMarkerCount(2);
700
+ jest
701
+ .spyOn(ProjectUtil, "getCurrentProjectId")
702
+ .mockReturnValue(new ObjectID(PROJECT_ID.toString()));
703
+
704
+ rerender(<Probe queryConfigs={[monitorConfig(MONITOR_A)]} />);
705
+ await act(async (): Promise<void> => {
706
+ await Promise.resolve();
707
+ });
708
+
709
+ expect(requestsFor("Incident")).toHaveLength(1);
710
+ expect(requestsFor("Alert")).toHaveLength(1);
711
+ });
712
+
713
+ test("refresh refetches the same scope and ignores an earlier unfinished refresh", async (): Promise<void> => {
714
+ const earlierRefresh: DeferredEvents = deferredEvents();
715
+ const latestRefresh: DeferredEvents = deferredEvents();
716
+ let incidentCalls: number = 0;
717
+ getListMock.mockImplementation((request: EventRequest) => {
718
+ if (request.modelType.name !== "Incident") {
719
+ return Promise.resolve({ data: [] });
720
+ }
721
+ incidentCalls++;
722
+ if (incidentCalls === 1) {
723
+ return Promise.resolve({ data: [event("Initial result")] });
724
+ }
725
+ return incidentCalls === 2
726
+ ? earlierRefresh.promise
727
+ : latestRefresh.promise;
728
+ });
729
+ const { rerender } = render(
730
+ <Probe queryConfigs={[monitorConfig(MONITOR_A)]} refreshTick={0} />,
731
+ );
732
+ await expectMarkerCount(1);
733
+
734
+ rerender(
735
+ <Probe queryConfigs={[monitorConfig(MONITOR_A)]} refreshTick={1} />,
736
+ );
737
+ rerender(
738
+ <Probe queryConfigs={[monitorConfig(MONITOR_A)]} refreshTick={2} />,
739
+ );
740
+ expect(incidentCalls).toBe(3);
741
+ await act(async (): Promise<void> => {
742
+ latestRefresh.resolve([event("Latest refresh")]);
743
+ await latestRefresh.promise;
744
+ });
745
+ await expectMarkerCount(1);
746
+ await act(async (): Promise<void> => {
747
+ earlierRefresh.resolve([event("Earlier refresh")]);
748
+ await earlierRefresh.promise;
749
+ });
750
+
751
+ expect(screen.getByText("Incident: Latest refresh")).toBeVisible();
752
+ expect(
753
+ screen.queryByText("Incident: Earlier refresh"),
754
+ ).not.toBeInTheDocument();
755
+ });
756
+
757
+ test("a different time window hides old markers and constrains every new request", async (): Promise<void> => {
758
+ getListMock.mockImplementation((request: EventRequest) => {
759
+ return Promise.resolve({ data: [event(request.modelType.name)] });
760
+ });
761
+ const { rerender } = render(<Probe />);
762
+ await expectMarkerCount(2);
763
+ const next: DeferredEvents = deferredEvents();
764
+ getListMock.mockReturnValue(next.promise);
765
+ analyticsGetListMock.mockReturnValue(next.promise);
766
+ const nextWindow: InBetween<Date> = new InBetween<Date>(
767
+ new Date("2026-08-21T10:00:00.000Z"),
768
+ new Date("2026-08-21T11:00:00.000Z"),
769
+ );
770
+
771
+ rerender(<Probe window={nextWindow} />);
772
+
773
+ expect(screen.getByTestId("marker-count").textContent).toBe("0");
774
+ expect(requestsFor("Incident")[1]!.query["createdAt"]).toEqual(nextWindow);
775
+ expect(requestsFor("Alert")[1]!.query["createdAt"]).toEqual(nextWindow);
776
+ expect(analyticsGetListMock.mock.calls[1]![0].query["time"]).toEqual(
777
+ nextWindow,
778
+ );
779
+ await act(async (): Promise<void> => {
780
+ next.resolve([]);
781
+ await next.promise;
782
+ });
783
+ });
784
+
785
+ test.each(["disabled", "public", "windowless", "projectless"])(
786
+ "%s charts do not fetch scoped event data",
787
+ async (state: string): Promise<void> => {
788
+ if (state === "public") {
789
+ isPublicDashboardMock.mockReturnValue(true);
790
+ }
791
+ if (state === "projectless") {
792
+ jest.spyOn(ProjectUtil, "getCurrentProjectId").mockReturnValue(null);
793
+ }
794
+ render(
795
+ <Probe
796
+ queryConfigs={[monitorConfig(MONITOR_A)]}
797
+ enabled={state !== "disabled"}
798
+ window={state === "windowless" ? null : WINDOW}
799
+ />,
800
+ );
801
+ await act(async (): Promise<void> => {
802
+ await Promise.resolve();
803
+ });
804
+
805
+ expect(getListMock).not.toHaveBeenCalled();
806
+ expect(analyticsGetListMock).not.toHaveBeenCalled();
807
+ expect(screen.getByTestId("marker-count").textContent).toBe("0");
808
+ },
809
+ );
810
+
811
+ test.each(["disabled", "public", "windowless", "projectless"])(
812
+ "entering the %s state removes existing markers without another request",
813
+ async (state: string): Promise<void> => {
814
+ getListMock.mockImplementation((request: EventRequest) => {
815
+ return Promise.resolve({ data: [event(request.modelType.name)] });
816
+ });
817
+ const { rerender } = render(
818
+ <Probe queryConfigs={[monitorConfig(MONITOR_A)]} />,
819
+ );
820
+ await expectMarkerCount(2);
821
+ const calls: number = getListMock.mock.calls.length;
822
+ const analyticsCalls: number = analyticsGetListMock.mock.calls.length;
823
+ if (state === "public") {
824
+ isPublicDashboardMock.mockReturnValue(true);
825
+ }
826
+ if (state === "projectless") {
827
+ jest.spyOn(ProjectUtil, "getCurrentProjectId").mockReturnValue(null);
828
+ }
829
+
830
+ rerender(
831
+ <Probe
832
+ queryConfigs={[monitorConfig(MONITOR_A)]}
833
+ enabled={state !== "disabled"}
834
+ window={state === "windowless" ? null : WINDOW}
835
+ />,
836
+ );
837
+
838
+ expect(screen.getByTestId("marker-count").textContent).toBe("0");
839
+ expect(getListMock.mock.calls.length).toBe(calls);
840
+ expect(analyticsGetListMock.mock.calls.length).toBe(analyticsCalls);
841
+ },
842
+ );
843
+
844
+ test("a request that resolves after disabling cannot reappear on re-enabling", async (): Promise<void> => {
845
+ const old: DeferredEvents = deferredEvents();
846
+ const current: DeferredEvents = deferredEvents();
847
+ let incidentCalls: number = 0;
848
+ getListMock.mockImplementation((request: EventRequest) => {
849
+ if (request.modelType.name !== "Incident") {
850
+ return Promise.resolve({ data: [] });
851
+ }
852
+ incidentCalls++;
853
+ return incidentCalls === 1 ? old.promise : current.promise;
854
+ });
855
+ const { rerender } = render(
856
+ <Probe queryConfigs={[monitorConfig(MONITOR_A)]} />,
857
+ );
858
+ rerender(
859
+ <Probe queryConfigs={[monitorConfig(MONITOR_A)]} enabled={false} />,
860
+ );
861
+ await act(async (): Promise<void> => {
862
+ old.resolve([event("Cancelled result")]);
863
+ await old.promise;
864
+ });
865
+ rerender(<Probe queryConfigs={[monitorConfig(MONITOR_A)]} />);
866
+
867
+ expect(screen.getByTestId("marker-count").textContent).toBe("0");
868
+ await act(async (): Promise<void> => {
869
+ current.resolve([event("Fresh result")]);
870
+ await current.promise;
871
+ });
872
+ await expectMarkerCount(1);
873
+ expect(screen.getByText("Incident: Fresh result")).toBeVisible();
874
+ expect(
875
+ screen.queryByText("Incident: Cancelled result"),
876
+ ).not.toBeInTheDocument();
877
+ });
878
+
879
+ test("an individual scope failure preserves another scope's incidents and alerts", async (): Promise<void> => {
880
+ getListMock.mockImplementation((request: EventRequest) => {
881
+ const monitorIds: Array<string> = queryValues(
882
+ request.query[
883
+ request.modelType.name === "Incident" ? "monitors" : "monitorId"
884
+ ],
885
+ );
886
+ if (monitorIds.includes(MONITOR_A)) {
887
+ return Promise.reject(
888
+ new Error("First monitor is temporarily unavailable"),
889
+ );
890
+ }
891
+ return Promise.resolve({ data: [event("Other monitor", 2, MONITOR_B)] });
892
+ });
893
+ render(
894
+ <Probe
895
+ queryConfigs={[monitorConfig(MONITOR_A), monitorConfig(MONITOR_B)]}
896
+ />,
897
+ );
898
+
899
+ await expectMarkerCount(2);
900
+ expect(screen.getByText("Incident: Other monitor")).toBeVisible();
901
+ expect(screen.getByText("Alert: Other monitor")).toBeVisible();
902
+ });
903
+ });