@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
@@ -32,19 +32,25 @@ import { describe, expect, test } from "@jest/globals";
32
32
  * run it through Markdown.convertToHTML for the email body.
33
33
  *
34
34
  * Before this suite existed, nothing anywhere pinned the Breaching
35
- * Samples table or the "- Unit:" line, and both rendered raw digits with
36
- * the exporter's raw UCUM code glued on: a memory breach that the
37
- * dashboard drew as "1.07 GB" arrived in the inbox as "1073741824 By",
38
- * and a ratio metric's Value column read "0.06 1".
35
+ * Samples block (a table back then) or the "- Unit:" line, and both
36
+ * rendered raw digits with the exporter's raw UCUM code glued on: a memory
37
+ * breach that the dashboard drew as "1.07 GB" arrived in the inbox as
38
+ * "1073741824 By", and a ratio metric's Value column read "0.06 1".
39
39
  *
40
40
  * These tests pin:
41
- * - the Value column at human scale, in the unit each row landed on,
42
- * - component columns each in their OWN unit, with no unit in the header
43
- * (auto-scaling means neighbouring rows disagree with any one header),
41
+ * - each sample's value at human scale, in the unit that sample landed
42
+ * on,
43
+ * - formula components each in their OWN unit, labelled by alias alone
44
+ * (auto-scaling means neighbouring samples disagree with any one
45
+ * configured unit),
44
46
  * - the "- Unit:" line spelled out, and dropped when there is no unit,
45
47
  * - the formula guard: a formula expression is not a metric name,
46
- * - that the table and the "Filter Conditions Met" sentence in the same
47
- * email render the same sample identically.
48
+ * - that the Breaching Samples list and the "Filter Conditions Met"
49
+ * sentence in the same email render the same sample identically.
50
+ *
51
+ * The list's own shape — its markdown, and how it parses and renders in
52
+ * the email, Slack and plain text — is pinned in
53
+ * MonitorCriteriaEvaluatorBreachingSamples.test.ts.
48
54
  */
49
55
 
