@oneuptime/common 13.0.7 → 14.0.0

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 (759) hide show
  1. package/Models/AnalyticsModels/AuditLog.ts +23 -15
  2. package/Models/DatabaseModels/GlobalConfig.ts +24 -0
  3. package/Models/DatabaseModels/Monitor.ts +3 -2
  4. package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
  5. package/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.ts +1 -1
  6. package/Models/DatabaseModels/ProjectOnCallCalendarFeed.ts +1 -1
  7. package/Models/DatabaseModels/UserOnCallCalendarFeed.ts +1 -1
  8. package/Scripts/generate-service-worker.js +65 -4
  9. package/Server/API/AIBillingAPI.ts +1 -0
  10. package/Server/API/AIInsightAPI.ts +1 -4
  11. package/Server/API/AIInvestigationAPI.ts +1 -4
  12. package/Server/API/AIReadinessAPI.ts +4 -5
  13. package/Server/API/AlertAPI.ts +1 -0
  14. package/Server/API/AutoRemediationAPI.ts +1 -4
  15. package/Server/API/BaseAPI.ts +34 -0
  16. package/Server/API/BaseAnalyticsAPI.ts +80 -9
  17. package/Server/API/BillingAPI.ts +2 -0
  18. package/Server/API/BillingInvoiceAPI.ts +1 -0
  19. package/Server/API/BillingPaymentMethodAPI.ts +2 -0
  20. package/Server/API/CodeFixRunAPI.ts +1 -3
  21. package/Server/API/CommonAPI.ts +68 -4
  22. package/Server/API/DashboardAPI.ts +12 -12
  23. package/Server/API/GlobalConfigAPI.ts +243 -460
  24. package/Server/API/IncidentAPI.ts +2 -0
  25. package/Server/API/IncidentEpisodeAPI.ts +1 -0
  26. package/Server/API/NotificationAPI.ts +1 -0
  27. package/Server/API/OnCallCalendarAPI.ts +4 -5
  28. package/Server/API/OnCallDutyPolicyAPI.ts +7 -0
  29. package/Server/API/OnCallReadinessAPI.ts +4 -1
  30. package/Server/API/OnCallScheduleTimelineAPI.ts +731 -0
  31. package/Server/API/ProjectAPI.ts +1 -0
  32. package/Server/API/ProjectOIDC.ts +25 -16
  33. package/Server/API/ProjectSSO.ts +24 -16
  34. package/Server/API/ScheduledMaintenanceAPI.ts +1 -0
  35. package/Server/API/StatusPageAPI.ts +261 -74
  36. package/Server/API/TeamMemberAPI.ts +13 -1
  37. package/Server/API/UserCallAPI.ts +2 -0
  38. package/Server/API/UserEmailAPI.ts +2 -0
  39. package/Server/API/UserIncomingCallNumberAPI.ts +2 -0
  40. package/Server/API/UserMicrosoftTeamsAPI.ts +1 -0
  41. package/Server/API/UserSlackAPI.ts +1 -0
  42. package/Server/API/UserSmsAPI.ts +2 -0
  43. package/Server/API/UserTotpAuthAPI.ts +1 -0
  44. package/Server/API/UserWebAuthnAPI.ts +2 -0
  45. package/Server/API/UserWebhookAPI.ts +1 -0
  46. package/Server/API/UserWhatsAppAPI.ts +2 -0
  47. package/Server/Enterprise/EnterpriseEdition.ts +649 -0
  48. package/Server/Enterprise/EnterpriseFeature.ts +48 -0
  49. package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +192 -0
  50. package/Server/Enterprise/EnterpriseServerModule.ts +233 -0
  51. package/Server/EnvironmentConfig.ts +147 -2
  52. package/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.ts +25 -0
  53. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  54. package/Server/Middleware/MasterAdminAuthorization.ts +13 -2
  55. package/Server/Middleware/UserAuthorization.ts +117 -21
  56. package/Server/Services/ApiKeyPermissionService.ts +101 -4
  57. package/Server/Services/AuditLogService.ts +84 -1079
  58. package/Server/Services/DatabaseService.ts +245 -0
  59. package/Server/Services/DetectionRuleService.ts +5 -4
  60. package/Server/Services/EnterpriseLicenseService.ts +38 -0
  61. package/Server/Services/GlobalConfigService.ts +80 -1
  62. package/Server/Services/MonitorProbeService.ts +116 -20
  63. package/Server/Services/MonitorService.ts +56 -4
  64. package/Server/Services/MonitorStatusTimelineService.ts +284 -0
  65. package/Server/Services/MonitorTemplateService.ts +26 -0
  66. package/Server/Services/OnCallDutyPolicyChildService.ts +261 -0
  67. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +2 -2
  68. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +2 -2
  69. package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +2 -2
  70. package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +2 -2
  71. package/Server/Services/PayAsYouGoBillingService.ts +23 -28
  72. package/Server/Services/ProjectService.ts +302 -0
  73. package/Server/Services/RumSessionPinService.ts +293 -22
  74. package/Server/Services/StatusPagePrivateUserService.ts +7 -3
  75. package/Server/Services/StatusPageService.ts +78 -1
  76. package/Server/Services/TeamMemberService.ts +11 -0
  77. package/Server/Services/TeamPermissionService.ts +120 -26
  78. package/Server/Services/TeamService.ts +10 -0
  79. package/Server/Services/ThreatIntelFeedService.ts +6 -3
  80. package/Server/Services/UserService.ts +10 -17
  81. package/Server/Types/Database/Permissions/BasePermission.ts +9 -7
  82. package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
  83. package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
  84. package/Server/Types/Database/Permissions/Index.ts +75 -11
  85. package/Server/Types/Database/Permissions/TablePermission.ts +34 -31
  86. package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
  87. package/Server/Types/Markdown.ts +41 -0
  88. package/Server/Utils/AI/AIChatPrivacyFilter.ts +8 -0
  89. package/Server/Utils/AI/AIRunPrivacyFilter.ts +8 -0
  90. package/Server/Utils/CommunityEditionSsoReport.ts +361 -0
  91. package/Server/Utils/EditionEnforcement.ts +233 -0
  92. package/Server/Utils/FrontendEnvironment.ts +41 -2
  93. package/Server/Utils/InstanceHealth/RedisHealth.ts +12 -277
  94. package/Server/Utils/MasterAdminPageAccess.ts +61 -0
  95. package/Server/Utils/Monitor/AffectedResourceList.ts +190 -0
  96. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
  97. package/Server/Utils/Monitor/MonitorAlert.ts +3 -1
  98. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +543 -333
  99. package/Server/Utils/Monitor/MonitorIncident.ts +3 -1
  100. package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
  101. package/Server/Utils/OnCall/OnCallCalendarFeedRenderer.ts +1 -1
  102. package/Server/Utils/Realtime.ts +163 -45
  103. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +11 -28
  104. package/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.ts +170 -0
  105. package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +1 -1
  106. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +6 -2
  107. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.ts +10 -9
  108. package/Server/Utils/Workspace/Slack/Slack.ts +423 -10
  109. package/Tests/App/Accounts/LoginPasskey.test.tsx +18 -0
  110. package/Tests/App/Accounts/LoginSsoEdition.test.tsx +616 -0
  111. package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +217 -0
  112. package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +357 -0
  113. package/Tests/App/AdminDashboard/EnterpriseLicensesShell.test.tsx +214 -0
  114. package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +271 -0
  115. package/Tests/App/AdminDashboard/HealthShells.test.tsx +659 -0
  116. package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +1059 -0
  117. package/Tests/App/Dashboard/AffectedResourcesPickerEditForm.test.tsx +376 -0
  118. package/Tests/App/Dashboard/AffectedResourcesPickerHiddenTypes.test.tsx +757 -0
  119. package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +307 -0
  120. package/Tests/App/Dashboard/ArgumentsFormGroupByUnlistedAttributes.test.tsx +131 -0
  121. package/Tests/App/Dashboard/AuditLogsAndComplianceShells.test.tsx +572 -0
  122. package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +1 -1
  123. package/Tests/App/Dashboard/DashboardMonitorLabelVariable.test.tsx +9 -1
  124. package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +24 -0
  125. package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +162 -8
  126. package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
  127. package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
  128. package/Tests/App/Dashboard/EntityFilterDropdownArchivedSlos.test.tsx +105 -6
  129. package/Tests/App/Dashboard/EntityFilterDropdownUnlistedSelection.test.tsx +434 -0
  130. package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +276 -1
  131. package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
  132. package/Tests/App/Dashboard/OnCallCalendarFeedSideMenus.test.tsx +9 -1
  133. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
  134. package/Tests/App/Dashboard/PayAsYouGoConsentGate.test.tsx +58 -42
  135. package/Tests/App/Dashboard/PayAsYouGoNotices.test.tsx +42 -5
  136. package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +34 -23
  137. package/Tests/App/Dashboard/ScheduleTimeline.test.tsx +1580 -0
  138. package/Tests/App/Dashboard/ScheduleTimelineAPI.test.ts +280 -0
  139. package/Tests/App/Dashboard/ScheduleTimelineModel.test.ts +673 -0
  140. package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +133 -70
  141. package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
  142. package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
  143. package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +86 -3
  144. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -58
  145. package/Tests/App/Dashboard/SecurityEventsGuideContent.test.ts +1313 -0
  146. package/Tests/App/Dashboard/SecurityEventsHowItWorksCard.test.tsx +536 -0
  147. package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
  148. package/Tests/App/Dashboard/SecurityEventsNoResults.test.tsx +222 -0
  149. package/Tests/App/Dashboard/SecurityEventsThreatIntelPage.test.tsx +199 -0
  150. package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
  151. package/Tests/App/Dashboard/SloOverviewHero.test.tsx +171 -36
  152. package/Tests/App/Dashboard/SloViewSideMenu.test.tsx +215 -0
  153. package/Tests/App/Dashboard/SloViewSideMenuCounts.test.tsx +40 -3
  154. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
  155. package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +12 -4
  156. package/Tests/App/PublicDashboard/PublicDashboardWidgetListAuth.test.tsx +623 -0
  157. package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +319 -0
  158. package/Tests/Helpers/RefreshAwareApiScan.ts +757 -0
  159. package/Tests/Helpers/TenantScopedRequestScan.ts +515 -0
  160. package/Tests/Models/OnCallCalendarFeedModels.test.ts +23 -1
  161. package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
  162. package/Tests/Server/API/AIChatRouteAuthorization.test.ts +138 -5
  163. package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +187 -0
  164. package/Tests/Server/API/AIInvestigationAvailabilityAuthorization.test.ts +51 -3
  165. package/Tests/Server/API/AIInvestigationEvidenceAPI.test.ts +55 -2
  166. package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
  167. package/Tests/Server/API/BaseAnalyticsAPIAggregateCache.test.ts +729 -0
  168. package/Tests/Server/API/BillingPayAsYouGoStatus.test.ts +93 -7
  169. package/Tests/Server/API/BillingPaymentMethodAPI.test.ts +36 -3
  170. package/Tests/Server/API/CommonAPIAuthGuard.test.ts +1003 -24
  171. package/Tests/Server/API/DashboardPublicRateLimit.test.ts +6 -3
  172. package/Tests/Server/API/ExpiredSessionAIRoutes.test.ts +708 -0
  173. package/Tests/Server/API/ExpiredSessionCustomRoutes.test.ts +928 -0
  174. package/Tests/Server/API/ExpiredSessionMonitorTemplate.test.ts +319 -0
  175. package/Tests/Server/API/ExpiredSessionOnCallDutyPolicy.test.ts +336 -0
  176. package/Tests/Server/API/ExpiredSessionRouteGuards.test.ts +820 -0
  177. package/Tests/Server/API/GlobalConfigLicense.test.ts +766 -381
  178. package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +115 -12
  179. package/Tests/Server/API/OnCallCalendarAPI.test.ts +375 -8
  180. package/Tests/Server/API/OnCallReadinessAPI.test.ts +196 -912
  181. package/Tests/Server/API/OnCallScheduleTimelineAPI.test.ts +1513 -0
  182. package/Tests/Server/API/OnCallSetupReminderAPI.test.ts +119 -7
  183. package/Tests/Server/API/ProjectScopedCustomRouteAuth.test.ts +111 -4
  184. package/Tests/Server/API/PublicRouteInvalidAccessToken.test.ts +615 -0
  185. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +89 -2
  186. package/Tests/Server/API/SessionReplayAPI.test.ts +121 -0
  187. package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
  188. package/Tests/Server/API/StatusPageMasterPasswordRateLimit.test.ts +4 -2
  189. package/Tests/Server/API/StatusPagePostmortemVisibility.test.ts +441 -0
  190. package/Tests/Server/API/StatusPageTestEmailReportAuth.test.ts +664 -0
  191. package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
  192. package/Tests/Server/API/TeamMemberRemoveUserFromProjectAPI.test.ts +7 -0
  193. package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +6 -0
  194. package/Tests/Server/API/UserNotificationSettingAPI.test.ts +65 -4
  195. package/Tests/Server/API/UserProjectsAPI.test.ts +63 -3
  196. package/Tests/Server/API/UserTotpAuthAPI.test.ts +48 -2
  197. package/Tests/Server/API/UserWebAuthnAuthenticationOptionsRoute.test.ts +11 -2
  198. package/Tests/Server/API/UserWebAuthnBackupCodeMinting.test.ts +46 -3
  199. package/Tests/Server/API/UserWebAuthnPasskeyAPI.test.ts +18 -2
  200. package/Tests/Server/API/ZZVerifyChatsAuth.test.ts +24 -7
  201. package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +824 -0
  202. package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +643 -0
  203. package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +294 -0
  204. package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +93 -0
  205. package/Tests/Server/Enterprise/EnterpriseOnlyModulesLiveInEe.test.ts +582 -0
  206. package/Tests/Server/Enterprise/EnterpriseServerModule.test.ts +247 -0
  207. package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +502 -0
  208. package/Tests/Server/Enterprise/TestBillingFlag.ts +70 -0
  209. package/Tests/Server/EnvironmentConfigEnterpriseEdition.test.ts +314 -0
  210. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +289 -0
  211. package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +5 -1
  212. package/Tests/Server/Middleware/ExpiredSessionUserMiddleware.test.ts +563 -0
  213. package/Tests/Server/Middleware/MasterAdminAuthorization.test.ts +299 -19
  214. package/Tests/Server/Middleware/PublicRouteUserMiddleware.test.ts +453 -0
  215. package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
  216. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
  217. package/Tests/Server/Services/AIChatPrivacyPin.test.ts +24 -0
  218. package/Tests/Server/Services/ApiKeyPermissionSecurity.test.ts +2 -0
  219. package/Tests/Server/Services/ApiKeyPermissionService.test.ts +3 -3
  220. package/Tests/Server/Services/AuditLogService.test.ts +460 -990
  221. package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
  222. package/Tests/Server/Services/DatabaseServiceCreateSuppliedId.test.ts +147 -0
  223. package/Tests/Server/Services/DatabaseServiceLoginBeforeHooks.test.ts +1078 -0
  224. package/Tests/Server/Services/DatabaseServiceTenantRelationGuard.test.ts +259 -0
  225. package/Tests/Server/Services/DatabaseServiceWriteOperatorValues.test.ts +147 -0
  226. package/Tests/Server/Services/EnterpriseLicenseServiceKeyGeneration.test.ts +151 -0
  227. package/Tests/Server/Services/GlobalConfigServiceLicenseColumns.test.ts +357 -0
  228. package/Tests/Server/Services/MonitorDestinationInfoIPv6.test.ts +101 -0
  229. package/Tests/Server/Services/MonitorPayAsYouGoBilling.test.ts +115 -1
  230. package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
  231. package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
  232. package/Tests/Server/Services/OnCallChildCreateAuthorizationPostgres.test.ts +711 -0
  233. package/Tests/Server/Services/OnCallDutyPolicyChildService.test.ts +733 -0
  234. package/Tests/Server/Services/PayAsYouGoBillingService.test.ts +190 -140
  235. package/Tests/Server/Services/PayAsYouGoStripeRateLimitBudget.test.ts +4 -9
  236. package/Tests/Server/Services/PermissionBlockDeletion.test.ts +780 -0
  237. package/Tests/Server/Services/PermissionBlockDeletionPostgres.test.ts +628 -0
  238. package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
  239. package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
  240. package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +77 -1
  241. package/Tests/Server/Services/RumSessionPinCreatePermission.test.ts +715 -0
  242. package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
  243. package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
  244. package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
  245. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
  246. package/Tests/Server/Services/TeamMemberMultiTenantReadPostgres.test.ts +394 -0
  247. package/Tests/Server/Services/TeamPrivilegeEscalation.test.ts +6 -0
  248. package/Tests/Server/Services/TelemetryPayAsYouGoBilling.test.ts +131 -0
  249. package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
  250. package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +13 -2
  251. package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
  252. package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
  253. package/Tests/Server/Types/Database/Permissions/ModelPermissionAnonymousRefusal.test.ts +518 -0
  254. package/Tests/Server/Types/Database/Permissions/MultiTenantPermissions.test.ts +350 -0
  255. package/Tests/Server/Types/Database/Permissions/OnCallCalendarFeedPermissions.test.ts +282 -25
  256. package/Tests/Server/Types/Database/Permissions/TableLevelBlockPermission.test.ts +459 -0
  257. package/Tests/Server/Types/Markdown.test.ts +181 -0
  258. package/Tests/Server/Utils/AI/AIRunPrivacyFilter.test.ts +101 -9
  259. package/Tests/Server/Utils/AI/ChatAgentHelpers.test.ts +88 -4
  260. package/Tests/Server/Utils/AI/Toolbox/ExceptionTools.test.ts +459 -0
  261. package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +794 -0
  262. package/Tests/Server/Utils/AI/Toolbox/RecentChangesTools.test.ts +574 -0
  263. package/Tests/Server/Utils/AI/Toolbox/SecurityEventTools.test.ts +596 -0
  264. package/Tests/Server/Utils/CaptchaRequestAndLogging.test.ts +395 -0
  265. package/Tests/Server/Utils/CommunityEditionSsoReport.test.ts +565 -0
  266. package/Tests/Server/Utils/EditionEnforcement.test.ts +303 -0
  267. package/Tests/Server/Utils/FrontendEnvironment.test.ts +367 -0
  268. package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +38 -418
  269. package/Tests/Server/Utils/MasterAdminPageAccess.test.ts +251 -0
  270. package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +518 -0
  271. package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
  272. package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +616 -0
  273. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +934 -96
  274. package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
  275. package/Tests/Server/Utils/Realtime.test.ts +502 -0
  276. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorSeverity.test.ts +216 -0
  277. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +142 -0
  278. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.test.ts +140 -0
  279. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepairClickhouseIntegration.test.ts +542 -0
  280. package/Tests/Server/Utils/Telemetry/ChangeEventRow.test.ts +743 -0
  281. package/Tests/Server/Utils/Telemetry/RuntimeMetrics.test.ts +465 -0
  282. package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/Alert.test.ts +202 -0
  283. package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.test.ts +194 -0
  284. package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/ScheduledMaintenance.test.ts +231 -0
  285. package/Tests/Server/Utils/Workspace/Slack/Messages/Alert.test.ts +194 -0
  286. package/Tests/Server/Utils/Workspace/Slack/Messages/AlertEpisode.test.ts +194 -0
  287. package/Tests/Server/Utils/Workspace/Slack/Messages/Incident.test.ts +194 -0
  288. package/Tests/Server/Utils/Workspace/Slack/Messages/IncidentEpisode.test.ts +194 -0
  289. package/Tests/Server/Utils/Workspace/Slack/Messages/ScheduledMaintenance.test.ts +247 -0
  290. package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
  291. package/Tests/Types/AI/AIInsightEvidence.test.ts +206 -0
  292. package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
  293. package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
  294. package/Tests/Types/BaseDatabase/DatabaseCommonInteractionPropsUtilAnonymous.test.ts +144 -0
  295. package/Tests/Types/Call/CallProvider.test.ts +528 -0
  296. package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -0
  297. package/Tests/Types/Kubernetes/KubernetesCostIngest.test.ts +236 -0
  298. package/Tests/Types/OnCallDutyPolicy/ScheduleTimeline.test.ts +736 -0
  299. package/Tests/Types/OnCallDutyPolicy/ScheduleTimelineLayout.test.ts +996 -0
  300. package/Tests/Types/SecurityEvent/SigmaRule.test.ts +142 -0
  301. package/Tests/Types/Workflow/Components/JSON.test.ts +182 -0
  302. package/Tests/UI/Components/BasicFormDropdownNormalization.test.tsx +116 -1
  303. package/Tests/UI/Components/Dropdown/DropdownAsyncOptions.test.tsx +81 -0
  304. package/Tests/UI/Components/EditionLabelLapseCopy.ts +104 -0
  305. package/Tests/UI/Components/EditionLabelLicenseManagerWiring.test.tsx +254 -0
  306. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +165 -171
  307. package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
  308. package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
  309. package/Tests/UI/Components/EventAttachmentList.test.tsx +174 -0
  310. package/Tests/UI/Components/Forms/BasicFormBurnRateTemplateDefaults.test.tsx +395 -0
  311. package/Tests/UI/Components/Forms/BasicFormCollapsibleSections.test.tsx +286 -0
  312. package/Tests/UI/Components/Forms/FormSummary.test.tsx +128 -0
  313. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
  314. package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
  315. package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
  316. package/Tests/UI/Components/ModelTable/BaseModelTableQueryChange.test.tsx +365 -0
  317. package/Tests/UI/Components/OpenAuthenticatedUrl.test.ts +358 -0
  318. package/Tests/UI/Components/SessionAwareImage.test.tsx +496 -0
  319. package/Tests/UI/Components/TelemetryHistogramZeroBuckets.test.tsx +190 -0
  320. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
  321. package/Tests/UI/Components/TooltipInteractive.test.tsx +97 -0
  322. package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
  323. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardInstallGuidance.test.tsx +1 -1
  324. package/Tests/UI/Monitor/EvaluationLogListTimestamps.test.tsx +367 -0
  325. package/Tests/UI/Utils/API/BaseAPIRefreshSession.test.ts +1087 -0
  326. package/Tests/UI/Utils/API/DashboardHost.ts +12 -0
  327. package/Tests/UI/Utils/API/FakeAxiosServer.ts +183 -0
  328. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
  329. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  330. package/Tests/UI/Utils/Cookie.test.ts +440 -0
  331. package/Tests/UI/Utils/ModelAPIRequestClient.test.ts +278 -0
  332. package/Tests/UI/Utils/Navigation.test.ts +33 -0
  333. package/Tests/UI/Utils/PricingPlan.test.ts +295 -0
  334. package/Tests/UI/Utils/Realtime.test.ts +759 -0
  335. package/Tests/UI/Utils/Telemetry/Telemetry.test.ts +500 -0
  336. package/Tests/Utils/APIInstanceDispatch.test.ts +311 -0
  337. package/Tests/Utils/HostAddressUtil.test.ts +138 -0
  338. package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
  339. package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
  340. package/Tests/Utils/SecurityEvent/GoogleSecOpsAlertNormalizerSeverity.test.ts +565 -0
  341. package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
  342. package/Types/API/Hostname.ts +63 -16
  343. package/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.ts +40 -0
  344. package/Types/Database/AccessControl/ColumnAccessControl.ts +19 -7
  345. package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +19 -7
  346. package/Types/Database/AccessControl/OwnerOnlyColumn.ts +15 -6
  347. package/Types/Database/CanonicalModelInstance.ts +102 -0
  348. package/Types/Database/TableColumn.ts +20 -6
  349. package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +29 -0
  350. package/Types/IP/IPv6.ts +6 -1
  351. package/Types/Monitor/MonitorEvaluationSummary.ts +3 -0
  352. package/Types/Monitor/MonitorStep.ts +6 -1
  353. package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
  354. package/Types/OnCallDutyPolicy/ScheduleTimeline.ts +507 -0
  355. package/Types/OnCallDutyPolicy/ScheduleTimelineLayout.ts +589 -0
  356. package/Types/Realtime/EventName.ts +11 -0
  357. package/Types/SecurityEvent/DetectionFindingConstants.ts +14 -0
  358. package/Types/SecurityEvent/OcsfSeverity.ts +31 -26
  359. package/Types/SecurityEvent/SigmaRule.ts +51 -0
  360. package/Types/SecurityEvent/ThreatIntelConstants.ts +18 -0
  361. package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
  362. package/UI/Components/AttachmentList/EventAttachmentList.tsx +30 -2
  363. package/UI/Components/Dashboard/DashboardVariableControl.tsx +12 -2
  364. package/UI/Components/Dropdown/Dropdown.tsx +6 -1
  365. package/UI/Components/EditionLabel/EditionLabel.tsx +808 -1195
  366. package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
  367. package/UI/Components/EventItem/EventItem.tsx +12 -1
  368. package/UI/Components/Forms/BasicForm.tsx +151 -126
  369. package/UI/Components/Forms/CollapsibleFormSection.tsx +63 -0
  370. package/UI/Components/Forms/Fields/FormField.tsx +10 -4
  371. package/UI/Components/Forms/FormSummary.tsx +7 -0
  372. package/UI/Components/Forms/Types/Field.ts +10 -0
  373. package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
  374. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  375. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +2 -1
  376. package/UI/Components/Markdown.tsx/SessionAwareImage.tsx +122 -0
  377. package/UI/Components/ModelList/ModelList.tsx +11 -1
  378. package/UI/Components/ModelTable/BaseModelTable.tsx +34 -5
  379. package/UI/Components/ModelTable/TableView.tsx +1 -1
  380. package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
  381. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
  382. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +8 -1
  383. package/UI/Components/Tooltip/Tooltip.tsx +8 -1
  384. package/UI/Utils/API/API.ts +173 -12
  385. package/UI/Utils/API/RequestOptions.ts +11 -0
  386. package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +31 -7
  387. package/UI/Utils/ModelAPI/ModelAPI.ts +30 -9
  388. package/UI/Utils/Navigation.ts +9 -0
  389. package/UI/Utils/OpenAuthenticatedUrl.ts +154 -0
  390. package/UI/Utils/Realtime.ts +176 -30
  391. package/UI/esbuild-enterprise.js +263 -0
  392. package/Utils/API.ts +14 -5
  393. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
  394. package/Utils/HostAddressUtil.ts +94 -0
  395. package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
  396. package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
  397. package/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.ts +157 -7
  398. package/Utils/SecurityEvent/Sigma/SigmaRuleParser.ts +9 -17
  399. package/Utils/Slo/SloBurnRateTemplate.ts +2 -2
  400. package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
  401. package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
  402. package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
  403. package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
  404. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  405. package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
  406. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  407. package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
  408. package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
  409. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js +1 -1
  410. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js.map +1 -1
  411. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js +1 -1
  412. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js.map +1 -1
  413. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js +1 -1
  414. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js.map +1 -1
  415. package/build/dist/Server/API/AIBillingAPI.js +1 -1
  416. package/build/dist/Server/API/AIBillingAPI.js.map +1 -1
  417. package/build/dist/Server/API/AIInsightAPI.js +1 -4
  418. package/build/dist/Server/API/AIInsightAPI.js.map +1 -1
  419. package/build/dist/Server/API/AIInvestigationAPI.js +1 -4
  420. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  421. package/build/dist/Server/API/AIReadinessAPI.js +1 -3
  422. package/build/dist/Server/API/AIReadinessAPI.js.map +1 -1
  423. package/build/dist/Server/API/AlertAPI.js +1 -1
  424. package/build/dist/Server/API/AlertAPI.js.map +1 -1
  425. package/build/dist/Server/API/AutoRemediationAPI.js +1 -4
  426. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
  427. package/build/dist/Server/API/BaseAPI.js +33 -0
  428. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  429. package/build/dist/Server/API/BaseAnalyticsAPI.js +55 -10
  430. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  431. package/build/dist/Server/API/BillingAPI.js +2 -2
  432. package/build/dist/Server/API/BillingAPI.js.map +1 -1
  433. package/build/dist/Server/API/BillingInvoiceAPI.js +1 -1
  434. package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
  435. package/build/dist/Server/API/BillingPaymentMethodAPI.js +2 -2
  436. package/build/dist/Server/API/BillingPaymentMethodAPI.js.map +1 -1
  437. package/build/dist/Server/API/CodeFixRunAPI.js +1 -3
  438. package/build/dist/Server/API/CodeFixRunAPI.js.map +1 -1
  439. package/build/dist/Server/API/CommonAPI.js +50 -5
  440. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  441. package/build/dist/Server/API/DashboardAPI.js +12 -12
  442. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  443. package/build/dist/Server/API/GlobalConfigAPI.js +158 -342
  444. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  445. package/build/dist/Server/API/IncidentAPI.js +2 -2
  446. package/build/dist/Server/API/IncidentAPI.js.map +1 -1
  447. package/build/dist/Server/API/IncidentEpisodeAPI.js +1 -1
  448. package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
  449. package/build/dist/Server/API/NotificationAPI.js +1 -1
  450. package/build/dist/Server/API/NotificationAPI.js.map +1 -1
  451. package/build/dist/Server/API/OnCallCalendarAPI.js +1 -4
  452. package/build/dist/Server/API/OnCallCalendarAPI.js.map +1 -1
  453. package/build/dist/Server/API/OnCallDutyPolicyAPI.js +6 -0
  454. package/build/dist/Server/API/OnCallDutyPolicyAPI.js.map +1 -1
  455. package/build/dist/Server/API/OnCallReadinessAPI.js +4 -1
  456. package/build/dist/Server/API/OnCallReadinessAPI.js.map +1 -1
  457. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js +494 -0
  458. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js.map +1 -0
  459. package/build/dist/Server/API/ProjectAPI.js +1 -1
  460. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  461. package/build/dist/Server/API/ProjectOIDC.js +24 -16
  462. package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
  463. package/build/dist/Server/API/ProjectSSO.js +24 -16
  464. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  465. package/build/dist/Server/API/ScheduledMaintenanceAPI.js +1 -1
  466. package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
  467. package/build/dist/Server/API/StatusPageAPI.js +218 -76
  468. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  469. package/build/dist/Server/API/TeamMemberAPI.js +11 -4
  470. package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
  471. package/build/dist/Server/API/UserCallAPI.js +2 -2
  472. package/build/dist/Server/API/UserCallAPI.js.map +1 -1
  473. package/build/dist/Server/API/UserEmailAPI.js +2 -2
  474. package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
  475. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +2 -2
  476. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
  477. package/build/dist/Server/API/UserMicrosoftTeamsAPI.js +1 -1
  478. package/build/dist/Server/API/UserMicrosoftTeamsAPI.js.map +1 -1
  479. package/build/dist/Server/API/UserSlackAPI.js +1 -1
  480. package/build/dist/Server/API/UserSlackAPI.js.map +1 -1
  481. package/build/dist/Server/API/UserSmsAPI.js +2 -2
  482. package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
  483. package/build/dist/Server/API/UserTotpAuthAPI.js +1 -1
  484. package/build/dist/Server/API/UserTotpAuthAPI.js.map +1 -1
  485. package/build/dist/Server/API/UserWebAuthnAPI.js +2 -2
  486. package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
  487. package/build/dist/Server/API/UserWebhookAPI.js +1 -1
  488. package/build/dist/Server/API/UserWebhookAPI.js.map +1 -1
  489. package/build/dist/Server/API/UserWhatsAppAPI.js +2 -2
  490. package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
  491. package/build/dist/Server/Enterprise/EnterpriseEdition.js +466 -0
  492. package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -0
  493. package/build/dist/Server/Enterprise/EnterpriseFeature.js +39 -0
  494. package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -0
  495. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +70 -0
  496. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js.map +1 -0
  497. package/build/dist/Server/Enterprise/EnterpriseServerModule.js +84 -0
  498. package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -0
  499. package/build/dist/Server/EnvironmentConfig.js +84 -2
  500. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  501. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js +18 -0
  502. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js.map +1 -0
  503. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  504. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  505. package/build/dist/Server/Middleware/MasterAdminAuthorization.js +11 -2
  506. package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
  507. package/build/dist/Server/Middleware/UserAuthorization.js +94 -15
  508. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  509. package/build/dist/Server/Services/ApiKeyPermissionService.js +80 -4
  510. package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
  511. package/build/dist/Server/Services/AuditLogService.js +71 -740
  512. package/build/dist/Server/Services/AuditLogService.js.map +1 -1
  513. package/build/dist/Server/Services/DatabaseService.js +171 -0
  514. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  515. package/build/dist/Server/Services/DetectionRuleService.js +4 -4
  516. package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
  517. package/build/dist/Server/Services/EnterpriseLicenseService.js +34 -0
  518. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  519. package/build/dist/Server/Services/GlobalConfigService.js +63 -0
  520. package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
  521. package/build/dist/Server/Services/MonitorProbeService.js +90 -17
  522. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  523. package/build/dist/Server/Services/MonitorService.js +45 -4
  524. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  525. package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
  526. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  527. package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
  528. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  529. package/build/dist/Server/Services/OnCallDutyPolicyChildService.js +170 -0
  530. package/build/dist/Server/Services/OnCallDutyPolicyChildService.js.map +1 -0
  531. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +2 -2
  532. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  533. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +2 -2
  534. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  535. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +2 -2
  536. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
  537. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +2 -2
  538. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
  539. package/build/dist/Server/Services/PayAsYouGoBillingService.js +20 -27
  540. package/build/dist/Server/Services/PayAsYouGoBillingService.js.map +1 -1
  541. package/build/dist/Server/Services/ProjectService.js +231 -0
  542. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  543. package/build/dist/Server/Services/RumSessionPinService.js +198 -16
  544. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  545. package/build/dist/Server/Services/StatusPagePrivateUserService.js +7 -3
  546. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  547. package/build/dist/Server/Services/StatusPageService.js +71 -0
  548. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  549. package/build/dist/Server/Services/TeamMemberService.js +10 -0
  550. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  551. package/build/dist/Server/Services/TeamPermissionService.js +89 -27
  552. package/build/dist/Server/Services/TeamPermissionService.js.map +1 -1
  553. package/build/dist/Server/Services/TeamService.js +9 -0
  554. package/build/dist/Server/Services/TeamService.js.map +1 -1
  555. package/build/dist/Server/Services/ThreatIntelFeedService.js +5 -4
  556. package/build/dist/Server/Services/ThreatIntelFeedService.js.map +1 -1
  557. package/build/dist/Server/Services/UserService.js +10 -16
  558. package/build/dist/Server/Services/UserService.js.map +1 -1
  559. package/build/dist/Server/Types/Database/Permissions/BasePermission.js +9 -6
  560. package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
  561. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +10 -0
  562. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  563. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +154 -14
  564. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
  565. package/build/dist/Server/Types/Database/Permissions/Index.js +60 -6
  566. package/build/dist/Server/Types/Database/Permissions/Index.js.map +1 -1
  567. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +24 -16
  568. package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
  569. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +17 -0
  570. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
  571. package/build/dist/Server/Types/Markdown.js +31 -0
  572. package/build/dist/Server/Types/Markdown.js.map +1 -1
  573. package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js +7 -0
  574. package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js.map +1 -1
  575. package/build/dist/Server/Utils/AI/AIRunPrivacyFilter.js +7 -0
  576. package/build/dist/Server/Utils/AI/AIRunPrivacyFilter.js.map +1 -1
  577. package/build/dist/Server/Utils/CommunityEditionSsoReport.js +223 -0
  578. package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +1 -0
  579. package/build/dist/Server/Utils/EditionEnforcement.js +187 -0
  580. package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -0
  581. package/build/dist/Server/Utils/FrontendEnvironment.js +31 -2
  582. package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -1
  583. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +6 -193
  584. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -1
  585. package/build/dist/Server/Utils/MasterAdminPageAccess.js +39 -0
  586. package/build/dist/Server/Utils/MasterAdminPageAccess.js.map +1 -0
  587. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +96 -0
  588. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
  589. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  590. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  591. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +3 -1
  592. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  593. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +449 -261
  594. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  595. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +3 -1
  596. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  597. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js +88 -0
  598. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js.map +1 -0
  599. package/build/dist/Server/Utils/Realtime.js +126 -37
  600. package/build/dist/Server/Utils/Realtime.js.map +1 -1
  601. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +7 -25
  602. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  603. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.js +127 -0
  604. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.js.map +1 -0
  605. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +1 -1
  606. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
  607. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +3 -2
  608. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js.map +1 -1
  609. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js +4 -8
  610. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js.map +1 -1
  611. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +331 -11
  612. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  613. package/build/dist/Types/API/Hostname.js +59 -11
  614. package/build/dist/Types/API/Hostname.js.map +1 -1
  615. package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js +31 -1
  616. package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js.map +1 -1
  617. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +19 -7
  618. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
  619. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +19 -7
  620. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
  621. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +13 -6
  622. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -1
  623. package/build/dist/Types/Database/CanonicalModelInstance.js +88 -0
  624. package/build/dist/Types/Database/CanonicalModelInstance.js.map +1 -0
  625. package/build/dist/Types/Database/TableColumn.js +19 -6
  626. package/build/dist/Types/Database/TableColumn.js.map +1 -1
  627. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +28 -0
  628. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js.map +1 -0
  629. package/build/dist/Types/IP/IPv6.js +6 -1
  630. package/build/dist/Types/IP/IPv6.js.map +1 -1
  631. package/build/dist/Types/Monitor/MonitorStep.js +5 -0
  632. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  633. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +1 -1
  634. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimeline.js +321 -0
  635. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimeline.js.map +1 -0
  636. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimelineLayout.js +372 -0
  637. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimelineLayout.js.map +1 -0
  638. package/build/dist/Types/Realtime/EventName.js +10 -0
  639. package/build/dist/Types/Realtime/EventName.js.map +1 -1
  640. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +11 -0
  641. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
  642. package/build/dist/Types/SecurityEvent/OcsfSeverity.js +30 -25
  643. package/build/dist/Types/SecurityEvent/OcsfSeverity.js.map +1 -1
  644. package/build/dist/Types/SecurityEvent/SigmaRule.js +47 -0
  645. package/build/dist/Types/SecurityEvent/SigmaRule.js.map +1 -1
  646. package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js +14 -0
  647. package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js.map +1 -1
  648. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js +32 -0
  649. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js.map +1 -0
  650. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js +9 -4
  651. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js.map +1 -1
  652. package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js +10 -2
  653. package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js.map +1 -1
  654. package/build/dist/UI/Components/Dropdown/Dropdown.js +5 -1
  655. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  656. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +425 -585
  657. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  658. package/build/dist/UI/Components/EditionLabel/LicenseManager.js +2 -0
  659. package/build/dist/UI/Components/EditionLabel/LicenseManager.js.map +1 -0
  660. package/build/dist/UI/Components/EventItem/EventItem.js +2 -2
  661. package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
  662. package/build/dist/UI/Components/Forms/BasicForm.js +70 -64
  663. package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
  664. package/build/dist/UI/Components/Forms/CollapsibleFormSection.js +27 -0
  665. package/build/dist/UI/Components/Forms/CollapsibleFormSection.js.map +1 -0
  666. package/build/dist/UI/Components/Forms/Fields/FormField.js +10 -7
  667. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  668. package/build/dist/UI/Components/Forms/FormSummary.js +7 -0
  669. package/build/dist/UI/Components/Forms/FormSummary.js.map +1 -1
  670. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +90 -17
  671. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  672. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  673. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  674. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +2 -1
  675. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  676. package/build/dist/UI/Components/Markdown.tsx/SessionAwareImage.js +84 -0
  677. package/build/dist/UI/Components/Markdown.tsx/SessionAwareImage.js.map +1 -0
  678. package/build/dist/UI/Components/ModelList/ModelList.js +4 -1
  679. package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
  680. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +14 -1
  681. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  682. package/build/dist/UI/Components/ModelTable/TableView.js +1 -1
  683. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  684. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +42 -1
  685. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  686. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +2 -2
  687. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  688. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +8 -1
  689. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  690. package/build/dist/UI/Components/Tooltip/Tooltip.js +2 -1
  691. package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
  692. package/build/dist/UI/Utils/API/API.js +143 -19
  693. package/build/dist/UI/Utils/API/API.js.map +1 -1
  694. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +21 -7
  695. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
  696. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +26 -9
  697. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  698. package/build/dist/UI/Utils/Navigation.js +8 -0
  699. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  700. package/build/dist/UI/Utils/OpenAuthenticatedUrl.js +92 -0
  701. package/build/dist/UI/Utils/OpenAuthenticatedUrl.js.map +1 -0
  702. package/build/dist/UI/Utils/Realtime.js +120 -15
  703. package/build/dist/UI/Utils/Realtime.js.map +1 -1
  704. package/build/dist/Utils/API.js +13 -5
  705. package/build/dist/Utils/API.js.map +1 -1
  706. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +6 -2
  707. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  708. package/build/dist/Utils/HostAddressUtil.js +80 -0
  709. package/build/dist/Utils/HostAddressUtil.js.map +1 -0
  710. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js +127 -0
  711. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js.map +1 -0
  712. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js +374 -0
  713. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js.map +1 -0
  714. package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js +123 -6
  715. package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js.map +1 -1
  716. package/build/dist/Utils/SecurityEvent/Sigma/SigmaRuleParser.js +4 -18
  717. package/build/dist/Utils/SecurityEvent/Sigma/SigmaRuleParser.js.map +1 -1
  718. package/build/dist/Utils/Slo/SloBurnRateTemplate.js +2 -2
  719. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
  720. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -0
  721. package/jest.config.json +3 -1
  722. package/package.json +1 -1
  723. package/test-setup.sh +103 -34
  724. package/tsconfig.json +13 -0
  725. package/Server/API/EnterpriseLicenseAPI.ts +0 -925
  726. package/Server/API/TeamComplianceAPI.ts +0 -158
  727. package/Server/Middleware/SCIMAuthorization.ts +0 -141
  728. package/Server/Services/TeamComplianceService.ts +0 -733
  729. package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +0 -186
  730. package/Server/Utils/InstanceHealth/PostgresHealth.ts +0 -286
  731. package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +0 -451
  732. package/Tests/App/Dashboard/AuditLogsTable.test.tsx +0 -598
  733. package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
  734. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
  735. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +0 -1851
  736. package/Tests/Server/Middleware/SCIMAuthorization.test.ts +0 -525
  737. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +0 -1845
  738. package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +0 -495
  739. package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +0 -337
  740. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +0 -576
  741. package/Tests/Utils/EnterpriseLicenseSync.test.ts +0 -568
  742. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +0 -287
  743. package/Utils/EnterpriseLicense/EnterpriseLicenseSync.ts +0 -244
  744. package/build/dist/Server/API/EnterpriseLicenseAPI.js +0 -646
  745. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +0 -1
  746. package/build/dist/Server/API/TeamComplianceAPI.js +0 -111
  747. package/build/dist/Server/API/TeamComplianceAPI.js.map +0 -1
  748. package/build/dist/Server/Middleware/SCIMAuthorization.js +0 -124
  749. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +0 -1
  750. package/build/dist/Server/Services/TeamComplianceService.js +0 -537
  751. package/build/dist/Server/Services/TeamComplianceService.js.map +0 -1
  752. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +0 -145
  753. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +0 -1
  754. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +0 -194
  755. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +0 -1
  756. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +0 -168
  757. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +0 -1
  758. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js +0 -174
  759. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js.map +0 -1
