@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
@@ -0,0 +1,518 @@
1
+ import AffectedResourceList, {
2
+ AffectedResourceListEntry,
3
+ } from "../../../../Server/Utils/Monitor/AffectedResourceList";
4
+ import Markdown, {
5
+ MarkdownContentType,
6
+ } from "../../../../Server/Types/Markdown";
7
+ import SlackUtil from "../../../../Server/Utils/Workspace/Slack/Slack";
8
+ import { marked, Tokens, Token } from "marked";
9
+
10
+ /*
11
+ * AffectedResourceList renders the "Affected Resources" block of a platform
12
+ * monitor's root cause. It replaced a GitHub-flavoured table that wrapped
13
+ * into fragments in the email card, reached Slack as raw pipe rows (or
14
+ * "_Row 1_" blocks) and let one long node name squeeze every other column
15
+ * on the dashboard.
16
+ *
17
+ * These tests pin two things:
18
+ *
19
+ * - the exact markdown — numbered items, a bold kind, the value at the
20
+ * end, labelled detail bullets indented to the item's content column,
21
+ * and the "... and N more" summary as its own paragraph,
22
+ * - that the markdown PARSES into that shape: a single ordered list whose
23
+ * items each own a nested bullet list, in marked (the email renderer),
24
+ * through slackify-markdown (Slack) and Markdown.convertToPlainText.
25
+ * A string that merely looks right can still parse as two lists or as
26
+ * an indented code block, and the reader would see the wreckage.
27
+ */
28
+
29
+ function entry(
30
+ overrides: Partial<AffectedResourceListEntry> = {},
31
+ ): AffectedResourceListEntry {
32
+ return {
33
+ kind: "Pod",
34
+ name: "`checkout-7d9f`",
35
+ value: "**3**",
36
+ details: [
37
+ { label: "Namespace", value: "`payments`" },
38
+ { label: "Deployment", value: "`checkout`" },
39
+ { label: "Node", value: "`gke-prod-pool-1-abcd`" },
40
+ ],
41
+ ...overrides,
42
+ };
43
+ }
44
+
45
+ function entries(count: number): Array<AffectedResourceListEntry> {
46
+ const result: Array<AffectedResourceListEntry> = [];
47
+
48
+ for (let i: number = 1; i <= count; i++) {
49
+ result.push(
50
+ entry({
51
+ name: `\`pod-${i}\``,
52
+ value: `**${100 - i}**`,
53
+ details: [
54
+ { label: "Namespace", value: `\`ns-${i}\`` },
55
+ { label: "Node", value: `\`node-${i}\`` },
56
+ ],
57
+ }),
58
+ );
59
+ }
60
+
61
+ return result;
62
+ }
63
+
64
+ function render(
65
+ shown: Array<AffectedResourceListEntry>,
66
+ totalCount?: number,
67
+ ): string {
68
+ return AffectedResourceList.render({
69
+ heading: "Affected Resources",
70
+ overflowNoun: "affected resources",
71
+ totalCount: totalCount === undefined ? shown.length : totalCount,
72
+ entries: shown,
73
+ });
74
+ }
75
+
76
+ // The top-level block tokens marked produces, without the blank-line spacers.
77
+ function blocks(markdown: string): Array<Token> {
78
+ return marked.lexer(markdown).filter((token: Token): boolean => {
79
+ return token.type !== "space";
80
+ });
81
+ }
82
+
83
+ function nestedList(item: Tokens.ListItem): Tokens.List | undefined {
84
+ return item.tokens.find((token: Token): boolean => {
85
+ return token.type === "list";
86
+ }) as Tokens.List | undefined;
87
+ }
88
+
89
+ describe("AffectedResourceList.render - markdown", () => {
90
+ test("renders one numbered item per resource with its details as nested bullets", () => {
91
+ expect(render([entry()])).toBe(
92
+ [
93
+ "",
94
+ "",
95
+ "**Affected Resources** (1 total)",
96
+ "",
97
+ "1. **Pod** `checkout-7d9f` — **3**",
98
+ " - Namespace: `payments`",
99
+ " - Deployment: `checkout`",
100
+ " - Node: `gke-prod-pool-1-abcd`",
101
+ ].join("\n"),
102
+ );
103
+ });
104
+
105
+ test("starts with a blank line so it is its own block after the previous section", () => {
106
+ const markdown: string = render([entry()]);
107
+
108
+ expect(markdown.startsWith("\n\n**Affected Resources**")).toBe(true);
109
+ });
110
+
111
+ test("numbers items in the order given, which the caller sorts worst first", () => {
112
+ const markdown: string = render(entries(3));
113
+
114
+ const first: number = markdown.indexOf("1. **Pod** `pod-1` — **99**");
115
+ const second: number = markdown.indexOf("2. **Pod** `pod-2` — **98**");
116
+ const third: number = markdown.indexOf("3. **Pod** `pod-3` — **97**");
117
+
118
+ expect(first).toBeGreaterThan(-1);
119
+ expect(second).toBeGreaterThan(first);
120
+ expect(third).toBeGreaterThan(second);
121
+ });
122
+
123
+ test("never emits GFM table syntax", () => {
124
+ const markdown: string = render(entries(10), 83);
125
+
126
+ expect(markdown).not.toMatch(/^\s*\|/m);
127
+ expect(markdown).not.toContain("| --- |");
128
+ expect(markdown).not.toContain("---");
129
+ });
130
+
131
+ test("indents details to the item's content column: three spaces under 1-9, four under 10", () => {
132
+ const markdown: string = render(entries(10));
133
+
134
+ expect(markdown).toContain(
135
+ "9. **Pod** `pod-9` — **91**\n - Namespace: `ns-9`",
136
+ );
137
+ expect(markdown).toContain(
138
+ "10. **Pod** `pod-10` — **90**\n - Namespace: `ns-10`\n - Node: `node-10`",
139
+ );
140
+ });
141
+
142
+ test("an item without details is a single line", () => {
143
+ const markdown: string = render([
144
+ entry({
145
+ kind: "Node",
146
+ name: "`node-a`",
147
+ value: "**85.00%**",
148
+ details: [],
149
+ }),
150
+ entry({
151
+ kind: "Node",
152
+ name: "`node-b`",
153
+ value: "**80.00%**",
154
+ details: [],
155
+ }),
156
+ ]);
157
+
158
+ expect(markdown).toContain(
159
+ "1. **Node** `node-a` — **85.00%**\n2. **Node** `node-b` — **80.00%**",
160
+ );
161
+ });
162
+
163
+ test("a detail with an empty value is left out rather than printed as a dash", () => {
164
+ const markdown: string = render([
165
+ entry({
166
+ details: [
167
+ { label: "Namespace", value: "`payments`" },
168
+ { label: "Deployment", value: "" },
169
+ { label: "Pod", value: " " },
170
+ { label: "Node", value: "`node-a`" },
171
+ ],
172
+ }),
173
+ ]);
174
+
175
+ expect(markdown).toContain(
176
+ "1. **Pod** `checkout-7d9f` — **3**\n - Namespace: `payments`\n - Node: `node-a`",
177
+ );
178
+ expect(markdown).not.toContain("Deployment");
179
+ expect(markdown).not.toContain("- Pod");
180
+ expect(markdown).not.toContain(": -");
181
+ });
182
+
183
+ test("an empty kind drops the bold marker instead of rendering '****'", () => {
184
+ const markdown: string = render([entry({ kind: "", details: [] })]);
185
+
186
+ expect(markdown).toContain("1. `checkout-7d9f` — **3**");
187
+ expect(markdown).not.toContain("****");
188
+ });
189
+
190
+ test("an empty name leaves just the kind", () => {
191
+ const markdown: string = render([
192
+ entry({ kind: "Cluster", name: "", details: [] }),
193
+ ]);
194
+
195
+ expect(markdown).toContain("1. **Cluster** — **3**");
196
+ });
197
+
198
+ test("markdown in a kind or label is escaped, not rendered", () => {
199
+ const markdown: string = render([
200
+ entry({
201
+ kind: "*bold* [link](https://evil.example)",
202
+ details: [
203
+ { label: "![img](https://evil.example/x.png)", value: "`x`" },
204
+ ],
205
+ }),
206
+ ]);
207
+
208
+ expect(markdown).toContain(
209
+ "1. **\\*bold\\* \\[link\\]\\(https://evil.example\\)** `checkout-7d9f` — **3**",
210
+ );
211
+ expect(markdown).toContain(
212
+ " - \\!\\[img\\]\\(https://evil.example/x.png\\): `x`",
213
+ );
214
+ });
215
+
216
+ describe("overflow summary", () => {
217
+ test("summarises the resources beyond the ones shown", () => {
218
+ const markdown: string = render(entries(10), 83);
219
+
220
+ expect(markdown).toContain("**Affected Resources** (83 total)");
221
+ expect(markdown.endsWith("*... and 73 more affected resources*")).toBe(
222
+ true,
223
+ );
224
+ });
225
+
226
+ test("the summary is separated from the last item by a blank line", () => {
227
+ const markdown: string = render(entries(10), 12);
228
+
229
+ expect(markdown).toContain(
230
+ " - Node: `node-10`\n\n*... and 2 more affected resources*",
231
+ );
232
+ });
233
+
234
+ test("no summary when every resource is shown", () => {
235
+ const markdown: string = render(entries(10), 10);
236
+
237
+ expect(markdown).toContain("**Affected Resources** (10 total)");
238
+ expect(markdown).not.toContain("more affected resources");
239
+ });
240
+
241
+ test("no summary when the total is smaller than the list (defensive)", () => {
242
+ const markdown: string = render(entries(3), 1);
243
+
244
+ expect(markdown).not.toContain("more affected resources");
245
+ expect(markdown).not.toContain("... and");
246
+ });
247
+
248
+ test("markdown in the heading or noun is escaped", () => {
249
+ const markdown: string = AffectedResourceList.render({
250
+ heading: "A*b",
251
+ overflowNoun: "x_y",
252
+ totalCount: 2,
253
+ entries: [entry({ details: [] })],
254
+ });
255
+
256
+ expect(markdown).toContain("**A\\*b** (2 total)");
257
+ expect(markdown).toContain("*... and 1 more x\\_y*");
258
+ });
259
+
260
+ test("uses the caller's heading and noun (Docker Swarm lists tasks)", () => {
261
+ const markdown: string = AffectedResourceList.render({
262
+ heading: "Affected Tasks",
263
+ overflowNoun: "affected tasks",
264
+ totalCount: 14,
265
+ entries: entries(10),
266
+ });
267
+
268
+ expect(markdown).toContain("**Affected Tasks** (14 total)");
269
+ expect(markdown).toContain("*... and 4 more affected tasks*");
270
+ expect(markdown).not.toContain("affected resources");
271
+ });
272
+ });
273
+
274
+ test("MAX_ENTRIES is ten, the size the table used to be capped at", () => {
275
+ expect(AffectedResourceList.MAX_ENTRIES).toBe(10);
276
+ });
277
+ });
278
+
279
+ describe("AffectedResourceList.render - parses as one ordered list of resources", () => {
280
+ test("marked sees the heading, one ordered list and the summary paragraph", () => {
281
+ const tokens: Array<Token> = blocks(render(entries(10), 83));
282
+
283
+ expect(
284
+ tokens.map((token: Token) => {
285
+ return token.type;
286
+ }),
287
+ ).toEqual(["paragraph", "list", "paragraph"]);
288
+
289
+ const list: Tokens.List = tokens[1] as Tokens.List;
290
+ expect(list.ordered).toBe(true);
291
+ expect(list.start).toBe(1);
292
+ expect(list.loose).toBe(false);
293
+ expect(list.items).toHaveLength(10);
294
+
295
+ expect((tokens[2] as Tokens.Paragraph).text).toBe(
296
+ "*... and 73 more affected resources*",
297
+ );
298
+ });
299
+
300
+ test("every item, including the tenth, owns its details as a nested bullet list", () => {
301
+ const list: Tokens.List = blocks(render(entries(10)))[1] as Tokens.List;
302
+
303
+ list.items.forEach((item: Tokens.ListItem, index: number) => {
304
+ const nested: Tokens.List | undefined = nestedList(item);
305
+
306
+ expect(nested).toBeDefined();
307
+ expect(nested!.ordered).toBe(false);
308
+ expect(
309
+ nested!.items.map((detail: Tokens.ListItem) => {
310
+ return detail.text;
311
+ }),
312
+ ).toEqual([
313
+ `Namespace: \`ns-${index + 1}\``,
314
+ `Node: \`node-${index + 1}\``,
315
+ ]);
316
+ });
317
+ });
318
+
319
+ test("no detail line is mistaken for an indented code block", () => {
320
+ const markdown: string = render(entries(10), 40);
321
+
322
+ const walk: (tokens: Array<Token>) => Array<string> = (
323
+ tokens: Array<Token>,
324
+ ): Array<string> => {
325
+ const types: Array<string> = [];
326
+
327
+ for (const token of tokens) {
328
+ types.push(token.type);
329
+
330
+ const children: Array<Token> | undefined = (
331
+ token as { tokens?: Array<Token> }
332
+ ).tokens;
333
+
334
+ if (children) {
335
+ types.push(...walk(children));
336
+ }
337
+
338
+ if (token.type === "list") {
339
+ for (const item of (token as Tokens.List).items) {
340
+ types.push(...walk(item.tokens));
341
+ }
342
+ }
343
+ }
344
+
345
+ return types;
346
+ };
347
+
348
+ expect(walk(marked.lexer(markdown))).not.toContain("code");
349
+ });
350
+
351
+ test("renders to an email as a styled <ol> with a nested <ul> in each <li>, and no table", async () => {
352
+ const html: string = await Markdown.convertToHTML(
353
+ render(entries(2), 5),
354
+ MarkdownContentType.Email,
355
+ );
356
+
357
+ expect(html).not.toContain("<table");
358
+ expect(html).toMatch(/<ol style="[^"]+">/);
359
+ expect(html).toMatch(/<ul style="[^"]+">/);
360
+
361
+ // Each item's details open inside that item, before it closes.
362
+ expect(html).toMatch(
363
+ /<li style="[^"]+">\s*<strong>Pod<\/strong> <code[^>]*>pod-1<\/code> — <strong>99<\/strong>\s*<ul style="[^"]+">\s*<li style="[^"]+">Namespace: <code[^>]*>ns-1<\/code><\/li>\s*<li style="[^"]+">Node: <code[^>]*>node-1<\/code><\/li>\s*<\/ul>\s*<\/li>/,
364
+ );
365
+
366
+ // The summary follows the list; it is not inside the last item.
367
+ const listEnd: number = html.lastIndexOf("</ol>");
368
+ const summary: number = html.indexOf("... and 3 more affected resources");
369
+ expect(summary).toBeGreaterThan(listEnd);
370
+ expect(html).toContain("<em>... and 3 more affected resources</em>");
371
+ });
372
+
373
+ test("renders to Slack as numbered lines with bullet details, not a '_Row 1_' table dump", () => {
374
+ const slack: string = SlackUtil.convertMarkdownToSlackRichText(
375
+ render(entries(2), 5),
376
+ );
377
+
378
+ expect(slack).not.toContain("_Row 1_");
379
+ expect(slack).not.toContain("*Namespace:*");
380
+ /*
381
+ * slackify-markdown turns **bold** into Slack's *bold* and fences it
382
+ * with zero-width spaces so it binds next to punctuation.
383
+ */
384
+ expect(slack).toMatch(
385
+ /1\.\s+\u200B?\*Pod\*\u200B? `pod-1` — \u200B?\*99\*\u200B?\n/,
386
+ );
387
+ expect(slack).toMatch(
388
+ /\n\s+•\s+Namespace: `ns-1`\n\s+•\s+Node: `node-1`\n/,
389
+ );
390
+ expect(slack).toMatch(/\n2\.\s+\u200B?\*Pod\*\u200B? `pod-2`/);
391
+ expect(slack).toContain("more affected resources");
392
+ });
393
+
394
+ test("renders to plain text as one readable line per resource and detail", () => {
395
+ const text: string = Markdown.convertToPlainText(render(entries(2), 5));
396
+
397
+ expect(text.split("\n")).toEqual([
398
+ "Affected Resources (5 total)",
399
+ "Pod pod-1 — 99",
400
+ "Namespace: ns-1",
401
+ "Node: node-1",
402
+ "Pod pod-2 — 98",
403
+ "Namespace: ns-2",
404
+ "Node: node-2",
405
+ "... and 3 more affected resources",
406
+ ]);
407
+ });
408
+ });
409
+
410
+ describe("AffectedResourceList.code", () => {
411
+ test("wraps an identifier in single backticks", () => {
412
+ expect(AffectedResourceList.code("checkout-7d9f")).toBe("`checkout-7d9f`");
413
+ });
414
+
415
+ test.each([
416
+ ["undefined", undefined],
417
+ ["null", null],
418
+ ["an empty string", ""],
419
+ ["whitespace", " "],
420
+ ["a lone line break", "\n"],
421
+ ])("returns an empty string for %s", (_label: string, value: unknown) => {
422
+ expect(AffectedResourceList.code(value as string | undefined | null)).toBe(
423
+ "",
424
+ );
425
+ });
426
+
427
+ test("trims surrounding whitespace", () => {
428
+ expect(AffectedResourceList.code(" web-01 ")).toBe("`web-01`");
429
+ });
430
+
431
+ test("turns line breaks into single spaces so the list item cannot be split", () => {
432
+ expect(AffectedResourceList.code("web\n01")).toBe("`web 01`");
433
+ expect(AffectedResourceList.code("web\r\n01")).toBe("`web 01`");
434
+ expect(AffectedResourceList.code("web \n\n 01")).toBe("`web 01`");
435
+ });
436
+
437
+ test("a name containing a backtick gets a longer fence, padded with spaces", () => {
438
+ expect(AffectedResourceList.code("db`01")).toBe("`` db`01 ``");
439
+ });
440
+
441
+ test("the fence is always longer than the longest backtick run", () => {
442
+ expect(AffectedResourceList.code("a``b`c")).toBe("``` a``b`c ```");
443
+ });
444
+
445
+ test("a name that starts or ends with a backtick still renders verbatim", async () => {
446
+ const code: string = AffectedResourceList.code("`vm`");
447
+
448
+ expect(code).toBe("`` `vm` ``");
449
+
450
+ const html: string = await Markdown.convertToHTML(
451
+ `x ${code} y`,
452
+ MarkdownContentType.Email,
453
+ );
454
+
455
+ expect(html).toMatch(/<code[^>]*>`vm`<\/code>/);
456
+ });
457
+
458
+ test("markdown inside a name stays inside the code span", async () => {
459
+ const code: string = AffectedResourceList.code(
460
+ "vm` **pwned** [x](https://evil.example)",
461
+ );
462
+
463
+ const html: string = await Markdown.convertToHTML(
464
+ `1. **Virtual Machine** ${code} — **3**`,
465
+ MarkdownContentType.Email,
466
+ );
467
+
468
+ expect(html).not.toContain("<strong>pwned</strong>");
469
+ expect(html).not.toContain('href="https://evil.example"');
470
+ expect(html).toMatch(
471
+ /<code[^>]*>vm` \*\*pwned\*\* \[x\]\(https:\/\/evil\.example\)<\/code>/,
472
+ );
473
+ });
474
+
475
+ test("a pipe needs no escaping any more — there is no table to break", () => {
476
+ expect(AffectedResourceList.code("a|b")).toBe("`a|b`");
477
+ });
478
+
479
+ test("a non-string value is stringified rather than crashing", () => {
480
+ expect(AffectedResourceList.code(42 as unknown as string)).toBe("`42`");
481
+ });
482
+ });
483
+
484
+ describe("AffectedResourceList.codeWithId", () => {
485
+ test("shows the name with its id beside it", () => {
486
+ expect(
487
+ AffectedResourceList.codeWithId({ name: "web-vm", id: "qemu/100" }),
488
+ ).toBe("`web-vm` (`qemu/100`)");
489
+ });
490
+
491
+ test("falls back to whichever half is present", () => {
492
+ expect(AffectedResourceList.codeWithId({ name: "web-vm" })).toBe(
493
+ "`web-vm`",
494
+ );
495
+ expect(AffectedResourceList.codeWithId({ id: "qemu/100" })).toBe(
496
+ "`qemu/100`",
497
+ );
498
+ });
499
+
500
+ test("shows a name that equals its id only once", () => {
501
+ expect(AffectedResourceList.codeWithId({ name: "rbd", id: "rbd" })).toBe(
502
+ "`rbd`",
503
+ );
504
+ });
505
+
506
+ test("an empty half counts as missing", () => {
507
+ expect(AffectedResourceList.codeWithId({ name: "", id: "qemu/100" })).toBe(
508
+ "`qemu/100`",
509
+ );
510
+ expect(AffectedResourceList.codeWithId({ name: "web-vm", id: " " })).toBe(
511
+ "`web-vm`",
512
+ );
513
+ });
514
+
515
+ test("returns an empty string when neither half is present", () => {
516
+ expect(AffectedResourceList.codeWithId({})).toBe("");
517
+ });
518
+ });
@@ -591,11 +591,14 @@ describe("EvaluateOverTime", () => {
591
591
  });
592
592
 
593
593
  /*
594
- * A monitoringInterval that is not a cron (the label form this repo's
595
- * own Terraform examples write) must not be trusted as a cadence - the
596
- * samples themselves are the only evidence left.
594
+ * A cadence LABEL is not a cron, but it is not unreadable either: "Every
595
+ * 5 minutes" is what this repo's own Terraform examples used to write, and
596
+ * 1fd4dc1542 taught the evaluator to read it through
597
+ * MonitoringIntervalUtil rather than shrugging and guessing from the data.
598
+ * A monitor that says five minutes is covered by one sample in a
599
+ * five-minute window, so this evaluates instead of reporting a gap.
597
600
  */
598
- test("an unparseable schedule falls back to the sampled cadence", async () => {
601
+ test("a cadence label is read as a schedule, not treated as unknown", async () => {
599
602
  mockSamples([sample({ value: 404, minutesAgo: 0 })]);
600
603
 
601
604
  const result: OverTimeEvaluation = await evaluate({
@@ -603,6 +606,23 @@ describe("EvaluateOverTime", () => {
603
606
  monitoringInterval: "Every 5 minutes",
604
607
  });
605
608
 
609
+ expect(result.status).toBe(OverTimeEvaluationStatus.Evaluated);
610
+ });
611
+
612
+ /*
613
+ * The original point of the case above, which still stands for a value
614
+ * NOTHING can read: neither the label grammar nor cron-parser makes sense
615
+ * of it, so it must not be trusted as a cadence - the samples themselves
616
+ * are the only evidence left, and one of them does not cover the window.
617
+ */
618
+ test("a schedule nothing can read falls back to the sampled cadence", async () => {
619
+ mockSamples([sample({ value: 404, minutesAgo: 0 })]);
620
+
621
+ const result: OverTimeEvaluation = await evaluate({
622
+ criteriaFilter: criteria(),
623
+ monitoringInterval: "whenever it feels like it",
624
+ });
625
+
606
626
  expect(result.status).toBe(OverTimeEvaluationStatus.InsufficientData);
607
627
  });
608
628
 
@@ -49,7 +49,7 @@ import { beforeEach, describe, expect, jest, test } from "@jest/globals";
49
49
  * "container.memory.usage value 1073741824.000 By is 4.20σ above ..."
50
50
  *
51
51
  * The quantities in it are now rendered exactly as the Breaching Samples
52
- * table renders them. σ is NOT one of those quantities: it is a count of
52
+ * list renders them. σ is NOT one of those quantities: it is a count of
53
53
  * standard deviations, dimensionless by construction, and must stay a
54
54
  * bare number no matter what unit the metric carries.
55
55
  */