50
56
  type EvaluatorPrivate = {
@@ -115,33 +121,57 @@ function rootCause(ctx: MetricCriteriaContext): string {
115
121
  return context as string;
116
122
  }
117
123
 
118
- /** The one data row of the Breaching Samples table. */
119
- function sampleRow(context: string): string {
120
- const row: string | undefined = context.split("\n").find((line: string) => {
121
- return line.includes(BREACH_TIME_ISO);
124
+ /*
125
+ * The Breaching Samples list item of the sample taken at BREACH_TIME: its
126
+ * first line ("1. `<timestamp>` — **<value>**"), the value on it, and the
127
+ * detail bullets nested under it.
128
+ */
129
+ const LIST_ITEM_LINE: RegExp = /^\d+\. /;
130
+ const DETAIL_LINE: RegExp = /^ {3,4}- /;
131
+
132
+ function sampleItemLines(context: string): Array<string> {
133
+ const lines: Array<string> = context.split("\n");
134
+ const index: number = lines.findIndex((line: string) => {
135
+ return LIST_ITEM_LINE.test(line) && line.includes(BREACH_TIME_ISO);
122
136
  });
123
137
 
124
- expect(row).toBeDefined();
125
- return row as string;
138
+ expect(index).toBeGreaterThan(-1);
139
+
140
+ const itemLines: Array<string> = [lines[index] as string];
141
+
142
+ for (const line of lines.slice(index + 1)) {
143
+ if (!DETAIL_LINE.test(line)) {
144
+ break;
145
+ }
146
+
147
+ itemLines.push(line);
148
+ }
149
+
150
+ return itemLines;
126
151
  }
127
152
 
128
- /** The header row of the Breaching Samples table. */
129
- function headerRow(context: string): string {
130
- const row: string | undefined = context.split("\n").find((line: string) => {
131
- return line.startsWith("| Timestamp |");
132
- });
153
+ function sampleItem(context: string): string {
154
+ return sampleItemLines(context)[0] as string;
155
+ }
133
156
 
134
- expect(row).toBeDefined();
135
- return row as string;
157
+ function sampleValue(context: string): string {
158
+ const match: RegExpMatchArray | null =
159
+ sampleItem(context).match(/ — \*\*(.*)\*\*$/);
160
+
161
+ expect(match).not.toBeNull();
162
+ return (match as RegExpMatchArray)[1] as string;
163
+ }
164
+
165
+ function sampleDetails(context: string): Array<string> {
166
+ return sampleItemLines(context).slice(1);
136
167
  }
137
168
 
138
- describe("MonitorCriteriaEvaluator - Breaching Samples value column", () => {
169
+ describe("MonitorCriteriaEvaluator - Breaching Samples values", () => {
139
170
  test("renders bytes at human scale instead of raw digits", () => {
140
171
  const context: string = rootCause(makeContext({ unit: "By" }));
141
172
 
142
- expect(sampleRow(context)).toBe(
143
- `| \`${BREACH_TIME_ISO}\` | \`k8s.pod.memory.usage\` | \`a\` | 1.07 GB |`,
144
- );
173
+ expect(sampleItem(context)).toBe(`1. \`${BREACH_TIME_ISO}\` — **1.07 GB**`);
174
+ expect(sampleDetails(context)).toEqual([]);
145
175
  expect(context).not.toContain("1073741824");
146
176
  });
147
177
 
@@ -156,7 +186,7 @@ describe("MonitorCriteriaEvaluator - Breaching Samples value column", () => {
156
186
  }),
157
187
  );
158
188
 
159
- expect(sampleRow(context)).toContain("| 1.5 sec |");
189
+ expect(sampleValue(context)).toBe("1.5 sec");
160
190
  });
161
191
 
162
192
  test("renders a value the user typed a GB threshold against in GB terms", () => {
@@ -175,10 +205,10 @@ describe("MonitorCriteriaEvaluator - Breaching Samples value column", () => {
175
205
  }),
176
206
  );
177
207
 
178
- expect(sampleRow(context)).toContain("| 2.5 TB |");
208
+ expect(sampleValue(context)).toBe("2.5 TB");
179
209
  });
180
210
 
181
- test("each row names the unit IT landed on", () => {
211
+ test("each sample names the unit IT landed on", () => {
182
212
  const context: string = rootCause(
183
213
  makeContext({
184
214
  unit: "By",
@@ -194,12 +224,12 @@ describe("MonitorCriteriaEvaluator - Breaching Samples value column", () => {
194
224
  );
195
225
 
196
226
  /*
197
- * 922 KB and 1.26 MB in the same table. This is exactly why the unit
198
- * rides each cell instead of the column header — no single header
199
- * could describe both rows.
227
+ * 922 KB and 1.26 MB in the same list. This is exactly why the unit
228
+ * rides each value instead of a heading — no single unit could
229
+ * describe both samples.
200
230
  */
201
- expect(context).toContain("| 922 KB |");
202
- expect(context).toContain("| 1.26 MB |");
231
+ expect(context).toContain("1. `2026-08-14T10:29:00.000Z` — **922 KB**");
232
+ expect(context).toContain(`2. \`${BREACH_TIME_ISO}\` — **1.26 MB**`);
203
233
  });
204
234
 
205
235
  test("a ratio metric's fraction is shown as the percentage it means", () => {
@@ -213,9 +243,9 @@ describe("MonitorCriteriaEvaluator - Breaching Samples value column", () => {
213
243
  }),
214
244
  );
215
245
 
216
- expect(sampleRow(context)).toContain("| 5.85% |");
246
+ expect(sampleValue(context)).toBe("5.85%");
217
247
  // The old rendering: a bare "0.06", which reads as 0.06%.
218
- expect(context).not.toContain("| 0.06 |");
248
+ expect(context).not.toContain("**0.06**");
219
249
  expect(context).not.toContain("0.06 1");
220
250
  });
221
251
 
@@ -230,14 +260,14 @@ describe("MonitorCriteriaEvaluator - Breaching Samples value column", () => {
230
260
  }),
231
261
  );
232
262
 
233
- expect(sampleRow(context)).toContain("| 512 |");
263
+ expect(sampleValue(context)).toBe("512");
234
264
  expect(context).not.toContain("{thread}");
235
265
  });
236
266
 
237
267
  /*
238
268
  * BACKWARD COMPATIBILITY. A metric with no unit must keep every digit —
239
269
  * a counter at 5000 is not "5K" in an alert, because the reader may be
240
- * scanning the table for the exact value that crossed the threshold.
270
+ * scanning the list for the exact value that crossed the threshold.
241
271
  */
242
272
  test("a unitless value keeps its exact digits", () => {
243
273
  const context: string = rootCause(
@@ -250,7 +280,7 @@ describe("MonitorCriteriaEvaluator - Breaching Samples value column", () => {
250
280
  }),
251
281
  );
252
282
 
253
- expect(sampleRow(context)).toContain("| 5000 |");
283
+ expect(sampleValue(context)).toBe("5000");
254
284
  expect(context).not.toContain("5K");
255
285
  });
256
286
 
@@ -264,7 +294,7 @@ describe("MonitorCriteriaEvaluator - Breaching Samples value column", () => {
264
294
  }),
265
295
  );
266
296
 
267
- expect(sampleRow(context)).toContain("| 2.33 |");
297
+ expect(sampleValue(context)).toBe("2.33");
268
298
  });
269
299
 
270
300
  /*
@@ -282,11 +312,11 @@ describe("MonitorCriteriaEvaluator - Breaching Samples value column", () => {
282
312
  }),
283
313
  );
284
314
 
285
- expect(sampleRow(context)).toContain("| Infinity |");
315
+ expect(sampleValue(context)).toBe("Infinity");
286
316
  expect(context).not.toContain("InfinityP");
287
317
  });
288
318
 
289
- test("attribute columns are unaffected", () => {
319
+ test("attributes are listed under the sample, unaffected by the unit", () => {
290
320
  const context: string = rootCause(
291
321
  makeContext({
292
322
  unit: "By",
@@ -301,14 +331,12 @@ describe("MonitorCriteriaEvaluator - Breaching Samples value column", () => {
301
331
  }),
302
332
  );
303
333
 
304
- expect(headerRow(context)).toBe(
305
- "| Timestamp | Metric | Alias | Value | k8s.pod.name |",
306
- );
307
- expect(sampleRow(context)).toContain("| web-1 |");
334
+ expect(sampleItem(context)).toBe(`1. \`${BREACH_TIME_ISO}\` — **1.07 GB**`);
335
+ expect(sampleDetails(context)).toEqual([" - `k8s.pod.name`: `web-1`"]);
308
336
  });
309
337
  });
310
338
 
311
- describe("MonitorCriteriaEvaluator - Breaching Samples component columns", () => {
339
+ describe("MonitorCriteriaEvaluator - Breaching Samples formula components", () => {
312
340
  function formulaContext(): MetricCriteriaContext {
313
341
  return makeContext({
314
342
  metricName: "a + b",
@@ -344,27 +372,27 @@ describe("MonitorCriteriaEvaluator - Breaching Samples component columns", () =>
344
372
  });
345
373
  }
346
374
 
347
- test("each component cell is formatted in its own unit", () => {
375
+ test("each component is formatted in its own unit", () => {
348
376
  const context: string = rootCause(formulaContext());
349
377
 
350
- expect(sampleRow(context)).toBe(
351
- `| \`${BREACH_TIME_ISO}\` | \`a + b\` | \`c\` | 1.07 GB | 537 MB | 1.5 sec |`,
352
- );
378
+ expect(sampleItemLines(context)).toEqual([
379
+ `1. \`${BREACH_TIME_ISO}\` — **1.07 GB**`,
380
+ " - `a`: 537 MB",
381
+ " - `b`: 1.5 sec",
382
+ ]);
353
383
  });
354
384
 
355
385
  /*
356
- * The header used to read "a (By)". Now that a cell says which scale it
357
- * landed on, a header unit is a claim two rows of the same column can
358
- * contradict — and the Components bullet list above the table still
359
- * records the configured unit, so nothing is lost.
386
+ * The table header used to read "a (By)". Now that each value says which
387
+ * scale it landed on, a configured unit beside the alias is a claim two
388
+ * samples can contradict — and the Components bullet list above the
389
+ * samples still records the configured unit, so nothing is lost.
360
390
  */
361
- test("component headers carry the alias only, not the configured unit", () => {
391
+ test("components are labelled by alias only, not the configured unit", () => {
362
392
  const context: string = rootCause(formulaContext());
363
393
 
364
- expect(headerRow(context)).toBe(
365
- "| Timestamp | Metric | Alias | Value | a | b |",
366
- );
367
- expect(context).not.toContain("| a (By) |");
394
+ expect(context).not.toContain("a (By)");
395
+ expect(context).not.toContain("`a (By)`");
368
396
  });
369
397
 
370
398
  test("the Components bullet list spells each component's unit out", () => {
@@ -376,14 +404,18 @@ describe("MonitorCriteriaEvaluator - Breaching Samples component columns", () =>
376
404
  );
377
405
  });
378
406
 
379
- test("a component with no value for this sample still renders a dash", () => {
407
+ test("a component with no value for this sample is left out, not printed as a dash", () => {
380
408
  const ctx: MetricCriteriaContext = formulaContext();
381
409
  ctx.breachingSamples![0]!.componentValues = [
382
410
  { alias: "a", value: 536870912 },
383
411
  { alias: "b", value: null },
384
412
  ];
385
413
 
386
- expect(sampleRow(rootCause(ctx))).toContain("| 537 MB | - |");
414
+ const context: string = rootCause(ctx);
415
+
416
+ expect(sampleDetails(context)).toEqual([" - `a`: 537 MB"]);
417
+ expect(context).not.toContain("`b`:");
418
+ expect(context).not.toContain(": -");
387
419
  });
388
420
  });
389
421
 
@@ -438,7 +470,7 @@ describe("MonitorCriteriaEvaluator - formula names are not metric names", () =>
438
470
  }),
439
471
  );
440
472
 
441
- expect(sampleRow(context)).toContain("| 0.42 |");
473
+ expect(sampleValue(context)).toBe("0.42");
442
474
  expect(context).not.toContain("42.00%");
443
475
  expect(context).not.toContain("- Unit:");
444
476
  });
@@ -470,7 +502,7 @@ describe("MonitorCriteriaEvaluator - formula names are not metric names", () =>
470
502
  }),
471
503
  );
