@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
@@ -22,6 +22,8 @@ import {
22
22
  OnUpdate,
23
23
  } from "../Types/Database/Hooks";
24
24
  import ModelPermission from "../Types/Database/Permissions/Index";
25
+ import PublicPermission from "../Types/Database/Permissions/PublicPermission";
26
+ import DatabaseRequestType from "../Types/BaseDatabase/DatabaseRequestType";
25
27
  import OwnerOnlyColumnPermission from "../Types/Database/Permissions/OwnerOnlyColumnPermission";
26
28
  import { CheckReadPermissionType } from "../Types/Database/Permissions/ReadPermission";
27
29
  import Query from "../Types/Database/Query";
@@ -57,6 +59,7 @@ import PartialEntity from "../../Types/Database/PartialEntity";
57
59
  import { TableColumnMetadata } from "../../Types/Database/TableColumn";
58
60
  import TableColumnType from "../../Types/Database/TableColumnType";
59
61
  import { getUniqueColumnsBy } from "../../Types/Database/UniqueColumnBy";
62
+ import QueryOperator from "../../Types/BaseDatabase/QueryOperator";
60
63
  import OneUptimeDate from "../../Types/Date";
61
64
  import Dictionary from "../../Types/Dictionary";
62
65
  import BadDataException from "../../Types/Exception/BadDataException";
@@ -96,6 +99,7 @@ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
96
99
  import type AuditLogServiceType from "./AuditLogService";
97
100
  import EnableAuditLogOn from "../../Types/BaseDatabase/EnableAuditLogOn";
98
101
  import RelationValueUtil from "../Utils/Database/RelationValueUtil";
102
+ import RelationIdUtil from "../Utils/Database/RelationIdUtil";
99
103
 
100
104
  const RULE_CRITERIA_RELATION_OPERATORS: ReadonlySet<RuleCriteriaOperator> =
101
105
  new Set<RuleCriteriaOperator>([
@@ -295,6 +299,31 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
295
299
  return data;
296
300
  }
297
301
 
302
+ /*
303
+ * The permission layer's login check, run BEFORE the hooks instead of only
304
+ * after them.
305
+ *
306
+ * The hooks run first, and many of them key off props.userId: a missing one
307
+ * reads as "userId is required" (400), "User should be logged in" (422), or,
308
+ * for Project reads, an empty list with a 200. For an anonymous caller that
309
+ * is almost always a dashboard tab whose access-token cookie expired, and
310
+ * only a 401 makes the browser client refresh the session and replay the
311
+ * request. Everything this admits, the permission check would have admitted
312
+ * too (same condition, same exemptions for API keys and public models), so
313
+ * it only changes which refusal an anonymous caller gets, and it keeps hooks
314
+ * with side effects from running for them at all.
315
+ */
316
+ private checkIfUserIsLoggedInBeforeHooks(
317
+ props: DatabaseCommonInteractionProps,
318
+ type: DatabaseRequestType,
319
+ ): void {
320
+ if (props.isRoot || props.isMasterAdmin) {
321
+ return;
322
+ }
323
+
324
+ PublicPermission.checkIfUserIsLoggedIn(this.modelType, props, type);
325
+ }
326
+
298
327
  protected async onBeforeCreate(
299
328
  createBy: CreateBy<TBaseModel>,
300
329
  ): Promise<OnCreate<TBaseModel>> {
@@ -347,6 +376,49 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
347
376
  }
348
377
  }
349
378
 
