@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,761 @@
1
+ import {
2
+ afterEach,
3
+ beforeEach,
4
+ describe,
5
+ expect,
6
+ jest,
7
+ test,
8
+ } from "@jest/globals";
9
+ import "@testing-library/jest-dom";
10
+ import {
11
+ act,
12
+ cleanup,
13
+ fireEvent,
14
+ render,
15
+ screen,
16
+ } from "@testing-library/react";
17
+ import React from "react";
18
+ import InvestigationPanel, {
19
+ InvestigationSubjectType,
20
+ } from "../../../../App/FeatureSet/Dashboard/src/Components/AI/InvestigationPanel";
21
+ import { AI_INVESTIGATION_PANEL_ID } from "../../../../App/FeatureSet/Dashboard/src/Components/AI/AIInvestigationStatus";
22
+ import HTTPErrorResponse from "../../../Types/API/HTTPErrorResponse";
23
+ import HTTPResponse from "../../../Types/API/HTTPResponse";
24
+ import AIRunStatus from "../../../Types/AI/AIRunStatus";
25
+ import InvestigationNotStartedReason, {
26
+ InvestigationNotStartedCode,
27
+ } from "../../../Types/AI/InvestigationNotStartedReason";
28
+ import { JSONObject } from "../../../Types/JSON";
29
+ import ObjectID from "../../../Types/ObjectID";
30
+ import Permission from "../../../Types/Permission";
31
+ import PermissionUtil from "../../../UI/Utils/Permission";
32
+ import ProjectUtil from "../../../UI/Utils/Project";
33
+ import getJestMockFunction, { MockFunction } from "../../MockType";
34
+
35
+ const postMock: MockFunction = getJestMockFunction();
36
+
37
+ jest.mock("../../../UI/Utils/API/API", () => {
38
+ return {
39
+ __esModule: true,
40
+ default: {
41
+ post: (...args: Array<unknown>): unknown => {
42
+ return postMock(...args);
43
+ },
44
+ getFriendlyMessage: (): string => {
45
+ return "Request failed";
46
+ },
47
+ },
48
+ };
49
+ });
50
+
51
+ jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
52
+ return {
53
+ __esModule: true,
54
+ default: {
55
+ getCommonHeaders: (): JSONObject => {
56
+ return { tenantid: "33333333-3333-4333-8333-333333333333" };
57
+ },
58
+ },
59
+ };
60
+ });
61
+
62
+ const SUBJECT_ID: ObjectID = new ObjectID(
63
+ "11111111-1111-4111-8111-111111111111",
64
+ );
65
+ const NEXT_SUBJECT_ID: ObjectID = new ObjectID(
66
+ "22222222-2222-4222-8222-222222222222",
67
+ );
68
+ const PROJECT_ID: ObjectID = new ObjectID(
69
+ "33333333-3333-4333-8333-333333333333",
70
+ );
71
+ const EVALUATED_AT: string = "2026-09-17T12:24:00.000Z";
72
+ const NEXT_EVALUATED_AT: string = "2026-09-17T12:25:00.000Z";
73
+
74
+ interface ReasonExample {
75
+ code: InvestigationNotStartedCode;
76
+ title: string;
77
+ description: string;
78
+ nextStep: string;
79
+ }
80
+
81
+ const REASONS: Array<ReasonExample> = [
82
+ {
83
+ code: "ai_disabled",
84
+ title: "AI is disabled for this project",
85
+ description: "The project AI switch is off.",
86
+ nextStep: "A project owner can enable AI for future events.",
87
+ },
88
+ {
89
+ code: "automatic_investigation_disabled",
90
+ title: "Automatic investigation is turned off",
91
+ description:
92
+ "The automatic investigation switch is off for this event type.",
93
+ nextStep: "Enable automatic investigation for future events.",
94
+ },
95
+ {
96
+ code: "provider_missing",
97
+ title: "No AI provider is configured",
98
+ description: "No project or global model provider was available.",
99
+ nextStep: "Configure a model provider for future investigations.",
100
+ },
101
+ {
102
+ code: "severity_below_threshold",
103
+ title: "Severity is below the investigation threshold",
104
+ description: "Low severity does not meet the configured High minimum.",
105
+ nextStep: "Review the minimum severity in investigation settings.",
106
+ },
107
+ {
108
+ code: "monitor_cooldown",
109
+ title: "This monitor was recently investigated",
110
+ description:
111
+ "A previous investigation was started inside the 30 minute cooldown.",
112
+ nextStep: "Review the previous investigation for this monitor.",
113
+ },
114
+ {
115
+ code: "daily_budget_exhausted",
116
+ title: "The daily AI token limit was reached",
117
+ description: "The daily token budget for this event type was exhausted.",
118
+ nextStep: "Review the budget for future investigations.",
119
+ },
120
+ {
121
+ code: "budget_check_failed",
122
+ title: "The AI budget could not be checked",
123
+ description: "The usage service could not confirm available budget.",
124
+ nextStep: "Check the service logs to resolve the budget lookup failure.",
125
+ },
126
+ {
127
+ code: "enqueue_failed",
128
+ title: "The investigation could not be queued",
129
+ description: "A service error prevented the investigation from starting.",
130
+ nextStep: "Check the service logs for a queue error.",
131
+ },
132
+ {
133
+ code: "eligibility_check_failed",
134
+ title: "Investigation eligibility could not be checked",
135
+ description:
136
+ "The service could not evaluate automatic investigation settings.",
137
+ nextStep: "Check the service logs for the eligibility lookup failure.",
138
+ },
139
+ {
140
+ code: "no_run_recorded",
141
+ title: "No investigation decision was recorded",
142
+ description:
143
+ "Current settings allow investigation, but the original reason is unknown.",
144
+ nextStep:
145
+ "Review AI logs; enabling AI does not investigate older events automatically.",
146
+ },
147
+ ];
148
+
149
+ function reasonFor(
150
+ code: InvestigationNotStartedCode = "monitor_cooldown",
151
+ overrides: Partial<InvestigationNotStartedReason> = {},
152
+ ): InvestigationNotStartedReason {
153
+ const example: ReasonExample = REASONS.find(
154
+ (item: ReasonExample): boolean => {
155
+ return item.code === code;
156
+ },
157
+ )!;
158
+ return {
159
+ ...example,
160
+ source: "recorded",
161
+ evaluatedAt: EVALUATED_AT,
162
+ ...overrides,
163
+ };
164
+ }
165
+
166
+ function noRunResponse(
167
+ reason: InvestigationNotStartedReason | null = reasonFor(),
168
+ ): HTTPResponse<JSONObject> {
169
+ return new HTTPResponse<JSONObject>(
170
+ 200,
171
+ {
172
+ run: null,
173
+ events: [],
174
+ notInvestigatedReason: reason as unknown as JSONObject | null,
175
+ },
176
+ {},
177
+ );
178
+ }
179
+
180
+ function runResponse(status: AIRunStatus): HTTPResponse<JSONObject> {
181
+ return new HTTPResponse<JSONObject>(
182
+ 200,
183
+ {
184
+ run: {
185
+ _id: "44444444-4444-4444-8444-444444444444",
186
+ status,
187
+ toolCallCount: 0,
188
+ totalTokens: 0,
189
+ },
190
+ events: [],
191
+ // A run always wins, even when a stale reason is returned with it.
192
+ notInvestigatedReason: reasonFor() as unknown as JSONObject,
193
+ },
194
+ {},
195
+ );
196
+ }
197
+
198
+ async function flush(): Promise<void> {
199
+ await act(async (): Promise<void> => {
200
+ await Promise.resolve();
201
+ await Promise.resolve();
202
+ await Promise.resolve();
203
+ await Promise.resolve();
204
+ });
205
+ }
206
+
207
+ async function advance(milliseconds: number = 2500): Promise<void> {
208
+ await act(async (): Promise<void> => {
209
+ jest.advanceTimersByTime(milliseconds);
210
+ await Promise.resolve();
211
+ await Promise.resolve();
212
+ await Promise.resolve();
213
+ await Promise.resolve();
214
+ });
215
+ }
216
+
217
+ function renderPanel(
218
+ subjectType: InvestigationSubjectType = "alert",
219
+ ): ReturnType<typeof render> {
220
+ return render(
221
+ <InvestigationPanel subjectType={subjectType} subjectId={SUBJECT_ID} />,
222
+ );
223
+ }
224
+
225
+ beforeEach(() => {
226
+ jest.useFakeTimers();
227
+ jest.setSystemTime(new Date(EVALUATED_AT));
228
+ postMock.mockReset();
229
+ jest
230
+ .spyOn(PermissionUtil, "getAllPermissions")
231
+ .mockReturnValue([Permission.ProjectOwner]);
232
+ jest.spyOn(ProjectUtil, "getCurrentProjectId").mockReturnValue(PROJECT_ID);
233
+ });
234
+
235
+ afterEach(() => {
236
+ cleanup();
237
+ jest.restoreAllMocks();
238
+ jest.clearAllTimers();
239
+ jest.useRealTimers();
240
+ });
241
+
242
+ describe.each<[InvestigationSubjectType]>([["alert"], ["incident"]])(
243
+ "%s investigation explanation",
244
+ (subjectType: InvestigationSubjectType) => {
245
+ test.each(REASONS)(
246
+ "shows the server's $code decision and next step",
247
+ async (example: ReasonExample) => {
248
+ postMock.mockResolvedValue(noRunResponse(reasonFor(example.code)));
249
+
250
+ renderPanel(subjectType);
251
+ await flush();
252
+
253
+ const panel: HTMLElement = screen.getByRole("region", {
254
+ name: "AI Investigation",
255
+ });
256
+ expect(panel).toHaveAttribute("id", AI_INVESTIGATION_PANEL_ID);
257
+ expect(panel).toHaveAttribute("tabindex", "-1");
258
+ expect(panel).toHaveAttribute("aria-busy", "false");
259
+ expect(screen.getByLabelText("Investigation status")).toHaveTextContent(
260
+ "Not investigated",
261
+ );
262
+ expect(
263
+ screen.getByRole("heading", { name: example.title }),
264
+ ).toBeVisible();
265
+ expect(screen.getByText(example.description)).toBeVisible();
266
+ expect(screen.getByText(example.nextStep)).toBeVisible();
267
+ expect(screen.getByText("Decision recorded at creation")).toBeVisible();
268
+ expect(panel.querySelector("time")).toHaveAttribute(
269
+ "datetime",
270
+ EVALUATED_AT,
271
+ );
272
+ expect(screen.queryByText("Investigation complete")).toBeNull();
273
+
274
+ const request: {
275
+ url: { toString: () => string };
276
+ data: JSONObject;
277
+ headers: JSONObject;
278
+ } = postMock.mock.calls[0]![0] as {
279
+ url: { toString: () => string };
280
+ data: JSONObject;
281
+ headers: JSONObject;
282
+ };
283
+ expect(request.url.toString()).toContain(
284
+ `/ai-investigation/${subjectType}`,
285
+ );
286
+ expect(request.data).toEqual({
287
+ [`${subjectType}Id`]: SUBJECT_ID.toString(),
288
+ });
289
+ expect(request.headers).toEqual({ tenantid: PROJECT_ID.toString() });
290
+ },
291
+ );
292
+
293
+ test("links investigation limits to this subject's AI settings", async () => {
294
+ postMock.mockResolvedValue(
295
+ noRunResponse(reasonFor("daily_budget_exhausted")),
296
+ );
297
+ renderPanel(subjectType);
298
+ await flush();
299
+
300
+ expect(
301
+ screen.getByRole("link", { name: `Review ${subjectType} AI settings` }),
302
+ ).toHaveAttribute(
303
+ "href",
304
+ expect.stringContaining(
305
+ `/${PROJECT_ID.toString()}/${subjectType}s/settings/ai`,
306
+ ),
307
+ );
308
+ });
309
+
310
+ test("replaces an explanation when an investigation is queued later", async () => {
311
+ postMock
312
+ .mockResolvedValueOnce(
313
+ noRunResponse(reasonFor("no_run_recorded", { source: "unknown" })),
314
+ )
315
+ .mockResolvedValue(runResponse(AIRunStatus.Queued));
316
+ renderPanel(subjectType);
317
+ await flush();
318
+ expect(screen.getByText("No recorded decision")).toBeVisible();
319
+
320
+ await advance();
321
+
322
+ expect(screen.getByText("Queued — waiting for a worker…")).toBeVisible();
323
+ expect(screen.queryByText("Not investigated")).toBeNull();
324
+ expect(
325
+ screen.queryByText("No investigation decision was recorded"),
326
+ ).toBeNull();
327
+ expect(
328
+ screen.queryByText("This monitor was recently investigated"),
329
+ ).toBeNull();
330
+ expect(
331
+ screen.getAllByRole("region", { name: "AI Investigation" }),
332
+ ).toHaveLength(1);
333
+ });
334
+ },
335
+ );
336
+
337
+ describe("investigation reason freshness and uncertainty", () => {
338
+ test("renders a recorded decision without invalid HTML nesting", async () => {
339
+ const consoleError: ReturnType<typeof jest.spyOn> = jest.spyOn(
340
+ console,
341
+ "error",
342
+ );
343
+ postMock.mockResolvedValue(noRunResponse());
344
+ renderPanel();
345
+ await flush();
346
+
347
+ expect(screen.getByText("Decision recorded at creation")).toBeVisible();
348
+ expect(
349
+ consoleError.mock.calls.some((args: Array<unknown>): boolean => {
350
+ return args.some((value: unknown): boolean => {
351
+ return (
352
+ typeof value === "string" && value.includes("validateDOMNesting")
353
+ );
354
+ });
355
+ }),
356
+ ).toBe(false);
357
+ });
358
+
359
+ test("shows a distinct loading state without guessing a skip reason", async () => {
360
+ postMock.mockReturnValue(new Promise<never>(() => {}));
361
+ renderPanel();
362
+
363
+ expect(
364
+ screen.getByRole("region", { name: "AI Investigation" }),
365
+ ).toHaveAttribute("aria-busy", "true");
366
+ expect(screen.getByText("Checking investigation status…")).toBeVisible();
367
+ expect(screen.queryByText("Not investigated")).toBeNull();
368
+ expect(screen.queryByText("No investigation has been recorded")).toBeNull();
369
+ expect(screen.queryByRole("link")).toBeNull();
370
+ });
371
+
372
+ test("labels current settings as current and never as the creation decision", async () => {
373
+ postMock.mockResolvedValue(
374
+ noRunResponse(
375
+ reasonFor("automatic_investigation_disabled", {
376
+ source: "current_configuration",
377
+ }),
378
+ ),
379
+ );
380
+ renderPanel();
381
+ await flush();
382
+
383
+ expect(screen.getByText("Based on current settings")).toBeVisible();
384
+ expect(
385
+ screen.getByText(
386
+ /Settings may have changed since this alert was created/,
387
+ ),
388
+ ).toBeVisible();
389
+ expect(screen.queryByText("Decision recorded at creation")).toBeNull();
390
+ });
391
+
392
+ test("keeps unknown historical reasons honest when settings allow investigation now", async () => {
393
+ postMock.mockResolvedValue(
394
+ noRunResponse(reasonFor("no_run_recorded", { source: "unknown" })),
395
+ );
396
+ renderPanel();
397
+ await flush();
398
+
399
+ expect(screen.getByText("No recorded decision")).toBeVisible();
400
+ expect(
401
+ screen.getByText(
402
+ /Current settings allow investigation, but the original reason is unknown/,
403
+ ),
404
+ ).toBeVisible();
405
+ expect(screen.queryByText("AI is disabled for this project")).toBeNull();
406
+ });
407
+
408
+ test("a legacy no-run payload shows a useful fallback without inventing a blocker", async () => {
409
+ postMock.mockResolvedValue(
410
+ new HTTPResponse<JSONObject>(200, { run: null, events: [] }, {}),
411
+ );
412
+ renderPanel();
413
+ await flush();
414
+
415
+ expect(
416
+ screen.getByText("No investigation has been recorded"),
417
+ ).toBeVisible();
418
+ expect(
419
+ screen.getByText(/no recorded explanation is available/),
420
+ ).toBeVisible();
421
+ expect(
422
+ screen.getByText(/does not automatically investigate older ones/),
423
+ ).toBeVisible();
424
+ expect(screen.queryByText("Decision recorded at creation")).toBeNull();
425
+ expect(screen.queryByText("AI is disabled for this project")).toBeNull();
426
+ });
427
+
428
+ test.each([
429
+ null,
430
+ "ai_disabled",
431
+ { code: "ai_disabled" },
432
+ { ...reasonFor(), code: "future_reason" },
433
+ { ...reasonFor(), title: " " },
434
+ { ...reasonFor(), nextStep: 3 },
435
+ { ...reasonFor(), source: "guessed" },
436
+ { ...reasonFor(), evaluatedAt: "not a date" },
437
+ ])(
438
+ "safely falls back when explanation data is malformed: %j",
439
+ async (reason: unknown) => {
440
+ postMock.mockResolvedValue(
441
+ new HTTPResponse<JSONObject>(
442
+ 200,
443
+ {
444
+ run: null,
445
+ events: [],
446
+ notInvestigatedReason: reason as JSONObject,
447
+ },
448
+ {},
449
+ ),
450
+ );
451
+ renderPanel();
452
+ await flush();
453
+
454
+ expect(
455
+ screen.getByText("No investigation has been recorded"),
456
+ ).toBeVisible();
457
+ expect(screen.queryByText("Decision recorded at creation")).toBeNull();
458
+ },
459
+ );
460
+
461
+ test("renders explanation strings as text instead of executable markup", async () => {
462
+ const title: string = '<img src=x onerror="alert(1)">';
463
+ const nextStep: string = "[Open settings](javascript:alert(1))";
464
+ postMock.mockResolvedValue(
465
+ noRunResponse(
466
+ reasonFor("enqueue_failed", {
467
+ title,
468
+ description: "<script>window.compromised = true</script>",
469
+ nextStep,
470
+ }),
471
+ ),
472
+ );
473
+ const view: ReturnType<typeof render> = renderPanel();
474
+ await flush();
475
+
476
+ expect(screen.getByText(title)).toBeVisible();
477
+ expect(screen.getByText(nextStep)).toBeVisible();
478
+ expect(view.container.querySelector("script")).toBeNull();
479
+ expect(view.container.querySelector("img")).toBeNull();
480
+ expect(view.container.querySelector('a[href^="javascript:"]')).toBeNull();
481
+ });
482
+
483
+ test("refreshes changed explanations even while no run exists", async () => {
484
+ postMock
485
+ .mockResolvedValueOnce(
486
+ noRunResponse(
487
+ reasonFor("provider_missing", { source: "current_configuration" }),
488
+ ),
489
+ )
490
+ .mockResolvedValue(
491
+ noRunResponse(
492
+ reasonFor("severity_below_threshold", {
493
+ source: "current_configuration",
494
+ evaluatedAt: NEXT_EVALUATED_AT,
495
+ }),
496
+ ),
497
+ );
498
+ const view: ReturnType<typeof render> = renderPanel();
499
+ await flush();
500
+ expect(screen.getByText("No AI provider is configured")).toBeVisible();
501
+
502
+ await advance();
503
+
504
+ expect(screen.queryByText("No AI provider is configured")).toBeNull();
505
+ expect(
506
+ screen.getByText("Severity is below the investigation threshold"),
507
+ ).toBeVisible();
508
+ expect(view.container.querySelector("time")).toHaveAttribute(
509
+ "datetime",
510
+ NEXT_EVALUATED_AT,
511
+ );
512
+ });
513
+
514
+ test("continues to discover queued work at the settled cadence after the initial checks", async () => {
515
+ postMock.mockResolvedValue(noRunResponse());
516
+ renderPanel();
517
+ await flush();
518
+ for (let count: number = 0; count < 4; count++) {
519
+ await advance();
520
+ }
521
+ expect(postMock).toHaveBeenCalledTimes(5);
522
+
523
+ postMock.mockResolvedValue(runResponse(AIRunStatus.Running));
524
+ await advance(29_999);
525
+ expect(postMock).toHaveBeenCalledTimes(5);
526
+ await advance(1);
527
+
528
+ expect(postMock).toHaveBeenCalledTimes(6);
529
+ expect(screen.getByText("Investigating…")).toBeVisible();
530
+ expect(screen.queryByText("Not investigated")).toBeNull();
531
+ });
532
+
533
+ test("clears the previous subject's explanation while a new subject loads", async () => {
534
+ let resolveNext: ((value: HTTPResponse<JSONObject>) => void) | undefined;
535
+ const nextResponse: Promise<HTTPResponse<JSONObject>> = new Promise(
536
+ (resolve: (value: HTTPResponse<JSONObject>) => void) => {
537
+ resolveNext = resolve;
538
+ },
539
+ );
540
+ postMock
541
+ .mockResolvedValueOnce(noRunResponse(reasonFor("monitor_cooldown")))
542
+ .mockReturnValueOnce(nextResponse);
543
+ const view: ReturnType<typeof render> = renderPanel();
544
+ await flush();
545
+ expect(
546
+ screen.getByText("This monitor was recently investigated"),
547
+ ).toBeVisible();
548
+
549
+ view.rerender(
550
+ <InvestigationPanel subjectType="incident" subjectId={NEXT_SUBJECT_ID} />,
551
+ );
552
+ expect(screen.getByText("Checking investigation status…")).toBeVisible();
553
+ expect(
554
+ screen.queryByText("This monitor was recently investigated"),
555
+ ).toBeNull();
556
+
557
+ resolveNext!(noRunResponse(reasonFor("provider_missing")));
558
+ await flush();
559
+ expect(screen.getByText("No AI provider is configured")).toBeVisible();
560
+ expect(
561
+ screen.queryByText("This monitor was recently investigated"),
562
+ ).toBeNull();
563
+ });
564
+
565
+ test("ignores a late explanation from the previous subject", async () => {
566
+ let resolveFirst: ((value: HTTPResponse<JSONObject>) => void) | undefined;
567
+ const firstResponse: Promise<HTTPResponse<JSONObject>> = new Promise(
568
+ (resolve: (value: HTTPResponse<JSONObject>) => void) => {
569
+ resolveFirst = resolve;
570
+ },
571
+ );
572
+ postMock
573
+ .mockReturnValueOnce(firstResponse)
574
+ .mockResolvedValueOnce(noRunResponse(reasonFor("provider_missing")));
575
+ const view: ReturnType<typeof render> = renderPanel();
576
+ view.rerender(
577
+ <InvestigationPanel subjectType="incident" subjectId={NEXT_SUBJECT_ID} />,
578
+ );
579
+ await flush();
580
+
581
+ resolveFirst!(noRunResponse(reasonFor("monitor_cooldown")));
582
+ await flush();
583
+
584
+ expect(screen.getByText("No AI provider is configured")).toBeVisible();
585
+ expect(
586
+ screen.queryByText("This monitor was recently investigated"),
587
+ ).toBeNull();
588
+ });
589
+ });
590
+
591
+ describe("investigation status failures and recovery", () => {
592
+ test.each(["http", "network"])(
593
+ "shows uncertainty and offers retry on an initial %s failure",
594
+ async (failure: string) => {
595
+ if (failure === "http") {
596
+ postMock.mockResolvedValueOnce(
597
+ new HTTPErrorResponse(
598
+ 503,
599
+ { message: "Internal configuration secret" },
600
+ {},
601
+ ),
602
+ );
603
+ } else {
604
+ postMock.mockRejectedValueOnce(
605
+ new Error("Network failure with internal details"),
606
+ );
607
+ }
608
+ postMock.mockResolvedValue(noRunResponse(reasonFor("monitor_cooldown")));
609
+ renderPanel();
610
+ await flush();
611
+
612
+ expect(
613
+ screen.getByText("Investigation status is unavailable"),
614
+ ).toBeVisible();
615
+ expect(
616
+ screen.getByText(/This does not mean AI is disabled/),
617
+ ).toBeVisible();
618
+ expect(screen.queryByText("Not investigated")).toBeNull();
619
+ expect(screen.queryByText(/Internal configuration secret/)).toBeNull();
620
+
621
+ fireEvent.click(
622
+ screen.getByRole("button", { name: "Retry investigation status" }),
623
+ );
624
+ await flush();
625
+
626
+ expect(
627
+ screen.getByText("This monitor was recently investigated"),
628
+ ).toBeVisible();
629
+ expect(
630
+ screen.queryByText("Investigation status is unavailable"),
631
+ ).toBeNull();
632
+ expect(
633
+ screen.queryByRole("button", { name: "Retry investigation status" }),
634
+ ).toBeNull();
635
+ },
636
+ );
637
+
638
+ test("preserves a known explanation through a transient failure, then clears the warning on recovery", async () => {
639
+ postMock
640
+ .mockResolvedValueOnce(noRunResponse())
641
+ .mockRejectedValueOnce(new Error("Offline"))
642
+ .mockResolvedValue(noRunResponse());
643
+ renderPanel();
644
+ await flush();
645
+ await advance();
646
+
647
+ expect(
648
+ screen.getByText("This monitor was recently investigated"),
649
+ ).toBeVisible();
650
+ expect(
651
+ screen.getByText(
652
+ "Could not refresh this status. Showing the last successful check.",
653
+ ),
654
+ ).toBeVisible();
655
+ expect(
656
+ screen.queryByText("Investigation status is unavailable"),
657
+ ).toBeNull();
658
+
659
+ await advance();
660
+
661
+ expect(
662
+ screen.getByText("This monitor was recently investigated"),
663
+ ).toBeVisible();
664
+ expect(screen.queryByText(/Could not refresh this status/)).toBeNull();
665
+ });
666
+
667
+ test("prevents repeated retry clicks from overlapping status requests", async () => {
668
+ let resolveRetry: ((value: HTTPResponse<JSONObject>) => void) | undefined;
669
+ const retryResponse: Promise<HTTPResponse<JSONObject>> = new Promise(
670
+ (resolve: (value: HTTPResponse<JSONObject>) => void) => {
671
+ resolveRetry = resolve;
672
+ },
673
+ );
674
+ postMock
675
+ .mockRejectedValueOnce(new Error("Offline"))
676
+ .mockReturnValueOnce(retryResponse);
677
+ renderPanel();
678
+ await flush();
679
+
680
+ const retry: HTMLElement = screen.getByRole("button", {
681
+ name: "Retry investigation status",
682
+ });
683
+ fireEvent.click(retry);
684
+ fireEvent.click(retry);
685
+ await advance();
686
+
687
+ expect(postMock).toHaveBeenCalledTimes(2);
688
+ expect(retry).toBeDisabled();
689
+
690
+ resolveRetry!(noRunResponse());
691
+ await flush();
692
+ expect(
693
+ screen.getByText("This monitor was recently investigated"),
694
+ ).toBeVisible();
695
+ });
696
+ });
697
+
698
+ describe("investigation settings actions", () => {
699
+ test("links provider failures to provider configuration", async () => {
700
+ postMock.mockResolvedValue(noRunResponse(reasonFor("provider_missing")));
701
+ renderPanel();
702
+ await flush();
703
+
704
+ expect(
705
+ screen.getByRole("link", { name: "Configure an AI provider" }),
706
+ ).toHaveAttribute(
707
+ "href",
708
+ expect.stringContaining(
709
+ `/${PROJECT_ID.toString()}/settings/llm-providers`,
710
+ ),
711
+ );
712
+ });
713
+
714
+ test("links the project AI switch to AI credits settings", async () => {
715
+ postMock.mockResolvedValue(noRunResponse(reasonFor("ai_disabled")));
716
+ renderPanel();
717
+ await flush();
718
+
719
+ expect(
720
+ screen.getByRole("link", { name: "Review project AI settings" }),
721
+ ).toHaveAttribute(
722
+ "href",
723
+ expect.stringContaining(`/${PROJECT_ID.toString()}/settings/ai-credits`),
724
+ );
725
+ });
726
+
727
+ test("keeps the reason available to viewers without offering settings they cannot change", async () => {
728
+ jest
729
+ .mocked(PermissionUtil.getAllPermissions)
730
+ .mockReturnValue([Permission.Viewer]);
731
+ postMock.mockResolvedValue(
732
+ noRunResponse(reasonFor("severity_below_threshold")),
733
+ );
734
+ renderPanel();
735
+ await flush();
736
+
737
+ expect(
738
+ screen.getByText("Severity is below the investigation threshold"),
739
+ ).toBeVisible();
740
+ expect(screen.queryByRole("link")).toBeNull();
741
+ expect(
742
+ screen.getByText("A project administrator can review these settings."),
743
+ ).toBeVisible();
744
+ });
745
+
746
+ test("respects a provider-specific permission without requiring project administrator access", async () => {
747
+ jest
748
+ .mocked(PermissionUtil.getAllPermissions)
749
+ .mockReturnValue([Permission.CreateProjectLlm]);
750
+ postMock.mockResolvedValue(noRunResponse(reasonFor("provider_missing")));
751
+ renderPanel();
752
+ await flush();
753
+
754
+ expect(
755
+ screen.getByRole("link", { name: "Configure an AI provider" }),
756
+ ).toBeVisible();
757
+ expect(
758
+ screen.queryByText("A project administrator can review these settings."),
759
+ ).toBeNull();
760
+ });
761
+ });