@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
@@ -3,6 +3,11 @@ import UserEmailAPI from "../../../Server/API/UserEmailAPI";
3
3
  import UserIncomingCallNumberAPI from "../../../Server/API/UserIncomingCallNumberAPI";
4
4
  import UserSmsAPI from "../../../Server/API/UserSmsAPI";
5
5
  import UserWhatsAppAPI from "../../../Server/API/UserWhatsAppAPI";
6
+ import UserMiddleware from "../../../Server/Middleware/UserAuthorization";
7
+ import VerificationCodeRateLimit, {
8
+ VerificationCodeRateLimitBucket,
9
+ VerificationCodeRateLimitOutcome,
10
+ } from "../../../Server/Middleware/VerificationCodeRateLimit";
6
11
  import UserCallService from "../../../Server/Services/UserCallService";
7
12
  import UserEmailService from "../../../Server/Services/UserEmailService";
8
13
  import UserIncomingCallNumberService from "../../../Server/Services/UserIncomingCallNumberService";
@@ -22,6 +27,9 @@ import {
22
27
  import Response from "../../../Server/Utils/Response";
23
28
  import { mockRouter } from "./Helpers";
24
29
  import BadDataException from "../../../Types/Exception/BadDataException";
30
+ import Exception from "../../../Types/Exception/Exception";
31
+ import ExceptionCode from "../../../Types/Exception/ExceptionCode";
32
+ import NotAuthenticatedException from "../../../Types/Exception/NotAuthenticatedException";
25
33
  import JSONWebTokenData from "../../../Types/JsonWebTokenData";
26
34
  import ObjectID from "../../../Types/ObjectID";
27
35
  import { beforeEach, describe, expect, it } from "@jest/globals";
@@ -517,27 +525,122 @@ describe.each(CHANNELS)("$name verification routes", (channel: Channel) => {
517
525
  * is asserted directly.
518
526
  */
519
527
  describe("rate limiting", () => {
528
+ /*
529
+ * The limiter each route was built with, by bucket, captured while the API
530
+ * class registers its routes. getMiddleware returns a fresh closure per
531
+ * call, so this is the only way to name "the limiter" by identity rather
532
+ * than by position.
533
+ */
534
+ let limiters: Map<VerificationCodeRateLimitBucket, unknown>;
535
+
536
+ beforeEach(() => {
537
+ limiters = new Map<VerificationCodeRateLimitBucket, unknown>();
538
+
539
+ const realGetMiddleware: typeof VerificationCodeRateLimit.getMiddleware =
540
+ VerificationCodeRateLimit.getMiddleware.bind(VerificationCodeRateLimit);
541
+
542
+ const capture: jest.SpyInstance = jest
543
+ .spyOn(VerificationCodeRateLimit, "getMiddleware")
544
+ .mockImplementation(((bucket: VerificationCodeRateLimitBucket) => {
545
+ const limiter: ReturnType<
546
+ typeof VerificationCodeRateLimit.getMiddleware
547
+ > = realGetMiddleware(bucket);
548
+ limiters.set(bucket, limiter);
549
+ return limiter;
550
+ }) as never);
551
+
552
+ mockRouter.routes.length = 0;
553
+ channel.build();
554
+
555
+ capture.mockRestore();
556
+ });
557
+
520
558
  it("registers a limiter in front of the verify handler", () => {
521
559
  expect(
522
- mockRouter.match("post", channel.verifyPath).middlewares.length,
523
- ).toBeGreaterThanOrEqual(2);
560
+ mockRouter.match("post", channel.verifyPath).middlewares,
561
+ ).toContain(limiters.get(VerificationCodeRateLimitBucket.Verify));
524
562
  });
525
563
 
526
564
  it("registers a limiter in front of the resend handler", () => {
527
565
  expect(
528
- mockRouter.match("post", channel.resendPath).middlewares.length,
529
- ).toBeGreaterThanOrEqual(2);
566
+ mockRouter.match("post", channel.resendPath).middlewares,
567
+ ).toContain(limiters.get(VerificationCodeRateLimitBucket.Resend));
530
568
  });
531
569
 
532
- it("runs the limiter after user authorization, so it can key on the user", () => {
533
- const middlewares: Array<unknown> = mockRouter.match(
534
- "post",
535
- channel.verifyPath,
536
- ).middlewares;
570
+ /*
571
+ * The limiter keys on the user, so it has to run after the session is
572
+ * resolved. It also has to run after the session is REQUIRED: an expired
573
+ * session arrives here as an anonymous request (the access-token cookie
574
+ * expires with the token), and if the limiter ran first that request
575
+ * would spend the item and IP budgets before being refused - and be
576
+ * refused with a 429 or a handler 400, neither of which makes the browser
577
+ * client refresh the session. requireUserAuthentication answers it with a
578
+ * 401 first, so the budget is only ever spent by a known caller.
579
+ */
580
+ it.each([
581
+ ["verify", VerificationCodeRateLimitBucket.Verify],
582
+ ["resend", VerificationCodeRateLimitBucket.Resend],
583
+ ])(
584
+ "runs the %s limiter after user authorization and the authentication guard",
585
+ (_label: string, bucket: VerificationCodeRateLimitBucket) => {
586
+ const path: string =
587
+ bucket === VerificationCodeRateLimitBucket.Verify
588
+ ? channel.verifyPath
589
+ : channel.resendPath;
590
+
591
+ const middlewares: Array<unknown> = mockRouter.match(
592
+ "post",
593
+ path,
594
+ ).middlewares;
595
+
596
+ expect(limiters.get(bucket)).toBeDefined();
597
+ expect(middlewares).toHaveLength(3);
598
+ expect(middlewares[0]).toBe(UserMiddleware.getUserMiddleware);
599
+ expect(middlewares[1]).toBe(UserMiddleware.requireUserAuthentication);
600
+ expect(middlewares[2]).toBe(limiters.get(bucket));
601
+ },
602
+ );
603
+
604
+ it("never spends verification budget on a request with no session", async () => {
605
+ const consume: jest.SpyInstance = jest
606
+ .spyOn(VerificationCodeRateLimit, "consume")
607
+ .mockResolvedValue({
608
+ outcome: VerificationCodeRateLimitOutcome.Allowed,
609
+ } as never);
610
+
611
+ const anonymous: OneUptimeRequest = {
612
+ body: { itemId: ITEM_ID, code: CORRECT_CODE },
613
+ headers: {},
614
+ } as unknown as OneUptimeRequest;
615
+
616
+ const middlewares: ReturnType<typeof mockRouter.match>["middlewares"] =
617
+ mockRouter.match("post", channel.verifyPath).middlewares;
618
+
619
+ // Everything after getUserMiddleware, in order, stopping at a refusal.
620
+ for (let index: number = 1; index < middlewares.length; index++) {
621
+ const next: jest.Mock = jest.fn();
622
+
623
+ await middlewares[index]!(
624
+ anonymous,
625
+ mockResponse,
626
+ next as unknown as NextFunction,
627
+ );
628
+
629
+ if (next.mock.calls.length === 0) {
630
+ break;
631
+ }
632
+ }
633
+
634
+ expect(consume).not.toHaveBeenCalled();
635
+ expect(Response.sendErrorResponse).toHaveBeenCalledTimes(1);
636
+
637
+ const error: Exception = (
638
+ Response.sendErrorResponse as unknown as jest.Mock
639
+ ).mock.calls[0]![2] as Exception;
537
640
 
538
- /* UserMiddleware.getUserMiddleware is registered first. */
539
- expect(middlewares[0]).not.toBe(middlewares[1]);
540
- expect(typeof middlewares[1]).toBe("function");
641
+ expect(error).toBeInstanceOf(NotAuthenticatedException);
642
+ expect(error.code).toBe(ExceptionCode.NotAuthenticatedException);
643
+ expect(store.current?.verificationFailedAttempts).toBe(0);
541
644
  });
542
645
  });
543
646
  });
@@ -271,6 +271,8 @@ import OnCallCalendarFeedRateLimit, {
271
271
  import OnCallDutyPolicyScheduleCalendarFeedService from "../../../Server/Services/OnCallDutyPolicyScheduleCalendarFeedService";
272
272
  import ProjectOnCallCalendarFeedService from "../../../Server/Services/ProjectOnCallCalendarFeedService";
273
273
  import UserOnCallCalendarFeedService from "../../../Server/Services/UserOnCallCalendarFeedService";
274
+ import SelectPermission from "../../../Server/Types/Database/Permissions/SelectPermission";
275
+ import Select from "../../../Server/Types/Database/Select";
274
276
  import {
275
277
  ExpressRequest,
276
278
  ExpressResponse,
@@ -294,6 +296,9 @@ import OnCallCalendarFeedUrls, {
294
296
  PROTOCOL_WARNING,
295
297
  } from "../../../Server/Utils/OnCall/OnCallCalendarFeedUrls";
296
298
  import Response from "../../../Server/Utils/Response";
299
+ import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
300
+ import OnCallDutyPolicyScheduleCalendarFeed from "../../../Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed";
301
+ import ProjectOnCallCalendarFeed from "../../../Models/DatabaseModels/ProjectOnCallCalendarFeed";
297
302
  import Protocol from "../../../Types/API/Protocol";
298
303
  import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
299
304
  import OneUptimeDate from "../../../Types/Date";
@@ -318,6 +323,7 @@ import Permission, {
318
323
  UserPermission,
319
324
  UserTenantAccessPermission,
320
325
  } from "../../../Types/Permission";
326
+ import UserType from "../../../Types/UserType";
321
327
  import {
322
328
  DASHBOARD_URL,
323
329
  at,
@@ -366,9 +372,7 @@ interface HttpResult {
366
372
  interface CapturedFindOneBy {
367
373
  query: Record<string, unknown>;
368
374
  select?: Record<string, unknown> | undefined;
369
- props?:
370
- | { isRoot?: boolean | undefined; ignoreHooks?: boolean | undefined }
371
- | undefined;
375
+ props?: DatabaseCommonInteractionProps | undefined;
372
376
  }
373
377
 
374
378
  interface CapturedUpdate {
@@ -458,11 +462,13 @@ function routeFor(method: string, uri: string): RegisteredRoute {
458
462
  function buildMemberProps(data: {
459
463
  projectId: ObjectID | undefined;
460
464
  userId: ObjectID | undefined;
465
+ permission?: Permission | undefined;
461
466
  }): DatabaseCommonInteractionProps {
462
467
  const memberPermission: UserPermission = {
463
468
  _type: "UserPermission",
464
- permission: Permission.ProjectMember,
469
+ permission: data.permission ?? Permission.ProjectMember,
465
470
  labelIds: [],
471
+ isBlockPermission: false,
466
472
  };
467
473
 
468
474
  const permissionMap: Dictionary<UserTenantAccessPermission> = {};
@@ -3386,7 +3392,13 @@ describe("GET /on-call-calendar/feed/current", () => {
3386
3392
  expect(personalFindOneBy).not.toHaveBeenCalled();
3387
3393
  });
3388
3394
 
3389
- test("an anonymous caller (no user) is refused", async () => {
3395
+ /*
3396
+ * Tightened from "any 4xx" to the exact 401. A caller with no user and no
3397
+ * key is, in practice, a dashboard tab whose access-token cookie expired;
3398
+ * the browser client refreshes the session and replays only on a 401, so
3399
+ * any other status leaves the user looking at an error on their own feed.
3400
+ */
3401
+ test("an anonymous caller (no user) is refused with 401", async () => {
3390
3402
  propsSpy.mockResolvedValue(
3391
3403
  buildMemberProps({ projectId, userId: undefined }),
3392
3404
  );
@@ -3395,7 +3407,43 @@ describe("GET /on-call-calendar/feed/current", () => {
3395
3407
  `${API_PREFIX}${FEED_CURRENT_ROUTE}`,
3396
3408
  );
3397
3409
 
3398
- expect(result.status).toBeGreaterThanOrEqual(400);
3410
+ expect(result.status).toBe(ExceptionCode.NotAuthenticatedException);
3411
+ expect(result.status).toBe(401);
3412
+ expect(json(result)["message"]).toBe(
3413
+ CommonAPI.AUTHENTICATION_REQUIRED_MESSAGE,
3414
+ );
3415
+ expect(personalFindOneBy).not.toHaveBeenCalled();
3416
+ });
3417
+
3418
+ test("an anonymous caller with no tenant header is the 401, not the missing-tenant 400", async () => {
3419
+ propsSpy.mockResolvedValue(
3420
+ buildMemberProps({ projectId: undefined, userId: undefined }),
3421
+ );
3422
+
3423
+ const result: HttpResult = await request(
3424
+ `${API_PREFIX}${FEED_CURRENT_ROUTE}`,
3425
+ );
3426
+
3427
+ expect(result.status).toBe(ExceptionCode.NotAuthenticatedException);
3428
+ expect(personalFindOneBy).not.toHaveBeenCalled();
3429
+ });
3430
+
3431
+ test("a project API key is authenticated but is nobody, so it gets 422 rather than a 401", async () => {
3432
+ /*
3433
+ * A personal feed belongs to a person. The key fails the member guard
3434
+ * (no userId) before requireUserId is reached, and the answer is the 422 -
3435
+ * a 401 would send an API client off to refresh a session it never had.
3436
+ */
3437
+ propsSpy.mockResolvedValue({
3438
+ ...buildMemberProps({ projectId, userId: undefined }),
3439
+ userType: UserType.API,
3440
+ });
3441
+
3442
+ const result: HttpResult = await request(
3443
+ `${API_PREFIX}${FEED_CURRENT_ROUTE}`,
3444
+ );
3445
+
3446
+ expect(result.status).toBe(ExceptionCode.NotAuthorizedException);
3399
3447
  expect(personalFindOneBy).not.toHaveBeenCalled();
3400
3448
  });
3401
3449
  });
@@ -3427,6 +3475,41 @@ describe("POST /on-call-calendar/feed/rotate", () => {
3427
3475
  expect(result.status).toBe(415);
3428
3476
  });
3429
3477
 
3478
+ test("an anonymous JSON POST is 401 and mints nothing", async () => {
3479
+ /*
3480
+ * The rotate button on a page left open past the access-token lifetime.
3481
+ * The 401 is what makes the dashboard refresh and replay the POST; the
3482
+ * guard runs before the lock, so nothing is minted for the refused call.
3483
+ */
3484
+ propsSpy.mockResolvedValue(
3485
+ buildMemberProps({ projectId, userId: undefined }),
3486
+ );
3487
+
3488
+ const result: HttpResult = await postJson(
3489
+ `${API_PREFIX}${FEED_ROTATE_ROUTE}`,
3490
+ );
3491
+
3492
+ expect(result.status).toBe(ExceptionCode.NotAuthenticatedException);
3493
+ expect(personalCreateForUser).not.toHaveBeenCalled();
3494
+ expect(personalRotate).not.toHaveBeenCalled();
3495
+ expect(semaphoreLock).not.toHaveBeenCalled();
3496
+ });
3497
+
3498
+ test("a project API key POST is 422 and mints nothing", async () => {
3499
+ propsSpy.mockResolvedValue({
3500
+ ...buildMemberProps({ projectId, userId: undefined }),
3501
+ userType: UserType.API,
3502
+ });
3503
+
3504
+ const result: HttpResult = await postJson(
3505
+ `${API_PREFIX}${FEED_ROTATE_ROUTE}`,
3506
+ );
3507
+
3508
+ expect(result.status).toBe(ExceptionCode.NotAuthorizedException);
3509
+ expect(personalCreateForUser).not.toHaveBeenCalled();
3510
+ expect(personalRotate).not.toHaveBeenCalled();
3511
+ });
3512
+
3430
3513
  test("first time: mints the row as root under the (project, user) lock, purges, and returns the plaintext once", async () => {
3431
3514
  const token: string = CalendarFeedToken.mint();
3432
3515
  let created: FeedRowFixture | null = null;
@@ -4232,6 +4315,237 @@ describe("project-feed session routes", () => {
4232
4315
  });
4233
4316
  });
4234
4317
 
4318
+ /*
4319
+ * Regression: these routes selected previousTokenExpiresAt as a caller even
4320
+ * though the column denied every reader. Returning fixture rows from a
4321
+ * mocked service hid the failure, including on an unpublished feed. Keep the
4322
+ * HTTP routes real and enforce the model's actual column permissions on the
4323
+ * exact select each route sends before the in-memory lookup runs.
4324
+ */
4325
+ describe.each([
4326
+ OnCallCalendarFeedKind.Schedule,
4327
+ OnCallCalendarFeedKind.Project,
4328
+ ])(
4329
+ "%s status routes with real select permissions",
4330
+ (kind: OnCallCalendarFeedKind) => {
4331
+ let scheduleId: ObjectID;
4332
+ let rows: Array<FeedRowFixture>;
4333
+ let token: string;
4334
+ let find: jest.SpyInstance;
4335
+ let findToken: jest.SpyInstance;
4336
+ let create: jest.SpyInstance;
4337
+ let update: jest.SpyInstance;
4338
+ let rotate: jest.SpyInstance;
4339
+
4340
+ function route(action: "current" | "publish" | "rotate"): string {
4341
+ const routes: Record<typeof action, string> =
4342
+ kind === OnCallCalendarFeedKind.Schedule
4343
+ ? {
4344
+ current: SCHEDULE_FEED_CURRENT_ROUTE,
4345
+ publish: SCHEDULE_FEED_PUBLISH_ROUTE,
4346
+ rotate: SCHEDULE_FEED_ROTATE_ROUTE,
4347
+ }
4348
+ : {
4349
+ current: PROJECT_FEED_CURRENT_ROUTE,
4350
+ publish: PROJECT_FEED_PUBLISH_ROUTE,
4351
+ rotate: PROJECT_FEED_ROTATE_ROUTE,
4352
+ };
4353
+
4354
+ return `${API_PREFIX}${routes[action].replace(":scheduleId", scheduleId.toString())}`;
4355
+ }
4356
+
4357
+ function addFeed(previousTokenExpiresAt?: Date): FeedRowFixture {
4358
+ const makeRow: typeof scheduleRow =
4359
+ kind === OnCallCalendarFeedKind.Schedule ? scheduleRow : projectRow;
4360
+ const row: FeedRowFixture = makeRow({
4361
+ projectId,
4362
+ onCallDutyPolicyScheduleId: scheduleId,
4363
+ tokenHash: CalendarFeedToken.hash(token),
4364
+ previousTokenExpiresAt,
4365
+ });
4366
+
4367
+ rows.push(row);
4368
+ return row;
4369
+ }
4370
+
4371
+ beforeEach(() => {
4372
+ scheduleId = ObjectID.generate();
4373
+ rows = [];
4374
+ token = CalendarFeedToken.mint();
4375
+
4376
+ const isSchedule: boolean = kind === OnCallCalendarFeedKind.Schedule;
4377
+ const modelType:
4378
+ | typeof OnCallDutyPolicyScheduleCalendarFeed
4379
+ | typeof ProjectOnCallCalendarFeed = isSchedule
4380
+ ? OnCallDutyPolicyScheduleCalendarFeed
4381
+ : ProjectOnCallCalendarFeed;
4382
+
4383
+ find = isSchedule ? scheduleFindOneBy : projectFindOneBy;
4384
+ findToken = isSchedule ? scheduleFindOneById : projectFindOneById;
4385
+ create = isSchedule ? scheduleCreate : projectCreate;
4386
+ update = isSchedule ? scheduleUpdateOneBy : projectUpdateOneBy;
4387
+ rotate = isSchedule ? scheduleRotate : projectRotate;
4388
+
4389
+ find.mockImplementation(async (args: CapturedFindOneBy) => {
4390
+ expect(args.props?.isRoot).not.toBe(true);
4391
+ SelectPermission.checkSelectPermission(
4392
+ modelType,
4393
+ args.select as Select<BaseModel>,
4394
+ args.props || {},
4395
+ );
4396
+
4397
+ return await lookupFrom(rows)(args);
4398
+ });
4399
+ findToken.mockImplementation(async (args: { id: ObjectID }) => {
4400
+ const row: FeedRowFixture | undefined = rows.find(
4401
+ (candidate: FeedRowFixture) => {
4402
+ return candidate.id.toString() === args.id.toString();
4403
+ },
4404
+ );
4405
+
4406
+ return row ? { id: row.id, token, tokenHash: row.tokenHash } : null;
4407
+ });
4408
+ });
4409
+
4410
+ test("a viewer can read an unpublished feed without a column permission error", async () => {
4411
+ propsSpy.mockResolvedValue(
4412
+ buildMemberProps({ projectId, userId, permission: Permission.Viewer }),
4413
+ );
4414
+
4415
+ const result: HttpResult = await request(route("current"));
4416
+
4417
+ expect(result.status).toBe(200);
4418
+ expect(json(result)).toEqual(buildAbsentFeedStatus(kind));
4419
+ expect(findToken).not.toHaveBeenCalled();
4420
+ });
4421
+
4422
+ test.each([undefined, at("2026-10-01T12:00:00Z")])(
4423
+ "a viewer can read the link and expiration %p without exposing token hashes",
4424
+ async (expiresAt: Date | undefined) => {
4425
+ propsSpy.mockResolvedValue(
4426
+ buildMemberProps({
4427
+ projectId,
4428
+ userId,
4429
+ permission: Permission.Viewer,
4430
+ }),
4431
+ );
4432
+ const row: FeedRowFixture = addFeed(expiresAt);
4433
+ row.previousTokenHash = CalendarFeedToken.hash(
4434
+ CalendarFeedToken.mint(),
4435
+ );
4436
+
4437
+ const result: HttpResult = await request(route("current"));
4438
+ const status: Record<string, unknown> = json(result);
4439
+
4440
+ expect(result.status).toBe(200);
4441
+ expect(status["exists"]).toBe(true);
4442
+ expect(status["needsRegeneration"]).toBe(false);
4443
+ expect(status["previousTokenExpiresAt"]).toBe(
4444
+ expiresAt?.toISOString() ?? null,
4445
+ );
4446
+ expect((status["urls"] as Record<string, string>)["https"]).toContain(
4447
+ token,
4448
+ );
4449
+ expect(result.body).not.toContain(row.tokenHash);
4450
+ expect(result.body).not.toContain(row.previousTokenHash);
4451
+ expect(status).not.toHaveProperty("token");
4452
+ expect(status).not.toHaveProperty("tokenHash");
4453
+ expect(status).not.toHaveProperty("previousTokenHash");
4454
+
4455
+ const read: CapturedFindOneBy = find.mock
4456
+ .calls[0]?.[0] as CapturedFindOneBy;
4457
+ expect(read.select?.["previousTokenExpiresAt"]).toBe(true);
4458
+ for (const secret of ["token", "tokenHash", "previousTokenHash"]) {
4459
+ expect(read.select?.[secret]).toBeUndefined();
4460
+ }
4461
+ expect(findToken.mock.invocationCallOrder[0]).toBeGreaterThan(
4462
+ find.mock.invocationCallOrder[0] as number,
4463
+ );
4464
+ },
4465
+ );
4466
+
4467
+ test("first publish passes both caller status reads and returns a null expiration", async () => {
4468
+ create.mockImplementation(async () => {
4469
+ return addFeed();
4470
+ });
4471
+
4472
+ const result: HttpResult = await postJson(route("publish"));
4473
+
4474
+ expect(result.status).toBe(200);
4475
+ expect(create).toHaveBeenCalledTimes(1);
4476
+ expect(find).toHaveBeenCalledTimes(2);
4477
+ expect(json(result)["previousTokenExpiresAt"]).toBeNull();
4478
+ expect(
4479
+ (json(result)["urls"] as Record<string, string>)["https"],
4480
+ ).toContain(token);
4481
+ });
4482
+
4483
+ test("rotation passes both caller status reads and returns the previous link's expiration", async () => {
4484
+ const row: FeedRowFixture = addFeed();
4485
+ const expiresAt: Date = at("2026-10-01T12:00:00Z");
4486
+ const newToken: string = CalendarFeedToken.mint();
4487
+
4488
+ rotate.mockImplementation(async (): Promise<CalendarFeedRotation> => {
4489
+ row.previousTokenHash = row.tokenHash;
4490
+ row.previousTokenExpiresAt = expiresAt;
4491
+ row.tokenHash = CalendarFeedToken.hash(newToken);
4492
+ row.tokenHint = newToken.slice(-4);
4493
+ row.rotatedAt = NOW;
4494
+
4495
+ return {
4496
+ token: newToken,
4497
+ tokenHash: row.tokenHash,
4498
+ tokenHint: row.tokenHint,
4499
+ rotatedAt: NOW,
4500
+ previousTokenHash: row.previousTokenHash,
4501
+ previousTokenExpiresAt: expiresAt,
4502
+ };
4503
+ });
4504
+
4505
+ const result: HttpResult = await postJson(route("rotate"));
4506
+
4507
+ expect(result.status).toBe(200);
4508
+ expect(find).toHaveBeenCalledTimes(2);
4509
+ expect(update).toHaveBeenCalledTimes(1);
4510
+ expect(rotate).toHaveBeenCalledTimes(1);
4511
+ expect(json(result)["previousTokenExpiresAt"]).toBe(
4512
+ expiresAt.toISOString(),
4513
+ );
4514
+ expect(
4515
+ (json(result)["urls"] as Record<string, string>)["https"],
4516
+ ).toContain(newToken);
4517
+ expect(findToken).not.toHaveBeenCalled();
4518
+ expect(result.body).not.toContain(token);
4519
+ });
4520
+
4521
+ test.each(["current", "publish", "rotate"] as const)(
4522
+ "%s refuses a member without shared-feed read permissions before secrets or writes",
4523
+ async (action: "current" | "publish" | "rotate") => {
4524
+ addFeed();
4525
+ propsSpy.mockResolvedValue(
4526
+ buildMemberProps({
4527
+ projectId,
4528
+ userId,
4529
+ permission: Permission.CurrentUser,
4530
+ }),
4531
+ );
4532
+
4533
+ const result: HttpResult =
4534
+ action === "current"
4535
+ ? await request(route(action))
4536
+ : await postJson(route(action));
4537
+
4538
+ expect(result.status).toBe(ExceptionCode.NotAuthorizedException);
4539
+ expect(findToken).not.toHaveBeenCalled();
4540
+ expect(create).not.toHaveBeenCalled();
4541
+ expect(update).not.toHaveBeenCalled();
4542
+ expect(rotate).not.toHaveBeenCalled();
4543
+ expect(result.body).not.toContain(token);
4544
+ },
4545
+ );
4546
+ },
4547
+ );
4548
+
4235
4549
  // -- Session route: /my-shifts --------------------------------------------------
4236
4550
 
4237
4551
  describe("GET /on-call-calendar/my-shifts", () => {
@@ -4303,12 +4617,65 @@ describe("GET /on-call-calendar/my-shifts", () => {
4303
4617
  expect(materializeSpy).not.toHaveBeenCalled();
4304
4618
  });
4305
4619
 
4306
- test("an anonymous caller is refused", async () => {
4620
+ /*
4621
+ * Was a 400 ("A logged-in user is required." as BadDataException). The
4622
+ * route's requireUserId now goes through CommonAPI.assertAuthenticatedUser,
4623
+ * which answers a caller with no credentials with 401 - the status the
4624
+ * dashboard and the mobile app both answer by refreshing the session.
4625
+ */
4626
+ test("an anonymous caller is refused with 401", async () => {
4307
4627
  propsSpy.mockResolvedValue({ tenantId: undefined, userId: undefined });
4308
4628
 
4309
4629
  const result: HttpResult = await request(`${API_PREFIX}${MY_SHIFTS_ROUTE}`);
4310
4630
 
4311
- expect(result.status).toBe(ExceptionCode.BadDataException);
4631
+ expect(result.status).toBe(ExceptionCode.NotAuthenticatedException);
4632
+ expect(result.status).toBe(401);
4633
+ expect(json(result)["message"]).toBe(
4634
+ CommonAPI.AUTHENTICATION_REQUIRED_MESSAGE,
4635
+ );
4636
+ expect(materializeSpy).not.toHaveBeenCalled();
4637
+ });
4638
+
4639
+ test("an anonymous caller with a tenant header is refused with 401 too", async () => {
4640
+ propsSpy.mockResolvedValue(
4641
+ buildMemberProps({ projectId, userId: undefined }),
4642
+ );
4643
+
4644
+ const result: HttpResult = await request(`${API_PREFIX}${MY_SHIFTS_ROUTE}`);
4645
+
4646
+ expect(result.status).toBe(ExceptionCode.NotAuthenticatedException);
4647
+ expect(materializeSpy).not.toHaveBeenCalled();
4648
+ });
4649
+
4650
+ /*
4651
+ * An API key is authenticated, so it is not a 401 - but "my shifts" needs a
4652
+ * person, so it is refused as not authorised (422) with the route's own
4653
+ * message. This used to be a BadDataException (400) with the same text.
4654
+ */
4655
+ test("a project API key without a tenant header is refused with 422 'A logged-in user is required.'", async () => {
4656
+ propsSpy.mockResolvedValue({
4657
+ tenantId: undefined,
4658
+ userId: undefined,
4659
+ userType: UserType.API,
4660
+ });
4661
+
4662
+ const result: HttpResult = await request(`${API_PREFIX}${MY_SHIFTS_ROUTE}`);
4663
+
4664
+ expect(result.status).toBe(ExceptionCode.NotAuthorizedException);
4665
+ expect(json(result)["message"]).toBe("A logged-in user is required.");
4666
+ expect(materializeSpy).not.toHaveBeenCalled();
4667
+ });
4668
+
4669
+ test("a project API key with a tenant header gets the same 422 - the user check runs first on this route", async () => {
4670
+ propsSpy.mockResolvedValue({
4671
+ ...buildMemberProps({ projectId, userId: undefined }),
4672
+ userType: UserType.API,
4673
+ });
4674
+
4675
+ const result: HttpResult = await request(`${API_PREFIX}${MY_SHIFTS_ROUTE}`);
4676
+
4677
+ expect(result.status).toBe(ExceptionCode.NotAuthorizedException);
4678
+ expect(json(result)["message"]).toBe("A logged-in user is required.");
4312
4679
  expect(materializeSpy).not.toHaveBeenCalled();
4313
4680
  });
4314
4681