472
504
 
473
- expect(sampleRow(context)).toContain("| 0.42 |");
505
+ expect(sampleDetails(context)).toEqual([" - `x`: 0.42"]);
474
506
  expect(context).not.toContain("42.00%");
475
507
  });
476
508
 
@@ -490,7 +522,7 @@ describe("MonitorCriteriaEvaluator - formula names are not metric names", () =>
490
522
  }),
491
523
  );
492
524
 
493
- expect(sampleRow(context)).toContain("| 42.00% |");
525
+ expect(sampleValue(context)).toBe("42.00%");
494
526
  });
495
527
  });
496
528
 
@@ -500,20 +532,20 @@ describe("MonitorCriteriaEvaluator - formula names are not metric names", () =>
500
532
  * The unit-suppression rule was hand-rolled three separate times before
501
533
  * this change — in CompareCriteria's "Filter Conditions Met" sentence, in
502
534
  * MonitorCriteriaObservationBuilder, and nowhere at all in the Breaching
503
- * Samples table — with the result that a single evaluation read
504
- * differently in its own two halves: "0.31" in the sentence and "0.31 1"
505
- * in the table directly beneath it.
535
+ * Samples table (now a list) — with the result that a single evaluation
536
+ * read differently in its own two halves: "0.31" in the sentence and
537
+ * "0.31 1" in the table directly beneath it.
506
538
  *
507
539
  * Both sections of one email now go through MetricValueFormatter. These
508
540
  * tests assert the two strings are IDENTICAL rather than merely both
509
541
  * plausible, so a fourth copy of the rule cannot quietly appear.
510
542
  */
511
- describe("MonitorCriteriaEvaluator - the table and the sentence agree", () => {
543
+ describe("MonitorCriteriaEvaluator - the Breaching Samples list and the sentence agree", () => {
512
544
  function bothRenderings(input: {
513
545
  value: number;
514
546
  unit: string | null;
515
547
  metricName: string;
516
- }): { cell: string; sentence: string } {
548
+ }): { sampleValue: string; sentence: string } {
517
549
  const ctx: MetricCriteriaContext = makeContext({
518
550
  metricName: input.metricName,
519
551
  unit: input.unit,
@@ -522,14 +554,8 @@ describe("MonitorCriteriaEvaluator - the table and the sentence agree", () => {
522
554
  ],
523
555
  });
524
556
 
525
- const row: string = sampleRow(rootCause(ctx));
526
- const cells: Array<string> = row.split("|").map((cell: string) => {
527
- return cell.trim();
528
- });
529
-
530
557
  return {
531
- // | ts | metric | alias | VALUE | → index 4 once the leading "" is counted.
532
- cell: cells[4] as string,
558
+ sampleValue: sampleValue(rootCause(ctx)),
533
559
  sentence: CompareCriteria.getCompareMessage({
534
560
  values: input.value,
535
561
  threshold: input.value,
@@ -559,12 +585,12 @@ describe("MonitorCriteriaEvaluator - the table and the sentence agree", () => {
559
585
 
560
586
  for (const testCase of cases) {
561
587
  test(`${testCase.metricName} @ ${testCase.unit ?? "no unit"} reads the same in both`, () => {
562
- const rendered: { cell: string; sentence: string } =
588
+ const rendered: { sampleValue: string; sentence: string } =
563
589
  bothRenderings(testCase);
564
590
 
565
- expect(rendered.cell.length).toBeGreaterThan(0);
591
+ expect(rendered.sampleValue.length).toBeGreaterThan(0);
566
592
  expect(rendered.sentence).toBe(
567
- `${testCase.metricName} was ${rendered.cell}. The condition requires the value to be above the ${rendered.cell} threshold.`,
593
+ `${testCase.metricName} was ${rendered.sampleValue}. The condition requires the value to be above the ${rendered.sampleValue} threshold.`,
568
594
  );
569
595
  });
570
596
  }
@@ -0,0 +1,188 @@
1
+ import MonitoringIntervalValidator from "../../../../Server/Utils/Monitor/MonitoringIntervalValidator";
2
+ import BadDataException from "../../../../Types/Exception/BadDataException";
3
+ import { describe, expect, test } from "@jest/globals";
4
+
5
+ /*
6
+ * WHAT THIS FILE IS DEFENDING
7
+ *
8
+ * The write-time policy for Monitor.monitoringInterval. The column was free
9
+ * text with no validation at all, which is how 103 monitors across 10
10
+ * projects ended up holding a human cadence ("5m", "Every 5 minutes") that
11
+ * the scheduler could not read — and silently probed four times too often.
12
+ *
13
+ * The policy has to hold two lines at once:
14
+ * - refuse values nobody can act on, so the column stops accumulating them;
15
+ * - never refuse a value the RUNTIME parser would happily have scheduled,
16
+ * because a validator that disagrees with the scheduler is this same bug
17
+ * in mirror image.
18
+ */
19
+
20
+ describe("MonitoringIntervalValidator.validateAndNormalize", () => {
21
+ describe("canonicalizes what it understands", () => {
22
+ test.each([
23
+ ["5m", "*/5 * * * *"],
24
+ ["Every 5 minutes", "*/5 * * * *"],
25
+ ["Every 5 Minutes", "*/5 * * * *"],
26
+ ["Every Five Minutes", "*/5 * * * *"],
27
+ ["1 minute", "* * * * *"],
28
+ ["Every 1 minute", "* * * * *"],
29
+ ["Every 2 minutes", "*/2 * * * *"],
30
+ ["5 minutes", "*/5 * * * *"],
31
+ ["1 day", "0 0 * * *"],
32
+ ["every-1-min", "* * * * *"],
33
+ ])("%j is stored as %j", (input: string, expected: string) => {
34
+ expect(MonitoringIntervalValidator.validateAndNormalize(input)).toBe(
35
+ expected,
36
+ );
37
+ });
38
+
39
+ test("already-canonical cron is stored byte-identical", () => {
40
+ for (const cron of [
41
+ "* * * * *",
42
+ "*/5 * * * *",
43
+ "0 */6 * * *",
44
+ "0 0 * * 0",
45
+ ]) {
46
+ expect(MonitoringIntervalValidator.validateAndNormalize(cron)).toBe(
47
+ cron,
48
+ );
49
+ }
50
+ });
51
+ });
52
+
53
+ describe("empty means no schedule, and is always legal", () => {
54
+ /*
55
+ * A Manual monitor is never probed. ~4,177 production rows are in this
56
+ * state and must not start throwing on an unrelated edit.
57
+ */
58
+ test.each([null, undefined, "", " "])(
59
+ "%j is accepted and stored as null",
60
+ (value: string | null | undefined) => {
61
+ expect(
62
+ MonitoringIntervalValidator.validateAndNormalize(value),
63
+ ).toBeNull();
64
+ },
65
+ );
66
+ });
67
+
68
+ describe("never refuses what the scheduler could run", () => {
69
+ test("accepts a cron-parser shortcut the isomorphic grammar does not know", () => {
70
+ /*
71
+ * The isomorphic normalizer reports "@hourly" as Unrecognized, but
72
+ * cron-parser — the thing that actually computes nextPingAt — reads it
73
+ * fine. The validator must defer to the runtime parser, and must pass
74
+ * the value through UNCHANGED rather than rewriting it.
75
+ */
76
+ expect(MonitoringIntervalValidator.validateAndNormalize("@hourly")).toBe(
77
+ "@hourly",
78
+ );
79
+ });
80
+
81
+ test.each(["@daily", "@weekly", "@monthly", "@yearly"])(
82
+ "accepts %j unchanged",
83
+ (shortcut: string) => {
84
+ expect(MonitoringIntervalValidator.validateAndNormalize(shortcut)).toBe(
85
+ shortcut,
86
+ );
87
+ },
88
+ );
89
+
90
+ test("accepts exotic but valid cron", () => {
91
+ for (const cron of [
92
+ "3-59/5 * * * *",
93
+ "0,15,30,45 * * * *",
94
+ "0 9 * * 1-5",
95
+ ]) {
96
+ expect(MonitoringIntervalValidator.validateAndNormalize(cron)).toBe(
97
+ cron,
98
+ );
99
+ }
100
+ });
101
+ });
102
+
103
+ describe("refuses what it cannot honour", () => {
104
+ test.each(["banana", "asap", "soon", "not a cron", "every 7 minutes"])(
105
+ "%j throws BadDataException",
106
+ (input: string) => {
107
+ expect(() => {
108
+ return MonitoringIntervalValidator.validateAndNormalize(input);
109
+ }).toThrow(BadDataException);
110
+ },
111
+ );
112
+
113
+ test("the error message names a cron the caller can copy", () => {
114
+ /*
115
+ * The whole reason these rows exist is that we never told anyone what
116
+ * this field wanted. An error that only says "invalid" repeats the
117
+ * mistake.
118
+ */
119
+ let message: string = "";
120
+
121
+ try {
122
+ MonitoringIntervalValidator.validateAndNormalize("banana");
123
+ } catch (err) {
124
+ message = (err as BadDataException).message;
125
+ }
126
+
127
+ expect(message).toContain("banana");
128
+ expect(message).toContain("*/5 * * * *");
129
+ expect(message.toLowerCase()).toContain("cron");
130
+ });
131
+
132
+ test("refuses a sub-minute schedule the probe fleet cannot deliver", () => {
133
+ /*
134
+ * cron-parser accepts 6-field per-second expressions. Without an
135
+ * explicit floor an API client would ask for a per-second probe and
136
+ * silently receive a per-minute one — the exact shape of the bug this
137
+ * file exists to close, just in the other direction.
138
+ */
139
+ expect(() => {
140
+ return MonitoringIntervalValidator.validateAndNormalize("* * * * * *");
141
+ }).toThrow(BadDataException);
142
+
143
+ expect(() => {
144
+ return MonitoringIntervalValidator.validateAndNormalize(
145
+ "*/30 * * * * *",
146
+ );
147
+ }).toThrow(BadDataException);
148
+ });
149
+
150
+ test("the fastest supported schedule is still accepted", () => {
151
+ expect(
152
+ MonitoringIntervalValidator.validateAndNormalize("* * * * *"),
153
+ ).toBe("* * * * *");
154
+ });
155
+ });
156
+
157
+ describe("idempotence", () => {
158
+ test("validating a stored value again changes nothing", () => {
159
+ for (const input of [
160
+ "5m",
161
+ "Every 5 minutes",
162
+ "1 day",
163
+ "*/5 * * * *",
164
+ "@hourly",
165
+ ]) {
166
+ const once: string | null =
167
+ MonitoringIntervalValidator.validateAndNormalize(input);
168
+ expect(MonitoringIntervalValidator.validateAndNormalize(once)).toBe(
169
+ once,
170
+ );
171
+ }
172
+ });
173
+ });
174
+
175
+ describe("normalizeForRead", () => {
176
+ test("is total — a row written before this validator existed is not an exception", () => {
177
+ expect(MonitoringIntervalValidator.normalizeForRead("5m")).toBe(
178
+ "*/5 * * * *",
179
+ );
180
+ expect(MonitoringIntervalValidator.normalizeForRead("banana")).toBeNull();
181
+ expect(MonitoringIntervalValidator.normalizeForRead(null)).toBeNull();
182
+
183
+ expect(() => {
184
+ return MonitoringIntervalValidator.normalizeForRead("🙂");
185
+ }).not.toThrow();
186
+ });
187
+ });
188
+ });