@oneuptime/common 13.0.7 → 13.0.8

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 (463) hide show
  1. package/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.ts +1 -1
  2. package/Models/DatabaseModels/ProjectOnCallCalendarFeed.ts +1 -1
  3. package/Models/DatabaseModels/UserOnCallCalendarFeed.ts +1 -1
  4. package/Server/API/AIBillingAPI.ts +1 -0
  5. package/Server/API/AIInsightAPI.ts +1 -4
  6. package/Server/API/AIInvestigationAPI.ts +1 -4
  7. package/Server/API/AIReadinessAPI.ts +4 -5
  8. package/Server/API/AlertAPI.ts +1 -0
  9. package/Server/API/AutoRemediationAPI.ts +1 -4
  10. package/Server/API/BaseAPI.ts +13 -0
  11. package/Server/API/BaseAnalyticsAPI.ts +80 -9
  12. package/Server/API/BillingAPI.ts +2 -0
  13. package/Server/API/BillingInvoiceAPI.ts +1 -0
  14. package/Server/API/BillingPaymentMethodAPI.ts +2 -0
  15. package/Server/API/CodeFixRunAPI.ts +1 -3
  16. package/Server/API/CommonAPI.ts +68 -4
  17. package/Server/API/DashboardAPI.ts +12 -12
  18. package/Server/API/GlobalConfigAPI.ts +17 -0
  19. package/Server/API/IncidentAPI.ts +2 -0
  20. package/Server/API/IncidentEpisodeAPI.ts +1 -0
  21. package/Server/API/NotificationAPI.ts +1 -0
  22. package/Server/API/OnCallCalendarAPI.ts +4 -5
  23. package/Server/API/OnCallDutyPolicyAPI.ts +7 -0
  24. package/Server/API/OnCallReadinessAPI.ts +4 -1
  25. package/Server/API/OnCallScheduleTimelineAPI.ts +731 -0
  26. package/Server/API/ProjectAPI.ts +1 -0
  27. package/Server/API/ScheduledMaintenanceAPI.ts +1 -0
  28. package/Server/API/StatusPageAPI.ts +161 -32
  29. package/Server/API/TeamMemberAPI.ts +3 -0
  30. package/Server/API/UserCallAPI.ts +2 -0
  31. package/Server/API/UserEmailAPI.ts +2 -0
  32. package/Server/API/UserIncomingCallNumberAPI.ts +2 -0
  33. package/Server/API/UserMicrosoftTeamsAPI.ts +1 -0
  34. package/Server/API/UserSlackAPI.ts +1 -0
  35. package/Server/API/UserSmsAPI.ts +2 -0
  36. package/Server/API/UserTotpAuthAPI.ts +1 -0
  37. package/Server/API/UserWebAuthnAPI.ts +2 -0
  38. package/Server/API/UserWebhookAPI.ts +1 -0
  39. package/Server/API/UserWhatsAppAPI.ts +2 -0
  40. package/Server/Middleware/MasterAdminAuthorization.ts +13 -2
  41. package/Server/Middleware/UserAuthorization.ts +79 -5
  42. package/Server/Services/ApiKeyPermissionService.ts +101 -4
  43. package/Server/Services/DatabaseService.ts +245 -0
  44. package/Server/Services/DetectionRuleService.ts +5 -4
  45. package/Server/Services/OnCallDutyPolicyChildService.ts +261 -0
  46. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +2 -2
  47. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +2 -2
  48. package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +2 -2
  49. package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +2 -2
  50. package/Server/Services/PayAsYouGoBillingService.ts +23 -28
  51. package/Server/Services/ProjectService.ts +18 -0
  52. package/Server/Services/RumSessionPinService.ts +274 -22
  53. package/Server/Services/TeamPermissionService.ts +120 -26
  54. package/Server/Services/ThreatIntelFeedService.ts +6 -3
  55. package/Server/Types/Database/Permissions/BasePermission.ts +9 -7
  56. package/Server/Types/Database/Permissions/Index.ts +75 -11
  57. package/Server/Types/Database/Permissions/TablePermission.ts +24 -28
  58. package/Server/Utils/AI/AIChatPrivacyFilter.ts +8 -0
  59. package/Server/Utils/AI/AIRunPrivacyFilter.ts +8 -0
  60. package/Server/Utils/MasterAdminPageAccess.ts +61 -0
  61. package/Server/Utils/Monitor/MonitorAlert.ts +3 -1
  62. package/Server/Utils/Monitor/MonitorIncident.ts +3 -1
  63. package/Server/Utils/OnCall/OnCallCalendarFeedRenderer.ts +1 -1
  64. package/Server/Utils/Realtime.ts +163 -45
  65. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +11 -28
  66. package/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.ts +170 -0
  67. package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +1 -1
  68. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +6 -2
  69. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.ts +10 -9
  70. package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +1059 -0
  71. package/Tests/App/Dashboard/AffectedResourcesPickerEditForm.test.tsx +376 -0
  72. package/Tests/App/Dashboard/AffectedResourcesPickerHiddenTypes.test.tsx +757 -0
  73. package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +307 -0
  74. package/Tests/App/Dashboard/ArgumentsFormGroupByUnlistedAttributes.test.tsx +131 -0
  75. package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +1 -1
  76. package/Tests/App/Dashboard/DashboardMonitorLabelVariable.test.tsx +9 -1
  77. package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +24 -0
  78. package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +162 -8
  79. package/Tests/App/Dashboard/EntityFilterDropdownArchivedSlos.test.tsx +105 -6
  80. package/Tests/App/Dashboard/EntityFilterDropdownUnlistedSelection.test.tsx +434 -0
  81. package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +276 -1
  82. package/Tests/App/Dashboard/OnCallCalendarFeedSideMenus.test.tsx +9 -1
  83. package/Tests/App/Dashboard/PayAsYouGoConsentGate.test.tsx +58 -42
  84. package/Tests/App/Dashboard/PayAsYouGoNotices.test.tsx +42 -5
  85. package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +34 -23
  86. package/Tests/App/Dashboard/ScheduleTimeline.test.tsx +1580 -0
  87. package/Tests/App/Dashboard/ScheduleTimelineAPI.test.ts +280 -0
  88. package/Tests/App/Dashboard/ScheduleTimelineModel.test.ts +673 -0
  89. package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +95 -68
  90. package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +86 -3
  91. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +28 -3
  92. package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +761 -0
  93. package/Tests/App/Dashboard/SecurityEventsGuideContent.test.ts +1313 -0
  94. package/Tests/App/Dashboard/SecurityEventsHowItWorksCard.test.tsx +536 -0
  95. package/Tests/App/Dashboard/SecurityEventsNoResults.test.tsx +222 -0
  96. package/Tests/App/Dashboard/SecurityEventsThreatIntelPage.test.tsx +199 -0
  97. package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +321 -0
  98. package/Tests/App/Dashboard/SloOverviewHero.test.tsx +171 -36
  99. package/Tests/App/Dashboard/SloViewSideMenu.test.tsx +215 -0
  100. package/Tests/App/Dashboard/SloViewSideMenuCounts.test.tsx +40 -3
  101. package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +12 -4
  102. package/Tests/App/PublicDashboard/PublicDashboardWidgetListAuth.test.tsx +623 -0
  103. package/Tests/Models/OnCallCalendarFeedModels.test.ts +23 -1
  104. package/Tests/Server/API/AIChatRouteAuthorization.test.ts +138 -5
  105. package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +187 -0
  106. package/Tests/Server/API/AIInvestigationAvailabilityAuthorization.test.ts +51 -3
  107. package/Tests/Server/API/AIInvestigationEvidenceAPI.test.ts +55 -2
  108. package/Tests/Server/API/BaseAnalyticsAPIAggregateCache.test.ts +729 -0
  109. package/Tests/Server/API/BillingPayAsYouGoStatus.test.ts +93 -7
  110. package/Tests/Server/API/BillingPaymentMethodAPI.test.ts +36 -3
  111. package/Tests/Server/API/CommonAPIAuthGuard.test.ts +1003 -24
  112. package/Tests/Server/API/DashboardPublicRateLimit.test.ts +6 -3
  113. package/Tests/Server/API/ExpiredSessionAIRoutes.test.ts +708 -0
  114. package/Tests/Server/API/ExpiredSessionCustomRoutes.test.ts +928 -0
  115. package/Tests/Server/API/ExpiredSessionMonitorTemplate.test.ts +319 -0
  116. package/Tests/Server/API/ExpiredSessionOnCallDutyPolicy.test.ts +336 -0
  117. package/Tests/Server/API/ExpiredSessionRouteGuards.test.ts +820 -0
  118. package/Tests/Server/API/GlobalConfigLicense.test.ts +140 -0
  119. package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +115 -12
  120. package/Tests/Server/API/OnCallCalendarAPI.test.ts +375 -8
  121. package/Tests/Server/API/OnCallReadinessAPI.test.ts +175 -17
  122. package/Tests/Server/API/OnCallScheduleTimelineAPI.test.ts +1513 -0
  123. package/Tests/Server/API/OnCallSetupReminderAPI.test.ts +119 -7
  124. package/Tests/Server/API/ProjectScopedCustomRouteAuth.test.ts +111 -4
  125. package/Tests/Server/API/PublicRouteInvalidAccessToken.test.ts +615 -0
  126. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +89 -2
  127. package/Tests/Server/API/SessionReplayAPI.test.ts +121 -0
  128. package/Tests/Server/API/StatusPageMasterPasswordRateLimit.test.ts +4 -2
  129. package/Tests/Server/API/StatusPagePostmortemVisibility.test.ts +441 -0
  130. package/Tests/Server/API/StatusPageTestEmailReportAuth.test.ts +664 -0
  131. package/Tests/Server/API/TeamMemberRemoveUserFromProjectAPI.test.ts +7 -0
  132. package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +6 -0
  133. package/Tests/Server/API/UserNotificationSettingAPI.test.ts +65 -4
  134. package/Tests/Server/API/UserProjectsAPI.test.ts +63 -3
  135. package/Tests/Server/API/UserTotpAuthAPI.test.ts +48 -2
  136. package/Tests/Server/API/UserWebAuthnAuthenticationOptionsRoute.test.ts +11 -2
  137. package/Tests/Server/API/UserWebAuthnBackupCodeMinting.test.ts +46 -3
  138. package/Tests/Server/API/UserWebAuthnPasskeyAPI.test.ts +18 -2
  139. package/Tests/Server/API/ZZVerifyChatsAuth.test.ts +24 -7
  140. package/Tests/Server/Middleware/ExpiredSessionUserMiddleware.test.ts +563 -0
  141. package/Tests/Server/Middleware/MasterAdminAuthorization.test.ts +299 -19
  142. package/Tests/Server/Middleware/PublicRouteUserMiddleware.test.ts +453 -0
  143. package/Tests/Server/Services/AIChatPrivacyPin.test.ts +24 -0
  144. package/Tests/Server/Services/ApiKeyPermissionSecurity.test.ts +2 -0
  145. package/Tests/Server/Services/ApiKeyPermissionService.test.ts +3 -3
  146. package/Tests/Server/Services/DatabaseServiceCreateSuppliedId.test.ts +147 -0
  147. package/Tests/Server/Services/DatabaseServiceLoginBeforeHooks.test.ts +1078 -0
  148. package/Tests/Server/Services/DatabaseServiceTenantRelationGuard.test.ts +259 -0
  149. package/Tests/Server/Services/DatabaseServiceWriteOperatorValues.test.ts +147 -0
  150. package/Tests/Server/Services/MonitorPayAsYouGoBilling.test.ts +115 -1
  151. package/Tests/Server/Services/OnCallChildCreateAuthorizationPostgres.test.ts +711 -0
  152. package/Tests/Server/Services/OnCallDutyPolicyChildService.test.ts +733 -0
  153. package/Tests/Server/Services/PayAsYouGoBillingService.test.ts +190 -140
  154. package/Tests/Server/Services/PayAsYouGoStripeRateLimitBudget.test.ts +4 -9
  155. package/Tests/Server/Services/PermissionBlockDeletion.test.ts +780 -0
  156. package/Tests/Server/Services/PermissionBlockDeletionPostgres.test.ts +628 -0
  157. package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +77 -1
  158. package/Tests/Server/Services/RumSessionPinCreatePermission.test.ts +715 -0
  159. package/Tests/Server/Services/TeamMemberMultiTenantReadPostgres.test.ts +394 -0
  160. package/Tests/Server/Services/TeamPrivilegeEscalation.test.ts +6 -0
  161. package/Tests/Server/Services/TelemetryPayAsYouGoBilling.test.ts +131 -0
  162. package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +13 -2
  163. package/Tests/Server/Types/Database/Permissions/ModelPermissionAnonymousRefusal.test.ts +518 -0
  164. package/Tests/Server/Types/Database/Permissions/MultiTenantPermissions.test.ts +350 -0
  165. package/Tests/Server/Types/Database/Permissions/OnCallCalendarFeedPermissions.test.ts +282 -25
  166. package/Tests/Server/Types/Database/Permissions/TableLevelBlockPermission.test.ts +459 -0
  167. package/Tests/Server/Utils/AI/AIRunPrivacyFilter.test.ts +101 -9
  168. package/Tests/Server/Utils/AI/ChatAgentHelpers.test.ts +88 -4
  169. package/Tests/Server/Utils/AI/Toolbox/ExceptionTools.test.ts +459 -0
  170. package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +794 -0
  171. package/Tests/Server/Utils/AI/Toolbox/RecentChangesTools.test.ts +574 -0
  172. package/Tests/Server/Utils/AI/Toolbox/SecurityEventTools.test.ts +596 -0
  173. package/Tests/Server/Utils/CaptchaRequestAndLogging.test.ts +395 -0
  174. package/Tests/Server/Utils/MasterAdminPageAccess.test.ts +251 -0
  175. package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +616 -0
  176. package/Tests/Server/Utils/Realtime.test.ts +502 -0
  177. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorSeverity.test.ts +216 -0
  178. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +142 -0
  179. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.test.ts +140 -0
  180. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepairClickhouseIntegration.test.ts +542 -0
  181. package/Tests/Server/Utils/Telemetry/ChangeEventRow.test.ts +743 -0
  182. package/Tests/Server/Utils/Telemetry/RuntimeMetrics.test.ts +465 -0
  183. package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/Alert.test.ts +202 -0
  184. package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.test.ts +194 -0
  185. package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/ScheduledMaintenance.test.ts +231 -0
  186. package/Tests/Server/Utils/Workspace/Slack/Messages/Alert.test.ts +194 -0
  187. package/Tests/Server/Utils/Workspace/Slack/Messages/AlertEpisode.test.ts +194 -0
  188. package/Tests/Server/Utils/Workspace/Slack/Messages/Incident.test.ts +194 -0
  189. package/Tests/Server/Utils/Workspace/Slack/Messages/IncidentEpisode.test.ts +194 -0
  190. package/Tests/Server/Utils/Workspace/Slack/Messages/ScheduledMaintenance.test.ts +247 -0
  191. package/Tests/Types/AI/AIInsightEvidence.test.ts +206 -0
  192. package/Tests/Types/BaseDatabase/DatabaseCommonInteractionPropsUtilAnonymous.test.ts +144 -0
  193. package/Tests/Types/Call/CallProvider.test.ts +528 -0
  194. package/Tests/Types/Kubernetes/KubernetesCostIngest.test.ts +236 -0
  195. package/Tests/Types/OnCallDutyPolicy/ScheduleTimeline.test.ts +736 -0
  196. package/Tests/Types/OnCallDutyPolicy/ScheduleTimelineLayout.test.ts +996 -0
  197. package/Tests/Types/SecurityEvent/SigmaRule.test.ts +142 -0
  198. package/Tests/Types/Workflow/Components/JSON.test.ts +182 -0
  199. package/Tests/UI/Components/BasicFormDropdownNormalization.test.tsx +116 -1
  200. package/Tests/UI/Components/Dropdown/DropdownAsyncOptions.test.tsx +81 -0
  201. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +89 -1
  202. package/Tests/UI/Components/EventAttachmentList.test.tsx +174 -0
  203. package/Tests/UI/Components/Forms/BasicFormBurnRateTemplateDefaults.test.tsx +395 -0
  204. package/Tests/UI/Components/Forms/BasicFormCollapsibleSections.test.tsx +286 -0
  205. package/Tests/UI/Components/Forms/FormSummary.test.tsx +128 -0
  206. package/Tests/UI/Components/ModelTable/BaseModelTableQueryChange.test.tsx +365 -0
  207. package/Tests/UI/Components/OpenAuthenticatedUrl.test.ts +358 -0
  208. package/Tests/UI/Components/SessionAwareImage.test.tsx +496 -0
  209. package/Tests/UI/Components/TelemetryHistogramZeroBuckets.test.tsx +190 -0
  210. package/Tests/UI/Components/TooltipInteractive.test.tsx +97 -0
  211. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardInstallGuidance.test.tsx +1 -1
  212. package/Tests/UI/Monitor/EvaluationLogListTimestamps.test.tsx +367 -0
  213. package/Tests/UI/Utils/API/BaseAPIRefreshSession.test.ts +1087 -0
  214. package/Tests/UI/Utils/API/DashboardHost.ts +12 -0
  215. package/Tests/UI/Utils/API/FakeAxiosServer.ts +183 -0
  216. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
  217. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  218. package/Tests/UI/Utils/Cookie.test.ts +440 -0
  219. package/Tests/UI/Utils/ModelAPIRequestClient.test.ts +278 -0
  220. package/Tests/UI/Utils/Navigation.test.ts +33 -0
  221. package/Tests/UI/Utils/PricingPlan.test.ts +295 -0
  222. package/Tests/UI/Utils/Realtime.test.ts +759 -0
  223. package/Tests/UI/Utils/Telemetry/Telemetry.test.ts +500 -0
  224. package/Tests/Utils/APIInstanceDispatch.test.ts +311 -0
  225. package/Tests/Utils/SecurityEvent/GoogleSecOpsAlertNormalizerSeverity.test.ts +565 -0
  226. package/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.ts +40 -0
  227. package/Types/Monitor/MonitorEvaluationSummary.ts +3 -0
  228. package/Types/OnCallDutyPolicy/ScheduleTimeline.ts +507 -0
  229. package/Types/OnCallDutyPolicy/ScheduleTimelineLayout.ts +589 -0
  230. package/Types/Realtime/EventName.ts +11 -0
  231. package/Types/SecurityEvent/DetectionFindingConstants.ts +14 -0
  232. package/Types/SecurityEvent/OcsfSeverity.ts +31 -26
  233. package/Types/SecurityEvent/SigmaRule.ts +51 -0
  234. package/Types/SecurityEvent/ThreatIntelConstants.ts +18 -0
  235. package/UI/Components/AttachmentList/EventAttachmentList.tsx +30 -2
  236. package/UI/Components/Dashboard/DashboardVariableControl.tsx +12 -2
  237. package/UI/Components/Dropdown/Dropdown.tsx +6 -1
  238. package/UI/Components/EditionLabel/EditionLabel.tsx +12 -0
  239. package/UI/Components/EventItem/EventItem.tsx +12 -1
  240. package/UI/Components/Forms/BasicForm.tsx +151 -126
  241. package/UI/Components/Forms/CollapsibleFormSection.tsx +63 -0
  242. package/UI/Components/Forms/Fields/FormField.tsx +10 -4
  243. package/UI/Components/Forms/FormSummary.tsx +7 -0
  244. package/UI/Components/Forms/Types/Field.ts +10 -0
  245. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +2 -1
  246. package/UI/Components/Markdown.tsx/SessionAwareImage.tsx +122 -0
  247. package/UI/Components/ModelTable/BaseModelTable.tsx +34 -5
  248. package/UI/Components/ModelTable/TableView.tsx +1 -1
  249. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +8 -1
  250. package/UI/Components/Tooltip/Tooltip.tsx +8 -1
  251. package/UI/Utils/API/API.ts +173 -12
  252. package/UI/Utils/API/RequestOptions.ts +11 -0
  253. package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +31 -7
  254. package/UI/Utils/ModelAPI/ModelAPI.ts +30 -9
  255. package/UI/Utils/Navigation.ts +9 -0
  256. package/UI/Utils/OpenAuthenticatedUrl.ts +154 -0
  257. package/UI/Utils/Realtime.ts +176 -30
  258. package/Utils/API.ts +14 -5
  259. package/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.ts +157 -7
  260. package/Utils/SecurityEvent/Sigma/SigmaRuleParser.ts +9 -17
  261. package/Utils/Slo/SloBurnRateTemplate.ts +2 -2
  262. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js +1 -1
  263. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js.map +1 -1
  264. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js +1 -1
  265. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js.map +1 -1
  266. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js +1 -1
  267. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js.map +1 -1
  268. package/build/dist/Server/API/AIBillingAPI.js +1 -1
  269. package/build/dist/Server/API/AIBillingAPI.js.map +1 -1
  270. package/build/dist/Server/API/AIInsightAPI.js +1 -4
  271. package/build/dist/Server/API/AIInsightAPI.js.map +1 -1
  272. package/build/dist/Server/API/AIInvestigationAPI.js +1 -4
  273. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  274. package/build/dist/Server/API/AIReadinessAPI.js +1 -3
  275. package/build/dist/Server/API/AIReadinessAPI.js.map +1 -1
  276. package/build/dist/Server/API/AlertAPI.js +1 -1
  277. package/build/dist/Server/API/AlertAPI.js.map +1 -1
  278. package/build/dist/Server/API/AutoRemediationAPI.js +1 -4
  279. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
  280. package/build/dist/Server/API/BaseAPI.js +12 -0
  281. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  282. package/build/dist/Server/API/BaseAnalyticsAPI.js +55 -10
  283. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  284. package/build/dist/Server/API/BillingAPI.js +2 -2
  285. package/build/dist/Server/API/BillingAPI.js.map +1 -1
  286. package/build/dist/Server/API/BillingInvoiceAPI.js +1 -1
  287. package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
  288. package/build/dist/Server/API/BillingPaymentMethodAPI.js +2 -2
  289. package/build/dist/Server/API/BillingPaymentMethodAPI.js.map +1 -1
  290. package/build/dist/Server/API/CodeFixRunAPI.js +1 -3
  291. package/build/dist/Server/API/CodeFixRunAPI.js.map +1 -1
  292. package/build/dist/Server/API/CommonAPI.js +50 -5
  293. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  294. package/build/dist/Server/API/DashboardAPI.js +12 -12
  295. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  296. package/build/dist/Server/API/GlobalConfigAPI.js +12 -0
  297. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  298. package/build/dist/Server/API/IncidentAPI.js +2 -2
  299. package/build/dist/Server/API/IncidentAPI.js.map +1 -1
  300. package/build/dist/Server/API/IncidentEpisodeAPI.js +1 -1
  301. package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
  302. package/build/dist/Server/API/NotificationAPI.js +1 -1
  303. package/build/dist/Server/API/NotificationAPI.js.map +1 -1
  304. package/build/dist/Server/API/OnCallCalendarAPI.js +1 -4
  305. package/build/dist/Server/API/OnCallCalendarAPI.js.map +1 -1
  306. package/build/dist/Server/API/OnCallDutyPolicyAPI.js +6 -0
  307. package/build/dist/Server/API/OnCallDutyPolicyAPI.js.map +1 -1
  308. package/build/dist/Server/API/OnCallReadinessAPI.js +4 -1
  309. package/build/dist/Server/API/OnCallReadinessAPI.js.map +1 -1
  310. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js +494 -0
  311. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js.map +1 -0
  312. package/build/dist/Server/API/ProjectAPI.js +1 -1
  313. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  314. package/build/dist/Server/API/ScheduledMaintenanceAPI.js +1 -1
  315. package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
  316. package/build/dist/Server/API/StatusPageAPI.js +125 -33
  317. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  318. package/build/dist/Server/API/TeamMemberAPI.js +3 -3
  319. package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
  320. package/build/dist/Server/API/UserCallAPI.js +2 -2
  321. package/build/dist/Server/API/UserCallAPI.js.map +1 -1
  322. package/build/dist/Server/API/UserEmailAPI.js +2 -2
  323. package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
  324. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +2 -2
  325. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
  326. package/build/dist/Server/API/UserMicrosoftTeamsAPI.js +1 -1
  327. package/build/dist/Server/API/UserMicrosoftTeamsAPI.js.map +1 -1
  328. package/build/dist/Server/API/UserSlackAPI.js +1 -1
  329. package/build/dist/Server/API/UserSlackAPI.js.map +1 -1
  330. package/build/dist/Server/API/UserSmsAPI.js +2 -2
  331. package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
  332. package/build/dist/Server/API/UserTotpAuthAPI.js +1 -1
  333. package/build/dist/Server/API/UserTotpAuthAPI.js.map +1 -1
  334. package/build/dist/Server/API/UserWebAuthnAPI.js +2 -2
  335. package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
  336. package/build/dist/Server/API/UserWebhookAPI.js +1 -1
  337. package/build/dist/Server/API/UserWebhookAPI.js.map +1 -1
  338. package/build/dist/Server/API/UserWhatsAppAPI.js +2 -2
  339. package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
  340. package/build/dist/Server/Middleware/MasterAdminAuthorization.js +11 -2
  341. package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
  342. package/build/dist/Server/Middleware/UserAuthorization.js +64 -4
  343. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  344. package/build/dist/Server/Services/ApiKeyPermissionService.js +80 -4
  345. package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
  346. package/build/dist/Server/Services/DatabaseService.js +171 -0
  347. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  348. package/build/dist/Server/Services/DetectionRuleService.js +4 -4
  349. package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
  350. package/build/dist/Server/Services/OnCallDutyPolicyChildService.js +170 -0
  351. package/build/dist/Server/Services/OnCallDutyPolicyChildService.js.map +1 -0
  352. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +2 -2
  353. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  354. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +2 -2
  355. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  356. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +2 -2
  357. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
  358. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +2 -2
  359. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
  360. package/build/dist/Server/Services/PayAsYouGoBillingService.js +20 -27
  361. package/build/dist/Server/Services/PayAsYouGoBillingService.js.map +1 -1
  362. package/build/dist/Server/Services/ProjectService.js +17 -0
  363. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  364. package/build/dist/Server/Services/RumSessionPinService.js +180 -16
  365. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  366. package/build/dist/Server/Services/TeamPermissionService.js +89 -27
  367. package/build/dist/Server/Services/TeamPermissionService.js.map +1 -1
  368. package/build/dist/Server/Services/ThreatIntelFeedService.js +5 -4
  369. package/build/dist/Server/Services/ThreatIntelFeedService.js.map +1 -1
  370. package/build/dist/Server/Types/Database/Permissions/BasePermission.js +9 -6
  371. package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
  372. package/build/dist/Server/Types/Database/Permissions/Index.js +60 -6
  373. package/build/dist/Server/Types/Database/Permissions/Index.js.map +1 -1
  374. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +14 -13
  375. package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
  376. package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js +7 -0
  377. package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js.map +1 -1
  378. package/build/dist/Server/Utils/AI/AIRunPrivacyFilter.js +7 -0
  379. package/build/dist/Server/Utils/AI/AIRunPrivacyFilter.js.map +1 -1
  380. package/build/dist/Server/Utils/MasterAdminPageAccess.js +39 -0
  381. package/build/dist/Server/Utils/MasterAdminPageAccess.js.map +1 -0
  382. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +3 -1
  383. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  384. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +3 -1
  385. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  386. package/build/dist/Server/Utils/Realtime.js +126 -37
  387. package/build/dist/Server/Utils/Realtime.js.map +1 -1
  388. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +7 -25
  389. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  390. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.js +127 -0
  391. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.js.map +1 -0
  392. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +1 -1
  393. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
  394. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +3 -2
  395. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js.map +1 -1
  396. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js +4 -8
  397. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js.map +1 -1
  398. package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js +31 -1
  399. package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js.map +1 -1
  400. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimeline.js +321 -0
  401. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimeline.js.map +1 -0
  402. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimelineLayout.js +372 -0
  403. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimelineLayout.js.map +1 -0
  404. package/build/dist/Types/Realtime/EventName.js +10 -0
  405. package/build/dist/Types/Realtime/EventName.js.map +1 -1
  406. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +11 -0
  407. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
  408. package/build/dist/Types/SecurityEvent/OcsfSeverity.js +30 -25
  409. package/build/dist/Types/SecurityEvent/OcsfSeverity.js.map +1 -1
  410. package/build/dist/Types/SecurityEvent/SigmaRule.js +47 -0
  411. package/build/dist/Types/SecurityEvent/SigmaRule.js.map +1 -1
  412. package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js +14 -0
  413. package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js.map +1 -1
  414. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js +9 -4
  415. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js.map +1 -1
  416. package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js +10 -2
  417. package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js.map +1 -1
  418. package/build/dist/UI/Components/Dropdown/Dropdown.js +5 -1
  419. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  420. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +11 -0
  421. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  422. package/build/dist/UI/Components/EventItem/EventItem.js +2 -2
  423. package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
  424. package/build/dist/UI/Components/Forms/BasicForm.js +70 -64
  425. package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
  426. package/build/dist/UI/Components/Forms/CollapsibleFormSection.js +27 -0
  427. package/build/dist/UI/Components/Forms/CollapsibleFormSection.js.map +1 -0
  428. package/build/dist/UI/Components/Forms/Fields/FormField.js +10 -7
  429. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  430. package/build/dist/UI/Components/Forms/FormSummary.js +7 -0
  431. package/build/dist/UI/Components/Forms/FormSummary.js.map +1 -1
  432. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +2 -1
  433. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  434. package/build/dist/UI/Components/Markdown.tsx/SessionAwareImage.js +84 -0
  435. package/build/dist/UI/Components/Markdown.tsx/SessionAwareImage.js.map +1 -0
  436. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +14 -1
  437. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  438. package/build/dist/UI/Components/ModelTable/TableView.js +1 -1
  439. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  440. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +8 -1
  441. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  442. package/build/dist/UI/Components/Tooltip/Tooltip.js +2 -1
  443. package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
  444. package/build/dist/UI/Utils/API/API.js +143 -19
  445. package/build/dist/UI/Utils/API/API.js.map +1 -1
  446. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +21 -7
  447. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
  448. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +26 -9
  449. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  450. package/build/dist/UI/Utils/Navigation.js +8 -0
  451. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  452. package/build/dist/UI/Utils/OpenAuthenticatedUrl.js +92 -0
  453. package/build/dist/UI/Utils/OpenAuthenticatedUrl.js.map +1 -0
  454. package/build/dist/UI/Utils/Realtime.js +120 -15
  455. package/build/dist/UI/Utils/Realtime.js.map +1 -1
  456. package/build/dist/Utils/API.js +13 -5
  457. package/build/dist/Utils/API.js.map +1 -1
  458. package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js +123 -6
  459. package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js.map +1 -1
  460. package/build/dist/Utils/SecurityEvent/Sigma/SigmaRuleParser.js +4 -18
  461. package/build/dist/Utils/SecurityEvent/Sigma/SigmaRuleParser.js.map +1 -1
  462. package/build/dist/Utils/Slo/SloBurnRateTemplate.js +2 -2
  463. package/package.json +1 -1