379
+ /*
380
+ * Query operators (StartsWith, NotNull, Search, GreaterThan, Includes...)
381
+ * belong in the `query` of a read/update, never in the `data` of a write.
382
+ * They can reach create/update data because JSONFunctions.deserialize - run
383
+ * on every request body while building the model - turns
384
+ * `{"_type":"StartsWith","value":"a"}` into a real operator instance, and
385
+ * DatabaseBaseModel._fromJSON assigns it to an id/text column unchanged.
386
+ *
387
+ * An operator is never a valid stored value, and leaving one on a write
388
+ * payload also feeds it to the lookups built from that data - the uniqueness
389
+ * check here and the findBy/countBy calls in service hooks - where QueryUtil
390
+ * turns the intended exact comparison into a pattern match, quietly matching
391
+ * rows the caller never named. Refuse such a write up front instead. JSON
392
+ * columns are exempt: they legitimately hold arbitrary objects, and their
393
+ * values are not used to build a query.
394
+ */
395
+ private rejectQueryOperatorsInData(
396
+ data: TBaseModel | PartialEntity<TBaseModel>,
397
+ ): void {
398
+ for (const columnName of Object.keys(data)) {
399
+ const value: unknown = (data as Record<string, unknown>)[columnName];
400
+
401
+ if (!(value instanceof QueryOperator)) {
402
+ continue;
403
+ }
404
+
405
+ if (!this.model.isTableColumn(columnName)) {
406
+ continue;
407
+ }
408
+
409
+ const metadata: TableColumnMetadata =
410
+ this.model.getTableColumnMetadata(columnName);
411
+
412
+ if (metadata && metadata.type === TableColumnType.JSON) {
413
+ continue;
414
+ }
415
+
416
+ throw new BadDataException(
417
+ `Invalid value for ${columnName}. A query operator cannot be used as a value when creating or updating ${this.model.singularName}.`,
418
+ );
419
+ }
420
+ }
421
+
350
422
  /*
351
423
  * Rows written before the fix above hold their ciphertext inside that
352
424
  * HashedString envelope. Decrypting the envelope itself is not just wrong
@@ -984,6 +1056,107 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
984
1056
  RULE_CRITERIA_LEGACY_NEVER_MATCH_PATTERN;
985
1057
  }
986
1058
 
1059
+ /*
1060
+ * A tenant model declares its tenant TWICE: a scalar column (e.g.
1061
+ * `projectId`) AND a ManyToOne relation (`project`) whose @JoinColumn names
1062
+ * that same scalar. Both are separately writable through the public API, and
1063
+ * both land on the entity that reaches getRepository().save()/update().
1064
+ * TypeORM (metadata/ColumnMetadata.js getEntityValue) resolves the relation
1065
+ * object to the join-column value with PRECEDENCE over the scalar, so a
1066
+ * request carrying `project: { _id: <another project> }` is persisted under
1067
+ * THAT project even though create() has just stamped the scalar to
1068
+ * props.tenantId. That is a cross-tenant write of the whole row (reproduced
1069
+ * end to end: the generated INSERT binds `projectId` to the relation's id,
1070
+ * not the stamped scalar).
1071
+ *
1072
+ * The stamped scalar is the authoritative tenant for every non-root write,
1073
+ * and no `project` relation in the schema legitimately points at a project
1074
+ * other than the tenant (every one joins on `projectId`; there is no second,
1075
+ * foreign-project reference to preserve). So neutralize the relation
1076
+ * spelling: reject a tenant relation that points anywhere other than the
1077
+ * request tenant, then delete it so the scalar is the single source of truth
1078
+ * and no TypeORM precedence rule between the two can move the row. This is
1079
+ * the framework-level generalisation of the per-service fixes already
1080
+ * shipped in ApiKeyPermissionService and UserTelegramService.
1081
+ *
1082
+ * Root / master-admin / internal callers are left untouched — they have no
1083
+ * request tenant (props.tenantId is unset) and legitimately set the tenant
1084
+ * relation for another project during seeding, migrations and
1085
+ * invitation-acceptance. This mirrors the create() scalar stamp, which is
1086
+ * likewise gated on props.tenantId.
1087
+ */
1088
+ private enforceTenantRelationMatchesScalar(
1089
+ data: TBaseModel | PartialEntity<TBaseModel>,
1090
+ props: DatabaseCommonInteractionProps,
1091
+ ): void {
1092
+ if (props.isRoot || props.isMasterAdmin) {
1093
+ return;
1094
+ }
1095
+
1096
+ const tenantColumn: string | null = this.model.getTenantColumn();
1097
+
1098
+ if (!tenantColumn || !props.tenantId) {
1099
+ return;
1100
+ }
1101
+
1102
+ const tenantRelationProperty: string | null =
1103
+ this.getTenantRelationProperty(tenantColumn);
1104
+
1105
+ if (!tenantRelationProperty) {
1106
+ /*
1107
+ * e.g. Project itself, whose tenant column is its own `_id`, has no such
1108
+ * relation; global (non-tenant) models return null from getTenantColumn.
1109
+ */
1110
+ return;
1111
+ }
1112
+
1113
+ const suppliedRelation: unknown = (data as Record<string, unknown>)[
1114
+ tenantRelationProperty
1115
+ ];
1116
+
1117
+ if (suppliedRelation === undefined) {
1118
+ return;
1119
+ }
1120
+
1121
+ const relationTenantId: ObjectID | null = RelationIdUtil.read(
1122
+ data as Record<string, unknown>,
1123
+ [tenantRelationProperty],
1124
+ );
1125
+
1126
+ if (
1127
+ relationTenantId &&
1128
+ relationTenantId.toString() !== props.tenantId.toString()
1129
+ ) {
1130
+ throw new BadDataException(
1131
+ `The ${tenantRelationProperty} relation does not belong to this project.`,
1132
+ );
1133
+ }
1134
+
1135
+ delete (data as Record<string, unknown>)[tenantRelationProperty];
1136
+ }
1137
+
1138
+ /*
1139
+ * Property name of the ManyToOne relation that shares the tenant scalar
1140
+ * column as its join column (`project` for the `projectId` tenant column),
1141
+ * or null when the model has no such relation.
1142
+ */
1143
+ private getTenantRelationProperty(tenantColumn: string): string | null {
1144
+ for (const columnName of this.model.getTableColumns().columns) {
1145
+ const metadata: TableColumnMetadata | undefined =
1146
+ this.model.getTableColumnMetadata(columnName);
1147
+
1148
+ if (
1149
+ metadata &&
1150
+ metadata.type === TableColumnType.Entity &&
1151
+ metadata.manyToOneRelationColumn === tenantColumn
1152
+ ) {
1153
+ return columnName;
1154
+ }
1155
+ }
1156
+
1157
+ return null;
1158
+ }
1159
+
987
1160
  private async sanitizeCreateOrUpdate(
988
1161
  data: TBaseModel | PartialEntity<TBaseModel>,
989
1162
  props: DatabaseCommonInteractionProps,
@@ -1368,6 +1541,34 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
1368
1541
 
1369
1542
  @CaptureSpan()
1370
1543
  public async create(createBy: CreateBy<TBaseModel>): Promise<TBaseModel> {
1544
+ this.checkIfUserIsLoggedInBeforeHooks(
1545
+ createBy.props,
1546
+ DatabaseRequestType.Create,
1547
+ );
1548
+
1549
+ /*
1550
+ * A non-root create must not pin the row's own primary key. save() treats
1551
+ * an entity carrying an existing id as an update of that row rather than an
1552
+ * insert, so a supplied `_id` turns a create into an in-place modification
1553
+ * of a record the caller never named. BaseAPI.createItem already strips it;
1554
+ * this guards every other non-root caller (custom routes, workflow
1555
+ * components) too. Root/internal seeding legitimately assigns ids and is
1556
+ * exempt. Only the top-level primary key is checked - nested relation
1557
+ * `_id`s reference existing related rows and are fine.
1558
+ */
1559
+ if (
1560
+ !createBy.props.isRoot &&
1561
+ !createBy.props.isMasterAdmin &&
1562
+ (createBy.data as TBaseModel)._id
1563
+ ) {
1564
+ throw new BadDataException(
1565
+ `An id cannot be supplied when creating ${this.model.singularName}.`,
1566
+ );
1567
+ }
1568
+
1569
+ // Query operators are for queries, not for write payloads. See the helper.
1570
+ this.rejectQueryOperatorsInData(createBy.data);
1571
+
1371
1572
  this.unwrapHashedStringsForUnhashedColumns(createBy.data);
1372
1573
 
1373
1574
  const onCreate: OnCreate<TBaseModel> = createBy.props.ignoreHooks
@@ -1389,6 +1590,15 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
1389
1590
  data.setColumnValue(tenantColumnName, _createdBy.props.tenantId);
1390
1591
  }
1391
1592
 
1593
+ /*
1594
+ * The tenant scalar has just been stamped to the request tenant, but the
1595
+ * matching tenant RELATION object (e.g. `project`) is still whatever the
1596
+ * caller sent, and TypeORM lets that relation override the scalar on the
1597
+ * INSERT. Force the relation to agree with — or be dropped in favour of —
1598
+ * the stamped scalar so a caller cannot write the row into another tenant.
1599
+ */
1600
+ this.enforceTenantRelationMatchesScalar(data, _createdBy.props);
1601
+
1392
1602
  data = this.generateDefaultValues(data);
1393
1603
 
1394
1604
  data = this.checkRequiredFields(data);
@@ -2291,6 +2501,11 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
2291
2501
  @CaptureSpan()
2292
2502
  public async hardDeleteBy(deleteBy: DeleteBy<TBaseModel>): Promise<number> {
2293
2503
  try {
2504
+ this.checkIfUserIsLoggedInBeforeHooks(
2505
+ deleteBy.props,
2506
+ DatabaseRequestType.Delete,
2507
+ );
2508
+
2294
2509
  const onDelete: OnDelete<TBaseModel> = deleteBy.props.ignoreHooks
2295
2510
  ? { deleteBy, carryForward: [] }
2296
2511
  : await this.onBeforeDelete(deleteBy);
@@ -2353,6 +2568,11 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
2353
2568
  try {
2354
2569
  this.setTelemetryContextFromProps(deleteBy.props);
2355
2570
 
2571
+ this.checkIfUserIsLoggedInBeforeHooks(
2572
+ deleteBy.props,
2573
+ DatabaseRequestType.Delete,
2574
+ );
2575
+
2356
2576
  if (this.doNotAllowDelete && !deleteBy.props.isRoot) {
2357
2577
  throw new BadDataException("Delete not allowed");
2358
2578
  }
@@ -2587,6 +2807,11 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
2587
2807
  try {
2588
2808
  this.setTelemetryContextFromProps(findBy.props);
2589
2809
 
2810
+ this.checkIfUserIsLoggedInBeforeHooks(
2811
+ findBy.props,
2812
+ DatabaseRequestType.Read,
2813
+ );
2814
+
2590
2815
  if (!findBy.sort || Object.keys(findBy.sort).length === 0) {
2591
2816
  findBy.sort = {
2592
2817
  createdAt: SortOrder.Descending,
@@ -2967,8 +3192,28 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
2967
3192
  try {
2968
3193
  this.setTelemetryContextFromProps(updateBy.props);
2969
3194
 
3195
+ this.checkIfUserIsLoggedInBeforeHooks(
3196
+ updateBy.props,
3197
+ DatabaseRequestType.Update,
3198
+ );
3199
+
2970
3200
  updateBy.data = this.sanitizeUpdateData(updateBy.data);
2971
3201
 
3202
+ // Query operators are for queries, not for write payloads. See the helper.
3203
+ this.rejectQueryOperatorsInData(updateBy.data);
3204
+
3205
+ /*
3206
+ * Defense in depth for the tenant confused-deputy on the update path.
3207
+ * Unlike create(), _updateBy() never re-stamps the tenant scalar, and a
3208
+ * tenant relation object would likewise override the scalar join column
3209
+ * on the UPDATE. Today the tenant columns carry `update: []` so the
3210
+ * column-permission check rejects them first, but that is incidental —
3211
+ * this keeps the row's tenant immutable even if a model ever grants
3212
+ * update on the tenant relation. Runs before the permission check so the
3213
+ * ACL stays a redundant second line rather than the only one.
3214
+ */
3215
+ this.enforceTenantRelationMatchesScalar(updateBy.data, updateBy.props);
3216
+
2972
3217
  this.unwrapHashedStringsForUnhashedColumns(updateBy.data);
2973
3218
 
2974
3219
  const onUpdate: OnUpdate<TBaseModel> = updateBy.props.ignoreHooks
@@ -5,6 +5,8 @@ import UpdateBy from "../Types/Database/UpdateBy";
5
5
  import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
6
6
  import BadDataException from "../../Types/Exception/BadDataException";
7
7
  import {
8
+ DETECTION_EVALUATION_INTERVAL_MAX_IN_MINUTES,
9
+ DETECTION_EVALUATION_INTERVAL_MIN_IN_MINUTES,
8
10
  DETECTION_MATCH_COUNT_THRESHOLD_MAX,
9
11
  DETECTION_MATCH_COUNT_THRESHOLD_MIN,
10
12
  } from "../../Types/SecurityEvent/DetectionFindingConstants";
@@ -52,10 +54,9 @@ export class Service extends DatabaseService<Model> {
52
54
  private validateEvaluationInterval(interval: number | undefined): void {
53
55
  this.validateIntegerInRange({
54
56
  value: interval,
55
- min: 1,
56
- max: 1440,
57
- message:
58
- "Evaluation interval must be a whole number of minutes between 1 and 1440.",
57
+ min: DETECTION_EVALUATION_INTERVAL_MIN_IN_MINUTES,
58
+ max: DETECTION_EVALUATION_INTERVAL_MAX_IN_MINUTES,
59
+ message: `Evaluation interval must be a whole number of minutes between ${DETECTION_EVALUATION_INTERVAL_MIN_IN_MINUTES} and ${DETECTION_EVALUATION_INTERVAL_MAX_IN_MINUTES}.`,
59
60
  });
60
61
  }
61
62
 
@@ -3,11 +3,26 @@ import EnterpriseLicense from "../../Models/DatabaseModels/EnterpriseLicense";
3
3
  import MarketingEventUtil from "../Utils/Marketing/MarketingEventUtil";
4
4
  import { MarketingEventType } from "../../Types/Marketing/MarketingEvent";
5
5
  import { OnCreate } from "../Types/Database/Hooks";
6
+ import CreateBy from "../Types/Database/CreateBy";
6
7
  import OneUptimeDate from "../../Types/Date";
7
8
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
8
9
  import ObjectID from "../../Types/ObjectID";
9
10
  import Semaphore, { SemaphoreMutex } from "../Infrastructure/Semaphore";
10
11
  import logger from "../Utils/Logger";
12
+ import crypto from "crypto";
13
+
14
+ /*
15
+ * Random bytes in a license key generated by the server: 256 bits, written as
16
+ * 64 hex characters (the column holds 100). Keys issued before server-side
17
+ * generation are browser-made UUIDs and keep working unchanged.
18
+ */
19
+ export const ENTERPRISE_LICENSE_KEY_RANDOM_BYTES: number = 32;
20
+
21
+ export const generateEnterpriseLicenseKey: () => string = (): string => {
22
+ return crypto
23
+ .randomBytes(ENTERPRISE_LICENSE_KEY_RANDOM_BYTES)
24
+ .toString("hex");
25
+ };
11
26
 
12
27
  export const ENTERPRISE_LICENSE_USAGE_AGGREGATION_LOCK_NAMESPACE: string =
13
28
  "EnterpriseLicenseService.usageAggregation";
@@ -66,6 +81,29 @@ export class Service extends DatabaseService<EnterpriseLicense> {
66
81
  }
67
82
  }
68
83
 
84
+ /*
85
+ * A license created with no key (the Admin Dashboard's "leave blank to
86
+ * auto-generate") gets one from the server's CSPRNG here, instead of from
87
+ * the browser. A key typed by the admin is kept, trimmed: installations
88
+ * trim the key they send, so stored whitespace would make it unmatchable.
89
+ */
90
+ @CaptureSpan()
91
+ protected override async onBeforeCreate(
92
+ createBy: CreateBy<EnterpriseLicense>,
93
+ ): Promise<OnCreate<EnterpriseLicense>> {
94
+ const providedKey: string =
95
+ typeof createBy.data.licenseKey === "string"
96
+ ? createBy.data.licenseKey.trim()
97
+ : "";
98
+
99
+ createBy.data.licenseKey = providedKey || generateEnterpriseLicenseKey();
100
+
101
+ return {
102
+ createBy,
103
+ carryForward: undefined,
104
+ };
105
+ }
106
+
69
107
  @CaptureSpan()
70
108
  protected override async onCreateSuccess(
71
109
  _onCreate: OnCreate<EnterpriseLicense>,
@@ -2,13 +2,45 @@ import DatabaseService from "./DatabaseService";
2
2
  import Model from "../../Models/DatabaseModels/GlobalConfig";
3
3
  import InMemoryTTLCache from "../Infrastructure/InMemoryTTLCache";
4
4
  import ObjectID from "../../Types/ObjectID";
5
- import { OnUpdate } from "../Types/Database/Hooks";
5
+ import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
6
6
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
7
+ import CreateBy from "../Types/Database/CreateBy";
7
8
  import UpdateBy from "../Types/Database/UpdateBy";
8
9
  import BadDataException from "../../Types/Exception/BadDataException";
10
+ import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
11
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
9
12
  import TelegramVerificationToken from "../Utils/TelegramVerificationToken";
10
13
  import GlobalCache from "../Infrastructure/GlobalCache";
11
14
 
15
+ /*
16
+ * The columns that hold this installation's license state and identity. They
17
+ * are written only by OneUptime itself - the license client (activation,
18
+ * refresh, the daily usage report), the first-boot stamp of the Enterprise
19
+ * Edition and the data migrations - and every one of those writes runs with
20
+ * isRoot. A master admin reaches GlobalConfig through the generic CRUD API
21
+ * too, and master admins bypass the (empty) column ACLs, so without this list
22
+ * one PUT could forge a license expiry, raise the seat limit, restart the
23
+ * unlicensed trial or swap the instance id an instance-bound license
24
+ * is checked against.
25
+ *
26
+ * enterpriseLicenseNotificationEmail and enterpriseLicenseExpiryReminderDays
27
+ * are deliberately NOT here: they are settings the oneuptime.com admin edits
28
+ * from the Admin Dashboard.
29
+ */
30
+ export const ROOT_ONLY_LICENSE_COLUMNS: ReadonlyArray<keyof Model> = [
31
+ "instanceId",
32
+ "enterpriseCompanyName",
33
+ "enterpriseLicenseKey",
34
+ "enterpriseLicenseExpiresAt",
35
+ "enterpriseLicenseToken",
36
+ "enterpriseLicenseIsEvaluation",
37
+ "enterpriseLicenseUserLimit",
38
+ "enterpriseLicenseCurrentUserCount",
39
+ "enterpriseLicenseUserCountUpdatedAt",
40
+ "enterpriseLicenseInstances",
41
+ "enterpriseEditionFirstSeenAt",
42
+ ];
43
+
12
44
  const TELEGRAM_WEBHOOK_SECRET_CACHE_NAMESPACE: string =
13
45
  "global-config-security";
14
46
  const TELEGRAM_WEBHOOK_SECRET_GENERATION_KEY: string =
@@ -203,10 +235,57 @@ export class Service extends DatabaseService<Model> {
203
235
  );
204
236
  }
205
237
 
238
+ /*
239
+ * Refuses any write to ROOT_ONLY_LICENSE_COLUMNS that does not come from
240
+ * OneUptime itself. An explicit null counts as a write: clearing the license
241
+ * token is as much a forgery as setting one.
242
+ */
243
+ public assertLicenseColumnsWrittenByRootOnly(
244
+ data: unknown,
245
+ props: DatabaseCommonInteractionProps,
246
+ ): void {
247
+ if (props.isRoot) {
248
+ return;
249
+ }
250
+
251
+ const writtenColumns: Array<string> = ROOT_ONLY_LICENSE_COLUMNS.filter(
252
+ (column: keyof Model): boolean => {
253
+ return (
254
+ (data as Record<string, unknown>)[column as string] !== undefined
255
+ );
256
+ },
257
+ ).map((column: keyof Model): string => {
258
+ return column as string;
259
+ });
260
+
261
+ if (writtenColumns.length === 0) {
262
+ return;
263
+ }
264
+
265
+ throw new NotAuthorizedException(
266
+ `${writtenColumns.join(", ")} can only be changed by OneUptime itself. ` +
267
+ "Use the license dialog in the Admin Dashboard to activate or refresh the Enterprise license.",
268
+ );
269
+ }
270
+
271
+ @CaptureSpan()
272
+ protected override async onBeforeCreate(
273
+ createBy: CreateBy<Model>,
274
+ ): Promise<OnCreate<Model>> {
275
+ this.assertLicenseColumnsWrittenByRootOnly(createBy.data, createBy.props);
276
+
277
+ return {
278
+ createBy,
279
+ carryForward: null,
280
+ };
281
+ }
282
+
206
283
  @CaptureSpan()
207
284
  protected override async onBeforeUpdate(
208
285
  updateBy: UpdateBy<Model>,
209
286
  ): Promise<OnUpdate<Model>> {
287
+ this.assertLicenseColumnsWrittenByRootOnly(updateBy.data, updateBy.props);
288
+
210
289
  if (updateBy.data.telegramWebhookSecretToken !== undefined) {
211
290
  const secret: unknown = updateBy.data.telegramWebhookSecretToken;
212
291
 
@@ -13,14 +13,66 @@ import MonitorService from "./MonitorService";
13
13
  import ProbeService from "./ProbeService";
14
14
  import { MonitorTypeHelper } from "../../Types/Monitor/MonitorType";
15
15
  import CronTab from "../Utils/CronTab";
16
- import logger, { LogAttributes } from "../Utils/Logger";
16
+ import logger, { EXTERNAL_FAULT, LogAttributes } from "../Utils/Logger";
17
17
  import { SubscriptionStatusUtil } from "../../Types/Billing/SubscriptionStatus";
18
+ import MonitoringIntervalValidator from "../Utils/Monitor/MonitoringIntervalValidator";
18
19
 
19
20
  export class Service extends DatabaseService<MonitorProbe> {
20
21
  public constructor() {
21
22
  super(MonitorProbe);
22
23
  }
23
24
 
25
+ /**
26
+ * The next time a monitor with this interval is due, or `fallback`.
27
+ *
28
+ * Exported on the class (and covered directly by tests) because both
29
+ * scheduling paths — the batch claim query and the single-monitor refresh
30
+ * after an edit — have to agree about what a stored interval means. They
31
+ * did not before: the claim query swallowed a parse failure silently and
32
+ * fell back to one minute, so a monitor asking for five minutes was probed
33
+ * four times more often than requested, indefinitely and invisibly.
34
+ *
35
+ * Order is load-bearing. cron-parser gets the RAW value first, so the
36
+ * thousands of rows that were always valid take a byte-identical path and
37
+ * anything the parser understands but our grammar does not ("@hourly") is
38
+ * still honoured. Only when that fails do we try to read the value as a
39
+ * human cadence ("5m", "Every 5 minutes"), which is what makes those rows
40
+ * schedule correctly on deploy — before the data migration has run, and
41
+ * for any row that later arrives through a hook-free write or a restore.
42
+ */
43
+ public static resolveNextPingAt(data: {
44
+ monitoringInterval: string | null | undefined;
45
+ fallback: Date;
46
+ onUnreadable?: (() => void) | undefined;
47
+ }): Date {
48
+ if (!data.monitoringInterval) {
49
+ return data.fallback;
50
+ }
51
+
52
+ try {
53
+ return CronTab.getNextExecutionTime(data.monitoringInterval);
54
+ } catch {
55
+ // Not a cron expression. Try to read it as a human cadence instead.
56
+ }
57
+
58
+ const normalizedCron: string | null =
59
+ MonitoringIntervalValidator.normalizeForRead(data.monitoringInterval);
60
+
61
+ if (normalizedCron) {
62
+ try {
63
+ return CronTab.getNextExecutionTime(normalizedCron);
64
+ } catch {
65
+ // Normalizer produced something cron-parser rejects. Report it.
66
+ }
67
+ }
68
+
69
+ if (data.onUnreadable) {
70
+ data.onUnreadable();
71
+ }
72
+
73
+ return data.fallback;
74
+ }
75
+
24
76
  public async pruneStaleLastMonitoringLogEntries(data: {
25
77
  monitorId: ObjectID;
26
78
  validMonitorStepIds: Array<string>;
@@ -103,20 +155,28 @@ export class Service extends DatabaseService<MonitorProbe> {
103
155
  continue;
104
156
  }
105
157
 
106
- let nextPing: Date = OneUptimeDate.addRemoveMinutes(
107
- OneUptimeDate.getCurrentDate(),
108
- 1,
109
- );
110
-
111
- try {
112
- nextPing = CronTab.getNextExecutionTime(
113
- monitorProbe?.monitor?.monitoringInterval as string,
114
- );
115
- } catch (err) {
116
- logger.error(err, {
117
- monitorId: data.monitorId?.toString(),
118
- } as LogAttributes);
119
- }
158
+ /*
159
+ * The falsy guard matters: a Manual monitor (and every other row with
160
+ * no interval) reaches here with undefined, and the old unguarded call
161
+ * handed that straight to cron-parser, which threw and logged an error
162
+ * for a perfectly ordinary row on every single interval edit.
163
+ */
164
+ const nextPing: Date = Service.resolveNextPingAt({
165
+ monitoringInterval: monitorProbe?.monitor?.monitoringInterval,
166
+ fallback: OneUptimeDate.addRemoveMinutes(
167
+ OneUptimeDate.getCurrentDate(),
168
+ 1,
169
+ ),
170
+ onUnreadable: () => {
171
+ logger.error(
172
+ `updateNextPingAtForMonitor: monitoringInterval "${monitorProbe?.monitor?.monitoringInterval}" cannot be read as a schedule; falling back to a 1-minute cadence.`,
173
+ {
174
+ ...EXTERNAL_FAULT,
175
+ monitorId: data.monitorId?.toString(),
176
+ } as LogAttributes,
177
+ );
178
+ },
179
+ });
120
180
 
121
181
  if (nextPing && monitorProbe.id) {
122
182
  await this.updateOneById({
@@ -223,6 +283,17 @@ export class Service extends DatabaseService<MonitorProbe> {
223
283
  const nextPingDates: Array<Date> = [];
224
284
  const caseFragments: Array<string> = [];
225
285
 
286
+ /*
287
+ * Rows whose interval neither cron-parser nor the normalizer could
288
+ * read. Collected and logged ONCE per batch below rather than per
289
+ * row: this loop runs for every claimed monitor, every minute, on
290
+ * every probe-ingest instance, so a per-row log line would flood.
291
+ */
292
+ const unreadableIntervals: Array<{
293
+ monitorProbeId: string;
294
+ monitoringInterval: string;
295
+ }> = [];
296
+
226
297
  for (let i: number = 0; i < selectedRows.length; i++) {
227
298
  const row: { _id: string; monitoringInterval: string | null } =
228
299
  selectedRows[i]!;
@@ -230,11 +301,16 @@ export class Service extends DatabaseService<MonitorProbe> {
230
301
 
231
302
  let nextPing: Date = defaultNextPing;
232
303
  if (row.monitoringInterval) {
233
- try {
234
- nextPing = CronTab.getNextExecutionTime(row.monitoringInterval);
235
- } catch {
236
- // fall back to default 1 minute
237
- }
304
+ nextPing = Service.resolveNextPingAt({
305
+ monitoringInterval: row.monitoringInterval,
306
+ fallback: defaultNextPing,
307
+ onUnreadable: () => {
308
+ unreadableIntervals.push({
309
+ monitorProbeId: row._id,
310
+ monitoringInterval: row.monitoringInterval as string,
311
+ });
312
+ },
313
+ });
238
314
  }
239
315
 
240
316
  nextPingDates.push(nextPing);
@@ -243,6 +319,26 @@ export class Service extends DatabaseService<MonitorProbe> {
243
319
  );
244
320
  }
245
321
 
322
+ /*
323
+ * One aggregated line per batch, at error level with EXTERNAL_FAULT.
324
+ *
325
+ * Not debug: LOG_LEVEL=ERROR is what ships, so a debug or warn line
326
+ * here is deleted from stdout on exactly the installs where an
327
+ * operator would go looking. This condition used to be swallowed by
328
+ * a bare `catch {}`, which is why a monitor storing "5m" was probed
329
+ * every minute instead of every five for as long as the row existed,
330
+ * with nothing anywhere to grep for. EXTERNAL_FAULT marks it as
331
+ * tenant data rather than our own failure, so it does not page us.
332
+ */
333
+ if (unreadableIntervals.length > 0) {
334
+ logger.error(
335
+ `claimMonitorProbesForProbing: ${unreadableIntervals.length} monitor(s) have a monitoringInterval that cannot be read as a schedule and are falling back to a 1-minute cadence. Fix the stored value - "*/5 * * * *" means every 5 minutes. Offenders: ${JSON.stringify(
336
+ unreadableIntervals.slice(0, 20),
337
+ )}`,
338
+ EXTERNAL_FAULT,
339
+ );
340
+ }
341
+
246
342
  const updateQuery: string = `
247
343
  UPDATE "MonitorProbe"
248
344
  SET "lastPingAt" = $1,