@oneuptime/common 14.0.10 → 14.0.11

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 (837) hide show
  1. package/Models/DatabaseModels/AIConversation.ts +127 -1
  2. package/Models/DatabaseModels/CephCluster.ts +12 -0
  3. package/Models/DatabaseModels/CloudResource.ts +12 -0
  4. package/Models/DatabaseModels/DatabaseServer.ts +12 -0
  5. package/Models/DatabaseModels/DockerHost.ts +12 -0
  6. package/Models/DatabaseModels/DockerSwarmCluster.ts +12 -0
  7. package/Models/DatabaseModels/GlobalOidc.ts +0 -4
  8. package/Models/DatabaseModels/GlobalOidcProject.ts +0 -4
  9. package/Models/DatabaseModels/GlobalSso.ts +0 -4
  10. package/Models/DatabaseModels/GlobalSsoProject.ts +0 -4
  11. package/Models/DatabaseModels/Host.ts +12 -0
  12. package/Models/DatabaseModels/IncidentForm.ts +594 -0
  13. package/Models/DatabaseModels/IncidentFormSubmission.ts +283 -0
  14. package/Models/DatabaseModels/IncidentTemplate.ts +59 -0
  15. package/Models/DatabaseModels/Index.ts +14 -0
  16. package/Models/DatabaseModels/IoTFleet.ts +12 -0
  17. package/Models/DatabaseModels/KubernetesCluster.ts +12 -0
  18. package/Models/DatabaseModels/MessageQueue.ts +1102 -0
  19. package/Models/DatabaseModels/MessageQueueLabelRule.ts +553 -0
  20. package/Models/DatabaseModels/MessageQueueOwnerRule.ts +633 -0
  21. package/Models/DatabaseModels/MessageQueueOwnerTeam.ts +491 -0
  22. package/Models/DatabaseModels/MessageQueueOwnerUser.ts +490 -0
  23. package/Models/DatabaseModels/PodmanHost.ts +12 -0
  24. package/Models/DatabaseModels/Project.ts +59 -0
  25. package/Models/DatabaseModels/ProjectOidc.ts +0 -4
  26. package/Models/DatabaseModels/ProjectSso.ts +0 -4
  27. package/Models/DatabaseModels/ProxmoxCluster.ts +12 -0
  28. package/Models/DatabaseModels/RumApplication.ts +12 -0
  29. package/Models/DatabaseModels/ServerlessFunction.ts +12 -0
  30. package/Models/DatabaseModels/Service.ts +12 -0
  31. package/Models/DatabaseModels/StatusPageOidc.ts +0 -4
  32. package/Models/DatabaseModels/StatusPageSso.ts +0 -4
  33. package/Models/DatabaseModels/TeamComplianceSetting.ts +47 -2
  34. package/Models/DatabaseModels/VMwareVCenter.ts +12 -0
  35. package/Server/API/AIChatAPI.ts +13 -114
  36. package/Server/API/AIInvestigationAPI.ts +3 -3
  37. package/Server/API/AIInvestigationConversationAPI.ts +266 -0
  38. package/Server/API/IncidentFormAPI.ts +376 -0
  39. package/Server/API/ProjectOIDC.ts +16 -25
  40. package/Server/API/ProjectSSO.ts +16 -24
  41. package/Server/API/StatusPageAPI.ts +42 -77
  42. package/Server/Enterprise/EnterpriseEdition.ts +93 -28
  43. package/Server/Enterprise/EnterpriseFeature.ts +25 -3
  44. package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +1 -1
  45. package/Server/Enterprise/EnterpriseServerModule.ts +4 -1
  46. package/Server/EnvironmentConfig.ts +1 -1
  47. package/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.ts +129 -0
  48. package/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.ts +52 -0
  49. package/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.ts +75 -0
  50. package/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.ts +477 -0
  51. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  52. package/Server/Middleware/IncidentFormRateLimit.ts +847 -0
  53. package/Server/Middleware/UserAuthorization.ts +16 -38
  54. package/Server/Services/AIService.ts +10 -13
  55. package/Server/Services/IncidentCustomFieldService.ts +112 -2
  56. package/Server/Services/IncidentEpisodeMemberService.ts +24 -4
  57. package/Server/Services/IncidentEpisodeService.ts +10 -1
  58. package/Server/Services/IncidentFormService.ts +1566 -0
  59. package/Server/Services/IncidentFormSubmissionService.ts +97 -0
  60. package/Server/Services/IncidentGroupingEngineService.ts +45 -8
  61. package/Server/Services/IncidentService.ts +123 -5
  62. package/Server/Services/IncidentTemplateService.ts +22 -0
  63. package/Server/Services/Index.ts +14 -0
  64. package/Server/Services/MessageQueueLabelRuleEngineService.ts +321 -0
  65. package/Server/Services/MessageQueueLabelRuleService.ts +14 -0
  66. package/Server/Services/MessageQueueOwnerRuleEngineService.ts +412 -0
  67. package/Server/Services/MessageQueueOwnerRuleService.ts +14 -0
  68. package/Server/Services/MessageQueueOwnerTeamService.ts +62 -0
  69. package/Server/Services/MessageQueueOwnerUserService.ts +62 -0
  70. package/Server/Services/MessageQueueService.ts +1463 -0
  71. package/Server/Services/OpenTelemetryIngestService.ts +37 -4
  72. package/Server/Services/ProjectService.ts +0 -59
  73. package/Server/Services/StatusPagePrivateUserService.ts +1 -4
  74. package/Server/Services/StatusPageService.ts +1 -51
  75. package/Server/Services/TeamComplianceSettingService.ts +163 -42
  76. package/Server/Services/UserNotificationRuleService.ts +8 -1
  77. package/Server/Services/WorkspaceNotificationSummaryService.ts +12 -3
  78. package/Server/Types/Database/Permissions/CreatePermission.ts +17 -3
  79. package/Server/Types/Database/Permissions/EditionPermission.ts +140 -38
  80. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +16 -0
  81. package/Server/Types/Database/Permissions/TablePermission.ts +3 -3
  82. package/Server/Types/Database/Permissions/UpdatePermission.ts +20 -6
  83. package/Server/Utils/AI/Chat/AgentContextCompactor.ts +200 -0
  84. package/Server/Utils/AI/Chat/ChatAgentRunner.ts +307 -48
  85. package/Server/Utils/AI/Chat/ChatRunCancellation.ts +156 -0
  86. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +78 -18
  87. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
  88. package/Server/Utils/AI/Chat/ToolOutputPager.ts +322 -0
  89. package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +88 -30
  90. package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +13 -1
  91. package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +0 -32
  92. package/Server/Utils/AI/CodeFix/FixRunBudget.ts +27 -25
  93. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +7 -1
  94. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +34 -14
  95. package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +69 -24
  96. package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +9 -0
  97. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +53 -10
  98. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +27 -10
  99. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +27 -10
  100. package/Server/Utils/AI/SRE/InvestigationQueue.ts +16 -19
  101. package/Server/Utils/AI/SRE/InvestigationThread.ts +646 -0
  102. package/Server/Utils/AI/SRE/InvestigationThreadService.ts +715 -0
  103. package/Server/Utils/AI/Toolbox/Serializer.ts +10 -3
  104. package/Server/Utils/EditionEnforcement.ts +19 -202
  105. package/Server/Utils/LLM/LLMService.ts +259 -63
  106. package/Server/Utils/RelaxedScimTeamLocksReport.ts +245 -0
  107. package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
  108. package/Server/Utils/SameOriginRequest.ts +203 -0
  109. package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
  110. package/Server/Utils/Telemetry/EntityRegistry.ts +4 -1
  111. package/Server/Utils/Telemetry/MessageQueueDiscovery.ts +1402 -0
  112. package/Server/Utils/Telemetry/ResourceEntityFilter.ts +4 -1
  113. package/Server/Utils/VendorAssets.ts +3 -3
  114. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +3 -1
  115. package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +3 -1
  116. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +10 -1
  117. package/Tests/App/Accounts/IncidentFormPage.test.tsx +2036 -0
  118. package/Tests/App/Accounts/IncidentFormServerMessages.test.ts +119 -0
  119. package/Tests/App/Accounts/IncidentFormUtils.test.ts +1157 -0
  120. package/Tests/App/Accounts/LoginPasskey.test.tsx +6 -4
  121. package/Tests/App/Accounts/LoginSso.test.tsx +724 -0
  122. package/Tests/App/AdminDashboard/AdminAuthenticationRequireSso.test.tsx +338 -0
  123. package/Tests/App/AdminDashboard/AdminAuthenticationSsoCardLocales.test.tsx +331 -0
  124. package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +47 -33
  125. package/Tests/App/AdminDashboard/GlobalSsoOidcPages.test.tsx +1021 -0
  126. package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +876 -78
  127. package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +20 -3
  128. package/Tests/App/Dashboard/CephProxmoxVMwareDocumentationCards.test.tsx +359 -0
  129. package/Tests/App/Dashboard/CephSetupGuide.test.ts +961 -0
  130. package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +381 -95
  131. package/Tests/App/Dashboard/CloudSetupGuide.test.ts +1463 -0
  132. package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +174 -12
  133. package/Tests/App/Dashboard/ContainerSetupGuideCards.test.tsx +345 -0
  134. package/Tests/App/Dashboard/CoreListEmptyStates.test.tsx +501 -0
  135. package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +0 -1
  136. package/Tests/App/Dashboard/DatabaseDocumentationCard.test.tsx +400 -0
  137. package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +5 -0
  138. package/Tests/App/Dashboard/DatabaseSetupGuide.test.ts +1869 -0
  139. package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +44 -0
  140. package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +50 -9
  141. package/Tests/App/Dashboard/DockerSetupGuide.test.ts +899 -0
  142. package/Tests/App/Dashboard/DockerSwarmSetupGuide.test.ts +964 -0
  143. package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +141 -7
  144. package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +52 -39
  145. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +7 -1
  146. package/Tests/App/Dashboard/GettingStartedTaskRoutes.test.tsx +331 -0
  147. package/Tests/App/Dashboard/HomeOverviewStatsFirstRun.test.tsx +925 -0
  148. package/Tests/App/Dashboard/HostDocumentationCard.test.tsx +225 -0
  149. package/Tests/App/Dashboard/HostSetupGuide.test.ts +1183 -0
  150. package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +69 -45
  151. package/Tests/App/Dashboard/IncidentCreateTemplateCustomFieldSettings.test.tsx +745 -0
  152. package/Tests/App/Dashboard/IncidentCreateTemplateOwners.test.tsx +414 -0
  153. package/Tests/App/Dashboard/IncidentCustomFieldCreateSettingsForm.test.ts +1042 -0
  154. package/Tests/App/Dashboard/IncidentCustomFieldSettingsCard.test.tsx +1816 -0
  155. package/Tests/App/Dashboard/IncidentFormPlan.test.ts +89 -0
  156. package/Tests/App/Dashboard/IncidentFormShareLinkCard.test.tsx +846 -0
  157. package/Tests/App/Dashboard/IncidentFormsPages.test.tsx +1324 -0
  158. package/Tests/App/Dashboard/IncidentTemplateCustomFieldSettings.test.tsx +630 -0
  159. package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +13 -0
  160. package/Tests/App/Dashboard/IncomingEmailMonitorLinkVerifyHint.test.tsx +104 -0
  161. package/Tests/App/Dashboard/InvestigationConversation.test.tsx +1107 -0
  162. package/Tests/App/Dashboard/InvestigationConversationData.test.ts +546 -0
  163. package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +170 -5
  164. package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +207 -2
  165. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +729 -34
  166. package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +9 -21
  167. package/Tests/App/Dashboard/InvestigationReportView.test.tsx +274 -37
  168. package/Tests/App/Dashboard/InvestigationStatusBadge.test.tsx +130 -0
  169. package/Tests/App/Dashboard/IoTDocumentationCard.test.tsx +218 -0
  170. package/Tests/App/Dashboard/IoTSetupGuide.test.ts +1124 -0
  171. package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +20 -6
  172. package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +107 -83
  173. package/Tests/App/Dashboard/KubernetesSetupGuide.test.ts +787 -0
  174. package/Tests/App/Dashboard/MessageQueueBreadcrumbs.test.tsx +228 -0
  175. package/Tests/App/Dashboard/MessageQueueBrokerHealth.test.tsx +1538 -0
  176. package/Tests/App/Dashboard/MessageQueueBrokerHealthMetricChart.test.tsx +969 -0
  177. package/Tests/App/Dashboard/MessageQueueBrokerHealthReads.test.ts +889 -0
  178. package/Tests/App/Dashboard/MessageQueueBrokerMetricsReach.test.ts +236 -0
  179. package/Tests/App/Dashboard/MessageQueueDocumentationCard.test.tsx +479 -0
  180. package/Tests/App/Dashboard/MessageQueueListPages.test.tsx +1232 -0
  181. package/Tests/App/Dashboard/MessageQueueMetricDescriptions.test.ts +244 -0
  182. package/Tests/App/Dashboard/MessageQueueMonitorLink.test.ts +952 -0
  183. package/Tests/App/Dashboard/MessageQueueMonitorLinkMonitorCreate.test.tsx +859 -0
  184. package/Tests/App/Dashboard/MessageQueueOverview.test.tsx +1773 -0
  185. package/Tests/App/Dashboard/MessageQueueOverviewPresentation.test.ts +196 -0
  186. package/Tests/App/Dashboard/MessageQueuePresentation.test.ts +799 -0
  187. package/Tests/App/Dashboard/MessageQueueProducersConsumers.test.tsx +680 -0
  188. package/Tests/App/Dashboard/MessageQueueRoutes.test.tsx +383 -0
  189. package/Tests/App/Dashboard/MessageQueueRulePages.test.tsx +278 -0
  190. package/Tests/App/Dashboard/MessageQueueSetupGuide.test.ts +2778 -0
  191. package/Tests/App/Dashboard/MessageQueueSideMenus.test.tsx +273 -0
  192. package/Tests/App/Dashboard/MessageQueueSpanPopulations.test.ts +930 -0
  193. package/Tests/App/Dashboard/MessageQueueSpanStore.ts +351 -0
  194. package/Tests/App/Dashboard/MessageQueueTelemetryScope.test.ts +375 -0
  195. package/Tests/App/Dashboard/MessageQueueTelemetryScopeTabs.test.tsx +668 -0
  196. package/Tests/App/Dashboard/MessageQueueViewPages.test.tsx +685 -0
  197. package/Tests/App/Dashboard/MonitorAndHomeNotOperationalMenus.test.tsx +342 -0
  198. package/Tests/App/Dashboard/MonitorCreateFirstRunDefaults.test.tsx +623 -0
  199. package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +442 -0
  200. package/Tests/App/Dashboard/MonitorLogsPageViewSummary.test.tsx +814 -0
  201. package/Tests/App/Dashboard/MonitorSetupCardBodies.test.tsx +246 -0
  202. package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +8 -0
  203. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +27 -12
  204. package/Tests/App/Dashboard/PlanGatedPage.test.tsx +292 -0
  205. package/Tests/App/Dashboard/PodmanSetupGuide.test.ts +948 -0
  206. package/Tests/App/Dashboard/ProductOrientation.test.tsx +5 -4
  207. package/Tests/App/Dashboard/ProductSettingsSectionCollapsed.test.tsx +266 -0
  208. package/Tests/App/Dashboard/ProxmoxSetupGuide.test.ts +1318 -0
  209. package/Tests/App/Dashboard/ResourceAiAgentAttentionServerParity.test.ts +555 -0
  210. package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +298 -9
  211. package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +453 -0
  212. package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +16 -0
  213. package/Tests/App/Dashboard/ResourceConnectionGuideCard.test.tsx +444 -0
  214. package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsInfra.test.tsx +798 -0
  215. package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsPlatforms.test.tsx +717 -0
  216. package/Tests/App/Dashboard/ResourceConnectionGuides.test.ts +981 -0
  217. package/Tests/App/Dashboard/ResourceConnectionState.test.ts +132 -0
  218. package/Tests/App/Dashboard/RumDocumentationCard.test.tsx +293 -0
  219. package/Tests/App/Dashboard/RumSessionReplayRetentionSettings.test.tsx +467 -0
  220. package/Tests/App/Dashboard/RumSetupGuide.test.ts +758 -0
  221. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +25 -0
  222. package/Tests/App/Dashboard/ServerlessDocumentationCard.test.tsx +254 -0
  223. package/Tests/App/Dashboard/ServerlessSetupGuide.test.ts +1074 -0
  224. package/Tests/App/Dashboard/SetupGuide.test.ts +246 -0
  225. package/Tests/App/Dashboard/SetupGuideCard.test.tsx +756 -0
  226. package/Tests/App/Dashboard/SloListSideMenu.test.tsx +120 -0
  227. package/Tests/App/Dashboard/SsoPages.test.tsx +833 -0
  228. package/Tests/App/Dashboard/TelemetryDocumentation.test.tsx +253 -0
  229. package/Tests/App/Dashboard/TelemetryRetentionShells.test.tsx +730 -0
  230. package/Tests/App/Dashboard/VMwareSetupGuide.test.ts +1033 -0
  231. package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +87 -7
  232. package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +28 -9
  233. package/Tests/Models/DatabaseModels/IncidentFormModel.test.ts +1250 -0
  234. package/Tests/Models/DatabaseModels/MessageQueueModels.test.ts +1983 -0
  235. package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
  236. package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +190 -14
  237. package/Tests/Models/IncidentTemplateCustomFieldSettingsColumn.test.ts +291 -0
  238. package/Tests/Server/API/AIInvestigationConversationAPI.test.ts +412 -0
  239. package/Tests/Server/API/GlobalConfigLicense.test.ts +38 -9
  240. package/Tests/Server/API/IncidentFormAPI.test.ts +942 -0
  241. package/Tests/Server/API/IncidentFormPublicRoutes.test.ts +1653 -0
  242. package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -1
  243. package/Tests/Server/API/{SsoProviderListingsEdition.test.ts → SsoProviderListings.test.ts} +164 -110
  244. package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +76 -54
  245. package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +125 -42
  246. package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +36 -10
  247. package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +51 -9
  248. package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +13 -8
  249. package/Tests/Server/Enterprise/SsoInCommunityEdition.test.ts +540 -0
  250. package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
  251. package/Tests/Server/Infrastructure/Postgres/AddIncidentFormsMigration.test.ts +438 -0
  252. package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleNotificationChannelsMigration.test.ts +255 -0
  253. package/Tests/Server/Infrastructure/Postgres/MessageQueueTablesMigration.test.ts +637 -0
  254. package/Tests/Server/Middleware/IncidentFormRateLimit.test.ts +1630 -0
  255. package/Tests/Server/Middleware/UserAuthorization.test.ts +16 -17
  256. package/Tests/Server/Middleware/UserAuthorizationSsoEnforcement.test.ts +544 -0
  257. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +37 -8
  258. package/Tests/Server/Services/IncidentCreatedFeedTitle.test.ts +212 -0
  259. package/Tests/Server/Services/IncidentCustomFieldDeleteFormQuestions.test.ts +297 -0
  260. package/Tests/Server/Services/IncidentFormOwnersCreatedNotification.test.ts +497 -0
  261. package/Tests/Server/Services/IncidentFormPostgres.test.ts +958 -0
  262. package/Tests/Server/Services/IncidentFormPublicForm.test.ts +1260 -0
  263. package/Tests/Server/Services/IncidentFormPublicSubmission.test.ts +2520 -0
  264. package/Tests/Server/Services/IncidentFormRegistration.test.ts +159 -0
  265. package/Tests/Server/Services/IncidentFormService.test.ts +663 -0
  266. package/Tests/Server/Services/IncidentFormSubmissionService.test.ts +430 -0
  267. package/Tests/Server/Services/IncidentFormSubmissionTemplateBranch.test.ts +473 -0
  268. package/Tests/Server/Services/IncidentGroupingTemplateSubstitution.test.ts +81 -0
  269. package/Tests/Server/Services/IncidentTemplateCustomFieldSettings.test.ts +262 -0
  270. package/Tests/Server/Services/IncidentTemplateOwnersOnDeclare.test.ts +566 -0
  271. package/Tests/Server/Services/IncidentTitleMarkdownSinks.test.ts +640 -0
  272. package/Tests/Server/Services/LlmLogServiceTokenAggregateParams.test.ts +3 -3
  273. package/Tests/Server/Services/MessageQueueOwnerServices.test.ts +440 -0
  274. package/Tests/Server/Services/MessageQueueRegistries.test.ts +577 -0
  275. package/Tests/Server/Services/MessageQueueRuleEngines.test.ts +900 -0
  276. package/Tests/Server/Services/MessageQueueService.test.ts +2210 -0
  277. package/Tests/Server/Services/MessageQueueSqlPostgres.test.ts +1271 -0
  278. package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
  279. package/Tests/Server/Services/OpenTelemetryRetentionOverrideEdition.test.ts +474 -0
  280. package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +21 -0
  281. package/Tests/Server/Services/OwnerRowUniqueness.test.ts +3 -0
  282. package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +0 -1
  283. package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +56 -6
  284. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -1
  285. package/Tests/Server/Services/SsoRequirementReads.test.ts +454 -0
  286. package/Tests/Server/Services/SsoRequirementWrites.test.ts +529 -0
  287. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
  288. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +107 -89
  289. package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +1068 -176
  290. package/Tests/Server/Services/TeamComplianceSettingService.test.ts +1962 -200
  291. package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +654 -297
  292. package/Tests/Server/Types/Database/Permissions/RetentionOverrideColumns.test.ts +784 -0
  293. package/Tests/Server/Types/Database/Permissions/SsoScalePlanGate.test.ts +418 -0
  294. package/Tests/Server/Utils/AI/AIAlertGating.test.ts +0 -1
  295. package/Tests/Server/Utils/AI/AIInvestigationEngineRunLimits.test.ts +136 -0
  296. package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +15 -14
  297. package/Tests/Server/Utils/AI/AgentContextCompactor.test.ts +351 -0
  298. package/Tests/Server/Utils/AI/ChatAgentRunnerSharedThread.test.ts +842 -0
  299. package/Tests/Server/Utils/AI/ChatRunCancellation.test.ts +195 -0
  300. package/Tests/Server/Utils/AI/CodeFixReadiness.test.ts +10 -57
  301. package/Tests/Server/Utils/AI/FixRunBudget.test.ts +20 -24
  302. package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +7 -30
  303. package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +225 -29
  304. package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +266 -25
  305. package/Tests/Server/Utils/AI/InvestigationThread.test.ts +580 -0
  306. package/Tests/Server/Utils/AI/InvestigationThreadService.test.ts +801 -0
  307. package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +525 -43
  308. package/Tests/Server/Utils/AI/KubectlJobRunner.test.ts +4 -2
  309. package/Tests/Server/Utils/AI/LLMServiceUnreachableProvider.test.ts +435 -0
  310. package/Tests/Server/Utils/AI/ObservabilityAssistantLimits.test.ts +462 -0
  311. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +14 -25
  312. package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +2 -0
  313. package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +297 -15
  314. package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +10 -6
  315. package/Tests/Server/Utils/AI/ToolOutputPager.test.ts +382 -0
  316. package/Tests/Server/Utils/AI/ToolResultSerializer.test.ts +23 -4
  317. package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +25 -6
  318. package/Tests/Server/Utils/AI/Toolbox/Serializer.test.ts +14 -3
  319. package/Tests/Server/Utils/EditionEnforcement.test.ts +107 -147
  320. package/Tests/Server/Utils/{CommunityEditionSsoReport.test.ts → RelaxedScimTeamLocksReport.test.ts} +212 -208
  321. package/Tests/Server/Utils/SameOriginRequest.test.ts +372 -0
  322. package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +20 -0
  323. package/Tests/Server/Utils/Telemetry/MessageQueueDiscovery.test.ts +2590 -0
  324. package/Tests/Server/Utils/Telemetry/MessageQueueSpanQueryTwin.ts +246 -0
  325. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +23 -0
  326. package/Tests/Types/AI/AIAgentRunLimits.test.ts +255 -0
  327. package/Tests/Types/Code/JsonSyntax.test.ts +1300 -0
  328. package/Tests/Types/CustomField/CustomFieldCreateSettings.test.ts +1113 -0
  329. package/Tests/Types/CustomField/CustomFieldMappingCatalog.test.ts +91 -0
  330. package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +30 -0
  331. package/Tests/Types/Incident/IncidentFormIpAllowlist.test.ts +227 -0
  332. package/Tests/Types/Incident/IncidentFormPublic.test.ts +1916 -0
  333. package/Tests/Types/MessageQueue/MessageQueueEntityKey.test.ts +916 -0
  334. package/Tests/Types/MessageQueue/MessageQueueIdentity.test.ts +567 -0
  335. package/Tests/Types/MessageQueue/MessageQueueManualIdentity.test.ts +686 -0
  336. package/Tests/Types/MessageQueue/MessageQueueMetricCatalog.test.ts +1726 -0
  337. package/Tests/Types/MessageQueue/MessageQueueMetricResolution.test.ts +1758 -0
  338. package/Tests/Types/MessageQueue/MessagingInstrumentationFixtures.test.ts +4686 -0
  339. package/Tests/Types/MessageQueue/MessagingSystem.test.ts +840 -0
  340. package/Tests/Types/MessageQueue/MessagingTelemetryFixtures.ts +3287 -0
  341. package/Tests/Types/MessageQueue/MessagingTelemetryResolver.test.ts +2966 -0
  342. package/Tests/Types/Monitor/MessageQueueAlertTemplates.test.ts +5401 -0
  343. package/Tests/Types/Monitor/MetricEngineFold.ts +154 -0
  344. package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +5 -3
  345. package/Tests/Types/Team/ComplianceRule.test.ts +588 -37
  346. package/Tests/Types/Team/TeamComplianceStatus.test.ts +64 -11
  347. package/Tests/Types/XML.test.ts +51 -0
  348. package/Tests/UI/Components/CodeEditor/CodeEditor.test.tsx +2362 -0
  349. package/Tests/UI/Components/CodeEditor/CodeEditorCommands.test.ts +810 -0
  350. package/Tests/UI/Components/CodeEditor/CodeEditorHighlight.test.ts +338 -0
  351. package/Tests/UI/Components/CodeEditor/CodeEditorLanguages.test.ts +222 -0
  352. package/Tests/UI/Components/CodeEditor/CodeEditorStyles.test.ts +807 -0
  353. package/Tests/UI/Components/CodeEditor/NoMonaco.test.ts +245 -0
  354. package/Tests/UI/Components/CodeEditor/YamlEditor.test.tsx +729 -0
  355. package/Tests/UI/Components/CopyTextButton.test.tsx +76 -0
  356. package/Tests/UI/Components/EditionLabelLapseCopy.ts +51 -14
  357. package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +131 -23
  358. package/Tests/UI/Components/ErrorMessageAction.test.tsx +142 -0
  359. package/Tests/UI/Components/FacetSidebarInScope.test.tsx +459 -0
  360. package/Tests/UI/Components/FacetValuesInScope.test.ts +270 -0
  361. package/Tests/UI/Components/Forms/FormFieldCodeEditors.test.tsx +294 -0
  362. package/Tests/UI/Components/Forms/FormFieldMarkdown.test.tsx +126 -0
  363. package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +22 -75
  364. package/Tests/UI/Components/Forms/ModelFormOnBeforeCreateMiscData.test.tsx +254 -0
  365. package/Tests/UI/Components/Icon.test.tsx +32 -0
  366. package/Tests/UI/Components/Input.test.tsx +31 -0
  367. package/Tests/UI/Components/LockedFilterChipScope.test.tsx +501 -0
  368. package/Tests/UI/Components/MarkdownConverters.test.ts +253 -1
  369. package/Tests/UI/Components/MarkdownEditor.test.tsx +2785 -2
  370. package/Tests/UI/Components/MarkdownEditorHistory.test.ts +243 -0
  371. package/Tests/UI/Components/MarkdownListEditing.test.ts +1118 -0
  372. package/Tests/UI/Components/MarkdownPaste.test.ts +1180 -0
  373. package/Tests/UI/Components/MarkdownViewerCopy.test.tsx +466 -0
  374. package/Tests/UI/Components/MarkdownVisualEditing.test.ts +1089 -0
  375. package/Tests/UI/Components/ModelTable/BaseModelTableEmptyStateAction.test.tsx +623 -0
  376. package/Tests/UI/Components/ResetObjectID.test.tsx +282 -0
  377. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
  378. package/Tests/UI/Components/Table/EmptyTableMessage.test.ts +439 -0
  379. package/Tests/UI/Components/Table/TableEmptyState.test.tsx +352 -0
  380. package/Tests/UI/Components/TableRowMobileTitles.test.tsx +78 -0
  381. package/Tests/UI/Components/TextArea.test.tsx +19 -0
  382. package/Tests/UI/Components/Workflow/ModelColumnEditor.render.test.tsx +12 -29
  383. package/Tests/UI/Components/fixtures/MarkdownPasteFixtures.ts +460 -0
  384. package/Tests/UI/EsbuildConfig.test.ts +115 -39
  385. package/Tests/UI/EsbuildEnterpriseAlias.test.ts +4 -4
  386. package/Tests/UI/Monitor/MonitorLogSummaryRender.test.tsx +377 -0
  387. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +81 -1
  388. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +17 -0
  389. package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
  390. package/Tests/Utils/Markdown/DashboardMarkdownRenderer.ts +81 -0
  391. package/Tests/Utils/Markdown/UntrustedMarkdown.test.ts +1339 -0
  392. package/Tests/Utils/Monitor/MonitorLogSummaryUtil.test.ts +862 -0
  393. package/Types/AI/AIAgentRunLimits.ts +146 -0
  394. package/Types/Code/CodeType.ts +2 -0
  395. package/Types/Code/JsonSyntax.ts +923 -0
  396. package/Types/CustomField/CustomFieldCreateSettings.ts +549 -0
  397. package/Types/CustomField/CustomFieldMappingCatalog.ts +77 -0
  398. package/Types/CustomField/CustomFieldValueValidator.ts +10 -7
  399. package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +1 -1
  400. package/Types/Icon/IconProp.ts +2 -0
  401. package/Types/Incident/IncidentFormIpAllowlist.ts +206 -0
  402. package/Types/Incident/IncidentFormPublic.ts +1145 -0
  403. package/Types/Kubernetes/KubernetesClusterAiAccess.ts +10 -3
  404. package/Types/MessageQueue/MessageQueueIdentity.ts +256 -0
  405. package/Types/MessageQueue/MessageQueueManualIdentity.ts +325 -0
  406. package/Types/MessageQueue/MessageQueueMetricCatalog.ts +1357 -0
  407. package/Types/MessageQueue/MessagingSystem.ts +518 -0
  408. package/Types/MessageQueue/MessagingTelemetryResolver.ts +2311 -0
  409. package/Types/Monitor/MessageQueueAlertTemplates.ts +2128 -0
  410. package/Types/Permission.ts +310 -0
  411. package/Types/ResourceAiAgent/ResourceAiAccess.ts +10 -4
  412. package/Types/Rules/RuleCriteriaFieldRegistry.ts +12 -0
  413. package/Types/Rules/RuleRun.ts +4 -0
  414. package/Types/Team/ComplianceNotificationChannel.ts +4 -3
  415. package/Types/Team/ComplianceRule.ts +71 -18
  416. package/Types/Team/ComplianceRuleType.ts +2 -2
  417. package/Types/Team/TeamComplianceStatus.ts +6 -2
  418. package/Types/Telemetry/EntityType.ts +16 -0
  419. package/Types/Telemetry/LockedFilterDetail.ts +22 -0
  420. package/Types/XML.ts +26 -0
  421. package/UI/Components/CodeEditor/CodeEditor.css +379 -0
  422. package/UI/Components/CodeEditor/CodeEditor.tsx +1128 -294
  423. package/UI/Components/CodeEditor/CodeEditorCommands.ts +774 -0
  424. package/UI/Components/CodeEditor/CodeEditorHighlight.ts +106 -0
  425. package/UI/Components/CodeEditor/CodeEditorLanguages.ts +164 -0
  426. package/UI/Components/CodeEditor/YamlEditor.tsx +28 -326
  427. package/UI/Components/CopyTextButton/CopyTextButton.tsx +5 -1
  428. package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +6 -25
  429. package/UI/Components/EditionLabel/EditionLabel.tsx +14 -13
  430. package/UI/Components/ErrorMessage/ErrorMessage.tsx +11 -1
  431. package/UI/Components/Forms/Fields/FormField.tsx +8 -0
  432. package/UI/Components/Forms/Types/Field.ts +8 -0
  433. package/UI/Components/Icon/Icon.tsx +18 -0
  434. package/UI/Components/Input/Input.tsx +11 -4
  435. package/UI/Components/LogsViewer/LogsViewer.tsx +4 -0
  436. package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +21 -3
  437. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  438. package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +877 -79
  439. package/UI/Components/Markdown.tsx/MarkdownEditorHistory.ts +284 -0
  440. package/UI/Components/Markdown.tsx/MarkdownListEditing.ts +1362 -0
  441. package/UI/Components/Markdown.tsx/MarkdownPaste.ts +1326 -0
  442. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +106 -10
  443. package/UI/Components/Markdown.tsx/MarkdownVisualEditing.ts +1032 -0
  444. package/UI/Components/ModelTable/BaseModelTable.tsx +85 -7
  445. package/UI/Components/ResetObjectID/ResetObjectID.tsx +35 -9
  446. package/UI/Components/Table/EmptyTableMessage.ts +81 -0
  447. package/UI/Components/Table/Table.tsx +50 -21
  448. package/UI/Components/Table/TableRow.tsx +9 -1
  449. package/UI/Components/TelemetryViewer/FacetVisibility.ts +97 -2
  450. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +13 -0
  451. package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +214 -7
  452. package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +21 -3
  453. package/UI/Components/TextArea/TextArea.tsx +9 -2
  454. package/UI/Components/Workflow/ModelFieldPicker.tsx +10 -12
  455. package/UI/Styles/Theme.css +8 -0
  456. package/UI/esbuild-config.js +2 -32
  457. package/Utils/LabelRuleImportExport.ts +2 -0
  458. package/Utils/Markdown/UntrustedMarkdown.ts +1513 -0
  459. package/Utils/Monitor/IncomingEmailMonitorRequestUtil.ts +41 -0
  460. package/Utils/Monitor/MonitorLogSummaryUtil.ts +212 -0
  461. package/Utils/Telemetry/EntityKey.ts +48 -0
  462. package/build/dist/Models/DatabaseModels/AIConversation.js +125 -1
  463. package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
  464. package/build/dist/Models/DatabaseModels/CephCluster.js +12 -0
  465. package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
  466. package/build/dist/Models/DatabaseModels/CloudResource.js +12 -0
  467. package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
  468. package/build/dist/Models/DatabaseModels/DatabaseServer.js +12 -0
  469. package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
  470. package/build/dist/Models/DatabaseModels/DockerHost.js +12 -0
  471. package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
  472. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +12 -0
  473. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
  474. package/build/dist/Models/DatabaseModels/GlobalOidc.js +0 -4
  475. package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
  476. package/build/dist/Models/DatabaseModels/GlobalOidcProject.js +0 -4
  477. package/build/dist/Models/DatabaseModels/GlobalOidcProject.js.map +1 -1
  478. package/build/dist/Models/DatabaseModels/GlobalSso.js +0 -4
  479. package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
  480. package/build/dist/Models/DatabaseModels/GlobalSsoProject.js +0 -4
  481. package/build/dist/Models/DatabaseModels/GlobalSsoProject.js.map +1 -1
  482. package/build/dist/Models/DatabaseModels/Host.js +12 -0
  483. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  484. package/build/dist/Models/DatabaseModels/IncidentForm.js +605 -0
  485. package/build/dist/Models/DatabaseModels/IncidentForm.js.map +1 -0
  486. package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js +299 -0
  487. package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js.map +1 -0
  488. package/build/dist/Models/DatabaseModels/IncidentTemplate.js +60 -0
  489. package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
  490. package/build/dist/Models/DatabaseModels/Index.js +14 -0
  491. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  492. package/build/dist/Models/DatabaseModels/IoTFleet.js +12 -0
  493. package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -1
  494. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +12 -0
  495. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  496. package/build/dist/Models/DatabaseModels/MessageQueue.js +1106 -0
  497. package/build/dist/Models/DatabaseModels/MessageQueue.js.map +1 -0
  498. package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js +562 -0
  499. package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js.map +1 -0
  500. package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js +643 -0
  501. package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js.map +1 -0
  502. package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js +506 -0
  503. package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js.map +1 -0
  504. package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js +505 -0
  505. package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js.map +1 -0
  506. package/build/dist/Models/DatabaseModels/PodmanHost.js +12 -0
  507. package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
  508. package/build/dist/Models/DatabaseModels/Project.js +61 -0
  509. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  510. package/build/dist/Models/DatabaseModels/ProjectOidc.js +0 -4
  511. package/build/dist/Models/DatabaseModels/ProjectOidc.js.map +1 -1
  512. package/build/dist/Models/DatabaseModels/ProjectSso.js +0 -4
  513. package/build/dist/Models/DatabaseModels/ProjectSso.js.map +1 -1
  514. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +12 -0
  515. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
  516. package/build/dist/Models/DatabaseModels/RumApplication.js +12 -0
  517. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  518. package/build/dist/Models/DatabaseModels/ServerlessFunction.js +12 -0
  519. package/build/dist/Models/DatabaseModels/ServerlessFunction.js.map +1 -1
  520. package/build/dist/Models/DatabaseModels/Service.js +12 -0
  521. package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
  522. package/build/dist/Models/DatabaseModels/StatusPageOidc.js +0 -4
  523. package/build/dist/Models/DatabaseModels/StatusPageOidc.js.map +1 -1
  524. package/build/dist/Models/DatabaseModels/StatusPageSso.js +0 -4
  525. package/build/dist/Models/DatabaseModels/StatusPageSso.js.map +1 -1
  526. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +49 -3
  527. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
  528. package/build/dist/Models/DatabaseModels/VMwareVCenter.js +12 -0
  529. package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
  530. package/build/dist/Server/API/AIChatAPI.js +9 -103
  531. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  532. package/build/dist/Server/API/AIInvestigationAPI.js +3 -3
  533. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  534. package/build/dist/Server/API/AIInvestigationConversationAPI.js +162 -0
  535. package/build/dist/Server/API/AIInvestigationConversationAPI.js.map +1 -0
  536. package/build/dist/Server/API/IncidentFormAPI.js +245 -0
  537. package/build/dist/Server/API/IncidentFormAPI.js.map +1 -0
  538. package/build/dist/Server/API/ProjectOIDC.js +16 -24
  539. package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
  540. package/build/dist/Server/API/ProjectSSO.js +16 -24
  541. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  542. package/build/dist/Server/API/StatusPageAPI.js +42 -75
  543. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  544. package/build/dist/Server/Enterprise/EnterpriseEdition.js +79 -25
  545. package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -1
  546. package/build/dist/Server/Enterprise/EnterpriseFeature.js +24 -3
  547. package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -1
  548. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +1 -1
  549. package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -1
  550. package/build/dist/Server/EnvironmentConfig.js +1 -1
  551. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js +63 -0
  552. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js.map +1 -0
  553. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js +41 -0
  554. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js.map +1 -0
  555. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js +40 -0
  556. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js.map +1 -0
  557. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js +183 -0
  558. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js.map +1 -0
  559. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  560. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  561. package/build/dist/Server/Middleware/IncidentFormRateLimit.js +559 -0
  562. package/build/dist/Server/Middleware/IncidentFormRateLimit.js.map +1 -0
  563. package/build/dist/Server/Middleware/UserAuthorization.js +11 -30
  564. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  565. package/build/dist/Server/Services/AIService.js +10 -13
  566. package/build/dist/Server/Services/AIService.js.map +1 -1
  567. package/build/dist/Server/Services/IncidentCustomFieldService.js +83 -0
  568. package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
  569. package/build/dist/Server/Services/IncidentEpisodeMemberService.js +8 -4
  570. package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
  571. package/build/dist/Server/Services/IncidentEpisodeService.js +10 -1
  572. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  573. package/build/dist/Server/Services/IncidentFormService.js +1202 -0
  574. package/build/dist/Server/Services/IncidentFormService.js.map +1 -0
  575. package/build/dist/Server/Services/IncidentFormSubmissionService.js +91 -0
  576. package/build/dist/Server/Services/IncidentFormSubmissionService.js.map +1 -0
  577. package/build/dist/Server/Services/IncidentGroupingEngineService.js +20 -8
  578. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  579. package/build/dist/Server/Services/IncidentService.js +106 -4
  580. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  581. package/build/dist/Server/Services/IncidentTemplateService.js +18 -0
  582. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  583. package/build/dist/Server/Services/Index.js +14 -0
  584. package/build/dist/Server/Services/Index.js.map +1 -1
  585. package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js +262 -0
  586. package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js.map +1 -0
  587. package/build/dist/Server/Services/MessageQueueLabelRuleService.js +13 -0
  588. package/build/dist/Server/Services/MessageQueueLabelRuleService.js.map +1 -0
  589. package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js +334 -0
  590. package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js.map +1 -0
  591. package/build/dist/Server/Services/MessageQueueOwnerRuleService.js +13 -0
  592. package/build/dist/Server/Services/MessageQueueOwnerRuleService.js.map +1 -0
  593. package/build/dist/Server/Services/MessageQueueOwnerTeamService.js +62 -0
  594. package/build/dist/Server/Services/MessageQueueOwnerTeamService.js.map +1 -0
  595. package/build/dist/Server/Services/MessageQueueOwnerUserService.js +62 -0
  596. package/build/dist/Server/Services/MessageQueueOwnerUserService.js.map +1 -0
  597. package/build/dist/Server/Services/MessageQueueService.js +1140 -0
  598. package/build/dist/Server/Services/MessageQueueService.js.map +1 -0
  599. package/build/dist/Server/Services/OpenTelemetryIngestService.js +25 -4
  600. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  601. package/build/dist/Server/Services/ProjectService.js +0 -54
  602. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  603. package/build/dist/Server/Services/StatusPagePrivateUserService.js +1 -4
  604. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  605. package/build/dist/Server/Services/StatusPageService.js +0 -46
  606. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  607. package/build/dist/Server/Services/TeamComplianceSettingService.js +120 -31
  608. package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
  609. package/build/dist/Server/Services/UserNotificationRuleService.js +8 -1
  610. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  611. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +12 -3
  612. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
  613. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +6 -3
  614. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  615. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +109 -37
  616. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
  617. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +16 -0
  618. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  619. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +3 -3
  620. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +9 -6
  621. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
  622. package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js +128 -0
  623. package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js.map +1 -0
  624. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +192 -50
  625. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
  626. package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js +133 -0
  627. package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js.map +1 -0
  628. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +53 -13
  629. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  630. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
  631. package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js +206 -0
  632. package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js.map +1 -0
  633. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +53 -26
  634. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
  635. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +4 -2
  636. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
  637. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +1 -29
  638. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
  639. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +24 -24
  640. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
  641. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +7 -2
  642. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
  643. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +29 -14
  644. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  645. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +38 -14
  646. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -1
  647. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +2 -0
  648. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -1
  649. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +40 -10
  650. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  651. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +19 -7
  652. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  653. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +19 -7
  654. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  655. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +15 -18
  656. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
  657. package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js +412 -0
  658. package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js.map +1 -0
  659. package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js +495 -0
  660. package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js.map +1 -0
  661. package/build/dist/Server/Utils/AI/Toolbox/Serializer.js +10 -3
  662. package/build/dist/Server/Utils/AI/Toolbox/Serializer.js.map +1 -1
  663. package/build/dist/Server/Utils/EditionEnforcement.js +20 -158
  664. package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -1
  665. package/build/dist/Server/Utils/LLM/LLMService.js +193 -54
  666. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  667. package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js +160 -0
  668. package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js.map +1 -0
  669. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
  670. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
  671. package/build/dist/Server/Utils/SameOriginRequest.js +151 -0
  672. package/build/dist/Server/Utils/SameOriginRequest.js.map +1 -0
  673. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
  674. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
  675. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +4 -1
  676. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  677. package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js +1015 -0
  678. package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js.map +1 -0
  679. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +4 -1
  680. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
  681. package/build/dist/Server/Utils/VendorAssets.js +3 -3
  682. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +3 -1
  683. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
  684. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +3 -1
  685. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
  686. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +10 -1
  687. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  688. package/build/dist/Types/AI/AIAgentRunLimits.js +91 -0
  689. package/build/dist/Types/AI/AIAgentRunLimits.js.map +1 -0
  690. package/build/dist/Types/Code/CodeType.js +2 -0
  691. package/build/dist/Types/Code/CodeType.js.map +1 -1
  692. package/build/dist/Types/Code/JsonSyntax.js +604 -0
  693. package/build/dist/Types/Code/JsonSyntax.js.map +1 -0
  694. package/build/dist/Types/CustomField/CustomFieldCreateSettings.js +310 -0
  695. package/build/dist/Types/CustomField/CustomFieldCreateSettings.js.map +1 -0
  696. package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js +38 -0
  697. package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js.map +1 -1
  698. package/build/dist/Types/CustomField/CustomFieldValueValidator.js +10 -7
  699. package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -1
  700. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +1 -1
  701. package/build/dist/Types/Icon/IconProp.js +2 -0
  702. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  703. package/build/dist/Types/Incident/IncidentFormIpAllowlist.js +119 -0
  704. package/build/dist/Types/Incident/IncidentFormIpAllowlist.js.map +1 -0
  705. package/build/dist/Types/Incident/IncidentFormPublic.js +678 -0
  706. package/build/dist/Types/Incident/IncidentFormPublic.js.map +1 -0
  707. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +10 -3
  708. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
  709. package/build/dist/Types/MessageQueue/MessageQueueIdentity.js +184 -0
  710. package/build/dist/Types/MessageQueue/MessageQueueIdentity.js.map +1 -0
  711. package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js +190 -0
  712. package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js.map +1 -0
  713. package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js +1057 -0
  714. package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js.map +1 -0
  715. package/build/dist/Types/MessageQueue/MessagingSystem.js +394 -0
  716. package/build/dist/Types/MessageQueue/MessagingSystem.js.map +1 -0
  717. package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js +1768 -0
  718. package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js.map +1 -0
  719. package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js +1207 -0
  720. package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js.map +1 -0
  721. package/build/dist/Types/Permission.js +274 -0
  722. package/build/dist/Types/Permission.js.map +1 -1
  723. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +10 -4
  724. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -1
  725. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +12 -0
  726. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
  727. package/build/dist/Types/Rules/RuleRun.js +4 -0
  728. package/build/dist/Types/Rules/RuleRun.js.map +1 -1
  729. package/build/dist/Types/Team/ComplianceNotificationChannel.js +4 -3
  730. package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -1
  731. package/build/dist/Types/Team/ComplianceRule.js +48 -14
  732. package/build/dist/Types/Team/ComplianceRule.js.map +1 -1
  733. package/build/dist/Types/Team/ComplianceRuleType.js +2 -2
  734. package/build/dist/Types/Telemetry/EntityType.js +16 -0
  735. package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
  736. package/build/dist/Types/XML.js +23 -0
  737. package/build/dist/Types/XML.js.map +1 -1
  738. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +641 -266
  739. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  740. package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js +464 -0
  741. package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js.map +1 -0
  742. package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js +69 -0
  743. package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js.map +1 -0
  744. package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js +108 -0
  745. package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js.map +1 -0
  746. package/build/dist/UI/Components/CodeEditor/YamlEditor.js +14 -186
  747. package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -1
  748. package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js +5 -1
  749. package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js.map +1 -1
  750. package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js +5 -14
  751. package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -1
  752. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +14 -13
  753. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  754. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +1 -1
  755. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
  756. package/build/dist/UI/Components/Forms/Fields/FormField.js +8 -3
  757. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  758. package/build/dist/UI/Components/Icon/Icon.js +8 -0
  759. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  760. package/build/dist/UI/Components/Input/Input.js +11 -3
  761. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  762. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +2 -1
  763. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  764. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +14 -4
  765. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
  766. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  767. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  768. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +710 -65
  769. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
  770. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js +238 -0
  771. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js.map +1 -0
  772. package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js +1028 -0
  773. package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js.map +1 -0
  774. package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js +1088 -0
  775. package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js.map +1 -0
  776. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +70 -10
  777. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  778. package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js +887 -0
  779. package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js.map +1 -0
  780. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +57 -6
  781. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  782. package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js +7 -5
  783. package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js.map +1 -1
  784. package/build/dist/UI/Components/Table/EmptyTableMessage.js +51 -0
  785. package/build/dist/UI/Components/Table/EmptyTableMessage.js.map +1 -0
  786. package/build/dist/UI/Components/Table/Table.js +30 -11
  787. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  788. package/build/dist/UI/Components/Table/TableRow.js +9 -2
  789. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  790. package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +63 -1
  791. package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -1
  792. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +4 -2
  793. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  794. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +91 -10
  795. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -1
  796. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +14 -4
  797. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
  798. package/build/dist/UI/Components/TextArea/TextArea.js +9 -3
  799. package/build/dist/UI/Components/TextArea/TextArea.js.map +1 -1
  800. package/build/dist/UI/Components/Workflow/ModelFieldPicker.js +1 -2
  801. package/build/dist/UI/Components/Workflow/ModelFieldPicker.js.map +1 -1
  802. package/build/dist/Utils/LabelRuleImportExport.js +2 -0
  803. package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
  804. package/build/dist/Utils/Markdown/UntrustedMarkdown.js +988 -0
  805. package/build/dist/Utils/Markdown/UntrustedMarkdown.js.map +1 -0
  806. package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js +34 -0
  807. package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js.map +1 -0
  808. package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js +148 -0
  809. package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js.map +1 -0
  810. package/build/dist/Utils/Telemetry/EntityKey.js +36 -0
  811. package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
  812. package/package.json +1 -3
  813. package/Server/Utils/CommunityEditionSsoReport.ts +0 -361
  814. package/Tests/App/Accounts/LoginSsoEdition.test.tsx +0 -616
  815. package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +0 -217
  816. package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +0 -271
  817. package/Tests/App/Dashboard/CloudDocumentationMarkdown.test.ts +0 -215
  818. package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +0 -784
  819. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +0 -518
  820. package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +0 -419
  821. package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +0 -769
  822. package/Tests/UI/Components/CodeEditor.test.tsx +0 -638
  823. package/Tests/UI/Components/MonacoLoader.test.ts +0 -67
  824. package/Tests/UI/Components/MonacoRuntime.test.ts +0 -121
  825. package/Tests/UI/Components/Telemetry/TelemetryRetentionConfigForm.test.tsx +0 -329
  826. package/Tests/UI/Components/YamlEditor.test.tsx +0 -847
  827. package/UI/Components/CodeEditor/MonacoLoader.ts +0 -36
  828. package/UI/Components/Telemetry/TelemetryRetentionConfigForm.tsx +0 -319
  829. package/UI/Components/Telemetry/TelemetryRetentionConfigSummary.tsx +0 -223
  830. package/build/dist/Server/Utils/CommunityEditionSsoReport.js +0 -223
  831. package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +0 -1
  832. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js +0 -34
  833. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js.map +0 -1
  834. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js +0 -171
  835. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js.map +0 -1
  836. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js +0 -119
  837. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js.map +0 -1
