@oneuptime/common 13.0.8 → 14.0.1

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 (514) hide show
  1. package/Models/AnalyticsModels/AuditLog.ts +23 -15
  2. package/Models/DatabaseModels/GlobalConfig.ts +24 -0
  3. package/Models/DatabaseModels/Index.ts +4 -0
  4. package/Models/DatabaseModels/Monitor.ts +3 -2
  5. package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
  6. package/Models/DatabaseModels/ServiceLevelObjectiveFeed.ts +2 -0
  7. package/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.ts +522 -0
  8. package/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.ts +38 -4
  9. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.ts +603 -0
  10. package/Scripts/generate-service-worker.js +65 -4
  11. package/Server/API/BaseAPI.ts +26 -5
  12. package/Server/API/GlobalConfigAPI.ts +228 -462
  13. package/Server/API/ProjectOIDC.ts +25 -16
  14. package/Server/API/ProjectSSO.ts +24 -16
  15. package/Server/API/StatusPageAPI.ts +100 -42
  16. package/Server/API/TeamMemberAPI.ts +10 -1
  17. package/Server/Enterprise/EnterpriseEdition.ts +649 -0
  18. package/Server/Enterprise/EnterpriseFeature.ts +48 -0
  19. package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +192 -0
  20. package/Server/Enterprise/EnterpriseServerModule.ts +233 -0
  21. package/Server/EnvironmentConfig.ts +147 -2
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.ts +25 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.ts +248 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.ts +19 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  26. package/Server/Middleware/UserAuthorization.ts +38 -16
  27. package/Server/Services/AuditLogService.ts +84 -1079
  28. package/Server/Services/DatabaseService.ts +10 -0
  29. package/Server/Services/EnterpriseLicenseService.ts +38 -0
  30. package/Server/Services/GlobalConfigService.ts +80 -1
  31. package/Server/Services/Index.ts +4 -0
  32. package/Server/Services/MonitorProbeService.ts +116 -20
  33. package/Server/Services/MonitorService.ts +59 -6
  34. package/Server/Services/MonitorStatusTimelineService.ts +284 -0
  35. package/Server/Services/MonitorTemplateService.ts +26 -0
  36. package/Server/Services/ProjectService.ts +284 -0
  37. package/Server/Services/RumSessionPinService.ts +25 -6
  38. package/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.ts +385 -0
  39. package/Server/Services/ServiceLevelObjectiveLabelRuleService.ts +51 -0
  40. package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +92 -16
  41. package/Server/Services/ServiceLevelObjectiveMonitorRuleService.ts +36 -1
  42. package/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.ts +521 -0
  43. package/Server/Services/ServiceLevelObjectiveOwnerRuleService.ts +51 -0
  44. package/Server/Services/ServiceLevelObjectiveService.ts +28 -0
  45. package/Server/Services/StatusPagePrivateUserService.ts +7 -3
  46. package/Server/Services/StatusPageService.ts +78 -1
  47. package/Server/Services/TeamMemberService.ts +11 -0
  48. package/Server/Services/TeamService.ts +10 -0
  49. package/Server/Services/UserService.ts +10 -17
  50. package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
  51. package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
  52. package/Server/Types/Database/Permissions/TablePermission.ts +10 -3
  53. package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
  54. package/Server/Types/Markdown.ts +41 -0
  55. package/Server/Types/Workflow/Components/Telegram/SendMessageToChat.ts +27 -1
  56. package/Server/Utils/AI/Toolbox/SloTools.ts +1 -0
  57. package/Server/Utils/CommunityEditionSsoReport.ts +361 -0
  58. package/Server/Utils/EditionEnforcement.ts +233 -0
  59. package/Server/Utils/FrontendEnvironment.ts +41 -2
  60. package/Server/Utils/InstanceHealth/RedisHealth.ts +12 -277
  61. package/Server/Utils/Monitor/AffectedResourceList.ts +148 -0
  62. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +1 -1
  63. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
  64. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +1 -1
  65. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +720 -465
  66. package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
  67. package/Server/Utils/Monitor/RootCauseList.ts +139 -0
  68. package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +28 -0
  69. package/Server/Utils/Slo/SloRulePatternValidator.ts +42 -0
  70. package/Server/Utils/Workspace/Slack/Slack.ts +423 -10
  71. package/Tests/App/Accounts/LoginPasskey.test.tsx +18 -0
  72. package/Tests/App/Accounts/LoginSsoEdition.test.tsx +616 -0
  73. package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +217 -0
  74. package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +357 -0
  75. package/Tests/App/AdminDashboard/EnterpriseLicensesShell.test.tsx +214 -0
  76. package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +271 -0
  77. package/Tests/App/AdminDashboard/HealthShells.test.tsx +659 -0
  78. package/Tests/App/Dashboard/AuditLogsAndComplianceShells.test.tsx +572 -0
  79. package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
  80. package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
  81. package/Tests/App/Dashboard/FeedFilterSortIntegration.test.tsx +1632 -0
  82. package/Tests/App/Dashboard/FeedOptionsLocales.test.ts +250 -0
  83. package/Tests/App/Dashboard/FeedOrdering.test.ts +279 -9
  84. package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
  85. package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +60 -1
  86. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +594 -3
  87. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
  88. package/Tests/App/Dashboard/ProductOrientation.test.tsx +646 -0
  89. package/Tests/App/Dashboard/ResourceFeed.test.tsx +612 -2
  90. package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +30 -0
  91. package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +1202 -0
  92. package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +52 -1
  93. package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +45 -9
  94. package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
  95. package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
  96. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -83
  97. package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
  98. package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
  99. package/Tests/App/Dashboard/SloFeed.test.tsx +106 -1
  100. package/Tests/App/Dashboard/SloMonitorRuleCriteria.test.tsx +566 -0
  101. package/Tests/App/Dashboard/SloNavigationWiring.test.tsx +6 -4
  102. package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +186 -0
  103. package/Tests/App/Dashboard/SloOverviewKpiStrip.test.tsx +388 -44
  104. package/Tests/App/Dashboard/SloOverviewLayout.test.tsx +613 -0
  105. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
  106. package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +319 -0
  107. package/Tests/Helpers/RefreshAwareApiScan.ts +757 -0
  108. package/Tests/Helpers/TenantScopedRequestScan.ts +515 -0
  109. package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +0 -8
  110. package/Tests/Models/DatabaseModels/SloLabelAndOwnerRuleModels.test.ts +404 -0
  111. package/Tests/Models/DatabaseModels/SloOverhaulModels.test.ts +17 -1
  112. package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
  113. package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
  114. package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
  115. package/Tests/Server/API/GlobalConfigLicense.test.ts +742 -497
  116. package/Tests/Server/API/OnCallReadinessAPI.test.ts +35 -909
  117. package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
  118. package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
  119. package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +824 -0
  120. package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +643 -0
  121. package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +294 -0
  122. package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +93 -0
  123. package/Tests/Server/Enterprise/EnterpriseOnlyModulesLiveInEe.test.ts +582 -0
  124. package/Tests/Server/Enterprise/EnterpriseServerModule.test.ts +247 -0
  125. package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +502 -0
  126. package/Tests/Server/Enterprise/TestBillingFlag.ts +70 -0
  127. package/Tests/Server/EnvironmentConfigEnterpriseEdition.test.ts +314 -0
  128. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +289 -0
  129. package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +5 -1
  130. package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
  131. package/Tests/Server/Infrastructure/Postgres/AddSloLabelAndOwnerRulesMigration.test.ts +407 -0
  132. package/Tests/Server/Infrastructure/Postgres/AddSloMonitorRuleMonitorTypeMigration.test.ts +171 -0
  133. package/Tests/Server/Infrastructure/Postgres/SloProductOverhaulMigration.test.ts +88 -4
  134. package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
  135. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
  136. package/Tests/Server/Services/AuditLogService.test.ts +460 -990
  137. package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
  138. package/Tests/Server/Services/DatabaseServiceRuleCriteriaValidation.test.ts +104 -0
  139. package/Tests/Server/Services/EnterpriseLicenseServiceKeyGeneration.test.ts +151 -0
  140. package/Tests/Server/Services/GlobalConfigServiceLicenseColumns.test.ts +357 -0
  141. package/Tests/Server/Services/MonitorDestinationInfoIPv6.test.ts +101 -0
  142. package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
  143. package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
  144. package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
  145. package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
  146. package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +48 -1
  147. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -0
  148. package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
  149. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleEngines.test.ts +1170 -0
  150. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleServices.test.ts +172 -0
  151. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +323 -0
  152. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleService.test.ts +115 -0
  153. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleTriggers.test.ts +21 -2
  154. package/Tests/Server/Services/ServiceLevelObjectiveMonitorTypePostgres.test.ts +480 -0
  155. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +162 -0
  156. package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
  157. package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
  158. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +45 -6
  159. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
  160. package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
  161. package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
  162. package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +745 -0
  163. package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
  164. package/Tests/Server/Types/Markdown.test.ts +183 -1
  165. package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +49 -0
  166. package/Tests/Server/Types/Workflow/Components/TelegramSendMessageToChat.test.ts +331 -0
  167. package/Tests/Server/Utils/AI/SloTools.test.ts +10 -0
  168. package/Tests/Server/Utils/CommunityEditionSsoReport.test.ts +565 -0
  169. package/Tests/Server/Utils/EditionEnforcement.test.ts +303 -0
  170. package/Tests/Server/Utils/FrontendEnvironment.test.ts +367 -0
  171. package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +38 -418
  172. package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +518 -0
  173. package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
  174. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +1 -1
  175. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +1339 -96
  176. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorBreachingSamples.test.ts +1101 -0
  177. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +106 -80
  178. package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
  179. package/Tests/Server/Utils/Monitor/RootCauseList.test.ts +252 -0
  180. package/Tests/Server/Utils/Rules/RuleRun/RuleRunPermission.test.ts +154 -0
  181. package/Tests/Server/Utils/SSRFProtection.test.ts +111 -0
  182. package/Tests/Server/Utils/Slo/SloRulePatternValidator.test.ts +67 -0
  183. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +213 -0
  184. package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
  185. package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
  186. package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
  187. package/Tests/Types/API/Route.test.ts +56 -0
  188. package/Tests/Types/API/URLSchemeLikePath.test.ts +304 -0
  189. package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -0
  190. package/Tests/UI/Components/EditionLabelLapseCopy.ts +104 -0
  191. package/Tests/UI/Components/EditionLabelLicenseManagerWiring.test.tsx +254 -0
  192. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +84 -178
  193. package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
  194. package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
  195. package/Tests/UI/Components/FeedOptions.test.ts +1404 -0
  196. package/Tests/UI/Components/FeedOptionsButton.test.tsx +2603 -0
  197. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
  198. package/Tests/UI/Components/Icon.test.tsx +26 -0
  199. package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
  200. package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
  201. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
  202. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
  203. package/Tests/UI/Components/useFeedItemsViewKey.test.tsx +1017 -0
  204. package/Tests/UI/Components/useFeedOptions.test.tsx +1107 -0
  205. package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
  206. package/Tests/Utils/HostAddressUtil.test.ts +138 -0
  207. package/Tests/Utils/LabelRuleImportExport.test.ts +102 -0
  208. package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
  209. package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
  210. package/Tests/Utils/Slo/SloDuration.test.ts +115 -24
  211. package/Tests/Utils/Slo/SloHealth.test.ts +93 -10
  212. package/Tests/Utils/Slo/SloMonitorRuleCriteria.test.ts +109 -0
  213. package/Tests/Utils/Slo/SloOverviewText.test.ts +64 -0
  214. package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
  215. package/Types/API/Hostname.ts +63 -16
  216. package/Types/API/Route.ts +19 -2
  217. package/Types/API/URL.ts +26 -2
  218. package/Types/Database/AccessControl/ColumnAccessControl.ts +19 -7
  219. package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +19 -7
  220. package/Types/Database/AccessControl/OwnerOnlyColumn.ts +15 -6
  221. package/Types/Database/CanonicalModelInstance.ts +102 -0
  222. package/Types/Database/TableColumn.ts +20 -6
  223. package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +29 -0
  224. package/Types/IP/IPv6.ts +6 -1
  225. package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +6 -5
  226. package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +9 -0
  227. package/Types/Monitor/MonitorStep.ts +6 -1
  228. package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
  229. package/Types/Permission.ts +90 -0
  230. package/Types/Rules/RuleCriteriaFieldRegistry.ts +11 -0
  231. package/Types/Rules/RuleRun.ts +4 -0
  232. package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
  233. package/UI/Components/EditionLabel/EditionLabel.tsx +796 -1195
  234. package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
  235. package/UI/Components/Feed/FeedOptions.ts +427 -0
  236. package/UI/Components/Feed/FeedOptionsButton.tsx +692 -0
  237. package/UI/Components/Feed/useFeedItems.ts +28 -9
  238. package/UI/Components/Feed/useFeedOptions.ts +225 -0
  239. package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
  240. package/UI/Components/Icon/Icon.tsx +1 -1
  241. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  242. package/UI/Components/ModelList/ModelList.tsx +11 -1
  243. package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
  244. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
  245. package/UI/esbuild-enterprise.js +263 -0
  246. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
  247. package/Utils/HostAddressUtil.ts +94 -0
  248. package/Utils/LabelRuleImportExport.ts +27 -9
  249. package/Utils/Monitor/MetricValueFormatter.ts +2 -2
  250. package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
  251. package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
  252. package/Utils/Rules/MonitorTypeRuleCriteria.ts +31 -0
  253. package/Utils/Slo/SloDuration.ts +22 -6
  254. package/Utils/Slo/SloHealth.ts +8 -7
  255. package/Utils/Slo/SloMonitorRuleCriteria.ts +33 -1
  256. package/Utils/Slo/SloOverviewText.ts +33 -0
  257. package/Utils/Slo/SloProjection.ts +4 -3
  258. package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
  259. package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
  260. package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
  261. package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
  262. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  263. package/build/dist/Models/DatabaseModels/Index.js +4 -0
  264. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  265. package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
  266. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  267. package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
  268. package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
  269. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js +2 -0
  270. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js.map +1 -1
  271. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js +530 -0
  272. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js.map +1 -0
  273. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js +39 -4
  274. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js.map +1 -1
  275. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js +612 -0
  276. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js.map +1 -0
  277. package/build/dist/Server/API/BaseAPI.js +26 -5
  278. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  279. package/build/dist/Server/API/GlobalConfigAPI.js +148 -344
  280. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  281. package/build/dist/Server/API/ProjectOIDC.js +24 -16
  282. package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
  283. package/build/dist/Server/API/ProjectSSO.js +24 -16
  284. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  285. package/build/dist/Server/API/StatusPageAPI.js +93 -43
  286. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  287. package/build/dist/Server/API/TeamMemberAPI.js +8 -1
  288. package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
  289. package/build/dist/Server/Enterprise/EnterpriseEdition.js +466 -0
  290. package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -0
  291. package/build/dist/Server/Enterprise/EnterpriseFeature.js +39 -0
  292. package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -0
  293. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +70 -0
  294. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js.map +1 -0
  295. package/build/dist/Server/Enterprise/EnterpriseServerModule.js +84 -0
  296. package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -0
  297. package/build/dist/Server/EnvironmentConfig.js +84 -2
  298. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  299. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js +18 -0
  300. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js.map +1 -0
  301. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js +93 -0
  302. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js.map +1 -0
  303. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js +12 -0
  304. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js.map +1 -0
  305. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  306. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  307. package/build/dist/Server/Middleware/UserAuthorization.js +30 -11
  308. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  309. package/build/dist/Server/Services/AuditLogService.js +71 -740
  310. package/build/dist/Server/Services/AuditLogService.js.map +1 -1
  311. package/build/dist/Server/Services/DatabaseService.js +7 -0
  312. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  313. package/build/dist/Server/Services/EnterpriseLicenseService.js +34 -0
  314. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  315. package/build/dist/Server/Services/GlobalConfigService.js +63 -0
  316. package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
  317. package/build/dist/Server/Services/Index.js +4 -0
  318. package/build/dist/Server/Services/Index.js.map +1 -1
  319. package/build/dist/Server/Services/MonitorProbeService.js +90 -17
  320. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  321. package/build/dist/Server/Services/MonitorService.js +48 -6
  322. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  323. package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
  324. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  325. package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
  326. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  327. package/build/dist/Server/Services/ProjectService.js +214 -0
  328. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  329. package/build/dist/Server/Services/RumSessionPinService.js +24 -6
  330. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  331. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js +295 -0
  332. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js.map +1 -0
  333. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js +56 -0
  334. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js.map +1 -0
  335. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +59 -14
  336. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -1
  337. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js +22 -1
  338. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js.map +1 -1
  339. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js +400 -0
  340. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js.map +1 -0
  341. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js +56 -0
  342. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js.map +1 -0
  343. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +21 -0
  344. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
  345. package/build/dist/Server/Services/StatusPagePrivateUserService.js +7 -3
  346. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  347. package/build/dist/Server/Services/StatusPageService.js +71 -0
  348. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  349. package/build/dist/Server/Services/TeamMemberService.js +10 -0
  350. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  351. package/build/dist/Server/Services/TeamService.js +9 -0
  352. package/build/dist/Server/Services/TeamService.js.map +1 -1
  353. package/build/dist/Server/Services/UserService.js +10 -16
  354. package/build/dist/Server/Services/UserService.js.map +1 -1
  355. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +10 -0
  356. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  357. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +154 -14
  358. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
  359. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +10 -3
  360. package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
  361. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +17 -0
  362. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
  363. package/build/dist/Server/Types/Markdown.js +31 -0
  364. package/build/dist/Server/Types/Markdown.js.map +1 -1
  365. package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js +20 -1
  366. package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js.map +1 -1
  367. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +1 -0
  368. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
  369. package/build/dist/Server/Utils/CommunityEditionSsoReport.js +223 -0
  370. package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +1 -0
  371. package/build/dist/Server/Utils/EditionEnforcement.js +187 -0
  372. package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -0
  373. package/build/dist/Server/Utils/FrontendEnvironment.js +31 -2
  374. package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -1
  375. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +6 -193
  376. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -1
  377. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +67 -0
  378. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
  379. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +1 -1
  380. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  381. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  382. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +1 -1
  383. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +585 -367
  384. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  385. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js +88 -0
  386. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js.map +1 -0
  387. package/build/dist/Server/Utils/Monitor/RootCauseList.js +101 -0
  388. package/build/dist/Server/Utils/Monitor/RootCauseList.js.map +1 -0
  389. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +28 -0
  390. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
  391. package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js +28 -0
  392. package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js.map +1 -0
  393. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +331 -11
  394. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  395. package/build/dist/Types/API/Hostname.js +59 -11
  396. package/build/dist/Types/API/Hostname.js.map +1 -1
  397. package/build/dist/Types/API/Route.js +18 -2
  398. package/build/dist/Types/API/Route.js.map +1 -1
  399. package/build/dist/Types/API/URL.js +23 -2
  400. package/build/dist/Types/API/URL.js.map +1 -1
  401. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +19 -7
  402. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
  403. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +19 -7
  404. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
  405. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +13 -6
  406. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -1
  407. package/build/dist/Types/Database/CanonicalModelInstance.js +88 -0
  408. package/build/dist/Types/Database/CanonicalModelInstance.js.map +1 -0
  409. package/build/dist/Types/Database/TableColumn.js +19 -6
  410. package/build/dist/Types/Database/TableColumn.js.map +1 -1
  411. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +28 -0
  412. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js.map +1 -0
  413. package/build/dist/Types/IP/IPv6.js +6 -1
  414. package/build/dist/Types/IP/IPv6.js.map +1 -1
  415. package/build/dist/Types/Monitor/MonitorStep.js +5 -0
  416. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  417. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +1 -1
  418. package/build/dist/Types/Permission.js +84 -0
  419. package/build/dist/Types/Permission.js.map +1 -1
  420. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +11 -0
  421. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
  422. package/build/dist/Types/Rules/RuleRun.js +4 -0
  423. package/build/dist/Types/Rules/RuleRun.js.map +1 -1
  424. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js +32 -0
  425. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js.map +1 -0
  426. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +414 -585
  427. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  428. package/build/dist/UI/Components/EditionLabel/LicenseManager.js +2 -0
  429. package/build/dist/UI/Components/EditionLabel/LicenseManager.js.map +1 -0
  430. package/build/dist/UI/Components/Feed/FeedOptions.js +235 -0
  431. package/build/dist/UI/Components/Feed/FeedOptions.js.map +1 -0
  432. package/build/dist/UI/Components/Feed/FeedOptionsButton.js +346 -0
  433. package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -0
  434. package/build/dist/UI/Components/Feed/useFeedItems.js +17 -7
  435. package/build/dist/UI/Components/Feed/useFeedItems.js.map +1 -1
  436. package/build/dist/UI/Components/Feed/useFeedOptions.js +130 -0
  437. package/build/dist/UI/Components/Feed/useFeedOptions.js.map +1 -0
  438. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +90 -17
  439. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  440. package/build/dist/UI/Components/Icon/Icon.js +1 -1
  441. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  442. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  443. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  444. package/build/dist/UI/Components/ModelList/ModelList.js +4 -1
  445. package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
  446. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +42 -1
  447. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  448. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +2 -2
  449. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  450. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +6 -2
  451. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  452. package/build/dist/Utils/HostAddressUtil.js +80 -0
  453. package/build/dist/Utils/HostAddressUtil.js.map +1 -0
  454. package/build/dist/Utils/LabelRuleImportExport.js +22 -6
  455. package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
  456. package/build/dist/Utils/Monitor/MetricValueFormatter.js +2 -2
  457. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js +127 -0
  458. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js.map +1 -0
  459. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js +374 -0
  460. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js.map +1 -0
  461. package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js +18 -0
  462. package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js.map +1 -0
  463. package/build/dist/Utils/Slo/SloDuration.js +13 -5
  464. package/build/dist/Utils/Slo/SloDuration.js.map +1 -1
  465. package/build/dist/Utils/Slo/SloHealth.js +8 -7
  466. package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
  467. package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js +16 -1
  468. package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js.map +1 -1
  469. package/build/dist/Utils/Slo/SloOverviewText.js +16 -0
  470. package/build/dist/Utils/Slo/SloOverviewText.js.map +1 -1
  471. package/build/dist/Utils/Slo/SloProjection.js.map +1 -1
  472. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
  473. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -0
  474. package/jest.config.json +3 -1
  475. package/package.json +1 -1
  476. package/test-setup.sh +103 -34
  477. package/tsconfig.json +13 -0
  478. package/Server/API/EnterpriseLicenseAPI.ts +0 -925
  479. package/Server/API/TeamComplianceAPI.ts +0 -158
  480. package/Server/Middleware/SCIMAuthorization.ts +0 -141
  481. package/Server/Services/TeamComplianceService.ts +0 -733
  482. package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +0 -186
  483. package/Server/Utils/InstanceHealth/PostgresHealth.ts +0 -286
  484. package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +0 -451
  485. package/Tests/App/Dashboard/AuditLogsTable.test.tsx +0 -598
  486. package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +0 -761
  487. package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
  488. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
  489. package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +0 -321
  490. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +0 -1851
  491. package/Tests/Server/Middleware/SCIMAuthorization.test.ts +0 -525
  492. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +0 -1845
  493. package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +0 -495
  494. package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +0 -337
  495. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +0 -576
  496. package/Tests/Utils/EnterpriseLicenseSync.test.ts +0 -568
  497. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +0 -287
  498. package/Utils/EnterpriseLicense/EnterpriseLicenseSync.ts +0 -244
  499. package/build/dist/Server/API/EnterpriseLicenseAPI.js +0 -646
  500. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +0 -1
  501. package/build/dist/Server/API/TeamComplianceAPI.js +0 -111
  502. package/build/dist/Server/API/TeamComplianceAPI.js.map +0 -1
  503. package/build/dist/Server/Middleware/SCIMAuthorization.js +0 -124
  504. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +0 -1
  505. package/build/dist/Server/Services/TeamComplianceService.js +0 -537
  506. package/build/dist/Server/Services/TeamComplianceService.js.map +0 -1
  507. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +0 -145
  508. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +0 -1
  509. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +0 -194
  510. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +0 -1
  511. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +0 -168
  512. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +0 -1
  513. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js +0 -174
  514. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js.map +0 -1