@@ -99,6 +99,7 @@ export default class MonitorIncident {
99
99
  select: {
100
100
  _id: true,
101
101
  title: true,
102
+ createdAt: true,
102
103
  createdCriteriaId: true,
103
104
  createdIncidentTemplateId: true,
104
105
  projectId: true,
@@ -579,6 +580,7 @@ export default class MonitorIncident {
579
580
  relatedIncidentNumber: alreadyOpenIncident?.incidentNumber,
580
581
  relatedIncidentNumberWithPrefix:
581
582
  alreadyOpenIncident?.incidentNumberWithPrefix,
583
+ relatedIncidentCreatedAt: alreadyOpenIncident?.createdAt,
582
584
  at: OneUptimeDate.getCurrentDate(),
583
585
  });
584
586
  continue;
@@ -913,7 +915,7 @@ export default class MonitorIncident {
913
915
  relatedIncidentNumber: createdIncident.incidentNumber,
914
916
  relatedIncidentNumberWithPrefix:
915
917
  createdIncident.incidentNumberWithPrefix,
916
- at: OneUptimeDate.getCurrentDate(),
918
+ at: createdIncident.createdAt || OneUptimeDate.getCurrentDate(),
917
919
  });
918
920
  } catch (err) {
919
921
  /*
@@ -0,0 +1,116 @@
1
+ import BadDataException from "../../../Types/Exception/BadDataException";
2
+ import MonitoringIntervalUtil, {
3
+ MonitoringIntervalNormalization,
4
+ MonitoringIntervalNormalizationStatus,
5
+ } from "../../../Utils/Monitor/MonitoringIntervalUtil";
6
+ import CronTab from "../CronTab";
7
+
8
+ /*
9
+ * Server-side policy for `Monitor.monitoringInterval`.
10
+ *
11
+ * MonitoringIntervalUtil says what a value MEANS and never throws.
12
+ * This says what we DO about it on a write: understood values are rewritten
13
+ * to canonical cron, and genuinely meaningless ones are refused with a
14
+ * message that names the cron to use instead.
15
+ *
16
+ * WHY THE RUNTIME PARSER GETS THE LAST WORD
17
+ *
18
+ * The isomorphic normalizer is a hand-rolled grammar; the scheduler runs on
19
+ * cron-parser. Where the two disagree, cron-parser wins, because it is what
20
+ * actually computes `nextPingAt`. Validation that rejected an expression the
21
+ * scheduler would happily honour ("@hourly", exotic step/range forms) would
22
+ * be this same bug in mirror image: the UI and the runtime disagreeing about
23
+ * a stored value, with the customer caught in between. So Unrecognized is
24
+ * re-checked against cron-parser before we refuse anything.
25
+ */
26
+
27
+ /*
28
+ * The shortest cadence the probe fleet can honour.
29
+ *
30
+ * `claimMonitorProbesForProbing` is driven by a cron that ticks once a
31
+ * minute, so a sub-minute schedule is a promise we cannot keep. cron-parser
32
+ * accepts 6-field per-second expressions such as "* * * * * *" quite
33
+ * happily; without this floor an API client could ask for a per-second probe
34
+ * and silently get a per-minute one — the exact class of bug this file
35
+ * exists to close.
36
+ */
37
+ export const MINIMUM_MONITORING_INTERVAL_IN_SECONDS: number = 60;
38
+
39
+ export default class MonitoringIntervalValidator {
40
+ /**
41
+ * Validate and canonicalize an inbound monitoring interval.
42
+ *
43
+ * Returns the value to persist: null for "no schedule" (legitimate — a
44
+ * Manual monitor is never probed), otherwise a cron expression the
45
+ * scheduler can parse. Throws BadDataException when the value cannot be
46
+ * understood by either the normalizer or cron-parser.
47
+ */
48
+ public static validateAndNormalize(
49
+ value: string | null | undefined,
50
+ ): string | null {
51
+ const result: MonitoringIntervalNormalization =
52
+ MonitoringIntervalUtil.normalize(value);
53
+
54
+ if (result.status === MonitoringIntervalNormalizationStatus.Empty) {
55
+ return null;
56
+ }
57
+
58
+ if (result.cron) {
59
+ MonitoringIntervalValidator.assertMeetsFloor(result.cron, result.input);
60
+ return result.cron;
61
+ }
62
+
63
+ /*
64
+ * Unrecognized by the grammar. Before refusing, ask the parser that
65
+ * actually schedules the probe — if it can read the expression, the
66
+ * scheduler can honour it and there is nothing to refuse.
67
+ */
68
+ const trimmed: string = (result.input || "").trim();
69
+ const intervalInSeconds: number | null =
70
+ CronTab.getIntervalInSeconds(trimmed);
71
+
72
+ if (intervalInSeconds !== null) {
73
+ MonitoringIntervalValidator.assertMeetsFloor(trimmed, result.input);
74
+ return trimmed;
75
+ }
76
+
77
+ throw new BadDataException(
78
+ `Invalid Monitoring Interval "${trimmed}". Expected a cron expression - use "${MonitoringIntervalUtil.getSuggestedCronForMessage()}" for every 5 minutes.`,
79
+ );
80
+ }
81
+
82
+ /*
83
+ * Applied to every accepted value, normalized or passed through, because
84
+ * the floor is about what the probe fleet can deliver and not about which
85
+ * code path produced the expression.
86
+ */
87
+ private static assertMeetsFloor(
88
+ cron: string,
89
+ input: string | null | undefined,
90
+ ): void {
91
+ const intervalInSeconds: number | null = CronTab.getIntervalInSeconds(cron);
92
+
93
+ if (
94
+ intervalInSeconds !== null &&
95
+ intervalInSeconds < MINIMUM_MONITORING_INTERVAL_IN_SECONDS
96
+ ) {
97
+ throw new BadDataException(
98
+ `Monitoring Interval "${(input || cron).trim()}" is faster than once a minute, which probes cannot deliver. Use "* * * * *" for the fastest supported schedule.`,
99
+ );
100
+ }
101
+ }
102
+
103
+ /**
104
+ * The cron a stored value means, for READ paths.
105
+ *
106
+ * Read paths must stay total: a row written before this validator existed
107
+ * (or restored from a backup, or written through a hook-free path) is not
108
+ * an exception, it is just a row. Callers fall back to their own default
109
+ * when this returns null.
110
+ */
111
+ public static normalizeForRead(
112
+ value: string | null | undefined,
113
+ ): string | null {
114
+ return MonitoringIntervalUtil.toCronOrNull(value);
115
+ }
116
+ }
@@ -176,7 +176,7 @@ export interface EmptyOutcomeOptions {
176
176
  }
177
177
 
178
178
  /* The schedule facts every render needs, read once per request. */
179
- interface ScheduleInfo {
179
+ export interface ScheduleInfo {
180
180
  id: ObjectID;
181
181
  name: string;
182
182
  timezone?: string | undefined;
@@ -24,6 +24,19 @@ import Dictionary from "../../Types/Dictionary";
24
24
  import UserPermissionUtil from "./UserPermission/UserPermission";
25
25
  import CaptureSpan from "./Telemetry/CaptureSpan";
26
26
 
27
+ // What became of one ListenToModelEvent request.
28
+ export enum ListenToModelEventOutcome {
29
+ Joined = "Joined",
30
+ // No access token, or one that no longer decodes. The client was told.
31
+ AuthenticationRequired = "AuthenticationRequired",
32
+ // A valid session without access to this tenant or model.
33
+ NotAuthorized = "NotAuthorized",
34
+ // The request itself was malformed.
35
+ InvalidRequest = "InvalidRequest",
36
+ // Something failed while authorizing (for example the permission cache).
37
+ Failed = "Failed",
38
+ }
39
+
27
40
  export default abstract class Realtime {
28
41
  private static socketServer: SocketServer | null = null;
29
42
 
@@ -45,37 +58,19 @@ export default abstract class Realtime {
45
58
  this.socketServer!.on("connection", (socket: Socket) => {
46
59
  logger.debug("New socket connection established");
47
60
 
48
- socket.on(EventName.ListenToModalEvent, async (data: JSONObject) => {
49
- logger.debug("Received ListenToModalEvent with data:");
50
- logger.debug(data);
51
-
52
- const socketLogAttributes: LogAttributes = {
53
- projectId: data["tenantId"]?.toString(),
54
- };
55
-
56
- if (typeof data["eventType"] !== "string") {
57
- logger.error("eventType is not a string", socketLogAttributes);
58
- throw new BadDataException("eventType is not a string");
59
- }
60
- if (typeof data["modelType"] !== "string") {
61
- logger.error("modelType is not a string", socketLogAttributes);
62
- throw new BadDataException("modelType is not a string");
63
- }
64
- if (typeof data["modelName"] !== "string") {
65
- logger.error("modelName is not a string", socketLogAttributes);
66
- throw new BadDataException("modelName is not a string");
67
- }
68
- if (typeof data["tenantId"] !== "string") {
69
- logger.error("tenantId is not a string", socketLogAttributes);
70
- throw new BadDataException("tenantId is not a string");
71
- }
72
-
73
- await Realtime.listenToModelEvent(socket, {
74
- eventType: data["eventType"] as ModelEventType,
75
- modelType: data["modelType"] as DatabaseType,
76
- modelName: data["modelName"] as string,
77
- tenantId: data["tenantId"] as string,
78
- });
61
+ /*
62
+ * socket.io calls a listener and throws away what it returns. An async
63
+ * listener that throws is therefore an unhandled rejection: nothing
64
+ * goes back to the client, and the subscription it asked for simply
65
+ * never happens. handleListenToModelEventRequest settles every outcome
66
+ * itself; the catch is a backstop, not the error handling.
67
+ */
68
+ socket.on(EventName.ListenToModalEvent, (data: JSONObject): void => {
69
+ Realtime.handleListenToModelEventRequest(socket, data).catch(
70
+ (err: unknown) => {
71
+ logger.error(err);
72
+ },
73
+ );
79
74
  });
80
75
  });
81
76
  }
@@ -83,11 +78,108 @@ export default abstract class Realtime {
83
78
  return this.socketServer;
84
79
  }
85
80
 
81
+ /*
82
+ * One ListenToModelEvent from a client, start to finish. Never throws: a
83
+ * malformed request, a missing or expired access token, a refused
84
+ * subscription and a failing permission lookup each end here as an outcome,
85
+ * so none of them can become an unhandled rejection in the socket listener.
86
+ */
87
+ @CaptureSpan()
88
+ public static async handleListenToModelEventRequest(
89
+ socket: Socket,
90
+ data: JSONObject,
91
+ ): Promise<ListenToModelEventOutcome> {
92
+ logger.debug("Received ListenToModalEvent with data:");
93
+ logger.debug(data);
94
+
95
+ let request: ListenToModelEventJSON;
96
+
97
+ try {
98
+ request = Realtime.parseListenToModelEventRequest(data);
99
+ } catch (err) {
100
+ logger.error(err);
101
+ return ListenToModelEventOutcome.InvalidRequest;
102
+ }
103
+
104
+ try {
105
+ return await Realtime.listenToModelEvent(socket, request);
106
+ } catch (err) {
107
+ // A permission-cache (Redis) failure, say. The room is not joined.
108
+ const failureLogAttributes: LogAttributes = {
109
+ projectId: request.tenantId,
110
+ };
111
+
112
+ logger.error(err, failureLogAttributes);
113
+ return ListenToModelEventOutcome.Failed;
114
+ }
115
+ }
116
+
117
+ private static parseListenToModelEventRequest(
118
+ data: JSONObject,
119
+ ): ListenToModelEventJSON {
120
+ if (!data || typeof data !== "object") {
121
+ logger.error("ListenToModelEvent data is not an object");
122
+ throw new BadDataException("ListenToModelEvent data is not an object");
123
+ }
124
+
125
+ const socketLogAttributes: LogAttributes = {
126
+ projectId: data["tenantId"]?.toString(),
127
+ };
128
+
129
+ if (typeof data["eventType"] !== "string") {
130
+ logger.error("eventType is not a string", socketLogAttributes);
131
+ throw new BadDataException("eventType is not a string");
132
+ }
133
+ if (typeof data["modelType"] !== "string") {
134
+ logger.error("modelType is not a string", socketLogAttributes);
135
+ throw new BadDataException("modelType is not a string");
136
+ }
137
+ if (typeof data["modelName"] !== "string") {
138
+ logger.error("modelName is not a string", socketLogAttributes);
139
+ throw new BadDataException("modelName is not a string");
140
+ }
141
+ if (typeof data["tenantId"] !== "string") {
142
+ logger.error("tenantId is not a string", socketLogAttributes);
143
+ throw new BadDataException("tenantId is not a string");
144
+ }
145
+
146
+ return {
147
+ eventType: data["eventType"] as ModelEventType,
148
+ modelType: data["modelType"] as DatabaseType,
149
+ modelName: data["modelName"] as string,
150
+ tenantId: data["tenantId"] as string,
151
+ };
152
+ }
153
+
154
+ /*
155
+ * The socket has no usable user session: tell the client, which refreshes
156
+ * its session and reconnects so the new handshake carries the new cookie.
157
+ * Dropping the request silently is what used to happen, and it left every
158
+ * subscription made after the access token expired dead (no live counters
159
+ * after switching project, no live logs) with nothing in the browser to
160
+ * show why.
161
+ */
162
+ private static rejectForMissingAuthentication(
163
+ socket: Socket,
164
+ data: ListenToModelEventJSON,
165
+ reason: string,
166
+ listenLogAttributes: LogAttributes,
167
+ ): ListenToModelEventOutcome {
168
+ logger.debug(
169
+ `${reason}, aborting joining room and asking the client to re-authenticate`,
170
+ listenLogAttributes,
171
+ );
172
+
173
+ socket.emit(EventName.AuthenticationRequired, data);
174
+
175
+ return ListenToModelEventOutcome.AuthenticationRequired;
176
+ }
177
+
86
178
  @CaptureSpan()
87
179
  public static async listenToModelEvent(
88
180
  socket: Socket,
89
181
  data: ListenToModelEventJSON,
90
- ): Promise<void> {
182
+ ): Promise<ListenToModelEventOutcome> {
91
183
  const listenLogAttributes: LogAttributes = {
92
184
  projectId: data.tenantId?.toString(),
93
185
  };
@@ -116,31 +208,51 @@ export default abstract class Realtime {
116
208
  this.getAccessTokenFromSocket(socket);
117
209
 
118
210
  if (!userAccessToken) {
119
- logger.debug(
120
- "User access token not found in socket, aborting joining room",
211
+ return this.rejectForMissingAuthentication(
212
+ socket,
213
+ data,
214
+ "User access token not found in socket",
121
215
  listenLogAttributes,
122
216
  );
123
- return;
124
217
  }
125
218
 
126
219
  logger.debug("Decoding user access token", listenLogAttributes);
127
- const userAuthorizationData: JSONWebTokenData =
128
- JSONWebToken.decode(userAccessToken);
220
+
221
+ /*
222
+ * The token is the one the browser sent with the handshake, and it is not
223
+ * re-read for the life of the connection. Once it expires every decode
224
+ * throws, which is the normal state of a dashboard tab left open past the
225
+ * access token's lifetime, not an error in the request.
226
+ */
227
+ let userAuthorizationData: JSONWebTokenData;
228
+
229
+ try {
230
+ userAuthorizationData = JSONWebToken.decode(userAccessToken);
231
+ } catch {
232
+ return this.rejectForMissingAuthentication(
233
+ socket,
234
+ data,
235
+ "User access token in socket is invalid or expired",
236
+ listenLogAttributes,
237
+ );
238
+ }
129
239
 
130
240
  if (!userAuthorizationData) {
131
- logger.debug(
132
- "User authorization data not found in socket, aborting joining room",
241
+ return this.rejectForMissingAuthentication(
242
+ socket,
243
+ data,
244
+ "User authorization data not found in socket",
133
245
  listenLogAttributes,
134
246
  );
135
- return;
136
247
  }
137
248
 
138
249
  if (!userAuthorizationData.userId) {
139
- logger.debug(
140
- "User ID not found in socket, aborting joining room",
250
+ return this.rejectForMissingAuthentication(
251
+ socket,
252
+ data,
253
+ "User ID not found in socket",
141
254
  listenLogAttributes,
142
255
  );
143
- return;
144
256
  }
145
257
 
146
258
  logger.debug("Checking user access permissions", listenLogAttributes);
@@ -179,7 +291,7 @@ export default abstract class Realtime {
179
291
  "User does not have access to this tenant, aborting joining room",
180
292
  listenLogAttributes,
181
293
  );
182
- return;
294
+ return ListenToModelEventOutcome.NotAuthorized;
183
295
  }
184
296
 
185
297
  logger.debug(
@@ -214,12 +326,16 @@ export default abstract class Realtime {
214
326
  }
215
327
  }
216
328
 
329
+ /*
330
+ * Authenticated but not allowed. The room is not joined and, as before,
331
+ * nothing is sent back: a fresh session would not change the answer.
332
+ */
217
333
  if (!hasAccess) {
218
334
  logger.debug(
219
335
  "User does not have access to this tenant, aborting joining room",
220
336
  listenLogAttributes,
221
337
  );
222
- return;
338
+ return ListenToModelEventOutcome.NotAuthorized;
223
339
  }
224
340
 
225
341
  if (data.modelId) {
@@ -244,6 +360,8 @@ export default abstract class Realtime {
244
360
  // join the room.
245
361
  await socket.join(roomId);
246
362
  }
363
+
364
+ return ListenToModelEventOutcome.Joined;
247
365
  }
248
366
 
249
367
  @CaptureSpan()
@@ -8,13 +8,18 @@ import OcsfSeverity, {
8
8
  OcsfSeverityId,
9
9
  } from "../../../Types/SecurityEvent/OcsfSeverity";
10
10
  import { ocsfCategoryForClassUid } from "../../../Types/SecurityEvent/OcsfEventClass";
11
- import SigmaRule, { SigmaLevel } from "../../../Types/SecurityEvent/SigmaRule";
11
+ import SigmaRule, {
12
+ SIGMA_LEVEL_TO_OCSF_SEVERITY,
13
+ isSevereSigmaLevel,
14
+ } from "../../../Types/SecurityEvent/SigmaRule";
12
15
  import {
13
16
  DETECTION_DISTINCT_COUNT_ATTRIBUTE,
14
17
  DETECTION_FINDING_CLASS_NAME,
15
18
  DETECTION_FINDING_CLASS_UID,
16
19
  DETECTION_GROUP_VALUE_ATTRIBUTE,
17
20
  DETECTION_MATCH_COUNT_ATTRIBUTE,
21
+ DETECTION_MAX_GROUPS_PER_EVALUATION,
22
+ DETECTION_MAX_LOOKBACK_IN_MINUTES,
18
23
  DETECTION_RULE_ID_ATTRIBUTE,
19
24
  DETECTION_RULE_NAME_ATTRIBUTE,
20
25
  DETECTION_SIGMA_ID_ATTRIBUTE,
@@ -49,24 +54,6 @@ import { buildSecurityEventDbRow } from "./SecurityEventRow";
49
54
 
50
55
  const DETECTIONS_SERVICE_NAME: string = "OneUptime Detections";
51
56
 
52
- /*
53
- * Cap on how far back one evaluation may scan, whatever lastEvaluatedAt
54
- * says — a rule re-enabled after a month must not trigger a month-long
55
- * table scan.
56
- */
57
- const MAX_LOOKBACK_IN_MINUTES: number = 24 * 60;
58
-
59
- // One alert per distinct group value per cycle, at most.
60
- const MAX_GROUPS_PER_EVALUATION: number = 100;
61
-
62
- const SIGMA_LEVEL_TO_OCSF: Record<SigmaLevel, OcsfSeverity> = {
63
- [SigmaLevel.Informational]: OcsfSeverity.Informational,
64
- [SigmaLevel.Low]: OcsfSeverity.Low,
65
- [SigmaLevel.Medium]: OcsfSeverity.Medium,
66
- [SigmaLevel.High]: OcsfSeverity.High,
67
- [SigmaLevel.Critical]: OcsfSeverity.Critical,
68
- };
69
-
70
57
  export interface DetectionRuleEvaluationResult {
71
58
  ruleId: string;
72
59
  matchedGroups: number;
@@ -190,7 +177,7 @@ export default class DetectionRuleEvaluator {
190
177
 
191
178
  const earliestAllowed: Date = OneUptimeDate.addRemoveMinutes(
192
179
  endTime,
193
- -MAX_LOOKBACK_IN_MINUTES,
180
+ -DETECTION_MAX_LOOKBACK_IN_MINUTES,
194
181
  );
195
182
 
196
183
  let startTime: Date = rule.lastEvaluatedAt
@@ -220,7 +207,7 @@ export default class DetectionRuleEvaluator {
220
207
  groupByExpression,
221
208
  distinctCountExpression,
222
209
  minMatchCount: matchCountThreshold,
223
- maxGroups: MAX_GROUPS_PER_EVALUATION,
210
+ maxGroups: DETECTION_MAX_GROUPS_PER_EVALUATION,
224
211
  });
225
212
 
226
213
  /*
@@ -500,7 +487,7 @@ export default class DetectionRuleEvaluator {
500
487
  });
501
488
 
502
489
  const severityName: OcsfSeverity =
503
- SIGMA_LEVEL_TO_OCSF[parsedRule.level] || OcsfSeverity.Medium;
490
+ SIGMA_LEVEL_TO_OCSF_SEVERITY[parsedRule.level] || OcsfSeverity.Medium;
504
491
 
505
492
  const { categoryUid, categoryName } = ocsfCategoryForClassUid(
506
493
  DETECTION_FINDING_CLASS_UID,
@@ -625,7 +612,7 @@ export default class DetectionRuleEvaluator {
625
612
  projectId: data.projectId,
626
613
  explicitSeverityId: data.rule.alertSeverityId,
627
614
  severityLabel: data.parsedRule.level,
628
- isSevere: this.isSevereLevel(data.parsedRule.level),
615
+ isSevere: isSevereSigmaLevel(data.parsedRule.level),
629
616
  });
630
617
  }
631
618
 
@@ -647,11 +634,7 @@ export default class DetectionRuleEvaluator {
647
634
  projectId: data.projectId,
648
635
  explicitSeverityId: data.rule.incidentSeverityId,
649
636
  severityLabel: data.parsedRule.level,
650
- isSevere: this.isSevereLevel(data.parsedRule.level),
637
+ isSevere: isSevereSigmaLevel(data.parsedRule.level),
651
638
  });
652
639
  }
653
-
654
- private static isSevereLevel(level: SigmaLevel): boolean {
655
- return level === SigmaLevel.Critical || level === SigmaLevel.High;
656
- }
657
640
  }
@@ -0,0 +1,170 @@
1
+ import OcsfSeverity, {
2
+ OCSF_SEVERITY_ALIASES,
3
+ OcsfSeverityId,
4
+ } from "../../../Types/SecurityEvent/OcsfSeverity";
5
+ import {
6
+ DETECTION_FINDING_CLASS_UID,
7
+ GOOGLE_SECOPS_PRODUCT_NAME,
8
+ GOOGLE_SECOPS_RISK_SCORE_BANDS,
9
+ GOOGLE_SECOPS_VENDOR_NAME,
10
+ } from "../../../Utils/SecurityEvent/GoogleSecOpsAlertNormalizer";
11
+
12
+ /*
13
+ * Re-grades Google SecOps detections that were stored as Unknown before the
14
+ * normalizer learned to read a custom rule's severity.
15
+ *
16
+ * Every stored row keeps its source payload flattened into `attributes`
17
+ * (`detection.0.ruleLabels.2.key` = "severity", `...2.value` = "Medium"), so
18
+ * the grade the fixed GoogleSecOpsAlertNormalizer would give a row can be
19
+ * computed in SQL from the row itself. The expression below is that
20
+ * normalizer's resolveSeverity, written against the flattened keys:
21
+ *
22
+ * 1. detection[0].severity (Google's grade on curated rules)
23
+ * 2. the Collection's severity
24
+ * 3. the first ruleLabels "severity" that names a grade (YARA-L meta)
25
+ * 4. the first outcomes "risk_score" that grades, on Google's bands
26
+ *
27
+ * Its text tables are generated from OCSF_SEVERITY_ALIASES and
28
+ * GOOGLE_SECOPS_RISK_SCORE_BANDS, the same tables the normalizer reads, so
29
+ * the two cannot drift apart. It reads the list form of ruleLabels and
30
+ * outcomes Google returns; a label map in a hand-built webhook body is
31
+ * graded at ingest but not here.
32
+ *
33
+ * Only rows that are still Unknown and that the expression grades are
34
+ * touched, so the repair is idempotent and never overrides a grade.
35
+ */
36
+ export default class GoogleSecOpsSeverityRepair {
37
+ /*
38
+ * The OCSF severity name a stored row's attributes grade to, or '' when
39
+ * nothing in them grades.
40
+ */
41
+ public static gradeExpression(): string {
42
+ const detectionSeverity: string = `if(attributes['detection.0.severity'] != '', attributes['detection.0.severity'], attributes['detection.severity'])`;
43
+ const graded: Array<string> = [
44
+ GoogleSecOpsSeverityRepair.gradeText(detectionSeverity),
45
+ GoogleSecOpsSeverityRepair.gradeText("attributes['severity']"),
46
+ GoogleSecOpsSeverityRepair.firstKeyedGrade(
47
+ "(ruleLabels|rule_labels)",
48
+ "severity",
49
+ GoogleSecOpsSeverityRepair.gradeText,
50
+ ),
51
+ GoogleSecOpsSeverityRepair.firstKeyedGrade(
52
+ "outcomes",
53
+ "risk_score",
54
+ GoogleSecOpsSeverityRepair.gradeRiskScore,
55
+ ),
56
+ ];
57
+
58
+ // The first of the four grades that is set, in the normalizer's order.
59
+ return `arrayFirst(grade -> grade != '', [${graded.join(", ")}])`;
60
+ }
61
+
62
+ /*
63
+ * The async ON CLUSTER mutation. `storageTable` is the local storage
64
+ * table and `onCluster` the cluster clause, as every data mutation on
65
+ * the clustered analytics schema is written.
66
+ */
67
+ public static repairStatement(data: {
68
+ storageTable: string;
69
+ onCluster: string;
70
+ }): string {
71
+ const grade: string = GoogleSecOpsSeverityRepair.gradeExpression();
72
+ const names: Array<OcsfSeverity> = Object.keys(
73
+ OcsfSeverityId,
74
+ ) as Array<OcsfSeverity>;
75
+ const severityId: string = `transform(${grade}, [${names
76
+ .map((name: OcsfSeverity): string => {
77
+ return GoogleSecOpsSeverityRepair.literal(name);
78
+ })
79
+ .join(", ")}], [${names
80
+ .map((name: OcsfSeverity): string => {
81
+ return String(OcsfSeverityId[name]);
82
+ })
83
+ .join(", ")}], ${OcsfSeverityId[OcsfSeverity.Unknown]})`;
84
+
85
+ return `ALTER TABLE ${data.storageTable}${data.onCluster} UPDATE severityName = ${grade}, severityId = ${severityId} WHERE ${GoogleSecOpsSeverityRepair.condition()}`;
86
+ }
87
+
88
+ /*
89
+ * The rows the repair rewrites: Google SecOps detection findings still
90
+ * stored as Unknown whose attributes now grade. The cheap column checks
91
+ * come first so ClickHouse evaluates the attribute expression only for
92
+ * those rows.
93
+ */
94
+ public static condition(): string {
95
+ return [
96
+ `vendorName = ${GoogleSecOpsSeverityRepair.literal(GOOGLE_SECOPS_VENDOR_NAME)}`,
97
+ `productName = ${GoogleSecOpsSeverityRepair.literal(GOOGLE_SECOPS_PRODUCT_NAME)}`,
98
+ `classUid = ${DETECTION_FINDING_CLASS_UID}`,
99
+ `severityId = ${OcsfSeverityId[OcsfSeverity.Unknown]}`,
100
+ `${GoogleSecOpsSeverityRepair.gradeExpression()} != ''`,
101
+ ].join(" AND ");
102
+ }
103
+
104
+ // normalizeOcsfSeverity, minus Unknown: text that names no grade is ''.
105
+ private static gradeText(expression: string): string {
106
+ const graded: Array<[string, OcsfSeverity]> = Object.entries(
107
+ OCSF_SEVERITY_ALIASES,
108
+ ).filter((entry: [string, OcsfSeverity]): boolean => {
109
+ return entry[1] !== OcsfSeverity.Unknown;
110
+ });
111
+
112
+ const from: string = graded
113
+ .map((entry: [string, OcsfSeverity]): string => {
114
+ return GoogleSecOpsSeverityRepair.literal(entry[0]);
115
+ })
116
+ .join(", ");
117
+ const to: string = graded
118
+ .map((entry: [string, OcsfSeverity]): string => {
119
+ return GoogleSecOpsSeverityRepair.literal(entry[1]);
120
+ })
121
+ .join(", ");
122
+
123
+ return `transform(upperUTF8(${GoogleSecOpsSeverityRepair.trimmed(expression)}), [${from}], [${to}], '')`;
124
+ }
125
+
126
+ /*
127
+ * The normalizer's gradeRiskScore: a finite score above zero grades into
128
+ * the first band whose minimum it reaches.
129
+ */
130
+ private static gradeRiskScore(expression: string): string {
131
+ const bands: string = GOOGLE_SECOPS_RISK_SCORE_BANDS.map(
132
+ (band: { minimum: number; severity: OcsfSeverity }): string => {
133
+ return `score >= ${band.minimum}, ${GoogleSecOpsSeverityRepair.literal(band.severity)}`;
134
+ },
135
+ ).join(", ");
136
+
137
+ return `arrayMap(score -> multiIf(NOT isFinite(score) OR score <= 0, '', ${bands}, ''), [ifNull(toFloat64OrNull(${GoogleSecOpsSeverityRepair.trimmed(expression)}), 0)])[1]`;
138
+ }
139
+
140
+ /*
141
+ * The first grade among the entries of detection[0].<list> whose key is
142
+ * `key`, in list order: the normalizer's readKeyedValues + firstGrade.
143
+ * A flattened entry is `detection.0.<list>.<index>.key` / `.value`
144
+ * (`detection.<list>...` when the webhook sent detection as an object).
145
+ */
146
+ private static firstKeyedGrade(
147
+ listPattern: string,
148
+ key: string,
149
+ grade: (expression: string) => string,
150
+ ): string {
151
+ const keyPattern: string = `^detection[.](0[.])?${listPattern}[.][0-9]+[.]key$`;
152
+ const keys: string = `arraySort(entryKey -> toUInt64OrZero(extract(entryKey, '[.]([0-9]+)[.]key$')), arrayFilter(entryKey -> match(entryKey, ${GoogleSecOpsSeverityRepair.literal(keyPattern)}), mapKeys(attributes)))`;
153
+ const value: string =
154
+ "attributes[concat(substring(entryKey, 1, length(entryKey) - 3), 'value')]";
155
+
156
+ return `arrayFirst(entryGrade -> entryGrade != '', arrayMap(entryKey -> if(lowerUTF8(${GoogleSecOpsSeverityRepair.trimmed("attributes[entryKey]")}) = ${GoogleSecOpsSeverityRepair.literal(key)}, ${grade(value)}, ''), ${keys}))`;
157
+ }
158
+
159
+ /*
160
+ * JavaScript's String.trim strips all surrounding whitespace; ClickHouse's
161
+ * trim() strips spaces only.
162
+ */
163
+ private static trimmed(expression: string): string {
164
+ return `replaceRegexpAll(${expression}, '^[[:space:]]+|[[:space:]]+$', '')`;
165
+ }
166
+
167
+ private static literal(value: string): string {
168
+ return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
169
+ }
170
+ }