@@ -1,14 +1,33 @@
1
1
  import { afterEach, describe, expect, jest, test } from "@jest/globals";
2
2
  import "@testing-library/jest-dom";
3
- import { cleanup, render, screen, within } from "@testing-library/react";
3
+ import {
4
+ cleanup,
5
+ fireEvent,
6
+ render,
7
+ screen,
8
+ within,
9
+ } from "@testing-library/react";
4
10
  import React, { ReactElement, ReactNode } from "react";
5
11
 
6
12
  /*
7
- * AffectedResourcesDisplay groups an event's resources into category cards.
13
+ * AffectedResourcesDisplay is the body of the "Affected Resources" card on
14
+ * the incident, alert and scheduled maintenance overview pages (and of the
15
+ * templates' cards). It groups an event's resources by category.
16
+ *
17
+ * Each category used to be a card of its own - bordered, shadowed, rounded,
18
+ * with a coloured bar across its top - so the page's card read as a stack of
19
+ * cards nested inside a card. The categories are now flat sections of the one
20
+ * card: a small tinted icon, the label and its count, then the resources
21
+ * indented under the label, split by hairlines like the details card's rows.
22
+ *
8
23
  * Its grid used to follow the viewport alone (two columns from md up), so on
9
- * an overview page's ~300px sidebar two cards shared the width and every name
10
- * was clipped mid-word ("Checkout A"). Callers in a narrow column now ask for
11
- * one column, and a long name ends in an ellipsis with the full name on hover.
24
+ * an overview page's ~300px sidebar two categories shared the width and every
25
+ * name was clipped mid-word ("Checkout A"). Callers in a narrow column ask
26
+ * for one column, and a long name ends in an ellipsis with the full name on
27
+ * hover.
28
+ *
29
+ * Browser-level checks (computed styles, the stretched link, hover, focus,
30
+ * dark mode) live in packages/E2E/EventOverview.
12
31
  */
