@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
@@ -11,6 +11,11 @@ import Color from "../../Types/Color";
11
11
  import LIMIT_MAX, { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
12
12
  import BadDataException from "../../Types/Exception/BadDataException";
13
13
  import ObjectID from "../../Types/ObjectID";
14
+ import MonitorType from "../../Types/Monitor/MonitorType";
15
+ import {
16
+ getMonitorTypeCriteriaValidationError,
17
+ isMonitorTypeCriteriaValue,
18
+ } from "../../Utils/Rules/MonitorTypeRuleCriteria";
14
19
  import { escapeMarkdownInline } from "../../Utils/Markdown/MarkdownEscape";
15
20
  import {
16
21
  getRuleCriteriaValidationError,
@@ -51,6 +56,7 @@ const RULE_SNAPSHOT_SELECT: Select<Model> = {
51
56
  _id: true,
52
57
  name: true,
53
58
  },
59
+ monitorType: true,
54
60
  monitorNamePattern: true,
55
61
  monitorDescriptionPattern: true,
56
62
  criteria: true,
@@ -92,6 +98,7 @@ export class Service extends DatabaseService<Model> {
92
98
 
93
99
  this.assertHasMatchCriteria({
94
100
  monitorLabelCount: (createBy.data.monitorLabels || []).length,
101
+ monitorType: createBy.data.monitorType,
95
102
  monitorNamePattern: createBy.data.monitorNamePattern,
96
103
  monitorDescriptionPattern: createBy.data.monitorDescriptionPattern,
97
104
  criteria: createBy.data.criteria,
@@ -188,6 +195,7 @@ export class Service extends DatabaseService<Model> {
188
195
 
189
196
  const touchesCriteria: boolean =
190
197
  updateBy.data.monitorLabels !== undefined ||
198
+ updateBy.data.monitorType !== undefined ||
191
199
  updateBy.data.monitorNamePattern !== undefined ||
192
200
  updateBy.data.monitorDescriptionPattern !== undefined ||
193
201
  updateBy.data.criteria !== undefined;
@@ -656,6 +664,7 @@ export class Service extends DatabaseService<Model> {
656
664
  */
657
665
  private assertHasMatchCriteria(data: {
658
666
  monitorLabelCount: number;
667
+ monitorType?: MonitorType | undefined;
659
668
  monitorNamePattern?: string | undefined;
660
669
  monitorDescriptionPattern?: string | undefined;
661
670
  criteria?: Model["criteria"];
@@ -673,6 +682,17 @@ export class Service extends DatabaseService<Model> {
673
682
  isValidRuleCriteria(data.criteria) &&
674
683
  data.criteria.filters.length > 0
675
684
  ) {
685
+ for (const filter of data.criteria.filters) {
686
+ if (filter.field === "monitorType") {
687
+ const typeError: string | null =
688
+ getMonitorTypeCriteriaValidationError(filter);
689
+
690
+ if (typeError) {
691
+ throw new BadDataException(typeError);
692
+ }
693
+ }
694
+ }
695
+
676
696
  return;
677
697
  }
678
698
 
@@ -681,13 +701,24 @@ export class Service extends DatabaseService<Model> {
681
701
  );
682
702
  }
683
703
 
704
+ if (
705
+ data.monitorType !== undefined &&
706
+ data.monitorType !== null &&
707
+ !isMonitorTypeCriteriaValue(data.monitorType)
708
+ ) {
709
+ throw new BadDataException(
710
+ "Monitor type criteria require a valid monitor type.",
711
+ );
712
+ }
713
+
684
714
  if (
685
715
  data.monitorLabelCount === 0 &&
716
+ !data.monitorType &&
686
717
  !data.monitorNamePattern &&
687
718
  !data.monitorDescriptionPattern
688
719
  ) {
689
720
  throw new BadDataException(
690
- "An SLO monitor rule needs at least one match criterion: monitor labels, a monitor name pattern, or a monitor description pattern. Use .* as the name pattern to match every monitor in the project.",
721
+ "An SLO monitor rule needs at least one match criterion: monitor labels, a monitor type, a monitor name pattern, or a monitor description pattern. Use .* as the name pattern to match every monitor in the project.",
691
722
  );
692
723
  }
693
724
  }
@@ -744,6 +775,10 @@ export class Service extends DatabaseService<Model> {
744
775
  ? rule.monitorLabels || []
745
776
  : nextLabels || []
746
777
  ).length,
778
+ monitorType:
779
+ updateBy.data.monitorType === undefined
780
+ ? rule.monitorType
781
+ : (updateBy.data.monitorType as MonitorType | undefined),
747
782
  monitorNamePattern:
748
783
  updateBy.data.monitorNamePattern === undefined
749
784
  ? rule.monitorNamePattern
@@ -0,0 +1,521 @@
1
+ import Label from "../../Models/DatabaseModels/Label";
2
+ import ServiceLevelObjective from "../../Models/DatabaseModels/ServiceLevelObjective";
3
+ import { ServiceLevelObjectiveFeedEventType } from "../../Models/DatabaseModels/ServiceLevelObjectiveFeed";
4
+ import ServiceLevelObjectiveOwnerRule from "../../Models/DatabaseModels/ServiceLevelObjectiveOwnerRule";
5
+ import ServiceLevelObjectiveOwnerTeam from "../../Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam";
6
+ import ServiceLevelObjectiveOwnerUser from "../../Models/DatabaseModels/ServiceLevelObjectiveOwnerUser";
7
+ import BaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
8
+ import { Purple500 } from "../../Types/BrandColors";
9
+ import BadDataException from "../../Types/Exception/BadDataException";
10
+ import ObjectID from "../../Types/ObjectID";
11
+ import { escapeMarkdownInline } from "../../Utils/Markdown/MarkdownEscape";
12
+ import { MAX_RULES_EVALUATED_PER_PROJECT } from "../../Utils/Rules/RuleEngineLimits";
13
+ import { RuleCriteriaMatcher } from "../../Utils/Rules/RuleCriteriaMatcher";
14
+ import RulePatternMatchUtil from "../../Utils/Rules/RulePatternMatchUtil";
15
+ import Select from "../Types/Database/Select";
16
+ import logger, { LogAttributes } from "../Utils/Logger";
17
+ import OwnerRuleAssignment, {
18
+ OwnersToAssign,
19
+ } from "../Utils/Rules/OwnerRuleAssignment";
20
+ import logIfRuleReadWasTruncated from "../Utils/Rules/RuleEngineRuleRead";
21
+ import {
22
+ ApplyRulesToExistingResourceData,
23
+ RuleApplicationResult,
24
+ RuleApplicationResultUtil,
25
+ RuleRunEngine,
26
+ } from "../Utils/Rules/RuleRun/RuleApplication";
27
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
28
+ import DatabaseService from "./DatabaseService";
29
+ import ServiceLevelObjectiveFeedService from "./ServiceLevelObjectiveFeedService";
30
+ import ServiceLevelObjectiveOwnerRuleService from "./ServiceLevelObjectiveOwnerRuleService";
31
+ import ServiceLevelObjectiveOwnerTeamService from "./ServiceLevelObjectiveOwnerTeamService";
32
+ import ServiceLevelObjectiveOwnerUserService from "./ServiceLevelObjectiveOwnerUserService";
33
+ import ServiceLevelObjectiveService from "./ServiceLevelObjectiveService";
34
+
35
+ // What adding one owner row did.
36
+ enum OwnerWriteOutcome {
37
+ Added = "Added",
38
+ AlreadyOwner = "AlreadyOwner",
39
+ Rejected = "Rejected",
40
+ }
41
+
42
+ class ServiceLevelObjectiveOwnerRuleEngineServiceClass
43
+ implements
44
+ RuleRunEngine<ServiceLevelObjective, ServiceLevelObjectiveOwnerRule>
45
+ {
46
+ public readonly ruleSelect: Select<ServiceLevelObjectiveOwnerRule> = {
47
+ _id: true,
48
+ name: true,
49
+ criteria: true,
50
+ notifyOwners: true,
51
+ serviceLevelObjectiveLabels: { _id: true },
52
+ serviceLevelObjectiveNamePattern: true,
53
+ serviceLevelObjectiveDescriptionPattern: true,
54
+ ownerUsers: { _id: true },
55
+ ownerTeams: { _id: true },
56
+ };
57
+
58
+ // Evaluation re-reads the SLO, so a run only has to name it.
59
+ public readonly resourceSelectForRuleRun: Select<ServiceLevelObjective> = {
60
+ _id: true,
61
+ projectId: true,
62
+ };
63
+
64
+ /**
65
+ * Evaluates ServiceLevelObjectiveOwnerRule rows for the given SLO and adds
66
+ * matched owner users / teams through the SLO owner services, so each one
67
+ * gets the usual owner-added feed item and notification. Rules with
68
+ * notifyOwners set notify the added owners; rules with notifyOwners off add
69
+ * silently.
70
+ */
71
+ @CaptureSpan()
72
+ public async applyRulesToServiceLevelObjective(
73
+ serviceLevelObjective: ServiceLevelObjective,
74
+ ): Promise<void> {
75
+ if (!serviceLevelObjective.id || !serviceLevelObjective.projectId) {
76
+ return;
77
+ }
78
+
79
+ try {
80
+ const rules: Array<ServiceLevelObjectiveOwnerRule> =
81
+ await ServiceLevelObjectiveOwnerRuleService.findBy({
82
+ query: {
83
+ projectId: serviceLevelObjective.projectId,
84
+ isEnabled: true,
85
+ },
86
+ props: { isRoot: true },
87
+ select: this.ruleSelect,
88
+ limit: MAX_RULES_EVALUATED_PER_PROJECT,
89
+ skip: 0,
90
+ });
91
+
92
+ logIfRuleReadWasTruncated({
93
+ ruleKind: "ServiceLevelObjectiveOwnerRule",
94
+ projectId: serviceLevelObjective.projectId,
95
+ rulesRead: rules.length,
96
+ });
97
+
98
+ if (rules.length === 0) {
99
+ return;
100
+ }
101
+
102
+ await this.applyRules({
103
+ serviceLevelObjective: serviceLevelObjective,
104
+ rules: rules,
105
+ allowOwnerNotification: true,
106
+ });
107
+ } catch (error) {
108
+ logger.error(`Error applying SLO owner rules: ${error}`, {
109
+ projectId: serviceLevelObjective.projectId?.toString(),
110
+ serviceLevelObjectiveId: serviceLevelObjective.id?.toString(),
111
+ } as LogAttributes);
112
+ }
113
+ }
114
+
115
+ /*
116
+ * "Run now": the same evaluation, for an SLO that already exists and only
117
+ * the rules being run.
118
+ */
119
+ @CaptureSpan()
120
+ public async applyRulesToExistingResource(
121
+ data: ApplyRulesToExistingResourceData<
122
+ ServiceLevelObjective,
123
+ ServiceLevelObjectiveOwnerRule
124
+ >,
125
+ ): Promise<RuleApplicationResult> {
126
+ try {
127
+ return await this.applyRules({
128
+ serviceLevelObjective: data.resource,
129
+ rules: data.rules,
130
+ allowOwnerNotification: data.allowOwnerNotification,
131
+ });
132
+ } catch (error) {
133
+ logger.error(`Error running SLO owner rules: ${error}`, {
134
+ projectId: data.resource.projectId?.toString(),
135
+ serviceLevelObjectiveId: data.resource.id?.toString(),
136
+ } as LogAttributes);
137
+
138
+ return RuleApplicationResultUtil.failed();
139
+ }
140
+ }
141
+
142
+ private async applyRules(data: {
143
+ serviceLevelObjective: ServiceLevelObjective;
144
+ rules: Array<ServiceLevelObjectiveOwnerRule>;
145
+ allowOwnerNotification: boolean;
146
+ }): Promise<RuleApplicationResult> {
147
+ const { serviceLevelObjective, rules } = data;
148
+
149
+ if (
150
+ !serviceLevelObjective.id ||
151
+ !serviceLevelObjective.projectId ||
152
+ rules.length === 0
153
+ ) {
154
+ return RuleApplicationResultUtil.noMatch();
155
+ }
156
+
157
+ const sloWithDetails: ServiceLevelObjective | null =
158
+ await ServiceLevelObjectiveService.findOneById({
159
+ id: serviceLevelObjective.id,
160
+ select: {
161
+ name: true,
162
+ description: true,
163
+ labels: { _id: true },
164
+ },
165
+ props: { isRoot: true },
166
+ });
167
+
168
+ if (!sloWithDetails) {
169
+ return RuleApplicationResultUtil.noMatch();
170
+ }
171
+
172
+ const usersByNotify: Map<boolean, Set<string>> = new Map([
173
+ [true, new Set()],
174
+ [false, new Set()],
175
+ ]);
176
+ const teamsByNotify: Map<boolean, Set<string>> = new Map([
177
+ [true, new Set()],
178
+ [false, new Set()],
179
+ ]);
180
+
181
+ const matchedRules: Array<ServiceLevelObjectiveOwnerRule> = [];
182
+ const allUserIds: Set<string> = new Set();
183
+ const allTeamIds: Set<string> = new Set();
184
+ let anyRuleMatched: boolean = false;
185
+
186
+ for (const rule of rules) {
187
+ if (!this.doesServiceLevelObjectiveMatchRule(sloWithDetails, rule)) {
188
+ continue;
189
+ }
190
+ anyRuleMatched = true;
191
+ let ruleAddedAny: boolean = false;
192
+ const notify: boolean =
193
+ rule.notifyOwners !== false && data.allowOwnerNotification;
194
+ for (const user of rule.ownerUsers || []) {
195
+ if (user.id) {
196
+ usersByNotify.get(notify)!.add(user.id.toString());
197
+ allUserIds.add(user.id.toString());
198
+ ruleAddedAny = true;
199
+ }
200
+ }
201
+ for (const team of rule.ownerTeams || []) {
202
+ if (team.id) {
203
+ teamsByNotify.get(notify)!.add(team.id.toString());
204
+ allTeamIds.add(team.id.toString());
205
+ ruleAddedAny = true;
206
+ }
207
+ }
208
+ if (ruleAddedAny) {
209
+ matchedRules.push(rule);
210
+ }
211
+ }
212
+
213
+ if (!anyRuleMatched) {
214
+ return RuleApplicationResultUtil.noMatch();
215
+ }
216
+
217
+ // The rules that matched name no owners, so there is nothing to add.
218
+ if (matchedRules.length === 0) {
219
+ return RuleApplicationResultUtil.alreadyApplied();
220
+ }
221
+
222
+ // Owners already on the SLO are skipped rather than duplicated.
223
+ const notYetAssigned: OwnersToAssign =
224
+ await OwnerRuleAssignment.getOwnersNotYetAssigned({
225
+ ownerUserService: ServiceLevelObjectiveOwnerUserService,
226
+ ownerTeamService: ServiceLevelObjectiveOwnerTeamService,
227
+ resourceIdColumn: "serviceLevelObjectiveId",
228
+ resourceId: serviceLevelObjective.id,
229
+ userIds: Array.from(allUserIds),
230
+ teamIds: Array.from(allTeamIds),
231
+ });
232
+
233
+ const userIdsToAdd: Set<string> = new Set(
234
+ notYetAssigned.userIds.map((id: ObjectID): string => {
235
+ return id.toString();
236
+ }),
237
+ );
238
+ const teamIdsToAdd: Set<string> = new Set(
239
+ notYetAssigned.teamIds.map((id: ObjectID): string => {
240
+ return id.toString();
241
+ }),
242
+ );
243
+
244
+ let ownersAdded: number = 0;
245
+ let ownersRejected: number = 0;
246
+
247
+ const count: (outcome: OwnerWriteOutcome) => void = (
248
+ outcome: OwnerWriteOutcome,
249
+ ): void => {
250
+ if (outcome === OwnerWriteOutcome.Added) {
251
+ ownersAdded++;
252
+ } else if (outcome === OwnerWriteOutcome.Rejected) {
253
+ ownersRejected++;
254
+ }
255
+ };
256
+
257
+ /*
258
+ * The notifying set goes first, so an owner two matching rules disagree
259
+ * about is added once, and notified.
260
+ */
261
+ for (const notify of [true, false]) {
262
+ const userIds: Array<string> = Array.from(
263
+ usersByNotify.get(notify)!,
264
+ ).filter((id: string): boolean => {
265
+ return userIdsToAdd.delete(id);
266
+ });
267
+ const teamIds: Array<string> = Array.from(
268
+ teamsByNotify.get(notify)!,
269
+ ).filter((id: string): boolean => {
270
+ return teamIdsToAdd.delete(id);
271
+ });
272
+
273
+ for (const userId of userIds) {
274
+ const owner: ServiceLevelObjectiveOwnerUser =
275
+ new ServiceLevelObjectiveOwnerUser();
276
+ owner.serviceLevelObjectiveId = serviceLevelObjective.id;
277
+ owner.projectId = serviceLevelObjective.projectId;
278
+ owner.userId = new ObjectID(userId);
279
+ owner.isOwnerNotified = !notify;
280
+ count(
281
+ await this.addOwner({
282
+ ownerService: ServiceLevelObjectiveOwnerUserService,
283
+ owner: owner,
284
+ serviceLevelObjective: serviceLevelObjective,
285
+ }),
286
+ );
287
+ }
288
+
289
+ for (const teamId of teamIds) {
290
+ const owner: ServiceLevelObjectiveOwnerTeam =
291
+ new ServiceLevelObjectiveOwnerTeam();
292
+ owner.serviceLevelObjectiveId = serviceLevelObjective.id;
293
+ owner.projectId = serviceLevelObjective.projectId;
294
+ owner.teamId = new ObjectID(teamId);
295
+ owner.isOwnerNotified = !notify;
296
+ count(
297
+ await this.addOwner({
298
+ ownerService: ServiceLevelObjectiveOwnerTeamService,
299
+ owner: owner,
300
+ serviceLevelObjective: serviceLevelObjective,
301
+ }),
302
+ );
303
+ }
304
+ }
305
+
306
+ if (ownersAdded === 0) {
307
+ /*
308
+ * Every owner the rules name was refused - a user who has since left the
309
+ * project, say. Nothing was added, and "already applied" would claim the
310
+ * SLO has owners it does not, so report the SLO as one the run could not
311
+ * update.
312
+ */
313
+ return ownersRejected > 0
314
+ ? RuleApplicationResultUtil.failed()
315
+ : RuleApplicationResultUtil.alreadyApplied();
316
+ }
317
+
318
+ logger.debug(
319
+ `ServiceLevelObjectiveOwnerRuleEngine added owners to SLO ${serviceLevelObjective.id}`,
320
+ {
321
+ projectId: serviceLevelObjective.projectId.toString(),
322
+ } as LogAttributes,
323
+ );
324
+
325
+ await this.postOwnerRuleFeedItem({
326
+ serviceLevelObjectiveId: serviceLevelObjective.id,
327
+ projectId: serviceLevelObjective.projectId,
328
+ sloName: sloWithDetails.name,
329
+ matchedRules: matchedRules,
330
+ });
331
+
332
+ return RuleApplicationResultUtil.updated(ownersAdded);
333
+ }
334
+
335
+ /*
336
+ * SLO owner services refuse a user who is not a member of the project, or a
337
+ * team from another one (see SloOwnerReferenceValidator) - which a rule can
338
+ * still name after the user left, or when it was written through the API.
339
+ * That owner is skipped so the rule's other owners are still added; any
340
+ * other failure is thrown as before.
341
+ */
342
+ private async addOwner<TOwner extends BaseModel>(data: {
343
+ ownerService: DatabaseService<TOwner>;
344
+ owner: TOwner;
345
+ serviceLevelObjective: ServiceLevelObjective;
346
+ }): Promise<OwnerWriteOutcome> {
347
+ try {
348
+ const added: boolean = await OwnerRuleAssignment.createOwner({
349
+ ownerService: data.ownerService,
350
+ owner: data.owner,
351
+ props: { isRoot: true },
352
+ });
353
+
354
+ return added ? OwnerWriteOutcome.Added : OwnerWriteOutcome.AlreadyOwner;
355
+ } catch (error) {
356
+ if (!(error instanceof BadDataException)) {
357
+ throw error;
358
+ }
359
+
360
+ logger.warn(
361
+ `SLO owner rule could not add an owner to SLO ${data.serviceLevelObjective.id?.toString()}: ${error.message}`,
362
+ {
363
+ projectId: data.serviceLevelObjective.projectId?.toString(),
364
+ } as LogAttributes,
365
+ );
366
+
367
+ return OwnerWriteOutcome.Rejected;
368
+ }
369
+ }
370
+
371
+ /*
372
+ * The individual OwnerUserAdded / OwnerTeamAdded items say who was added;
373
+ * this one says which rule is responsible, which is what somebody asking
374
+ * "why am I on the hook for this SLO?" actually needs. The owners are
375
+ * already added by now, so a feed failure is logged, never thrown.
376
+ */
377
+ private async postOwnerRuleFeedItem(data: {
378
+ serviceLevelObjectiveId: ObjectID;
379
+ projectId: ObjectID;
380
+ sloName: string | undefined;
381
+ matchedRules: Array<ServiceLevelObjectiveOwnerRule>;
382
+ }): Promise<void> {
383
+ try {
384
+ const sloLink: string =
385
+ await ServiceLevelObjectiveService.getSloMarkdownLink({
386
+ projectId: data.projectId,
387
+ sloId: data.serviceLevelObjectiveId,
388
+ sloName: data.sloName,
389
+ });
390
+
391
+ await ServiceLevelObjectiveFeedService.createServiceLevelObjectiveFeedItem(
392
+ {
393
+ serviceLevelObjectiveId: data.serviceLevelObjectiveId,
394
+ projectId: data.projectId,
395
+ serviceLevelObjectiveFeedEventType:
396
+ ServiceLevelObjectiveFeedEventType.OwnerRuleExecuted,
397
+ displayColor: Purple500,
398
+ feedInfoInMarkdown: `👥 Owners were added to ${sloLink} by ${data.matchedRules.length} owner ${data.matchedRules.length === 1 ? "rule" : "rules"}.`,
399
+ moreInformationInMarkdown: `**Owner rules that matched**: ${data.matchedRules
400
+ .map((rule: ServiceLevelObjectiveOwnerRule): string => {
401
+ // Rule names are user-controlled and the feed renders markdown.
402
+ return `**${escapeMarkdownInline(
403
+ rule.name || rule.id?.toString() || "Unnamed rule",
404
+ )}**`;
405
+ })
406
+ .join(", ")}`,
407
+ },
408
+ );
409
+ } catch (error) {
410
+ logger.error(
411
+ `Error writing the owner rule feed item for SLO ${data.serviceLevelObjectiveId.toString()}: ${error}`,
412
+ { projectId: data.projectId.toString() } as LogAttributes,
413
+ );
414
+ }
415
+ }
416
+
417
+ private doesServiceLevelObjectiveMatchRule(
418
+ serviceLevelObjective: ServiceLevelObjective,
419
+ rule: ServiceLevelObjectiveOwnerRule,
420
+ ): boolean {
421
+ return RuleCriteriaMatcher.matchesWithLegacySync({
422
+ rule,
423
+ legacyFields: [
424
+ "serviceLevelObjectiveLabels",
425
+ "serviceLevelObjectiveNamePattern",
426
+ "serviceLevelObjectiveDescriptionPattern",
427
+ ],
428
+ emptyResult: true,
429
+ matchesLegacyRule: (
430
+ legacyRule: ServiceLevelObjectiveOwnerRule,
431
+ ): boolean => {
432
+ return this.doesServiceLevelObjectiveMatchLegacyRule(
433
+ serviceLevelObjective,
434
+ legacyRule,
435
+ );
436
+ },
437
+ });
438
+ }
439
+
440
+ private doesServiceLevelObjectiveMatchLegacyRule(
441
+ serviceLevelObjective: ServiceLevelObjective,
442
+ rule: ServiceLevelObjectiveOwnerRule,
443
+ ): boolean {
444
+ if (
445
+ rule.serviceLevelObjectiveLabels &&
446
+ rule.serviceLevelObjectiveLabels.length > 0
447
+ ) {
448
+ if (
449
+ !serviceLevelObjective.labels ||
450
+ serviceLevelObjective.labels.length === 0
451
+ ) {
452
+ return false;
453
+ }
454
+ const ruleLabelIds: Array<string> = rule.serviceLevelObjectiveLabels.map(
455
+ (l: Label) => {
456
+ return l.id?.toString() || "";
457
+ },
458
+ );
459
+ const labelIds: Array<string> = serviceLevelObjective.labels.map(
460
+ (l: Label) => {
461
+ return l.id?.toString() || "";
462
+ },
463
+ );
464
+ if (
465
+ !ruleLabelIds.some((id: string) => {
466
+ return labelIds.includes(id);
467
+ })
468
+ ) {
469
+ return false;
470
+ }
471
+ }
472
+
473
+ if (
474
+ rule.serviceLevelObjectiveNamePattern &&
475
+ (!serviceLevelObjective.name ||
476
+ !this.testPattern(
477
+ rule.serviceLevelObjectiveNamePattern,
478
+ serviceLevelObjective.name,
479
+ rule,
480
+ ))
481
+ ) {
482
+ return false;
483
+ }
484
+
485
+ if (
486
+ rule.serviceLevelObjectiveDescriptionPattern &&
487
+ (!serviceLevelObjective.description ||
488
+ !this.testPattern(
489
+ rule.serviceLevelObjectiveDescriptionPattern,
490
+ serviceLevelObjective.description,
491
+ rule,
492
+ ))
493
+ ) {
494
+ return false;
495
+ }
496
+
497
+ return true;
498
+ }
499
+
500
+ /*
501
+ * Patterns are regexes, with a '*' wildcard fallback - the same two syntaxes
502
+ * the SLO monitor rules take. SloRulePatternValidator rejects anything else
503
+ * on save, so this only warns about a rule written before that check.
504
+ */
505
+ private testPattern(
506
+ pattern: string,
507
+ value: string,
508
+ rule: ServiceLevelObjectiveOwnerRule,
509
+ ): boolean {
510
+ if (!RulePatternMatchUtil.isSupportedPattern(pattern)) {
511
+ logger.warn(
512
+ `Invalid pattern in SLO owner rule ${rule.id}: ${pattern}. It is neither a valid regular expression nor a wildcard pattern, so it will never match.`,
513
+ );
514
+ return false;
515
+ }
516
+
517
+ return RulePatternMatchUtil.matches(value, pattern);
518
+ }
519
+ }
520
+
521
+ export default new ServiceLevelObjectiveOwnerRuleEngineServiceClass();
@@ -0,0 +1,51 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/ServiceLevelObjectiveOwnerRule";
3
+ import CreateBy from "../Types/Database/CreateBy";
4
+ import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
5
+ import UpdateBy from "../Types/Database/UpdateBy";
6
+ import SloRulePatternValidator from "../Utils/Slo/SloRulePatternValidator";
7
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
8
+
9
+ /*
10
+ * No hard-delete retention: a rule is configuration, not an event log, so it
11
+ * stays until somebody deletes it.
12
+ */
13
+ export class Service extends DatabaseService<Model> {
14
+ public constructor() {
15
+ super(Model);
16
+ }
17
+
18
+ /*
19
+ * A pattern that is neither a valid regex nor a wildcard can only ever match
20
+ * nothing, and the rule engine has no way to say so - it just quietly stops
21
+ * assigning owners. Reject it while the user is still looking at the form.
22
+ */
23
+ @CaptureSpan()
24
+ protected override async onBeforeCreate(
25
+ createBy: CreateBy<Model>,
26
+ ): Promise<OnCreate<Model>> {
27
+ SloRulePatternValidator.validate({
28
+ namePattern: createBy.data.serviceLevelObjectiveNamePattern,
29
+ descriptionPattern: createBy.data.serviceLevelObjectiveDescriptionPattern,
30
+ });
31
+
32
+ return { createBy: createBy, carryForward: null };
33
+ }
34
+
35
+ @CaptureSpan()
36
+ protected override async onBeforeUpdate(
37
+ updateBy: UpdateBy<Model>,
38
+ ): Promise<OnUpdate<Model>> {
39
+ SloRulePatternValidator.validate({
40
+ namePattern: updateBy.data.serviceLevelObjectiveNamePattern as
41
+ | string
42
+ | undefined,
43
+ descriptionPattern: updateBy.data
44
+ .serviceLevelObjectiveDescriptionPattern as string | undefined,
45
+ });
46
+
47
+ return { updateBy: updateBy, carryForward: null };
48
+ }
49
+ }
50
+
51
+ export default new Service();