@@ -0,0 +1,507 @@
1
+ import OneUptimeDate from "../Date";
2
+ import BadDataException from "../Exception/BadDataException";
3
+ import { MaterializedShift } from "./MaterializedShift";
4
+
5
+ /*
6
+ * The wire contract of the schedule timeline: every on-call schedule a caller
7
+ * can read, side by side over one week or one month, with who is on call on
8
+ * each (the "who is on call across my team / my whole org" view).
9
+ *
10
+ * The shifts come from the same pipeline as the calendar feeds, /my-shifts
11
+ * and the shift reminders (OnCallShiftMaterializer through the schedule-level
12
+ * cache), so the timeline can never disagree with the person who actually
13
+ * gets paged. This file holds what both ends need: the route, the window
14
+ * rules, the JSON shapes, the server-side projection of a MaterializedShift
15
+ * and a defensive client-side parser.
16
+ */
17
+
18
+ export const SCHEDULE_TIMELINE_ROUTE: string = "/on-call-schedule-timeline";
19
+
20
+ /*
21
+ * How far back and ahead the timeline may look, in days. Past shifts are
22
+ * recomputed from the CURRENT configuration (the engine does not keep
23
+ * history), so looking back is useful for "who had last weekend" and not for
24
+ * audits; the on-call time logs are the record of what actually happened.
25
+ * Ahead is bounded because every distinct window is a fresh expansion of
26
+ * every layer of every schedule.
27
+ */
28
+ export const TIMELINE_MAX_PAST_DAYS: number = 180;
29
+ export const TIMELINE_MAX_FUTURE_DAYS: number = 365;
30
+
31
+ /*
32
+ * The widest single request. A month view in any timezone spans at most 31
33
+ * days plus a day of zone offset on each side; anything wider is a client
34
+ * asking for more than it can draw.
35
+ */
36
+ export const TIMELINE_MAX_SPAN_DAYS: number = 45;
37
+
38
+ // Span used when `to` is absent.
39
+ export const TIMELINE_DEFAULT_SPAN_DAYS: number = 7;
40
+
41
+ /*
42
+ * The most schedules one response carries. Past this the response says how
43
+ * many there were so the page can ask the reader to narrow by team.
44
+ */
45
+ export const TIMELINE_MAX_SCHEDULES: number = 250;
46
+
47
+ const MILLISECONDS_PER_DAY: number = 24 * 60 * 60 * 1000;
48
+
49
+ export interface ScheduleTimelineOverrideJson {
50
+ // The person whose shift this was before the override.
51
+ originalUserId: string;
52
+ originalUserName: string;
53
+ overrideStartsAt: string;
54
+ overrideEndsAt: string;
55
+ // Set when the override is scoped to one on-call policy; null when global.
56
+ onCallDutyPolicyId: string | null;
57
+ }
58
+
59
+ export interface ScheduleTimelineShiftJson {
60
+ shiftKey: string;
61
+ userId: string;
62
+ userName: string;
63
+ // ISO strings; `end` is exclusive.
64
+ start: string;
65
+ end: string;
66
+ layerId: string | null;
67
+ layerName: string | null;
68
+ override: ScheduleTimelineOverrideJson | null;
69
+ }
70
+
71
+ export interface ScheduleTimelineScheduleJson {
72
+ scheduleId: string;
73
+ scheduleName: string;
74
+ // The zone the schedule's rotations are authored in; null for legacy rows.
75
+ scheduleTimezone: string | null;
76
+ // Teams listed as owners of the schedule, for grouping and filtering.
77
+ ownerTeamIds: Array<string>;
78
+ // The caller is assigned to at least one of the schedule's layers.
79
+ isCurrentUserOnRoster: boolean;
80
+ // The rotation engine hit its iteration cap: shifts may be missing.
81
+ truncated: boolean;
82
+ shifts: Array<ScheduleTimelineShiftJson>;
83
+ }
84
+
85
+ export interface ScheduleTimelineTeamJson {
86
+ teamId: string;
87
+ teamName: string;
88
+ isCurrentUserMember: boolean;
89
+ }
90
+
91
+ export interface ScheduleTimelineResponse {
92
+ // The window actually served, after clamping. ISO strings.
93
+ from: string;
94
+ to: string;
95
+ generatedAt: string;
96
+ // Any schedule's expansion hit the iteration cap.
97
+ truncated: boolean;
98
+ // How many schedules matched before TIMELINE_MAX_SCHEDULES was applied.
99
+ totalScheduleCount: number;
100
+ schedulesTruncated: boolean;
101
+ schedules: Array<ScheduleTimelineScheduleJson>;
102
+ // Every team that owns at least one of the schedules above, by name.
103
+ teams: Array<ScheduleTimelineTeamJson>;
104
+ }
105
+
106
+ export interface TimelineWindow {
107
+ from: Date;
108
+ to: Date;
109
+ }
110
+
111
+ export default class ScheduleTimelineUtil {
112
+ /*
113
+ * The range a timeline request may address at `now`:
114
+ * [now - TIMELINE_MAX_PAST_DAYS, now + TIMELINE_MAX_FUTURE_DAYS]. The
115
+ * dashboard uses the same numbers to stop the reader navigating somewhere
116
+ * the server would refuse to draw.
117
+ */
118
+ public static getAddressableRange(now: Date): TimelineWindow {
119
+ return {
120
+ from: OneUptimeDate.addRemoveDays(now, -TIMELINE_MAX_PAST_DAYS),
121
+ to: OneUptimeDate.addRemoveDays(now, TIMELINE_MAX_FUTURE_DAYS),
122
+ };
123
+ }
124
+
125
+ /*
126
+ * Validate and clamp a requested window. Garbage is refused (400); a window
127
+ * that is merely too wide or too far away is pulled back in rather than
128
+ * refused, so a client that is a release ahead still gets an answer.
129
+ *
130
+ * - `from` is required; `to` defaults to from + TIMELINE_DEFAULT_SPAN_DAYS.
131
+ * - `to` must be after `from`.
132
+ * - the span is capped at TIMELINE_MAX_SPAN_DAYS by moving `to` in;
133
+ * - both edges are clamped into the addressable range. A window that lies
134
+ * wholly outside it collapses onto the nearest edge day, never to an
135
+ * empty or inverted window.
136
+ */
137
+ public static clampWindow(data: {
138
+ from: unknown;
139
+ to: unknown;
140
+ now: Date;
141
+ }): TimelineWindow {
142
+ const from: Date = ScheduleTimelineUtil.readDate(data.from, "from", true)!;
143
+
144
+ let to: Date =
145
+ ScheduleTimelineUtil.readDate(data.to, "to", false) ||
146
+ OneUptimeDate.addRemoveDays(from, TIMELINE_DEFAULT_SPAN_DAYS);
147
+
148
+ if (to.getTime() <= from.getTime()) {
149
+ throw new BadDataException("to must be after from.");
150
+ }
151
+
152
+ const spanCap: Date = OneUptimeDate.addRemoveDays(
153
+ from,
154
+ TIMELINE_MAX_SPAN_DAYS,
155
+ );
156
+
157
+ if (to.getTime() > spanCap.getTime()) {
158
+ to = spanCap;
159
+ }
160
+
161
+ const addressable: TimelineWindow =
162
+ ScheduleTimelineUtil.getAddressableRange(data.now);
163
+
164
+ let clampedFrom: Date = from;
165
+ let clampedTo: Date = to;
166
+
167
+ if (clampedFrom.getTime() < addressable.from.getTime()) {
168
+ clampedFrom = addressable.from;
169
+ }
170
+
171
+ if (clampedTo.getTime() > addressable.to.getTime()) {
172
+ clampedTo = addressable.to;
173
+ }
174
+
175
+ /*
176
+ * Entirely before the addressable range, or entirely after it: serve the
177
+ * one day at that edge. The page shades everything outside the served
178
+ * window, so the reader sees WHY there is nothing there.
179
+ */
180
+ if (clampedTo.getTime() <= clampedFrom.getTime()) {
181
+ if (to.getTime() <= addressable.from.getTime()) {
182
+ clampedFrom = addressable.from;
183
+ clampedTo = OneUptimeDate.addRemoveDays(addressable.from, 1);
184
+ } else {
185
+ clampedTo = addressable.to;
186
+ clampedFrom = OneUptimeDate.addRemoveDays(addressable.to, -1);
187
+ }
188
+ }
189
+
190
+ return { from: clampedFrom, to: clampedTo };
191
+ }
192
+
193
+ /*
194
+ * The window handed to the schedule-level cache: widened to whole UTC days,
195
+ * exactly like /my-shifts does, so a timeline and a feed that cover the
196
+ * same days share one expansion per schedule.
197
+ */
198
+ public static getCacheWindow(window: TimelineWindow): {
199
+ windowStart: Date;
200
+ windowEnd: Date;
201
+ } {
202
+ const windowStart: Date = new Date(
203
+ ScheduleTimelineUtil.startOfUtcDay(window.from),
204
+ );
205
+
206
+ const endDayStart: number = ScheduleTimelineUtil.startOfUtcDay(window.to);
207
+
208
+ const windowEnd: Date = new Date(
209
+ window.to.getTime() > endDayStart
210
+ ? endDayStart + MILLISECONDS_PER_DAY
211
+ : endDayStart,
212
+ );
213
+
214
+ return { windowStart, windowEnd };
215
+ }
216
+
217
+ /*
218
+ * Project one materialized shift onto the timeline's wire shape, or null
219
+ * when it does not belong on the timeline:
220
+ *
221
+ * - policy-variant shifts are dropped. They exist only for one
222
+ * escalation policy's view of a schedule attached to several, and they
223
+ * overlap the base shift for the same interval; a row can only show one
224
+ * person at a time, and the base resolution is the one the schedule's
225
+ * own roster (and its page) shows.
226
+ * - shifts that do not overlap the served window are dropped (the cache
227
+ * window is day-aligned and therefore a little wider).
228
+ */
229
+ public static toTimelineShift(
230
+ shift: MaterializedShift,
231
+ window: TimelineWindow,
232
+ ): ScheduleTimelineShiftJson | null {
233
+ if (shift.policyVariantOf) {
234
+ return null;
235
+ }
236
+
237
+ if (
238
+ shift.end.getTime() <= window.from.getTime() ||
239
+ shift.start.getTime() >= window.to.getTime()
240
+ ) {
241
+ return null;
242
+ }
243
+
244
+ return {
245
+ shiftKey: shift.shiftKey,
246
+ userId: shift.userId,
247
+ userName: shift.userName,
248
+ start: shift.start.toISOString(),
249
+ end: shift.end.toISOString(),
250
+ layerId: shift.layerId ?? null,
251
+ layerName: shift.layerName ?? null,
252
+ override: shift.override
253
+ ? {
254
+ originalUserId: shift.override.originalUserId,
255
+ originalUserName: shift.override.originalUserName,
256
+ overrideStartsAt: shift.override.overrideStartsAt.toISOString(),
257
+ overrideEndsAt: shift.override.overrideEndsAt.toISOString(),
258
+ onCallDutyPolicyId: shift.override.onCallDutyPolicyId ?? null,
259
+ }
260
+ : null,
261
+ };
262
+ }
263
+
264
+ /*
265
+ * Parse a response on the dashboard. DEFENSIVE by design, like the other
266
+ * on-call wire parsers: the dashboard is routinely a release ahead of or
267
+ * behind the API during a rolling upgrade, so a missing field reads as its
268
+ * empty value, a malformed shift is skipped (never thrown on), and only a
269
+ * body that is not an object at all is an error.
270
+ */
271
+ public static parseResponse(value: unknown): ScheduleTimelineResponse {
272
+ if (!ScheduleTimelineUtil.isObject(value)) {
273
+ throw new BadDataException("Invalid schedule timeline response.");
274
+ }
275
+
276
+ const schedules: Array<ScheduleTimelineScheduleJson> = [];
277
+
278
+ for (const item of ScheduleTimelineUtil.readArray(value["schedules"])) {
279
+ const schedule: ScheduleTimelineScheduleJson | null =
280
+ ScheduleTimelineUtil.parseSchedule(item);
281
+
282
+ if (schedule) {
283
+ schedules.push(schedule);
284
+ }
285
+ }
286
+
287
+ const teams: Array<ScheduleTimelineTeamJson> = [];
288
+
289
+ for (const item of ScheduleTimelineUtil.readArray(value["teams"])) {
290
+ if (!ScheduleTimelineUtil.isObject(item)) {
291
+ continue;
292
+ }
293
+
294
+ const teamId: string | null = ScheduleTimelineUtil.readString(
295
+ item["teamId"],
296
+ );
297
+
298
+ if (!teamId) {
299
+ continue;
300
+ }
301
+
302
+ teams.push({
303
+ teamId,
304
+ teamName:
305
+ ScheduleTimelineUtil.readString(item["teamName"]) || "Unnamed team",
306
+ isCurrentUserMember: item["isCurrentUserMember"] === true,
307
+ });
308
+ }
309
+
310
+ const totalScheduleCount: number =
311
+ typeof value["totalScheduleCount"] === "number" &&
312
+ Number.isFinite(value["totalScheduleCount"])
313
+ ? (value["totalScheduleCount"] as number)
314
+ : schedules.length;
315
+
316
+ return {
317
+ from: ScheduleTimelineUtil.readString(value["from"]) || "",
318
+ to: ScheduleTimelineUtil.readString(value["to"]) || "",
319
+ generatedAt: ScheduleTimelineUtil.readString(value["generatedAt"]) || "",
320
+ truncated: value["truncated"] === true,
321
+ totalScheduleCount,
322
+ schedulesTruncated: value["schedulesTruncated"] === true,
323
+ schedules,
324
+ teams,
325
+ };
326
+ }
327
+
328
+ // -- Internals ----------------------------------------------------------
329
+
330
+ private static parseSchedule(
331
+ value: unknown,
332
+ ): ScheduleTimelineScheduleJson | null {
333
+ if (!ScheduleTimelineUtil.isObject(value)) {
334
+ return null;
335
+ }
336
+
337
+ const scheduleId: string | null = ScheduleTimelineUtil.readString(
338
+ value["scheduleId"],
339
+ );
340
+
341
+ if (!scheduleId) {
342
+ return null;
343
+ }
344
+
345
+ const shifts: Array<ScheduleTimelineShiftJson> = [];
346
+
347
+ for (const item of ScheduleTimelineUtil.readArray(value["shifts"])) {
348
+ const shift: ScheduleTimelineShiftJson | null =
349
+ ScheduleTimelineUtil.parseShift(item);
350
+
351
+ if (shift) {
352
+ shifts.push(shift);
353
+ }
354
+ }
355
+
356
+ shifts.sort(
357
+ (a: ScheduleTimelineShiftJson, b: ScheduleTimelineShiftJson): number => {
358
+ return Date.parse(a.start) - Date.parse(b.start);
359
+ },
360
+ );
361
+
362
+ return {
363
+ scheduleId,
364
+ scheduleName:
365
+ ScheduleTimelineUtil.readString(value["scheduleName"]) ||
366
+ "Unnamed schedule",
367
+ scheduleTimezone: ScheduleTimelineUtil.readString(
368
+ value["scheduleTimezone"],
369
+ ),
370
+ ownerTeamIds: ScheduleTimelineUtil.readArray(value["ownerTeamIds"])
371
+ .map((id: unknown) => {
372
+ return ScheduleTimelineUtil.readString(id);
373
+ })
374
+ .filter((id: string | null): id is string => {
375
+ return Boolean(id);
376
+ }),
377
+ isCurrentUserOnRoster: value["isCurrentUserOnRoster"] === true,
378
+ truncated: value["truncated"] === true,
379
+ shifts,
380
+ };
381
+ }
382
+
383
+ private static parseShift(value: unknown): ScheduleTimelineShiftJson | null {
384
+ if (!ScheduleTimelineUtil.isObject(value)) {
385
+ return null;
386
+ }
387
+
388
+ const userId: string | null = ScheduleTimelineUtil.readString(
389
+ value["userId"],
390
+ );
391
+ const start: string | null = ScheduleTimelineUtil.readString(
392
+ value["start"],
393
+ );
394
+ const end: string | null = ScheduleTimelineUtil.readString(value["end"]);
395
+
396
+ if (!userId || !start || !end) {
397
+ return null;
398
+ }
399
+
400
+ const startMs: number = Date.parse(start);
401
+ const endMs: number = Date.parse(end);
402
+
403
+ // An unparseable or empty interval cannot be drawn.
404
+ if (!Number.isFinite(startMs) || !Number.isFinite(endMs)) {
405
+ return null;
406
+ }
407
+
408
+ if (endMs <= startMs) {
409
+ return null;
410
+ }
411
+
412
+ let override: ScheduleTimelineOverrideJson | null = null;
413
+
414
+ if (ScheduleTimelineUtil.isObject(value["override"])) {
415
+ const raw: Record<string, unknown> = value["override"];
416
+ const originalUserId: string | null = ScheduleTimelineUtil.readString(
417
+ raw["originalUserId"],
418
+ );
419
+
420
+ if (originalUserId) {
421
+ override = {
422
+ originalUserId,
423
+ originalUserName:
424
+ ScheduleTimelineUtil.readString(raw["originalUserName"]) ||
425
+ "Unknown user",
426
+ overrideStartsAt:
427
+ ScheduleTimelineUtil.readString(raw["overrideStartsAt"]) || start,
428
+ overrideEndsAt:
429
+ ScheduleTimelineUtil.readString(raw["overrideEndsAt"]) || end,
430
+ onCallDutyPolicyId: ScheduleTimelineUtil.readString(
431
+ raw["onCallDutyPolicyId"],
432
+ ),
433
+ };
434
+ }
435
+ }
436
+
437
+ return {
438
+ shiftKey:
439
+ ScheduleTimelineUtil.readString(value["shiftKey"]) ||
440
+ `${userId}:${start}`,
441
+ userId,
442
+ userName:
443
+ ScheduleTimelineUtil.readString(value["userName"]) || "Unknown user",
444
+ start,
445
+ end,
446
+ layerId: ScheduleTimelineUtil.readString(value["layerId"]),
447
+ layerName: ScheduleTimelineUtil.readString(value["layerName"]),
448
+ override,
449
+ };
450
+ }
451
+
452
+ private static readDate(
453
+ value: unknown,
454
+ name: string,
455
+ required: boolean,
456
+ ): Date | null {
457
+ if (value === undefined || value === null || value === "") {
458
+ if (required) {
459
+ throw new BadDataException(`${name} is required.`);
460
+ }
461
+
462
+ return null;
463
+ }
464
+
465
+ if (typeof value !== "string" || !value.trim()) {
466
+ throw new BadDataException(`${name} must be an ISO 8601 date.`);
467
+ }
468
+
469
+ const trimmed: string = value.trim();
470
+
471
+ if (!OneUptimeDate.isValidDateString(trimmed)) {
472
+ throw new BadDataException(`${name} must be an ISO 8601 date.`);
473
+ }
474
+
475
+ const date: Date = OneUptimeDate.fromString(trimmed);
476
+
477
+ if (Number.isNaN(date.getTime())) {
478
+ throw new BadDataException(`${name} must be an ISO 8601 date.`);
479
+ }
480
+
481
+ return date;
482
+ }
483
+
484
+ private static startOfUtcDay(date: Date): number {
485
+ return Date.UTC(
486
+ date.getUTCFullYear(),
487
+ date.getUTCMonth(),
488
+ date.getUTCDate(),
489
+ );
490
+ }
491
+
492
+ private static isObject(value: unknown): value is Record<string, unknown> {
493
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
494
+ }
495
+
496
+ private static readArray(value: unknown): Array<unknown> {
497
+ return Array.isArray(value) ? value : [];
498
+ }
499
+
500
+ private static readString(value: unknown): string | null {
501
+ if (typeof value === "string" && value.length > 0) {
502
+ return value;
503
+ }
504
+
505
+ return null;
506
+ }
507
+ }