13
32
 
14
33
  jest.mock(
@@ -32,90 +51,289 @@ jest.mock(
32
51
  );
33
52
 
34
53
  import AffectedResourcesDisplay, {
54
+ AFFECTED_RESOURCE_ITEM_CLASS_NAME,
35
55
  getAffectedResourcesGridClassName,
56
+ getAffectedResourcesSectionClassName,
36
57
  } from "../../../../App/FeatureSet/Dashboard/src/Components/AffectedResources/AffectedResourcesDisplay";
37
58
  import AffectedResourcesCell from "../../../../App/FeatureSet/Dashboard/src/Components/AffectedResources/AffectedResourcesCell";
59
+ import CephCluster from "../../../Models/DatabaseModels/CephCluster";
60
+ import DatabaseServer from "../../../Models/DatabaseModels/DatabaseServer";
61
+ import DockerHost from "../../../Models/DatabaseModels/DockerHost";
62
+ import DockerSwarmCluster from "../../../Models/DatabaseModels/DockerSwarmCluster";
63
+ import Host from "../../../Models/DatabaseModels/Host";
64
+ import IoTFleet from "../../../Models/DatabaseModels/IoTFleet";
65
+ import KubernetesCluster from "../../../Models/DatabaseModels/KubernetesCluster";
38
66
  import Monitor from "../../../Models/DatabaseModels/Monitor";
67
+ import NetworkSite from "../../../Models/DatabaseModels/NetworkSite";
68
+ import PodmanHost from "../../../Models/DatabaseModels/PodmanHost";
69
+ import ProxmoxCluster from "../../../Models/DatabaseModels/ProxmoxCluster";
39
70
  import Service from "../../../Models/DatabaseModels/Service";
40
- import Host from "../../../Models/DatabaseModels/Host";
41
- import DatabaseServer from "../../../Models/DatabaseModels/DatabaseServer";
71
+ import ServiceLevelObjective from "../../../Models/DatabaseModels/ServiceLevelObjective";
72
+ import VMwareVCenter from "../../../Models/DatabaseModels/VMwareVCenter";
42
73
  import Color from "../../../Types/Color";
43
74
 
44
75
  const LONG_MONITOR_NAME: string =
45
76
  "Checkout API p95 latency above two seconds in eu-west-1";
46
77
 
47
- type BuildMonitorFunction = (id: string, name: string) => Monitor;
78
+ interface NamedModel {
79
+ _id?: string | undefined;
80
+ name?: string | undefined;
81
+ }
48
82
 
49
- const buildMonitor: BuildMonitorFunction = (
83
+ type NamedFunction = <T extends NamedModel>(
84
+ type: new () => T,
50
85
  id: string,
51
86
  name: string,
87
+ ) => T;
88
+
89
+ const named: NamedFunction = <T extends NamedModel>(
90
+ type: new () => T,
91
+ id: string,
92
+ name: string,
93
+ ): T => {
94
+ const model: T = new type();
95
+ model._id = id;
96
+ model.name = name;
97
+ return model;
98
+ };
99
+
100
+ type IdFunction = (hex: string, n: number) => string;
101
+
102
+ // A valid UUID per model and index: "aaaaaaaa-aaaa-4aaa-8aaa-000000000001".
103
+ const id: IdFunction = (hex: string, n: number): string => {
104
+ const block: string = hex.repeat(8);
105
+
106
+ return `${block}-${hex.repeat(4)}-4${hex.repeat(3)}-8${hex.repeat(3)}-${String(n).padStart(12, "0")}`;
107
+ };
108
+
109
+ type BuildMonitorFunction = (n: number, name: string) => Monitor;
110
+
111
+ const buildMonitor: BuildMonitorFunction = (
112
+ n: number,
113
+ name: string,
52
114
  ): Monitor => {
53
- const monitor: Monitor = new Monitor();
54
- monitor._id = id;
55
- monitor.name = name;
56
- return monitor;
115
+ return named(Monitor, id("a", n), name);
116
+ };
117
+
118
+ type BuildMonitorsFunction = (count: number) => Array<Monitor>;
119
+
120
+ const buildMonitors: BuildMonitorsFunction = (
121
+ count: number,
122
+ ): Array<Monitor> => {
123
+ return Array.from({ length: count }, (_: unknown, i: number): Monitor => {
124
+ return buildMonitor(i + 1, `probe-${String(i + 1).padStart(3, "0")}`);
125
+ });
57
126
  };
58
127
 
59
- type BuildServiceFunction = (id: string, name: string) => Service;
128
+ type BuildServiceFunction = (n: number, name: string) => Service;
60
129
 
61
130
  const buildService: BuildServiceFunction = (
62
- id: string,
131
+ n: number,
63
132
  name: string,
64
133
  ): Service => {
65
- const service: Service = new Service();
66
- service._id = id;
67
- service.name = name;
134
+ const service: Service = named(Service, id("b", n), name);
68
135
  service.serviceColor = new Color("#6366f1");
69
136
  return service;
70
137
  };
71
138
 
72
139
  const MONITORS: Array<Monitor> = [
73
- buildMonitor("aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaa1", LONG_MONITOR_NAME),
74
- buildMonitor("aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaa2", "orders-db primary"),
140
+ buildMonitor(1, LONG_MONITOR_NAME),
141
+ buildMonitor(2, "orders-db primary"),
75
142
  ];
76
143
 
77
- const SERVICES: Array<Service> = [
78
- buildService("bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbb1", "checkout-api"),
79
- ];
144
+ const SERVICES: Array<Service> = [buildService(1, "checkout-api")];
80
145
 
81
146
  afterEach(() => {
82
147
  cleanup();
83
148
  });
84
149
 
150
+ /*
151
+ * Every class token on an element and its descendants: what the stylesheet
152
+ * can paint on this display, whatever the markup nests.
153
+ */
154
+ function classTokensWithin(element: Element): Array<string> {
155
+ return [element, ...Array.from(element.querySelectorAll("*"))].flatMap(
156
+ (node: Element): Array<string> => {
157
+ return Array.from(node.classList);
158
+ },
159
+ );
160
+ }
161
+
162
+ /*
163
+ * What made a category a card: a border (other than the grid's hairlines,
164
+ * which are divide-* on the grid), a shadow, a white fill of its own, card
165
+ * rounding, a ring, clipping, and the coloured bar across its top.
166
+ */
167
+ const BORDER_OR_SHADOW: RegExp = /^(hover:)?(border|shadow)(-|$)/;
168
+ const RING: RegExp = /^ring(-|$)/;
169
+ const CARD_ROUNDING: RegExp = /^rounded-(lg|xl|2xl|3xl)$/;
170
+
171
+ function cardChromeIn(element: Element): Array<string> {
172
+ return classTokensWithin(element).filter((token: string): boolean => {
173
+ return (
174
+ BORDER_OR_SHADOW.test(token) ||
175
+ RING.test(token) ||
176
+ token === "bg-white" ||
177
+ token === "overflow-hidden" ||
178
+ CARD_ROUNDING.test(token) ||
179
+ token === "h-1"
180
+ );
181
+ });
182
+ }
183
+
184
+ type SectionsFunction = () => Array<HTMLElement>;
185
+
186
+ const sections: SectionsFunction = (): Array<HTMLElement> => {
187
+ return screen.getAllByTestId("affected-resource-category");
188
+ };
189
+
190
+ type HeadingNamesFunction = () => Array<string>;
191
+
192
+ // The category headings, as a screen reader names them: label, then count.
193
+ const headingNames: HeadingNamesFunction = (): Array<string> => {
194
+ return screen
195
+ .getAllByRole("heading", { level: 3 })
196
+ .map((heading: HTMLElement): string => {
197
+ return (heading.textContent || "").replace(/\s+/g, " ").trim();
198
+ });
199
+ };
200
+
85
201
  describe("getAffectedResourcesGridClassName", () => {
86
- test("follows the viewport by default: one column, two from md up", () => {
87
- expect(getAffectedResourcesGridClassName(undefined)).toBe(
88
- "grid grid-cols-1 gap-3 md:grid-cols-2",
202
+ test("one column stacks the sections, split by hairlines", () => {
203
+ expect(getAffectedResourcesGridClassName(1)).toBe(
204
+ "grid grid-cols-1 divide-y divide-gray-100",
205
+ );
206
+ });
207
+
208
+ test("by default the sections sit two abreast from md up, spaced instead of divided", () => {
209
+ const className: string = getAffectedResourcesGridClassName(undefined);
210
+
211
+ expect(className).toBe(
212
+ "grid grid-cols-1 divide-y divide-gray-100 md:grid-cols-2 md:gap-x-10 md:gap-y-6 md:divide-y-0",
213
+ );
214
+ // Phones still get one divided column.
215
+ expect(className.split(" ")).toEqual(
216
+ expect.arrayContaining(["grid-cols-1", "divide-y", "divide-gray-100"]),
89
217
  );
90
218
  });
91
219
 
92
220
  test("two columns is the same viewport-based grid", () => {
93
221
  expect(getAffectedResourcesGridClassName(2)).toBe(
94
- "grid grid-cols-1 gap-3 md:grid-cols-2",
222
+ getAffectedResourcesGridClassName(undefined),
95
223
  );
96
224
  });
97
225
 
98
226
  test("one column never splits, whatever the viewport", () => {
99
227
  const className: string = getAffectedResourcesGridClassName(1);
100
228
 
101
- expect(className).toBe("grid grid-cols-1 gap-3");
102
229
  expect(className).not.toContain("md:grid-cols-2");
230
+ expect(className).not.toContain("md:divide-y-0");
231
+ });
232
+
233
+ test("no layout spaces the sections with a gap between cards", () => {
234
+ for (const columns of [1, 2, undefined] as const) {
235
+ expect(getAffectedResourcesGridClassName(columns).split(" ")).not.toEqual(
236
+ expect.arrayContaining(["gap-3"]),
237
+ );
238
+ }
103
239
  });
104
240
  });
105
241
 
106
- describe("AffectedResourcesDisplay columns", () => {
107
- test("renders today's two-column grid when columns is left out", () => {
242
+ describe("getAffectedResourcesSectionClassName", () => {
243
+ test("in one column a section is padded between hairlines, flush at both ends", () => {
244
+ expect(getAffectedResourcesSectionClassName(1)).toBe(
245
+ "min-w-0 py-4 first:pt-0 last:pb-0",
246
+ );
247
+ });
248
+
249
+ test("side by side the padding goes, since whitespace separates the sections", () => {
250
+ expect(getAffectedResourcesSectionClassName(undefined)).toBe(
251
+ "min-w-0 py-4 first:pt-0 last:pb-0 md:py-0",
252
+ );
253
+ expect(getAffectedResourcesSectionClassName(2)).toBe(
254
+ getAffectedResourcesSectionClassName(undefined),
255
+ );
256
+ });
257
+
258
+ test("the grid and its sections agree on the layout", () => {
259
+ render(
260
+ <AffectedResourcesDisplay
261
+ monitors={MONITORS}
262
+ services={SERVICES}
263
+ columns={1}
264
+ />,
265
+ );
266
+
267
+ for (const section of sections()) {
268
+ expect(section.className).toBe(getAffectedResourcesSectionClassName(1));
269
+ }
270
+
271
+ cleanup();
108
272
  render(
109
273
  <AffectedResourcesDisplay monitors={MONITORS} services={SERVICES} />,
110
274
  );
111
275
 
112
- const grid: HTMLElement = screen.getByTestId("affected-resources-grid");
276
+ for (const section of sections()) {
277
+ expect(section.className).toBe(
278
+ getAffectedResourcesSectionClassName(undefined),
279
+ );
280
+ }
281
+ });
282
+ });
113
283
 
114
- expect(grid).toHaveClass("grid", "grid-cols-1", "gap-3", "md:grid-cols-2");
115
- expect(grid.children).toHaveLength(2);
284
+ describe("AffectedResourcesDisplay: sections of one card, not cards in a card", () => {
285
+ const EVERY_CATEGORY: Array<ReactElement> = [
286
+ <AffectedResourcesDisplay
287
+ key="sidebar"
288
+ monitors={buildMonitors(7)}
289
+ hosts={[named(Host, id("c", 1), "web-01")]}
290
+ services={SERVICES}
291
+ serviceLevelObjectives={[
292
+ named(ServiceLevelObjective, id("d", 1), "Checkout availability"),
293
+ ]}
294
+ columns={1}
295
+ />,
296
+ <AffectedResourcesDisplay
297
+ key="full-width"
298
+ monitors={buildMonitors(7)}
299
+ hosts={[named(Host, id("c", 1), "web-01")]}
300
+ services={SERVICES}
301
+ />,
302
+ ];
303
+
304
+ test.each([
305
+ ["the sidebar layout", 0],
306
+ ["the full-width layout", 1],
307
+ ])(
308
+ "no category in %s carries a border, shadow, fill, card rounding or accent bar",
309
+ (_layout: string, index: number) => {
310
+ const { container } = render(EVERY_CATEGORY[index]!);
311
+
312
+ expect(sections().length).toBeGreaterThan(1);
313
+ expect(cardChromeIn(container)).toEqual([]);
314
+ },
315
+ );
316
+
317
+ test("a category is a plain section: its own classes are only layout", () => {
318
+ render(
319
+ <AffectedResourcesDisplay
320
+ monitors={MONITORS}
321
+ services={SERVICES}
322
+ columns={1}
323
+ />,
324
+ );
325
+
326
+ for (const section of sections()) {
327
+ expect(section.className.split(" ")).toEqual([
328
+ "min-w-0",
329
+ "py-4",
330
+ "first:pt-0",
331
+ "last:pb-0",
332
+ ]);
333
+ }
116
334
  });
117
335
 
118
- test("renders one column for a narrow sidebar", () => {
336
+ test("the sections are split by the grid's hairlines, not spaced apart as tiles", () => {
119
337
  render(
120
338
  <AffectedResourcesDisplay
121
339
  monitors={MONITORS}
@@ -126,21 +344,260 @@ describe("AffectedResourcesDisplay columns", () => {
126
344
 
127
345
  const grid: HTMLElement = screen.getByTestId("affected-resources-grid");
128
346
 
129
- expect(grid).toHaveClass("grid", "grid-cols-1", "gap-3");
130
- expect(grid).not.toHaveClass("md:grid-cols-2");
131
- // Both categories still render, one under the other.
132
- expect(within(grid).getByText("Monitors")).toBeInTheDocument();
133
- expect(within(grid).getByText("Services")).toBeInTheDocument();
347
+ expect(grid).toHaveClass("divide-y", "divide-gray-100");
348
+ expect(grid).not.toHaveClass("gap-3");
349
+ expect(Array.from(grid.children)).toEqual(sections());
350
+ });
351
+
352
+ test("expanding a category and hitting the cap adds no box either", () => {
353
+ const { container } = render(
354
+ <AffectedResourcesDisplay monitors={buildMonitors(130)} columns={1} />,
355
+ );
356
+
357
+ fireEvent.click(screen.getByRole("button", { name: "Show 96 more" }));
358
+
359
+ expect(
360
+ screen.getByTestId("affected-resource-truncated-note"),
361
+ ).toBeInTheDocument();
362
+ expect(cardChromeIn(container)).toEqual([]);
363
+ // The note is tinted text, not a tinted banner.
364
+ expect(
365
+ classTokensWithin(screen.getByTestId("affected-resource-truncated-note")),
366
+ ).not.toEqual(expect.arrayContaining(["bg-amber-50"]));
367
+ });
368
+
369
+ test("the empty state is open text inside the card, not a dashed box", () => {
370
+ const { container } = render(<AffectedResourcesDisplay columns={1} />);
371
+
372
+ expect(screen.getByTestId("affected-resources-empty")).toBeInTheDocument();
373
+ expect(cardChromeIn(container)).toEqual([]);
374
+ expect(classTokensWithin(container)).not.toEqual(
375
+ expect.arrayContaining(["border-dashed"]),
376
+ );
377
+ expect(classTokensWithin(container)).not.toEqual(
378
+ expect.arrayContaining(["bg-gray-50/50"]),
379
+ );
380
+ });
381
+ });
382
+
383
+ describe("AffectedResourcesDisplay: category headings", () => {
384
+ const ALL_CATEGORIES: ReactElement = (
385
+ <AffectedResourcesDisplay
386
+ monitors={[buildMonitor(1, "api.acme.com")]}
387
+ hosts={[named(Host, id("c", 1), "web-01")]}
388
+ kubernetesClusters={[
389
+ named(KubernetesCluster, id("e", 1), "prod-eks-eu-west-1"),
390
+ ]}
391
+ dockerHosts={[named(DockerHost, id("f", 1), "docker-edge-01")]}
392
+ podmanHosts={[named(PodmanHost, id("1", 1), "podman-01")]}
393
+ proxmoxClusters={[named(ProxmoxCluster, id("2", 1), "pve-lab")]}
394
+ vmwareVCenters={[named(VMwareVCenter, id("3", 1), "vcenter-01")]}
395
+ cephClusters={[named(CephCluster, id("4", 1), "ceph-prod")]}
396
+ dockerSwarmClusters={[named(DockerSwarmCluster, id("5", 1), "swarm-1")]}
397
+ iotFleets={[named(IoTFleet, id("6", 1), "sensors-eu")]}
398
+ databaseServers={[
399
+ named(DatabaseServer, id("7", 1), "PostgreSQL db.prod:5432"),
400
+ ]}
401
+ networkSites={[named(NetworkSite, id("9", 1), "Frankfurt DC")]}
402
+ services={[buildService(1, "checkout-api"), buildService(2, "payments")]}
403
+ serviceLevelObjectives={[
404
+ named(ServiceLevelObjective, id("d", 1), "Checkout availability"),
405
+ ]}
406
+ columns={1}
407
+ />
408
+ );
409
+
410
+ /*
411
+ * Label, then the icon tile's tint and the icon's colour. Each pair has a
412
+ * dark-mode remap in Theme.css (see AffectedResourcesDisplayDarkMode in the
413
+ * App tests).
414
+ */
415
+ const CATEGORIES: Array<[string, string, string]> = [
416
+ ["Monitors", "bg-blue-50", "text-blue-600"],
417
+ ["Hosts", "bg-emerald-50", "text-emerald-600"],
418
+ ["Kubernetes Clusters", "bg-indigo-50", "text-indigo-600"],
419
+ ["Docker Hosts", "bg-sky-50", "text-sky-600"],
420
+ ["Podman Hosts", "bg-violet-50", "text-violet-600"],
421
+ ["Proxmox Clusters", "bg-orange-50", "text-orange-600"],
422
+ ["vCenters", "bg-sky-50", "text-sky-600"],
423
+ ["Ceph Clusters", "bg-rose-50", "text-rose-600"],
424
+ ["Docker Swarm Clusters", "bg-cyan-50", "text-cyan-600"],
425
+ ["IoT Fleets", "bg-teal-50", "text-teal-600"],
426
+ ["Databases", "bg-purple-50", "text-purple-600"],
427
+ ["Network Sites", "bg-indigo-50", "text-indigo-600"],
428
+ ["Services", "bg-amber-50", "text-amber-600"],
429
+ ["SLOs", "bg-fuchsia-50", "text-fuchsia-600"],
430
+ ];
431
+
432
+ test("every category is a level-3 heading naming its label and count, in a fixed order", () => {
433
+ render(ALL_CATEGORIES);
434
+
435
+ expect(headingNames()).toEqual(
436
+ CATEGORIES.map(([label]: [string, string, string]): string => {
437
+ return label === "Services" ? `${label} 2` : `${label} 1`;
438
+ }),
439
+ );
440
+ });
441
+
442
+ test.each(CATEGORIES)(
443
+ "%s has its own tinted icon tile beside the label",
444
+ (label: string, tint: string, iconColour: string) => {
445
+ render(ALL_CATEGORIES);
446
+
447
+ const section: HTMLElement = sections().find(
448
+ (candidate: HTMLElement): boolean => {
449
+ return (
450
+ within(candidate).getByRole("heading", { level: 3 })
451
+ .firstElementChild?.textContent === label
452
+ );
453
+ },
454
+ )!;
455
+ const tile: HTMLElement = section.firstElementChild!
456
+ .firstElementChild as HTMLElement;
457
+
458
+ expect(tile).toHaveClass(
459
+ "flex",
460
+ "h-6",
461
+ "w-6",
462
+ "shrink-0",
463
+ "items-center",
464
+ "justify-center",
465
+ "rounded-md",
466
+ tint,
467
+ );
468
+ expect(tile.querySelector("svg")).toHaveClass(
469
+ "h-3.5",
470
+ "w-3.5",
471
+ iconColour,
472
+ );
473
+ // The tile is not part of the heading: an icon is no part of the name.
474
+ expect(
475
+ within(section).getByRole("heading", { level: 3 }),
476
+ ).not.toContainElement(tile);
477
+ },
478
+ );
479
+
480
+ test("each list is named by its heading, so the count is read before the items", () => {
481
+ render(
482
+ <AffectedResourcesDisplay
483
+ monitors={buildMonitors(7)}
484
+ services={SERVICES}
485
+ columns={1}
486
+ />,
487
+ );
488
+
489
+ const monitors: HTMLElement = screen.getByRole("list", {
490
+ name: "Monitors 7",
491
+ });
492
+ const services: HTMLElement = screen.getByRole("list", {
493
+ name: "Services 1",
494
+ });
495
+
496
+ expect(within(monitors).getAllByRole("listitem")).toHaveLength(4);
497
+ expect(within(services).getAllByRole("listitem")).toHaveLength(1);
498
+ });
499
+
500
+ test("the count covers every item, including those behind Show more", () => {
501
+ render(<AffectedResourcesDisplay monitors={buildMonitors(12)} />);
502
+
503
+ expect(
504
+ screen.getByTestId("affected-resource-category-count"),
505
+ ).toHaveTextContent(/^12$/);
506
+ expect(screen.getAllByTestId("affected-resource-item")).toHaveLength(4);
507
+ });
508
+
509
+ test("a four-digit count is grouped the way the locale groups it", () => {
510
+ render(<AffectedResourcesDisplay monitors={buildMonitors(1200)} />);
511
+
512
+ expect(
513
+ screen.getByTestId("affected-resource-category-count"),
514
+ ).toHaveTextContent((1200).toLocaleString());
515
+ });
516
+
517
+ test("the label can truncate but the count never shrinks, and it sits right after the label", () => {
518
+ render(<AffectedResourcesDisplay monitors={MONITORS} columns={1} />);
519
+
520
+ const heading: HTMLElement = screen.getByRole("heading", { level: 3 });
521
+ const label: HTMLElement = within(heading).getByText("Monitors");
522
+ const count: HTMLElement = within(heading).getByText("2");
523
+
524
+ expect(heading).toHaveClass("flex", "min-w-0", "flex-1", "items-center");
525
+ expect(label).toHaveClass("min-w-0", "truncate");
526
+ // Not pushed to the far edge: in a wide card that parted it from its label.
527
+ expect(label).not.toHaveClass("flex-1");
528
+ expect(count).toHaveClass("shrink-0", "rounded-full", "tabular-nums");
529
+ expect(label.nextElementSibling).toBe(count);
530
+ });
531
+
532
+ test("the resources are indented under the label, past the icon tile", () => {
533
+ render(<AffectedResourcesDisplay monitors={MONITORS} columns={1} />);
534
+
535
+ // The tile is h-6 w-6 and the header row has gap-2: 24px + 8px = pl-8.
536
+ expect(screen.getByRole("list")).toHaveClass("pl-8");
537
+ expect(screen.getByRole("heading", { level: 3 }).parentElement).toHaveClass(
538
+ "flex",
539
+ "items-center",
540
+ "gap-2",
541
+ );
542
+ });
543
+
544
+ test("hidden categories are left out of the headings", () => {
545
+ render(
546
+ <AffectedResourcesDisplay
547
+ monitors={MONITORS}
548
+ services={SERVICES}
549
+ hideMonitors={true}
550
+ columns={1}
551
+ />,
552
+ );
553
+
554
+ expect(headingNames()).toEqual(["Services 1"]);
555
+ });
556
+ });
557
+
558
+ describe("AffectedResourcesDisplay: summary", () => {
559
+ test("two or more categories add up to one line above them", () => {
560
+ render(
561
+ <AffectedResourcesDisplay
562
+ monitors={MONITORS}
563
+ services={SERVICES}
564
+ columns={1}
565
+ />,
566
+ );
567
+
568
+ const summary: HTMLElement = screen.getByTestId(
569
+ "affected-resources-summary",
570
+ );
571
+
572
+ expect(summary).toHaveTextContent("3 resources across 2 categories");
573
+ // The total is the emphasised part.
574
+ expect(within(summary).getByText("3 resources")).toHaveClass(
575
+ "font-semibold",
576
+ "text-gray-900",
577
+ );
578
+ expect(screen.getByText("across 2 categories")).toBe(summary);
579
+ expect(summary.nextElementSibling).toBe(
580
+ screen.getByTestId("affected-resources-grid"),
581
+ );
582
+ });
583
+
584
+ test("a single category counts itself in its heading, so there is no summary", () => {
585
+ render(<AffectedResourcesDisplay monitors={MONITORS} columns={1} />);
586
+
587
+ expect(screen.queryByTestId("affected-resources-summary")).toBeNull();
588
+ expect(screen.queryByText(/across/)).toBeNull();
589
+ expect(headingNames()).toEqual(["Monitors 2"]);
134
590
  });
135
591
 
136
- test("keeps the summary counts in either layout", () => {
592
+ test("the summary reads the same in either layout, with no separator to dangle", () => {
137
593
  const { rerender } = render(
138
594
  <AffectedResourcesDisplay monitors={MONITORS} services={SERVICES} />,
139
595
  );
140
596
 
141
- expect(screen.getByText("3 resources")).toBeInTheDocument();
142
- expect(screen.getByText("across 2 categories")).toBeInTheDocument();
143
- expect(screen.getByText("·")).toBeInTheDocument();
597
+ expect(screen.getByTestId("affected-resources-summary")).toHaveTextContent(
598
+ "3 resources across 2 categories",
599
+ );
600
+ expect(screen.queryByText("·")).toBeNull();
144
601
 
145
602
  rerender(
146
603
  <AffectedResourcesDisplay
@@ -150,23 +607,42 @@ describe("AffectedResourcesDisplay columns", () => {
150
607
  />,
151
608
  );
152
609
 
153
- expect(screen.getByText("3 resources")).toBeInTheDocument();
154
- expect(screen.getByText("across 2 categories")).toBeInTheDocument();
155
- // The separator would dangle at the end of a wrapped first line.
610
+ expect(screen.getByTestId("affected-resources-summary")).toHaveTextContent(
611
+ "3 resources across 2 categories",
612
+ );
156
613
  expect(screen.queryByText("·")).toBeNull();
157
614
  });
158
615
 
159
- test("the empty state does not depend on columns", () => {
616
+ test("a hidden category is not added up", () => {
160
617
  render(
161
- <AffectedResourcesDisplay columns={1} emptyMessage="Nothing hit." />,
618
+ <AffectedResourcesDisplay
619
+ monitors={MONITORS}
620
+ services={SERVICES}
621
+ hosts={[named(Host, id("c", 1), "web-01")]}
622
+ hideHosts={true}
623
+ />,
162
624
  );
163
625
 
164
- expect(screen.getByText("Nothing hit.")).toBeInTheDocument();
165
- expect(screen.queryByTestId("affected-resources-grid")).toBeNull();
626
+ expect(screen.getByTestId("affected-resources-summary")).toHaveTextContent(
627
+ "3 resources across 2 categories",
628
+ );
629
+ });
630
+
631
+ test("large totals are grouped the way the locale groups them", () => {
632
+ render(
633
+ <AffectedResourcesDisplay
634
+ monitors={buildMonitors(1500)}
635
+ services={SERVICES}
636
+ />,
637
+ );
638
+
639
+ expect(screen.getByTestId("affected-resources-summary")).toHaveTextContent(
640
+ `${(1501).toLocaleString()} resources across 2 categories`,
641
+ );
166
642
  });
167
643
  });
168
644
 
169
- describe("AffectedResourcesDisplay item names", () => {
645
+ describe("AffectedResourcesDisplay: rows", () => {
170
646
  test("every item carries its full name as a title", () => {
171
647
  render(
172
648
  <AffectedResourcesDisplay
@@ -194,7 +670,6 @@ describe("AffectedResourcesDisplay item names", () => {
194
670
 
195
671
  expect(item).toHaveClass(
196
672
  "min-w-0",
197
- "flex-1",
198
673
  "truncate",
199
674
  "[&_span.flex]:block",
200
675
  "[&_span.flex]:truncate",
@@ -206,10 +681,86 @@ describe("AffectedResourcesDisplay item names", () => {
206
681
 
207
682
  expect(nameSpan).not.toBeNull();
208
683
  expect(nameSpan).toHaveTextContent(LONG_MONITOR_NAME);
209
- expect(link).toHaveAttribute(
210
- "href",
211
- expect.stringContaining("aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaa1"),
684
+ expect(link).toHaveAttribute("href", expect.stringContaining(id("a", 1)));
685
+ });
686
+
687
+ test("the link is stretched over its whole row, so the row that highlights is the row that opens", () => {
688
+ render(<AffectedResourcesDisplay monitors={MONITORS} columns={1} />);
689
+
690
+ const item: HTMLElement = screen.getByTitle(LONG_MONITOR_NAME);
691
+ const row: HTMLElement = item.closest("li")!;
692
+
693
+ expect(item.className).toBe(AFFECTED_RESOURCE_ITEM_CLASS_NAME);
694
+ expect(item).toHaveClass(
695
+ "[&_a]:after:absolute",
696
+ "[&_a]:after:inset-0",
697
+ "[&_a]:after:rounded-md",
212
698
  );
699
+ // The row is what the link's ::after fills: positioned, and hoverable.
700
+ expect(row).toHaveClass("relative", "rounded-md", "hover:bg-gray-50");
701
+ /*
702
+ * Nothing between the row and the link may be positioned, or the ::after
703
+ * would fill that element instead of the row.
704
+ */
705
+ let node: HTMLElement | null = within(item).getByRole("link");
706
+ while (node && node !== row) {
707
+ expect(node.className.split(" ")).not.toEqual(
708
+ expect.arrayContaining(["relative"]),
709
+ );
710
+ node = node.parentElement;
711
+ }
712
+ // One link per row: the stretched one.
713
+ expect(within(row).getAllByRole("link")).toHaveLength(1);
714
+ });
715
+
716
+ test("keyboard focus draws a ring around the row, not a clipped outline round the name", () => {
717
+ render(<AffectedResourcesDisplay monitors={MONITORS} columns={1} />);
718
+
719
+ expect(screen.getByTitle(LONG_MONITOR_NAME)).toHaveClass(
720
+ "[&_a:focus-visible]:outline-none",
721
+ "[&_a:focus-visible]:after:ring-2",
722
+ "[&_a:focus-visible]:after:ring-indigo-500",
723
+ );
724
+ });
725
+
726
+ /*
727
+ * Tailwind v3 applies stacked variants right to left, so
728
+ * "[&_a]:focus-visible:x" would style an <a> inside a focused wrapper,
729
+ * which never happens. The focused link has to be in the arbitrary variant.
730
+ */
731
+ test("no class stacks a pseudo-class after the descendant variant", () => {
732
+ for (const token of AFFECTED_RESOURCE_ITEM_CLASS_NAME.split(" ")) {
733
+ expect(token).not.toMatch(/^\[&_a\]:(focus|hover|active)/);
734
+ }
735
+ });
736
+
737
+ test("the row's hover sits flush with the dividers on the right", () => {
738
+ render(<AffectedResourcesDisplay monitors={MONITORS} columns={1} />);
739
+
740
+ const row: HTMLElement = screen
741
+ .getByTitle(LONG_MONITOR_NAME)
742
+ .closest("li")!;
743
+
744
+ // Pulled left by its own padding so the name lines up with the label...
745
+ expect(row).toHaveClass("-ml-2", "px-2");
746
+ // ...but not past the right edge, where the dividers and counts end.
747
+ expect(row).not.toHaveClass("-mx-2");
748
+ expect(row).not.toHaveClass("-mr-2");
749
+ });
750
+
751
+ test("the old chevron is gone: the whole row says it is a link", () => {
752
+ const { container } = render(
753
+ <AffectedResourcesDisplay monitors={MONITORS} columns={1} />,
754
+ );
755
+
756
+ for (const row of Array.from(container.querySelectorAll("li"))) {
757
+ // Only the element inside the link draws anything.
758
+ expect(row.children).toHaveLength(1);
759
+ expect(row.firstElementChild).toHaveAttribute(
760
+ "data-testid",
761
+ "affected-resource-item",
762
+ );
763
+ }
213
764
  });
214
765
 
215
766
  test("a service name truncates beside its colour swatch", () => {
@@ -231,41 +782,289 @@ describe("AffectedResourcesDisplay item names", () => {
231
782
  );
232
783
  });
233
784
 
234
- test("the category label and count cannot push each other out of the card", () => {
235
- render(<AffectedResourcesDisplay monitors={MONITORS} columns={1} />);
785
+ test("a resource without an id is named without a link, so there is nothing to stretch", () => {
786
+ const unsaved: Host = new Host();
787
+ unsaved.name = "Unsaved host";
788
+
789
+ render(<AffectedResourcesDisplay hosts={[unsaved]} columns={1} />);
790
+
791
+ const item: HTMLElement = screen.getByTitle("Unsaved host");
792
+
793
+ expect(within(item).queryByRole("link")).toBeNull();
794
+ expect(item).toHaveTextContent("Unsaved host");
795
+ });
796
+ });
797
+
798
+ describe("AffectedResourcesDisplay: Show more", () => {
799
+ test("four resources fit without a toggle", () => {
800
+ render(<AffectedResourcesDisplay monitors={buildMonitors(4)} />);
801
+
802
+ expect(screen.getAllByTestId("affected-resource-item")).toHaveLength(4);
803
+ expect(screen.queryByRole("button")).toBeNull();
804
+ });
805
+
806
+ test("a fifth resource waits behind 'Show 1 more'", () => {
807
+ render(<AffectedResourcesDisplay monitors={buildMonitors(5)} />);
808
+
809
+ expect(screen.getAllByTestId("affected-resource-item")).toHaveLength(4);
810
+ expect(
811
+ screen.getByRole("button", { name: "Show 1 more" }),
812
+ ).toBeInTheDocument();
813
+ expect(screen.queryByText("probe-005")).toBeNull();
814
+ });
815
+
816
+ test("the toggle expands and collapses its list, and says so", () => {
817
+ render(<AffectedResourcesDisplay monitors={buildMonitors(7)} />);
818
+
819
+ const list: HTMLElement = screen.getByRole("list", { name: "Monitors 7" });
820
+ const toggle: HTMLElement = screen.getByRole("button", {
821
+ name: "Show 3 more",
822
+ });
823
+
824
+ expect(toggle).toHaveAttribute("type", "button");
825
+ expect(toggle).toHaveAttribute("aria-expanded", "false");
826
+ expect(toggle).toHaveAttribute("aria-controls", list.id);
827
+ expect(list.id).not.toBe("");
828
+
829
+ fireEvent.click(toggle);
830
+
831
+ expect(within(list).getAllByRole("listitem")).toHaveLength(7);
832
+ expect(screen.getByText("probe-007")).toBeInTheDocument();
833
+ expect(toggle).toHaveAttribute("aria-expanded", "true");
834
+ expect(toggle).toHaveTextContent("Show less");
835
+
836
+ fireEvent.click(screen.getByRole("button", { name: "Show less" }));
837
+
838
+ expect(within(list).getAllByRole("listitem")).toHaveLength(4);
839
+ expect(screen.queryByText("probe-007")).toBeNull();
840
+ expect(screen.getByRole("button", { name: "Show 3 more" })).toHaveAttribute(
841
+ "aria-expanded",
842
+ "false",
843
+ );
844
+ });
845
+
846
+ test("the toggle is a quiet inline control lined up with the names, not a footer bar", () => {
847
+ render(<AffectedResourcesDisplay monitors={buildMonitors(7)} />);
848
+
849
+ const toggle: HTMLElement = screen.getByRole("button", {
850
+ name: "Show 3 more",
851
+ });
852
+
853
+ // ml-6 plus its own px-2 puts its text on the names' pl-8 line.
854
+ expect(toggle).toHaveClass(
855
+ "ml-6",
856
+ "px-2",
857
+ "inline-flex",
858
+ "text-xs",
859
+ "text-indigo-600",
860
+ );
861
+ expect(toggle).not.toHaveClass("w-full");
862
+ expect(cardChromeIn(toggle)).toEqual([]);
863
+ });
864
+
865
+ test("each category keeps its own toggle", () => {
866
+ render(
867
+ <AffectedResourcesDisplay
868
+ monitors={buildMonitors(6)}
869
+ services={[1, 2, 3, 4, 5].map((n: number): Service => {
870
+ return buildService(n, `service-${n}`);
871
+ })}
872
+ />,
873
+ );
874
+
875
+ fireEvent.click(screen.getByRole("button", { name: "Show 2 more" }));
876
+
877
+ expect(
878
+ within(screen.getByRole("list", { name: "Monitors 6" })).getAllByRole(
879
+ "listitem",
880
+ ),
881
+ ).toHaveLength(6);
882
+ expect(
883
+ within(screen.getByRole("list", { name: "Services 5" })).getAllByRole(
884
+ "listitem",
885
+ ),
886
+ ).toHaveLength(4);
887
+ expect(screen.getByRole("button", { name: "Show 1 more" })).toHaveAttribute(
888
+ "aria-expanded",
889
+ "false",
890
+ );
891
+ });
892
+
893
+ test("past 100 rows the rest is counted in a note instead of rendered", () => {
894
+ render(<AffectedResourcesDisplay monitors={buildMonitors(130)} />);
895
+
896
+ // The toggle offers only what it will render.
897
+ fireEvent.click(screen.getByRole("button", { name: "Show 96 more" }));
898
+
899
+ expect(screen.getAllByTestId("affected-resource-item")).toHaveLength(100);
900
+ expect(screen.getByText("probe-100")).toBeInTheDocument();
901
+ expect(screen.queryByText("probe-101")).toBeNull();
236
902
 
237
- const label: HTMLElement = screen.getByText("Monitors");
238
- const count: HTMLElement = screen.getByText("2");
903
+ const note: HTMLElement = screen.getByTestId(
904
+ "affected-resource-truncated-note",
905
+ );
906
+
907
+ expect(note).toHaveTextContent(
908
+ "Showing the first 100 of 130. 30 more attached — edit affected resources to manage the full list.",
909
+ );
910
+ // Lined up with the names, and a div: the icon renders a <div> of its own.
911
+ expect(note.tagName).toBe("DIV");
912
+ expect(note).toHaveClass("ml-8", "text-amber-700");
913
+ // The count still covers every item.
914
+ expect(
915
+ screen.getByTestId("affected-resource-category-count"),
916
+ ).toHaveTextContent(/^130$/);
917
+
918
+ fireEvent.click(screen.getByRole("button", { name: "Show less" }));
919
+
920
+ expect(screen.getAllByTestId("affected-resource-item")).toHaveLength(4);
921
+ expect(screen.queryByTestId("affected-resource-truncated-note")).toBeNull();
922
+ });
923
+
924
+ test("exactly 100 rows expand fully with no note", () => {
925
+ render(<AffectedResourcesDisplay monitors={buildMonitors(100)} />);
926
+
927
+ fireEvent.click(screen.getByRole("button", { name: "Show 96 more" }));
928
+
929
+ expect(screen.getAllByTestId("affected-resource-item")).toHaveLength(100);
930
+ expect(screen.queryByTestId("affected-resource-truncated-note")).toBeNull();
931
+ });
932
+ });
933
+
934
+ describe("AffectedResourcesDisplay: empty state", () => {
935
+ test("says nothing is affected and how to attach resources", () => {
936
+ render(<AffectedResourcesDisplay columns={1} />);
937
+
938
+ const empty: HTMLElement = screen.getByTestId("affected-resources-empty");
939
+
940
+ expect(within(empty).getByText("No resources affected.")).toHaveClass(
941
+ "text-sm",
942
+ "font-medium",
943
+ "text-gray-900",
944
+ );
945
+ expect(empty).toHaveTextContent(
946
+ "Attach monitors, hosts, clusters, or services to track which parts of your infrastructure are impacted.",
947
+ );
948
+ expect(screen.queryByTestId("affected-resources-grid")).toBeNull();
949
+ expect(screen.queryByTestId("affected-resources-summary")).toBeNull();
950
+ });
951
+
952
+ test("a caller's own message replaces the default", () => {
953
+ render(
954
+ <AffectedResourcesDisplay columns={1} emptyMessage="Nothing hit." />,
955
+ );
956
+
957
+ expect(screen.getByText("Nothing hit.")).toBeInTheDocument();
958
+ expect(screen.queryByText("No resources affected.")).toBeNull();
959
+ });
960
+
961
+ test("the empty state does not depend on columns", () => {
962
+ render(
963
+ <AffectedResourcesDisplay columns={1} emptyMessage="Nothing hit." />,
964
+ );
965
+
966
+ expect(screen.getByText("Nothing hit.")).toBeInTheDocument();
967
+ expect(screen.queryByTestId("affected-resources-grid")).toBeNull();
968
+ });
969
+
970
+ test("its icon sits in a plain tinted circle, with no ring or shadow", () => {
971
+ render(<AffectedResourcesDisplay columns={1} />);
972
+
973
+ const circle: HTMLElement = screen.getByTestId("affected-resources-empty")
974
+ .firstElementChild as HTMLElement;
975
+
976
+ expect(circle.tagName).toBe("DIV");
977
+ expect(circle).toHaveClass("rounded-full", "bg-gray-100");
978
+ expect(circle).not.toHaveClass("bg-white", "shadow-sm", "ring-1");
979
+ });
980
+
981
+ test("only a caller that shows SLOs promises that burn rate rules link them", () => {
982
+ const SLO_HINT: RegExp =
983
+ /SLOs are linked automatically when their burn rate rules fire\./;
984
+
985
+ // The incident and alert pages pass their SLOs, even an empty list.
986
+ render(<AffectedResourcesDisplay serviceLevelObjectives={[]} />);
987
+ expect(screen.getByText(SLO_HINT)).toBeInTheDocument();
988
+ cleanup();
989
+
990
+ // Scheduled maintenance and the templates never link an SLO.
991
+ render(<AffectedResourcesDisplay monitors={[]} services={[]} />);
992
+ expect(screen.queryByText(SLO_HINT)).toBeNull();
993
+ cleanup();
239
994
 
240
- expect(label).toHaveClass("truncate");
241
- expect(label.parentElement).toHaveClass("min-w-0");
242
- expect(count).toHaveClass("flex-shrink-0");
995
+ // Nor does a caller that hides them.
996
+ render(
997
+ <AffectedResourcesDisplay
998
+ serviceLevelObjectives={[]}
999
+ hideServiceLevelObjectives={true}
1000
+ />,
1001
+ );
1002
+ expect(screen.queryByText(SLO_HINT)).toBeNull();
1003
+ });
1004
+
1005
+ test("resources a caller hides do not count, so everything hidden is empty", () => {
1006
+ render(
1007
+ <AffectedResourcesDisplay
1008
+ monitors={MONITORS}
1009
+ services={SERVICES}
1010
+ hideMonitors={true}
1011
+ hideServices={true}
1012
+ />,
1013
+ );
1014
+
1015
+ expect(screen.getByText("No resources affected.")).toBeInTheDocument();
1016
+ expect(screen.queryByRole("heading", { level: 3 })).toBeNull();
1017
+ });
1018
+ });
1019
+
1020
+ describe("AffectedResourcesDisplay columns", () => {
1021
+ test("renders today's two-column grid when columns is left out", () => {
1022
+ render(
1023
+ <AffectedResourcesDisplay monitors={MONITORS} services={SERVICES} />,
1024
+ );
1025
+
1026
+ const grid: HTMLElement = screen.getByTestId("affected-resources-grid");
1027
+
1028
+ expect(grid).toHaveClass("grid", "grid-cols-1", "md:grid-cols-2");
1029
+ expect(grid.children).toHaveLength(2);
1030
+ });
1031
+
1032
+ test("renders one column for a narrow sidebar", () => {
1033
+ render(
1034
+ <AffectedResourcesDisplay
1035
+ monitors={MONITORS}
1036
+ services={SERVICES}
1037
+ columns={1}
1038
+ />,
1039
+ );
1040
+
1041
+ const grid: HTMLElement = screen.getByTestId("affected-resources-grid");
1042
+
1043
+ expect(grid).toHaveClass("grid", "grid-cols-1", "divide-y");
1044
+ expect(grid).not.toHaveClass("md:grid-cols-2");
1045
+ // Both categories still render, one under the other.
1046
+ expect(within(grid).getByText("Monitors")).toBeInTheDocument();
1047
+ expect(within(grid).getByText("Services")).toBeInTheDocument();
243
1048
  });
244
1049
  });
245
1050
 
246
1051
  describe("AffectedResourcesDisplay databases", () => {
247
- const DATABASE_ID: string = "dddddddd-dddd-4ddd-8ddd-ddddddddddd1";
1052
+ const DATABASE_ID: string = id("d", 9);
248
1053
 
249
- const buildDatabase: (id: string, name: string) => DatabaseServer = (
250
- id: string,
1054
+ const buildDatabase: (databaseId: string, name: string) => DatabaseServer = (
1055
+ databaseId: string,
251
1056
  name: string,
252
1057
  ): DatabaseServer => {
253
- const database: DatabaseServer = new DatabaseServer();
254
- database._id = id;
255
- database.name = name;
256
- return database;
1058
+ return named(DatabaseServer, databaseId, name);
257
1059
  };
258
1060
 
259
- test("attached databases get their own card, counted with the rest", () => {
1061
+ test("attached databases get their own section, counted with the rest", () => {
260
1062
  render(
261
1063
  <AffectedResourcesDisplay
262
1064
  monitors={MONITORS}
263
1065
  databaseServers={[
264
1066
  buildDatabase(DATABASE_ID, "PostgreSQL db.prod:5432"),
265
- buildDatabase(
266
- "dddddddd-dddd-4ddd-8ddd-ddddddddddd2",
267
- "Redis cache.prod:6379",
268
- ),
1067
+ buildDatabase(id("d", 8), "Redis cache.prod:6379"),
269
1068
  ]}
270
1069
  />,
271
1070
  );
@@ -305,8 +1104,7 @@ describe("AffectedResourcesDisplay databases", () => {
305
1104
  );
306
1105
 
307
1106
  expect(screen.queryByText("Nothing hit.")).toBeNull();
308
- expect(screen.getByText("1 resource")).toBeInTheDocument();
309
- expect(screen.getByText("across 1 category")).toBeInTheDocument();
1107
+ expect(headingNames()).toEqual(["Databases 1"]);
310
1108
  });
311
1109
 
312
1110
  test("the table cell lists a database beside the other resources", () => {
@@ -326,7 +1124,7 @@ describe("AffectedResourcesDisplay databases", () => {
326
1124
  );
327
1125
  });
328
1126
 
329
- test("hideDatabaseServers drops the card", () => {
1127
+ test("hideDatabaseServers drops the section", () => {
330
1128
  render(
331
1129
  <AffectedResourcesDisplay
332
1130
  monitors={MONITORS}
@@ -337,6 +1135,6 @@ describe("AffectedResourcesDisplay databases", () => {
337
1135
 
338
1136
  expect(screen.queryByText("Databases")).toBeNull();
339
1137
  expect(screen.queryByText("MySQL orders:3306")).toBeNull();
340
- expect(screen.getByText("2 resources")).toBeInTheDocument();
1138
+ expect(headingNames()).toEqual(["Monitors 2"]);
341
1139
  });
342
1140
  });