@@ -1,4 +1,11 @@
1
- import { afterEach, describe, expect, jest, test } from "@jest/globals";
1
+ import {
2
+ afterEach,
3
+ beforeEach,
4
+ describe,
5
+ expect,
6
+ jest,
7
+ test,
8
+ } from "@jest/globals";
2
9
  import "@testing-library/jest-dom";
3
10
  import {
4
11
  act,
@@ -105,6 +112,7 @@ import SortOrder from "../../../Types/BaseDatabase/SortOrder";
105
112
  import { DEFAULT_LIMIT } from "../../../Types/Database/LimitMax";
106
113
  import IconProp from "../../../Types/Icon/IconProp";
107
114
  import ObjectID from "../../../Types/ObjectID";
115
+ import { getSortOrderStorageKey } from "../../../UI/Components/Feed/useFeedOptions";
108
116
 
109
117
  interface RenderedFeedItem {
110
118
  key: string;
@@ -204,6 +212,15 @@ async function chooseAction(text: string): Promise<void> {
204
212
  await flush();
205
213
  }
206
214
 
215
+ /*
216
+ * The feed opens in the sort order the reader last chose, read from
217
+ * localStorage on mount, so one test's choice must not reorder the next
218
+ * test's requests.
219
+ */
220
+ beforeEach(() => {
221
+ window.localStorage.clear();
222
+ });
223
+
207
224
  afterEach(() => {
208
225
  cleanup();
209
226
  getListMock.mockReset();
@@ -279,6 +296,40 @@ describe("ScheduledMaintenanceFeedElement refresh", () => {
279
296
  expect(lastRenderedItems()[0]!.icon).toBe(IconProp.ArrowCircleRight);
280
297
  });
281
298
 
299
+ /*
300
+ * The refresh after a state change re-reads the view the reader is looking
301
+ * at. A reader who keeps this feed oldest first must not see it flip back
302
+ * to newest first because the page asked for a refresh.
303
+ */
304
+ test("a new refreshToken re-reads the feed in the reader's remembered order", async () => {
305
+ window.localStorage.setItem(
306
+ getSortOrderStorageKey("scheduled-maintenance"),
307
+ SortOrder.Ascending,
308
+ );
309
+ getListMock.mockResolvedValue(listResult([]) as never);
310
+
311
+ const view: RenderResult = renderFeed(0);
312
+ await flush();
313
+
314
+ view.rerender(
315
+ <ScheduledMaintenanceFeedElement
316
+ scheduledMaintenanceId={new ObjectID(EVENT_ID)}
317
+ refreshToken={1}
318
+ />,
319
+ );
320
+ await flush();
321
+
322
+ expect(getListMock).toHaveBeenCalledTimes(2);
323
+
324
+ for (const call of getListMock.mock.calls) {
325
+ const request: FeedListRequest = call[0] as FeedListRequest;
326
+
327
+ expect(request.sort).toEqual({ postedAt: SortOrder.Ascending });
328
+ expect(request.skip).toBe(0);
329
+ expect(request.limit).toBe(DEFAULT_LIMIT);
330
+ }
331
+ });
332
+
282
333
  test("re-rendering with the same token, or a new ObjectID for the same event, does not refetch", async () => {
283
334
  getListMock.mockResolvedValue(listResult([]) as never);
284
335
 
@@ -48,7 +48,6 @@ import ListResult from "../../../Types/BaseDatabase/ListResult";
48
48
  import RangeStartAndEndDateTime from "../../../Types/Time/RangeStartAndEndDateTime";
49
49
  import TimeRange from "../../../Types/Time/TimeRange";
50
50
  import { JSONObject } from "../../../Types/JSON";
51
- import JSONFunctions from "../../../Types/JSONFunctions";
52
51
  import ObjectID from "../../../Types/ObjectID";
53
52
  import {
54
53
  SecurityConnectorSample,
@@ -269,12 +268,36 @@ function eventsParams(route: Route): URLSearchParams {
269
268
  return new URLSearchParams(text.slice(text.indexOf("?")));
270
269
  }
271
270
 
272
- // The table's own filter on the link; {} when the link sets none.
271
+ /*
272
+ * The chips the link opens the events explorer with, re-shaped as
273
+ * `{ attributes: { key: value } }` — the reading these assertions have always
274
+ * used.
275
+ *
276
+ * The link's grammar is the explorers' own `filters` param
277
+ * (`[["attributes.<key>", "<value>"], ...]`); it used to be the model
278
+ * table's serialized column filter, which went away with the table. Anything
279
+ * the explorer does not express as an attribute chip is left out, so an
280
+ * assertion that a key is absent still means "the link does not filter on
281
+ * it".
282
+ */
273
283
  function eventsFilter(route: Route): JSONObject {
274
- const raw: string | null = eventsParams(route).get(
275
- "security-events-table-filter",
276
- );
277
- return raw ? JSONFunctions.deserialize(JSON.parse(raw) as JSONObject) : {};
284
+ const raw: string | null = eventsParams(route).get("filters");
285
+
286
+ if (!raw) {
287
+ return {};
288
+ }
289
+
290
+ const attributes: JSONObject = {};
291
+
292
+ for (const pair of JSON.parse(raw) as Array<[string, string]>) {
293
+ if (!Array.isArray(pair) || !pair[0]?.startsWith("attributes.")) {
294
+ continue;
295
+ }
296
+
297
+ attributes[pair[0].substring("attributes.".length)] = pair[1];
298
+ }
299
+
300
+ return Object.keys(attributes).length > 0 ? { attributes } : {};
278
301
  }
279
302
 
280
303
  /*
@@ -1481,25 +1504,38 @@ describe("View events for a connection run", () => {
1481
1504
  expect(eventsFilter(route)["attributes"]).toBeUndefined();
1482
1505
  });
1483
1506
 
1484
- test("the window is the page's time range, not a table filter", (): void => {
1507
+ test("the window is the page's time range, not a chip", (): void => {
1485
1508
  const route: Route = connectionEventsRoute(result(), CONNECTION_ID);
1486
1509
  const params: URLSearchParams = eventsParams(route);
1487
1510
 
1488
1511
  expect(params.get("range")).toBe(TimeRange.CUSTOM);
1489
1512
  expect(params.get("start")).toBe("2026-09-09T01:30:29.000Z");
1490
1513
  expect(params.get("end")).toBe("2026-09-09T01:30:31.000Z");
1491
- // The table no longer offers a Time filter, so none is written for it.
1514
+ // The window is the explorer's own range, never one of its chips.
1492
1515
  expect(eventsFilter(route)["time"]).toBeUndefined();
1493
1516
  expect(eventsFilter(route)["attributes"]).toEqual({
1494
1517
  [SECURITY_CONNECTION_ID_ATTRIBUTE]: CONNECTION_ID,
1495
1518
  });
1496
1519
  });
1497
1520
 
1498
- test("a link with nothing to filter on sets no table filter at all", (): void => {
1521
+ test("the connection chip is written in the explorer's filters grammar", (): void => {
1522
+ const raw: string | null = eventsParams(
1523
+ connectionEventsRoute(result(), CONNECTION_ID),
1524
+ ).get("filters");
1525
+
1526
+ expect(raw).not.toBeNull();
1527
+ expect(JSON.parse(raw as string)).toEqual([
1528
+ [`attributes.${SECURITY_CONNECTION_ID_ATTRIBUTE}`, CONNECTION_ID],
1529
+ ]);
1530
+ });
1531
+
1532
+ test("a link with nothing to filter on sets no chips at all", (): void => {
1499
1533
  const params: URLSearchParams = eventsParams(
1500
1534
  connectionEventsRoute(result()),
1501
1535
  );
1502
1536
 
1537
+ expect(params.get("filters")).toBeNull();
1538
+ // The retired model table's own filter param is gone for good.
1503
1539
  expect(params.get("security-events-table-filter")).toBeNull();
1504
1540
  expect(params.get("range")).toBe(TimeRange.CUSTOM);
1505
1541
  });
@@ -0,0 +1,399 @@
1
+ /** @timezone UTC */
2
+
3
+ import {
4
+ afterEach,
5
+ beforeEach,
6
+ describe,
7
+ expect,
8
+ jest,
9
+ test,
10
+ } from "@jest/globals";
11
+ import "@testing-library/jest-dom";
12
+ import {
13
+ cleanup,
14
+ fireEvent,
15
+ render,
16
+ screen,
17
+ within,
18
+ } from "@testing-library/react";
19
+ import * as React from "react";
20
+ import { MemoryRouter } from "react-router-dom";
21
+ import SecurityEvent from "../../../Models/AnalyticsModels/SecurityEvent";
22
+ import OcsfSeverity from "../../../Types/SecurityEvent/OcsfSeverity";
23
+ import Navigation from "../../../UI/Utils/Navigation";
24
+ import getJestMockFunction, { MockFunction } from "../../MockType";
25
+ import SecurityEventDetailPanel, {
26
+ SECURITY_EVENT_DETAIL_ATTRIBUTES_TAB_ID,
27
+ SECURITY_EVENT_DETAIL_JSON_TAB_ID,
28
+ SECURITY_EVENT_DETAIL_OVERVIEW_TAB_ID,
29
+ SECURITY_EVENT_DETAIL_PANEL_TEST_ID,
30
+ } from "../../../../App/FeatureSet/Dashboard/src/Components/SecurityEvents/SecurityEventDetailPanel";
31
+ import { SECURITY_EVENT_ATTRIBUTE_FACET_PREFIX } from "../../../../App/FeatureSet/Dashboard/src/Components/SecurityEvents/SecurityEventsFacets";
32
+
33
+ /*
34
+ * One security event, opened from the list.
35
+ *
36
+ * Built on the shared TelemetryDetailPanel — the drawer the traces and
37
+ * exceptions explorers open — rather than a SideOver, so the list stays
38
+ * usable behind it. What is pinned here is what the drawer is FOR: reading
39
+ * the whole event (typed fields, every source attribute, the raw record) and
40
+ * turning anything in it into a filter on the list behind it without
41
+ * re-typing it into the search bar.
42
+ */
43
+
44
+ const PROJECT_ID: string = "11111111-1111-4111-8111-111111111111";
45
+
46
+ function event(fields: Partial<SecurityEvent> = {}): SecurityEvent {
47
+ return Object.assign(new SecurityEvent(), fields);
48
+ }
49
+
50
+ const FULL_EVENT: SecurityEvent = event({
51
+ time: new Date("2026-09-17T10:00:00.000Z"),
52
+ eventUid: "abc123",
53
+ severityName: OcsfSeverity.Critical,
54
+ className: "Authentication",
55
+ categoryName: "IAM",
56
+ activityName: "Logon",
57
+ statusName: "Failure",
58
+ message: "Failed logon for alice",
59
+ vendorName: "Acme",
60
+ productName: "Defender",
61
+ ruleName: "BruteForce",
62
+ principalUser: "alice",
63
+ principalHost: "web-01",
64
+ observables: ["alice", "10.0.0.4"],
65
+ attributes: {
66
+ "threat.matched": "true",
67
+ "device.hostname": "web-01",
68
+ },
69
+ });
70
+
71
+ function renderPanel(
72
+ securityEvent: SecurityEvent = FULL_EVENT,
73
+ props: {
74
+ onClose?: () => void;
75
+ onFilterBy?: (facetKey: string, value: string) => void;
76
+ onCorrelateObservable?: (observable: string) => void;
77
+ } = {},
78
+ ): void {
79
+ render(
80
+ <MemoryRouter>
81
+ <SecurityEventDetailPanel
82
+ securityEvent={securityEvent}
83
+ onClose={props.onClose || ((): void => {})}
84
+ {...(props.onFilterBy ? { onFilterBy: props.onFilterBy } : {})}
85
+ {...(props.onCorrelateObservable
86
+ ? { onCorrelateObservable: props.onCorrelateObservable }
87
+ : {})}
88
+ />
89
+ </MemoryRouter>,
90
+ );
91
+ }
92
+
93
+ function panel(): HTMLElement {
94
+ return screen.getByTestId(SECURITY_EVENT_DETAIL_PANEL_TEST_ID);
95
+ }
96
+
97
+ function tab(label: string): HTMLElement {
98
+ return screen.getByRole("tab", { name: new RegExp(`^${label}`) });
99
+ }
100
+
101
+ function filterButton(label: string): HTMLElement {
102
+ return screen.getByRole("button", { name: `Filter by ${label}` });
103
+ }
104
+
105
+ beforeEach(() => {
106
+ window.history.replaceState(
107
+ null,
108
+ "",
109
+ `/dashboard/${PROJECT_ID}/security-events`,
110
+ );
111
+ });
112
+
113
+ afterEach(() => {
114
+ cleanup();
115
+ jest.restoreAllMocks();
116
+ });
117
+
118
+ describe("the drawer", () => {
119
+ test("names the event and when it happened", () => {
120
+ renderPanel();
121
+
122
+ expect(panel()).toHaveTextContent("Failed logon for alice");
123
+ expect(panel().textContent).toContain("2026");
124
+ });
125
+
126
+ test("falls back to the event class when there is no message", () => {
127
+ renderPanel(event({ className: "Authentication" }));
128
+
129
+ expect(panel()).toHaveTextContent("Authentication");
130
+ });
131
+
132
+ test("offers Overview, Attributes and JSON, opening on Overview", () => {
133
+ renderPanel();
134
+
135
+ expect(
136
+ screen.getAllByRole("tab").map((node: HTMLElement): string => {
137
+ return node.getAttribute("id") || "";
138
+ }),
139
+ ).toEqual(
140
+ expect.arrayContaining([
141
+ expect.stringContaining(SECURITY_EVENT_DETAIL_OVERVIEW_TAB_ID),
142
+ expect.stringContaining(SECURITY_EVENT_DETAIL_ATTRIBUTES_TAB_ID),
143
+ expect.stringContaining(SECURITY_EVENT_DETAIL_JSON_TAB_ID),
144
+ ]),
145
+ );
146
+ expect(tab("Overview")).toHaveAttribute("aria-selected", "true");
147
+ });
148
+
149
+ test("the Attributes tab counts what it holds, so a reader knows before opening it", () => {
150
+ renderPanel();
151
+
152
+ expect(tab("Attributes")).toHaveTextContent("2");
153
+ });
154
+
155
+ test("closing it tells the page", () => {
156
+ const onClose: MockFunction = getJestMockFunction();
157
+
158
+ renderPanel(FULL_EVENT, { onClose: onClose as unknown as () => void });
159
+
160
+ fireEvent.click(screen.getByRole("button", { name: /close/i }));
161
+
162
+ expect(onClose).toHaveBeenCalledTimes(1);
163
+ });
164
+ });
165
+
166
+ describe("Overview", () => {
167
+ test("shows the typed OCSF fields, severity as a pill", () => {
168
+ renderPanel();
169
+
170
+ expect(panel()).toHaveTextContent("Event Class");
171
+ expect(panel()).toHaveTextContent("Authentication");
172
+ expect(panel()).toHaveTextContent("Status");
173
+ expect(panel()).toHaveTextContent("Failure");
174
+ expect(panel()).toHaveTextContent(OcsfSeverity.Critical);
175
+ });
176
+
177
+ test("omits what the source did not say", () => {
178
+ renderPanel(event({ className: "Authentication" }));
179
+
180
+ expect(panel()).not.toHaveTextContent("Target Host");
181
+ expect(panel()).not.toHaveTextContent("MITRE Tactics");
182
+ });
183
+
184
+ test("lists observables as chips, and says so when there are none", () => {
185
+ renderPanel();
186
+
187
+ expect(
188
+ screen.getByTestId("security-event-panel-observable-chip-0"),
189
+ ).toHaveTextContent("alice");
190
+ expect(
191
+ screen.getByTestId("security-event-panel-observable-chip-1"),
192
+ ).toHaveTextContent("10.0.0.4");
193
+
194
+ cleanup();
195
+ renderPanel(event({ message: "no observables" }));
196
+
197
+ expect(panel()).toHaveTextContent(
198
+ "No observables extracted from this event.",
199
+ );
200
+ });
201
+ });
202
+
203
+ describe("filtering the list from the drawer", () => {
204
+ test("severity, and every typed field the sidebar also facets, offers a filter", () => {
205
+ const onFilterBy: MockFunction = getJestMockFunction();
206
+
207
+ renderPanel(FULL_EVENT, {
208
+ onFilterBy: onFilterBy as unknown as (
209
+ facetKey: string,
210
+ value: string,
211
+ ) => void,
212
+ });
213
+
214
+ fireEvent.click(filterButton("Severity"));
215
+ expect(onFilterBy).toHaveBeenLastCalledWith(
216
+ "severityName",
217
+ OcsfSeverity.Critical,
218
+ );
219
+
220
+ fireEvent.click(filterButton("Event Class"));
221
+ expect(onFilterBy).toHaveBeenLastCalledWith("className", "Authentication");
222
+
223
+ fireEvent.click(filterButton("Principal User"));
224
+ expect(onFilterBy).toHaveBeenLastCalledWith("principalUser", "alice");
225
+
226
+ fireEvent.click(filterButton("Detection Rule"));
227
+ expect(onFilterBy).toHaveBeenLastCalledWith("ruleName", "BruteForce");
228
+ });
229
+
230
+ /*
231
+ * Filtering on a value that is unique per row would return the one event
232
+ * already on screen, so those fields deliberately offer no action.
233
+ */
234
+ test("free-text and unique fields offer none", () => {
235
+ renderPanel(FULL_EVENT, {
236
+ onFilterBy: getJestMockFunction() as unknown as (
237
+ facetKey: string,
238
+ value: string,
239
+ ) => void,
240
+ });
241
+
242
+ expect(
243
+ screen.queryByRole("button", { name: "Filter by Message" }),
244
+ ).toBeNull();
245
+ expect(
246
+ screen.queryByRole("button", { name: "Filter by Event UID" }),
247
+ ).toBeNull();
248
+ });
249
+
250
+ test("an attribute filters under its own attributes.<key> chip", () => {
251
+ const onFilterBy: MockFunction = getJestMockFunction();
252
+
253
+ renderPanel(FULL_EVENT, {
254
+ onFilterBy: onFilterBy as unknown as (
255
+ facetKey: string,
256
+ value: string,
257
+ ) => void,
258
+ });
259
+
260
+ fireEvent.click(tab("Attributes"));
261
+ fireEvent.click(filterButton("threat.matched"));
262
+
263
+ expect(onFilterBy).toHaveBeenCalledWith(
264
+ `${SECURITY_EVENT_ATTRIBUTE_FACET_PREFIX}threat.matched`,
265
+ "true",
266
+ );
267
+ });
268
+
269
+ test("a page that cannot filter gets no filter actions at all", () => {
270
+ renderPanel();
271
+
272
+ expect(screen.queryByRole("button", { name: /^Filter by/ })).toBeNull();
273
+ });
274
+ });
275
+
276
+ describe("Attributes", () => {
277
+ test("lists every source attribute, sorted, with its value", () => {
278
+ renderPanel();
279
+
280
+ fireEvent.click(tab("Attributes"));
281
+
282
+ const terms: Array<string> = Array.from(panel().querySelectorAll("dt")).map(
283
+ (node: Element): string => {
284
+ return node.textContent || "";
285
+ },
286
+ );
287
+
288
+ expect(terms).toEqual(["device.hostname", "threat.matched"]);
289
+ expect(panel()).toHaveTextContent("web-01");
290
+ expect(panel()).toHaveTextContent("true");
291
+ });
292
+
293
+ test("an event with none says so", () => {
294
+ renderPanel(event({ message: "bare" }));
295
+
296
+ fireEvent.click(tab("Attributes"));
297
+
298
+ expect(panel()).toHaveTextContent("No attributes recorded for this event.");
299
+ });
300
+ });
301
+
302
+ describe("JSON", () => {
303
+ test("prints the record, including what the source left empty", () => {
304
+ renderPanel();
305
+
306
+ fireEvent.click(tab("JSON"));
307
+
308
+ const json: Record<string, unknown> = JSON.parse(
309
+ screen.getByTestId("security-event-detail-json").textContent || "{}",
310
+ );
311
+
312
+ expect(json["message"]).toBe("Failed logon for alice");
313
+ expect(json["severityName"]).toBe(OcsfSeverity.Critical);
314
+ expect(json["targetHost"]).toBe("");
315
+ expect(json["attributes"]).toEqual({
316
+ "threat.matched": "true",
317
+ "device.hostname": "web-01",
318
+ });
319
+ });
320
+
321
+ /*
322
+ * An analytics model carries its whole table definition on the object;
323
+ * serializing that would bury twenty facts about the event under a few
324
+ * hundred about the table.
325
+ */
326
+ test("describes the event, not the table", () => {
327
+ renderPanel();
328
+
329
+ fireEvent.click(tab("JSON"));
330
+
331
+ const text: string =
332
+ screen.getByTestId("security-event-detail-json").textContent || "";
333
+
334
+ expect(text).not.toContain("tableColumns");
335
+ expect(text).not.toContain("accessControl");
336
+ });
337
+ });
338
+
339
+ describe("correlating an observable", () => {
340
+ test("deep-links to the Correlate tab seeded with the observable", () => {
341
+ const navigate: MockFunction = getJestMockFunction();
342
+ jest
343
+ .spyOn(Navigation, "navigate")
344
+ .mockImplementation(navigate as unknown as typeof Navigation.navigate);
345
+
346
+ renderPanel();
347
+
348
+ fireEvent.click(
349
+ screen.getByTestId("security-event-panel-observable-chip-1"),
350
+ );
351
+
352
+ expect(navigate).toHaveBeenCalledTimes(1);
353
+ const route: string = String((navigate.mock.calls[0] as Array<unknown>)[0]);
354
+
355
+ expect(route).toContain("/security-events/correlate");
356
+ expect(route).toContain(`observable=${encodeURIComponent("10.0.0.4")}`);
357
+ });
358
+
359
+ test("a host that already shows a graph pivots in place instead", () => {
360
+ const onCorrelateObservable: MockFunction = getJestMockFunction();
361
+ const navigate: MockFunction = getJestMockFunction();
362
+ jest
363
+ .spyOn(Navigation, "navigate")
364
+ .mockImplementation(navigate as unknown as typeof Navigation.navigate);
365
+
366
+ renderPanel(FULL_EVENT, {
367
+ onCorrelateObservable: onCorrelateObservable as unknown as (
368
+ observable: string,
369
+ ) => void,
370
+ });
371
+
372
+ fireEvent.click(
373
+ screen.getByTestId("security-event-panel-observable-chip-0"),
374
+ );
375
+
376
+ expect(onCorrelateObservable).toHaveBeenCalledWith("alice");
377
+ expect(navigate).not.toHaveBeenCalled();
378
+ });
379
+ });
380
+
381
+ describe("the drawer is a modal", () => {
382
+ test("Escape closes it", () => {
383
+ const onClose: MockFunction = getJestMockFunction();
384
+
385
+ renderPanel(FULL_EVENT, { onClose: onClose as unknown as () => void });
386
+
387
+ fireEvent.keyDown(document, { key: "Escape" });
388
+
389
+ expect(onClose).toHaveBeenCalledTimes(1);
390
+ });
391
+
392
+ test("its tabs are a real tablist", () => {
393
+ renderPanel();
394
+
395
+ const tablist: HTMLElement = screen.getByRole("tablist");
396
+
397
+ expect(within(tablist).getAllByRole("tab")).toHaveLength(3);
398
+ });
399
+ });